partition.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. * File : partition.h
  3. * COPYRIGHT (C) 2016, Shanghai Real-Thread Technology Co., Ltd
  4. *
  5. * Change Logs:
  6. * Date Author Notes
  7. * 2016-09-20 Bernard the first version
  8. */
  9. #include <stdint.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <rtthread.h>
  13. #include <rtdevice.h>
  14. #include "partition.h"
  15. // #define PARTITION_DEBUG
  16. #ifdef PARTITION_DEBUG
  17. #define DEBUG_TRACE rt_kprintf("[part] "); rt_kprintf
  18. #else
  19. #define DEBUG_TRACE(...)
  20. #endif
  21. struct partition_device
  22. {
  23. struct rt_device parent; /* parent block device */
  24. int sector_size;
  25. int block_size;
  26. struct rt_device *block_device;
  27. const struct rt_partition *partition;
  28. };
  29. /* RT-Thread device interface */
  30. static rt_err_t partition_init(rt_device_t dev)
  31. {
  32. return RT_EOK;
  33. }
  34. static rt_err_t partition_open(rt_device_t dev, rt_uint16_t oflag)
  35. {
  36. return RT_EOK;
  37. }
  38. static rt_err_t partition_close(rt_device_t dev)
  39. {
  40. return RT_EOK;
  41. }
  42. #if RTTHREAD_VERSION >= 30000
  43. static rt_err_t partition_control(rt_device_t dev, int cmd, void *args)
  44. #else
  45. static rt_err_t partition_control(rt_device_t dev, rt_uint8_t cmd, void *args)
  46. #endif
  47. {
  48. struct partition_device *part;
  49. part = (struct partition_device*) dev;
  50. RT_ASSERT(part != RT_NULL);
  51. if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
  52. {
  53. struct rt_device_blk_geometry *geometry;
  54. geometry = (struct rt_device_blk_geometry *)args;
  55. if (geometry == RT_NULL) return -RT_ERROR;
  56. geometry->bytes_per_sector = part->sector_size;
  57. geometry->sector_count = part->partition->size / part->sector_size;
  58. geometry->block_size = part->block_size;
  59. }
  60. return RT_EOK;
  61. }
  62. static rt_size_t partition_read(rt_device_t dev,
  63. rt_off_t pos,
  64. void* buffer,
  65. rt_size_t size)
  66. {
  67. struct partition_device *part;
  68. part = (struct partition_device*) dev;
  69. RT_ASSERT(part != RT_NULL);
  70. DEBUG_TRACE("read block: %d, size=%d\n", pos + part->partition->offset/part->sector_size, size);
  71. return rt_device_read(part->block_device, pos + part->partition->offset/part->sector_size, buffer, size);
  72. }
  73. static rt_size_t partition_write(rt_device_t dev,
  74. rt_off_t pos,
  75. const void* buffer,
  76. rt_size_t size)
  77. {
  78. struct partition_device *part;
  79. part = (struct partition_device*) dev;
  80. RT_ASSERT(part != RT_NULL);
  81. if (part->partition->flags & PARTITION_WRITEABLE)
  82. {
  83. DEBUG_TRACE("write block: %d, size=%d\n", pos + part->partition->offset/part->sector_size, size);
  84. return rt_device_write(part->block_device, pos + part->partition->offset/part->sector_size,
  85. buffer, size);
  86. }
  87. DEBUG_TRACE("read-only partition!\n");
  88. return 0;
  89. }
  90. #ifdef RT_USING_DEVICE_OPS
  91. const static struct rt_device_ops partition_dev_ops =
  92. {
  93. .init = partition_init,
  94. .open = partition_open,
  95. .close = partition_close,
  96. .read = partition_read,
  97. .write = partition_write,
  98. .control = partition_control
  99. };
  100. #endif
  101. int rt_partition_init(const char* flash_device, const struct rt_partition* parts, rt_size_t num)
  102. {
  103. struct rt_device *device;
  104. struct partition_device *part_dev;
  105. const struct rt_partition* part;
  106. struct rt_device_blk_geometry geometry;
  107. device = (struct rt_device *)rt_device_find(flash_device);
  108. if(device == RT_NULL)
  109. {
  110. DEBUG_TRACE("block device %s not found!\r\n", flash_device);
  111. return -RT_ENOSYS;
  112. }
  113. /* open the block device */
  114. rt_device_open(device, RT_DEVICE_OFLAG_RDWR);
  115. /* get block device geometry */
  116. rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
  117. /* create each partition device */
  118. while(num --)
  119. {
  120. part = parts ++;
  121. part_dev = (struct partition_device*)rt_malloc (sizeof(struct partition_device));
  122. if (part_dev)
  123. {
  124. part_dev->block_device = device;
  125. part_dev->partition = part;
  126. part_dev->sector_size = geometry.bytes_per_sector;
  127. part_dev->block_size = geometry.block_size;
  128. /* register device */
  129. part_dev->parent.type = RT_Device_Class_Block;
  130. #ifdef RT_USING_DEVICE_OPS
  131. part_dev->parent.ops = &partition_dev_ops;
  132. #else
  133. part_dev->parent.init = partition_init;
  134. part_dev->parent.open = partition_open;
  135. part_dev->parent.close = partition_close;
  136. part_dev->parent.read = partition_read;
  137. part_dev->parent.write = partition_write;
  138. part_dev->parent.control = partition_control;
  139. #endif
  140. /* no private */
  141. part_dev->parent.user_data = RT_NULL;
  142. DEBUG_TRACE("add partition: %s\n", part->name);
  143. rt_device_register(RT_DEVICE(part_dev), part->name,
  144. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
  145. }
  146. }
  147. return RT_EOK;
  148. }