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