bootuf2.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. * Copyright (c) 2024, sakumisu
  3. * Copyright (c) 2024, Egahp
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. */
  7. #ifndef BOOTUF2_H
  8. #define BOOTUF2_H
  9. #include <stdint.h>
  10. #include <stddef.h>
  11. #include <string.h>
  12. #include <stdbool.h>
  13. #include <stdio.h>
  14. #include <bootuf2_config.h>
  15. #ifndef __PACKED
  16. #define __PACKED __attribute__((packed))
  17. #endif
  18. #ifndef ARRAY_SIZE
  19. #define ARRAY_SIZE(array) \
  20. ((int)((sizeof(array) / sizeof((array)[0]))))
  21. #endif
  22. struct bootuf2_BLOCK
  23. {
  24. // 32 byte header
  25. uint32_t MagicStart0;
  26. uint32_t MagicStart1;
  27. uint32_t Flags;
  28. uint32_t TargetAddress;
  29. uint32_t PayloadSize;
  30. uint32_t BlockIndex;
  31. uint32_t NumberOfBlock;
  32. uint32_t FamilyID; // or file_size
  33. uint8_t Data[476];
  34. uint32_t MagicEnd;
  35. } __PACKED;
  36. //BUILD_ASSERT(sizeof(struct bootuf2_BLOCK) == 512, "bootuf2_BLOCK not sector sized");
  37. struct bootuf2_STATE
  38. {
  39. uint32_t NumberOfBlock;
  40. uint32_t NumberOfWritten;
  41. uint8_t *const Mask;
  42. uint8_t Enable;
  43. };
  44. struct bootuf2_DBR
  45. {
  46. /*!< offset 0 */
  47. uint8_t JMPInstruction[3];
  48. /*!< offset 3 */
  49. uint8_t OEM[8];
  50. /*!< offset 11 */
  51. struct
  52. {
  53. uint16_t BytesPerSector;
  54. uint8_t SectorsPerCluster;
  55. uint16_t ReservedSectors;
  56. uint8_t NumberOfFAT;
  57. uint16_t RootEntries;
  58. uint16_t Sectors;
  59. uint8_t MediaDescriptor;
  60. uint16_t SectorsPerFAT;
  61. uint16_t SectorsPerTrack;
  62. uint16_t Heads;
  63. uint32_t HiddenSectors;
  64. uint32_t SectorsOver32MB;
  65. uint8_t BIOSDrive;
  66. uint8_t Reserved;
  67. uint8_t ExtendBootSignature;
  68. uint32_t VolumeSerialNumber;
  69. uint8_t VolumeLabel[11];
  70. uint8_t FileSystem[8];
  71. } __PACKED BPB;
  72. /*!< offset 62 */
  73. /*!< BootLoader */
  74. /*!< offset 511 */
  75. /*!< 0x55 0xAA */
  76. } __PACKED;
  77. //BUILD_ASSERT(sizeof(struct bootuf2_DBR) == 62, "bootuf2_DBR size must be 62 byte");
  78. struct bootuf2_ENTRY
  79. {
  80. char Name[11];
  81. uint8_t Attribute;
  82. uint8_t NTReserved;
  83. uint8_t CreateTimeTeenth;
  84. uint16_t CreateTime;
  85. uint16_t CreateDate;
  86. uint16_t LastAccessDate;
  87. uint16_t FirstClustH16;
  88. uint16_t UpdateTime;
  89. uint16_t UpdateDate;
  90. uint16_t FirstClustL16;
  91. uint32_t FileSize;
  92. } __PACKED;
  93. //BUILD_ASSERT(sizeof(struct bootuf2_ENTRY) == 32, "bootuf2_ENTRY size must be 32 byte");
  94. struct bootuf2_FILE
  95. {
  96. const char *const Name;
  97. const void *const Content;
  98. uint32_t FileSize;
  99. uint16_t ClusterBeg;
  100. uint16_t ClusterEnd;
  101. };
  102. #define BOOTUF2_DIVCEIL(_v, _d) (((_v) / (_d)) + ((_v) % (_d) ? 1 : 0))
  103. #define BOOTUF2_MAGIC_START0 0x0A324655u
  104. #define BOOTUF2_MAGIC_START1 0x9E5D5157u
  105. #define BOOTUF2_MAGIC_SERIAL 0x251B18BDu
  106. #define BOOTUF2_MAGIC_END 0x0AB16F30u
  107. #define BOOTUF2_FLAG_NOT_MAIN_FLASH 0x00000001u
  108. #define BOOTUF2_FLAG_FILE_CONTAINER 0x00001000u
  109. #define BOOTUF2_FLAG_FAMILID_PRESENT 0x00002000u
  110. #define BOOTUF2_FLAG_MD5_PRESENT 0x00004000u
  111. #define BOOTUF2_CMD_READ 0
  112. #define BOOTUF2_CMD_SYNC 1
  113. #define BOOTUF2_BLOCKSMAX (((CONFIG_BOOTUF2_FLASHMAX) / 256) + (((CONFIG_BOOTUF2_FLASHMAX) % 256) ? 1 : 0))
  114. #define BOOTUF2_FAMILYID_POSNUM(n) (((CONFIG_BOOTUF2_FAMILYID) / (0x10000000 >> ((n) * 4))) % 0x10)
  115. #define BOOTUF2_FAMILYID_ARRAY \
  116. { \
  117. ((BOOTUF2_FAMILYID_POSNUM(0) >= 10) ? BOOTUF2_FAMILYID_POSNUM(0) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(0) + '0'), \
  118. ((BOOTUF2_FAMILYID_POSNUM(1) >= 10) ? BOOTUF2_FAMILYID_POSNUM(1) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(1) + '0'), \
  119. ((BOOTUF2_FAMILYID_POSNUM(2) >= 10) ? BOOTUF2_FAMILYID_POSNUM(2) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(2) + '0'), \
  120. ((BOOTUF2_FAMILYID_POSNUM(3) >= 10) ? BOOTUF2_FAMILYID_POSNUM(3) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(3) + '0'), \
  121. ((BOOTUF2_FAMILYID_POSNUM(4) >= 10) ? BOOTUF2_FAMILYID_POSNUM(4) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(4) + '0'), \
  122. ((BOOTUF2_FAMILYID_POSNUM(5) >= 10) ? BOOTUF2_FAMILYID_POSNUM(5) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(5) + '0'), \
  123. ((BOOTUF2_FAMILYID_POSNUM(6) >= 10) ? BOOTUF2_FAMILYID_POSNUM(6) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(6) + '0'), \
  124. ((BOOTUF2_FAMILYID_POSNUM(7) >= 10) ? BOOTUF2_FAMILYID_POSNUM(7) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(7) + '0'), \
  125. ('I'), \
  126. ('D'), \
  127. (' '), \
  128. ('\0'), \
  129. };
  130. #define BOOTUF2_FAT16_PER_SECTOR(pDBR) (pDBR->BPB.BytesPerSector / 2)
  131. #define BOOTUF2_ENTRY_PER_SECTOR(pDBR) (pDBR->BPB.BytesPerSector / sizeof(struct bootuf2_ENTRY))
  132. #define BOOTUF2_CLUSTERSMAX (0xFFF0 - 2)
  133. #define BOOTUF2_SECTOR_DBR_END (0)
  134. #define BOOTUF2_SECTOR_RSVD_END(pDBR) BOOTUF2_SECTOR_DBR_END + (pDBR->BPB.ReservedSectors)
  135. #define BOOTUF2_SECTOR_FAT_END(pDBR) BOOTUF2_SECTOR_RSVD_END(pDBR) + (pDBR->BPB.SectorsPerFAT * pDBR->BPB.NumberOfFAT)
  136. #define BOOTUF2_SECTOR_ROOT_END(pDBR) BOOTUF2_SECTOR_FAT_END(pDBR) + (pDBR->BPB.RootEntries / (pDBR->BPB.BytesPerSector / sizeof(struct bootuf2_ENTRY)))
  137. #define BOOTUF2_SECTOR_DATA_END(pDBR) (pDBR->BPB.Sectors + pDBR->BPB.SectorsOver32MB)
  138. #define BOOTUF2_SECTORS_PER_FAT(n) \
  139. BOOTUF2_DIVCEIL(BOOTUF2_CLUSTERSMAX, (CONFIG_BOOTUF2_SECTOR_SIZE / 2))
  140. #define BOOTUF2_SECTORS_FOR_ENTRIES(n) \
  141. (CONFIG_BOOTUF2_ROOT_ENTRIES / (CONFIG_BOOTUF2_SECTOR_SIZE / sizeof(struct bootuf2_ENTRY)))
  142. #define BOOTUF2_SECTORS(n) \
  143. (CONFIG_BOOTUF2_SECTOR_RESERVED + \
  144. CONFIG_BOOTUF2_NUM_OF_FAT * BOOTUF2_SECTORS_PER_FAT(n) + \
  145. BOOTUF2_SECTORS_FOR_ENTRIES(n) + \
  146. BOOTUF2_CLUSTERSMAX * CONFIG_BOOTUF2_SECTOR_PER_CLUSTER)
  147. #define BOOTUF2_YEAR_INT ( \
  148. (__DATE__[7u] - '0') * 1000u + \
  149. (__DATE__[8u] - '0') * 100u + \
  150. (__DATE__[9u] - '0') * 10u + \
  151. (__DATE__[10u] - '0') * 1u)
  152. #define BOOTUF2_MONTH_INT ( \
  153. (__DATE__[2u] == 'n' && __DATE__[1u] == 'a') ? 1u /*Jan*/ \
  154. : (__DATE__[2u] == 'b') ? 2u /*Feb*/ \
  155. : (__DATE__[2u] == 'r' && __DATE__[1u] == 'a') ? 3u /*Mar*/ \
  156. : (__DATE__[2u] == 'r') ? 4u /*Apr*/ \
  157. : (__DATE__[2u] == 'y') ? 5u /*May*/ \
  158. : (__DATE__[2u] == 'n') ? 6u /*Jun*/ \
  159. : (__DATE__[2u] == 'l') ? 7u /*Jul*/ \
  160. : (__DATE__[2u] == 'g') ? 8u /*Aug*/ \
  161. : (__DATE__[2u] == 'p') ? 9u /*Sep*/ \
  162. : (__DATE__[2u] == 't') ? 10u /*Oct*/ \
  163. : (__DATE__[2u] == 'v') ? 11u /*Nov*/ \
  164. : 12u /*Dec*/)
  165. #define BOOTUF2_DAY_INT ( \
  166. (__DATE__[4u] == ' ' ? 0 : __DATE__[4u] - '0') * 10u + \
  167. (__DATE__[5u] - '0'))
  168. #define BOOTUF2_HOUR_INT ( \
  169. (__TIME__[0u] == '?' ? 0 : __TIME__[0u] - '0') * 10u + (__TIME__[1u] == '?' ? 0 : __TIME__[1u] - '0'))
  170. #define BOOTUF2_MINUTE_INT ( \
  171. (__TIME__[3u] == '?' ? 0 : __TIME__[3u] - '0') * 10u + (__TIME__[4u] == '?' ? 0 : __TIME__[4u] - '0'))
  172. #define BOOTUF2_SECONDS_INT ( \
  173. (__TIME__[6u] == '?' ? 0 : __TIME__[6u] - '0') * 10u + (__TIME__[7u] == '?' ? 0 : __TIME__[7u] - '0'))
  174. #define BOOTUF2_DOS_DATE ( \
  175. ((BOOTUF2_YEAR_INT - 1980u) << 9u) | \
  176. (BOOTUF2_MONTH_INT << 5u) | \
  177. (BOOTUF2_DAY_INT << 0u))
  178. #define BOOTUF2_DOS_TIME ( \
  179. (BOOTUF2_HOUR_INT << 11u) | \
  180. (BOOTUF2_MINUTE_INT << 5u) | \
  181. (BOOTUF2_SECONDS_INT << 0u))
  182. void bootuf2_init(void);
  183. int boot2uf2_read_sector(uint32_t start_sector, uint8_t *buff, uint32_t sector_count);
  184. int bootuf2_write_sector(uint32_t start_sector, const uint8_t *buff, uint32_t sector_count);
  185. uint16_t bootuf2_get_sector_size(void);
  186. uint32_t bootuf2_get_sector_count(void);
  187. bool bootuf2_is_write_done(void);
  188. void boot2uf2_flash_init(void);
  189. int bootuf2_flash_write(uint32_t address, const uint8_t *data, size_t size);
  190. #endif /* BOOTUF2_H */