efi.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. #include "typedefs.h"
  2. #include "print.h"
  3. #include "blkdev.h"
  4. #include "dram_buffer.h"
  5. #include "partition_api.h"
  6. #include "pal_log.h"
  7. #include "storage_api.h"
  8. typedef struct {
  9. u8 b[16];
  10. } __attribute__((packed)) efi_guid_t;
  11. typedef struct {
  12. u64 signature;
  13. u32 revision;
  14. u32 header_size;
  15. u32 header_crc32;
  16. u32 reserved;
  17. u64 my_lba;
  18. u64 alternate_lba;
  19. u64 first_usable_lba;
  20. u64 last_usable_lba;
  21. efi_guid_t disk_guid;
  22. u64 partition_entry_lba;
  23. u32 num_partition_entries;
  24. u32 sizeof_partition_entry;
  25. u32 partition_entry_array_crc32;
  26. } __attribute__((packed)) gpt_header;
  27. #define GPT_ENTRY_NAME_LEN (72 / sizeof(u16))
  28. typedef struct {
  29. efi_guid_t partition_type_guid;
  30. efi_guid_t unique_partition_guid;
  31. u64 starting_lba;
  32. u64 ending_lba;
  33. u64 attributes;
  34. u16 partition_name[GPT_ENTRY_NAME_LEN];
  35. } __attribute__((packed))gpt_entry;
  36. static part_t *part_ptr = NULL;
  37. /*
  38. ********** Definition of Debug Macro **********
  39. */
  40. #define TAG "[GPT_PL]"
  41. /*
  42. ********** Definition of GPT buffer **********
  43. */
  44. #define GPT_HEADER_BUF g_dram_buf->gpt_header_buf
  45. #define GPT_ENTRIES_BUF g_dram_buf->gpt_entries_buf
  46. /*
  47. ********** Definition of CRC32 Calculation **********
  48. */
  49. #define gpt_dram_crc32_table g_dram_buf->crc32_table
  50. #define GPT_HEADER_SIGNATURE 0x5452415020494645ULL
  51. #ifdef EARLY_PARTITION_ACCESS
  52. #define GPT_SRAM_BUF_SIZE 4096
  53. unsigned char __NOBITS_SECTION__(.gpt_sram_buf) gpt_sram_buf[GPT_SRAM_BUF_SIZE];
  54. u32 __NOBITS_SECTION__(.gpt_sram_crc32_table) gpt_sram_crc32_table[256];
  55. part_t __NOBITS_SECTION__(.gpt_sram_part_info) gpt_sram_part_info;
  56. struct part_meta_info __NOBITS_SECTION__(.gpt_sram_part_meta_info) gpt_sram_part_meta_info;
  57. #endif
  58. static void init_crc32_table(u32* crc32_table)
  59. {
  60. int i, j;
  61. u32 crc;
  62. for (i = 0; i < 256; i++) {
  63. crc = i;
  64. for (j = 0; j < 8; j++) {
  65. if (crc & 1) {
  66. crc = (crc >> 1) ^ 0xEDB88320;
  67. } else {
  68. crc >>= 1;
  69. }
  70. }
  71. crc32_table[i] = crc;
  72. }
  73. }
  74. static u32 crc32(u32 crc, u8 *p, u32 len, u32* crc32_table)
  75. {
  76. while (len--) {
  77. crc ^= *p++;
  78. crc = (crc >> 8) ^ crc32_table[crc & 255];
  79. }
  80. return crc;
  81. }
  82. static u32 efi_crc32(u32 crc, u8 *p, u32 len, u32* crc32_table)
  83. {
  84. return crc32(crc, p, len, crc32_table);
  85. }
  86. static u32 efi_crc32_finalize(u32 crc)
  87. {
  88. return crc ^ ~0L;
  89. }
  90. static void get_part_name(u8 *dst, u16 *src, int len)
  91. {
  92. int i = 0;
  93. if ((src[0] & 0xFF00) == 0) { // word to ascii string
  94. while (i < len - 1) {
  95. if (!src[i])
  96. break;
  97. dst[i] = src[i] & 0xFF;
  98. i++;
  99. }
  100. dst[i] = 0;
  101. } else {
  102. memcpy(dst, src, len - 1);
  103. dst[len-1] = 0;
  104. }
  105. }
  106. static void get_part_info(u32 part_id, part_t *part_ptr, gpt_entry *entry)
  107. {
  108. get_part_name(part_ptr->info->name, entry->partition_name, min(PART_META_INFO_NAMELEN, GPT_ENTRY_NAME_LEN));
  109. part_ptr->start_sect = (unsigned long)entry->starting_lba;
  110. part_ptr->nr_sects = (unsigned long)(entry->ending_lba - entry->starting_lba + 1);
  111. part_ptr->part_id = part_id;
  112. part_ptr->part_attr = (unsigned long)entry->attributes;
  113. pal_log_debug("%sname=%s, start_sect=0x%x, nr_sects=0x%x\n", TAG, part_ptr->info->name,
  114. (unsigned long)entry->starting_lba, (unsigned long)(entry->ending_lba - entry->starting_lba + 1));
  115. }
  116. extern u64 g_emmc_user_size;
  117. static u64 last_lba(u32 part_id)
  118. {
  119. #if !defined(BOOTDEV_SDMMC_UFS_COMBO)
  120. /* Only support USER region now */
  121. #if (CFG_BOOT_DEV == BOOTDEV_SDMMC)
  122. return g_emmc_user_size / 512 - 1;
  123. #elif (CFG_BOOT_DEV == BOOTDEV_UFS)
  124. {
  125. blkdev_t *dev;
  126. u64 bytes;
  127. dev = blkdev_get(CFG_BOOT_DEV);
  128. if (dev == NULL)
  129. return 0;
  130. bytes = dev->get_part_size(dev, part_id);
  131. if (bytes)
  132. return bytes / dev->blksz - 1;
  133. else
  134. return 0;
  135. }
  136. #endif
  137. #else
  138. #if (CFG_BOOT_DEV == BOOTDEV_SDMMC) || (CFG_BOOT_DEV == BOOTDEV_UFS)
  139. blkdev_t *dev;
  140. u64 bytes;
  141. dev = blkdev_get(CFG_BOOT_DEV);
  142. if (dev == NULL)
  143. return 0;
  144. if (dev->type == BOOTDEV_SDMMC) {
  145. return g_emmc_user_size / 512 - 1;
  146. } else if (dev->type == BOOTDEV_UFS) {
  147. bytes = dev->get_part_size(dev, part_id);
  148. if (bytes)
  149. return bytes / dev->blksz - 1;
  150. else
  151. return 0;
  152. }
  153. #endif
  154. #endif
  155. return 0;
  156. }
  157. static int read_data(u8 *buf, u32 part_id, u64 lba, u64 size)
  158. {
  159. int err;
  160. blkdev_t *dev;
  161. dev = blkdev_get(CFG_BOOT_DEV);
  162. if (!dev) {
  163. pal_log_err("%sread data, err(no dev)\n", TAG);
  164. return 1;
  165. }
  166. err = blkdev_read(dev, lba * dev->blksz, (u32)size, buf, part_id);
  167. if (err) {
  168. pal_log_err("%sread data, err(%d)\n", TAG, err);
  169. return err;
  170. }
  171. return 0;
  172. }
  173. static int get_gpt_header(u32 part_id, u64 header_lba, u8 *header_buf, u32 len, u32 *crc32_table)
  174. {
  175. int err;
  176. u32 calc_crc, orig_header_crc;
  177. gpt_header *header = (gpt_header *)header_buf;
  178. err = read_data(header_buf, part_id, header_lba, len);
  179. if (err) {
  180. pal_log_err("%sread header(part_id=%d,lba=%llx), err(%d)\n",
  181. TAG, part_id, header_lba, err);
  182. return err;
  183. }
  184. if (header->signature != GPT_HEADER_SIGNATURE) {
  185. pal_log_err("%scheck header, err(signature 0x%llx!=0x%llx)\n",
  186. TAG, header->signature, GPT_HEADER_SIGNATURE);
  187. return 1;
  188. }
  189. orig_header_crc = header->header_crc32;
  190. header->header_crc32 = 0;
  191. calc_crc = efi_crc32(~0L, (u8 *)header, header->header_size, crc32_table);
  192. calc_crc = efi_crc32_finalize(calc_crc);
  193. if (orig_header_crc != calc_crc) {
  194. pal_log_err("%scheck header, err(crc 0x%x!=0x%x(calc))\n",
  195. TAG, orig_header_crc, calc_crc);
  196. return 1;
  197. }
  198. header->header_crc32 = orig_header_crc;
  199. if (header->my_lba != header_lba) {
  200. pal_log_err("%scheck header, err(my_lba 0x%llx!=0x%llx)\n",
  201. TAG, header->my_lba, header_lba);
  202. return 1;
  203. }
  204. return 0;
  205. }
  206. #ifdef EARLY_PARTITION_ACCESS
  207. static u64 get_part_ptr_by_gpt(u32 part_id, u64 header_lba, u8 *entries_buf, part_t *part_ptr, const char *part_name, u32 blksz) {
  208. int err, i, found;
  209. int entries_cnt, cur_entry_idx;
  210. u32 calc_crc, orig_header_crc;
  211. u64 entries_read_size, num_block_entry, read_lba;
  212. gpt_header gpt_header_buf;
  213. gpt_header *header = &gpt_header_buf;
  214. gpt_entry *entries = (gpt_entry *)entries_buf;
  215. init_crc32_table(gpt_sram_crc32_table);
  216. part_ptr->start_sect = 0;
  217. if (get_gpt_header(part_id, header_lba, (u8*) &gpt_header_buf, sizeof(gpt_header_buf), gpt_sram_crc32_table)) {
  218. pal_log_err("%s get_gpt_header fail\n", TAG);
  219. return 1;
  220. }
  221. num_block_entry = (u64)(blksz / header->sizeof_partition_entry);
  222. entries_read_size = (u64)((header->num_partition_entries + (num_block_entry - 1)) / num_block_entry) * blksz;
  223. calc_crc = ~0L;
  224. read_lba = header->partition_entry_lba;
  225. found = 0;
  226. while (entries_read_size > 0) {
  227. err = read_data((u8*)entries_buf, part_id, read_lba, GPT_SRAM_BUF_SIZE);
  228. read_lba = read_lba + GPT_SRAM_BUF_SIZE/blksz;
  229. calc_crc = efi_crc32(calc_crc, (u8 *)entries_buf, (u32)GPT_SRAM_BUF_SIZE, gpt_sram_crc32_table);
  230. entries_read_size -= GPT_SRAM_BUF_SIZE;
  231. entries_cnt = GPT_SRAM_BUF_SIZE/header->sizeof_partition_entry;
  232. for (i = 0; i < entries_cnt && found == 0; i++) {
  233. if(!entries[i].starting_lba)
  234. break;
  235. get_part_info(part_id, part_ptr, &entries[i]);
  236. if (!strcmp(part_ptr->info->name, part_name)) {
  237. found = 1;
  238. break;
  239. }
  240. }
  241. }
  242. calc_crc = efi_crc32_finalize(calc_crc);
  243. if (header->partition_entry_array_crc32 != calc_crc) {
  244. pal_log_err("%scheck header, err(entries crc 0x%x!=0x%x(calc))\n",
  245. TAG, header->partition_entry_array_crc32, calc_crc);
  246. memset(part_ptr, 0, sizeof(part_t));
  247. return 1;
  248. }
  249. if (found == 0)
  250. memset(part_ptr, 0, sizeof(part_t));
  251. return 0;
  252. }
  253. part_t *mt_get_part_sram(const char *name)
  254. {
  255. u32 part_id;
  256. part_id = storage_get_part_id(STORAGE_PHYS_PART_USER);
  257. if (name == NULL) {
  258. pal_log_err("%s[%s]invalid argument\n", TAG, __func__);
  259. return NULL;
  260. }
  261. blkdev_t *dev = blkdev_get(CFG_BOOT_DEV);
  262. if (!dev) {
  263. pal_log_err("%s%s fail, err(no dev)\n", TAG, __func__);
  264. return NULL;
  265. }
  266. gpt_sram_part_info.info = &gpt_sram_part_meta_info;
  267. if (get_part_ptr_by_gpt(part_id, 1, gpt_sram_buf, &gpt_sram_part_info, name, dev->blksz) != 0) {
  268. if (get_part_ptr_by_gpt(part_id, last_lba(part_id), gpt_sram_buf, &gpt_sram_part_info, name, dev->blksz) != 0) {
  269. pal_log_err("%sFailure to find valid GPT.\n", TAG);
  270. return NULL;
  271. }
  272. }
  273. if (gpt_sram_part_info.start_sect == 0 && gpt_sram_part_info.nr_sects == 0)
  274. return NULL;
  275. else
  276. return &gpt_sram_part_info;
  277. }
  278. int mt_get_part_info_by_name(const char *name, struct part_info_t *part_info)
  279. {
  280. part_t *part;
  281. blkdev_t *dev = blkdev_get(CFG_BOOT_DEV);
  282. if (!dev) {
  283. pal_log_err("%s%s fail, err(no dev)\n", TAG, __func__);
  284. return 1;
  285. }
  286. part = mt_get_part_sram(name);
  287. if (part != NULL && part_info != NULL) {
  288. part_info->addr = (u64)part->start_sect * (u64)dev->blksz;
  289. part_info->active = (part->part_attr & PART_ATTR_LEGACY_BIOS_BOOTABLE);
  290. return 0;
  291. }
  292. return 1;
  293. }
  294. u64 get_part_addr(const char *name) {
  295. struct part_info_t part_info;
  296. if (mt_get_part_info_by_name(name, &part_info) != 0) {
  297. pal_log_err("%smt_get_part_info_by_name fail\n", TAG);
  298. return 0;
  299. } else {
  300. return (u64)part_info.addr;
  301. }
  302. }
  303. #endif
  304. static int parse_gpt_header(u32 part_id, u64 header_lba, u8 *header_buf, u8 *entries_buf)
  305. {
  306. int i;
  307. blkdev_t *dev;
  308. int err;
  309. u32 calc_crc, orig_header_crc;
  310. u64 entries_real_size, entries_read_size, num_block_entry;
  311. gpt_header *header = (gpt_header *)header_buf;
  312. gpt_entry *entries = (gpt_entry *)entries_buf;
  313. init_crc32_table(gpt_dram_crc32_table);
  314. dev = blkdev_get(CFG_BOOT_DEV);
  315. if (!dev) {
  316. pal_log_err("%sparse_gpt_header fail, err(no dev)\n", TAG);
  317. return 1;
  318. }
  319. if (get_gpt_header(part_id, header_lba, header_buf, dev->blksz, gpt_dram_crc32_table)) {
  320. pal_log_err("%s get_gpt_header fail\n", TAG);
  321. return 1;
  322. }
  323. entries_real_size = (u64)header->num_partition_entries * header->sizeof_partition_entry;
  324. num_block_entry = (u64)(dev->blksz / header->sizeof_partition_entry);
  325. entries_read_size = (u64)((header->num_partition_entries + (num_block_entry - 1)) / num_block_entry) * dev->blksz;
  326. err = read_data(entries_buf, part_id, header->partition_entry_lba, entries_read_size);
  327. if (err) {
  328. pal_log_err("%sread entries(part_id=%d,lba=%llx), err(%d)\n",
  329. TAG, part_id, header->partition_entry_lba, err);
  330. return err;
  331. }
  332. calc_crc = efi_crc32(~0L, (u8 *)entries, (u32)entries_real_size, gpt_dram_crc32_table);
  333. calc_crc = efi_crc32_finalize(calc_crc);
  334. if (header->partition_entry_array_crc32 != calc_crc) {
  335. pal_log_err("%scheck header, err(entries crc 0x%x!=0x%x(calc))\n",
  336. TAG, header->partition_entry_array_crc32, calc_crc);
  337. return 1;
  338. }
  339. for (i = 0; i < header->num_partition_entries; i++) {
  340. /* break if partition entry is empty */
  341. if(!entries[i].starting_lba)
  342. break;
  343. part_ptr[i].info = &g_dram_buf->meta_info[i];
  344. get_part_info(part_id, &part_ptr[i], &entries[i]);
  345. }
  346. return 0;
  347. }
  348. int read_gpt(part_t *part)
  349. {
  350. int err;
  351. u64 lba;
  352. u32 part_id;
  353. part_id = storage_get_part_id(STORAGE_PHYS_PART_USER);
  354. part_ptr = part;
  355. pal_log_debug("%sParsing Primary GPT now...\n", TAG);
  356. err = parse_gpt_header(part_id, 1, GPT_HEADER_BUF, GPT_ENTRIES_BUF);
  357. if (!err) {
  358. goto find;
  359. }
  360. pal_log_debug("%sParsing Secondary GPT now...\n", TAG);
  361. lba = last_lba(part_id);
  362. if (!lba){
  363. pal_log_err("%sFailure to find last lba.\n", TAG);
  364. return 1;
  365. }
  366. err = parse_gpt_header(part_id, lba, GPT_HEADER_BUF, GPT_ENTRIES_BUF);
  367. if (!err) {
  368. goto find;
  369. }
  370. pal_log_err("%sFailure to find valid GPT.\n", TAG);
  371. return err;
  372. find:
  373. pal_log_err("%sSuccess to find valid GPT.\n", TAG);
  374. return 0;
  375. }