partition.c 5.0 KB

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