partition.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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. static rt_err_t partition_control(rt_device_t dev, rt_uint8_t cmd, void *args)
  43. {
  44. struct partition_device *part;
  45. part = (struct partition_device*) dev;
  46. RT_ASSERT(part != RT_NULL);
  47. if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
  48. {
  49. struct rt_device_blk_geometry *geometry;
  50. geometry = (struct rt_device_blk_geometry *)args;
  51. if (geometry == RT_NULL) return -RT_ERROR;
  52. geometry->bytes_per_sector = part->sector_size;
  53. geometry->sector_count = part->partition->size / part->sector_size;
  54. geometry->block_size = part->block_size;
  55. }
  56. return RT_EOK;
  57. }
  58. static rt_size_t partition_read(rt_device_t dev,
  59. rt_off_t pos,
  60. void* buffer,
  61. rt_size_t size)
  62. {
  63. struct partition_device *part;
  64. part = (struct partition_device*) dev;
  65. RT_ASSERT(part != RT_NULL);
  66. DEBUG_TRACE("read block: %d, size=%d\n", pos + part->partition->offset/part->sector_size, size);
  67. return rt_device_read(part->block_device, pos + part->partition->offset/part->sector_size, buffer, size);
  68. }
  69. static rt_size_t partition_write(rt_device_t dev,
  70. rt_off_t pos,
  71. const void* buffer,
  72. rt_size_t size)
  73. {
  74. struct partition_device *part;
  75. part = (struct partition_device*) dev;
  76. RT_ASSERT(part != RT_NULL);
  77. if (part->partition->flags & PARTITION_WRITEABLE)
  78. {
  79. DEBUG_TRACE("write block: %d, size=%d\n", pos + part->partition->offset/part->sector_size, size);
  80. return rt_device_write(part->block_device, pos + part->partition->offset/part->sector_size,
  81. buffer, size);
  82. }
  83. DEBUG_TRACE("read-only partition!\n");
  84. return 0;
  85. }
  86. int rt_partition_init(const char* flash_device, const struct rt_partition* parts, rt_size_t num)
  87. {
  88. struct rt_device *device;
  89. struct partition_device *part_dev;
  90. const struct rt_partition* part;
  91. struct rt_device_blk_geometry geometry;
  92. device = (struct rt_device *)rt_device_find(flash_device);
  93. if(device == RT_NULL)
  94. {
  95. DEBUG_TRACE("block device %s not found!\r\n", flash_device);
  96. return -RT_ENOSYS;
  97. }
  98. /* open the block device */
  99. rt_device_open(device, RT_DEVICE_OFLAG_RDWR);
  100. /* get block device geometry */
  101. rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
  102. /* create each partition device */
  103. while(num --)
  104. {
  105. part = parts ++;
  106. part_dev = (struct partition_device*)rt_malloc (sizeof(struct partition_device));
  107. if (part_dev)
  108. {
  109. part_dev->block_device = device;
  110. part_dev->partition = part;
  111. part_dev->sector_size = geometry.bytes_per_sector;
  112. part_dev->block_size = geometry.block_size;
  113. /* register device */
  114. part_dev->parent.type = RT_Device_Class_Block;
  115. part_dev->parent.init = partition_init;
  116. part_dev->parent.open = partition_open;
  117. part_dev->parent.close = partition_close;
  118. part_dev->parent.read = partition_read;
  119. part_dev->parent.write = partition_write;
  120. part_dev->parent.control = partition_control;
  121. /* no private */
  122. part_dev->parent.user_data = RT_NULL;
  123. DEBUG_TRACE("add partition: %s\n", part->name);
  124. rt_device_register(RT_DEVICE(part_dev), part->name,
  125. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
  126. }
  127. }
  128. return RT_EOK;
  129. }