efi.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part, shall be strictly prohibited.
  9. */
  10. /* MediaTek Inc. (C) 2015. All rights reserved.
  11. *
  12. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  13. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  14. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  15. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  18. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  19. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  20. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  21. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
  22. * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
  23. * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
  24. * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
  26. * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  27. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  28. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  29. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. */
  31. #include <printf.h>
  32. #include <malloc.h>
  33. #include <string.h>
  34. #include <lib/crc.h>
  35. #include <platform/mt_typedefs.h>
  36. #include <platform/partition.h>
  37. #include <efi.h>
  38. #include <part_interface.h>
  39. #include <block_generic_interface.h>
  40. #include <pal_log.h>
  41. #ifndef min
  42. #define min(x, y) (x < y ? x : y)
  43. #endif
  44. extern bool cmdline_append(const char *append_string);
  45. static part_t *g_part_ptr = NULL;
  46. u32 sgpt_partition_lba_size;
  47. static u64 g_gpt_entry_cnt = 0;
  48. /*
  49. ********** Definition of Debug Macro **********
  50. */
  51. #define TAG "[GPT_LK]"
  52. #define LEVEL_ERR (0x0001)
  53. #define LEVEL_INFO (0x0004)
  54. #define DEBUG_LEVEL (LEVEL_ERR | LEVEL_INFO)
  55. #define efi_err(fmt, args...) \
  56. do { \
  57. if (DEBUG_LEVEL & LEVEL_ERR) { \
  58. pal_log_err(fmt, ##args); \
  59. } \
  60. } while (0)
  61. #define efi_critical(fmt, args...) \
  62. do { \
  63. if (DEBUG_LEVEL & LEVEL_INFO) { \
  64. pal_log_err(fmt, ##args); \
  65. } \
  66. } while (0)
  67. /*
  68. ********** Definition of GPT buffer **********
  69. */
  70. static u32 efi_crc32(u8 *p, u32 len)
  71. {
  72. return (crc32_no_comp(~0L, p, len) ^ ~0L); /* from zlib */
  73. }
  74. static void w2s(u8 *dst, int dst_max, u16 *src, int src_max)
  75. {
  76. int i = 0;
  77. int len = min(src_max, dst_max - 1);
  78. while (i < len) {
  79. if (!src[i]) {
  80. break;
  81. }
  82. dst[i] = src[i] & 0xFF;
  83. i++;
  84. }
  85. dst[i] = 0;
  86. return;
  87. }
  88. u64 get_entry_count()
  89. {
  90. return g_gpt_entry_cnt;
  91. }
  92. extern u64 g_emmc_user_size;
  93. u64 last_lba(u32 part_id)
  94. {
  95. part_dev_t *dev;
  96. dev = mt_part_get_device();
  97. if (!dev) {
  98. efi_err("%s%s, err(no dev)\n", TAG, __func__);
  99. return 1;
  100. }
  101. /* Only support USER region now */
  102. #if (defined(MTK_EMMC_SUPPORT) || defined(MTK_UFS_SUPPORT))
  103. if (dev->blkdev->type == BOOTDEV_SDMMC) {
  104. return g_emmc_user_size / dev->blkdev->blksz - 1;
  105. } else if (dev->blkdev->type == BOOTDEV_UFS) {
  106. u64 bytes;
  107. bytes = dev->get_part_size(dev, part_id);
  108. if (bytes)
  109. return bytes / dev->blkdev->blksz - 1;
  110. else
  111. return 0;
  112. }
  113. #endif
  114. return 0;
  115. }
  116. static void set_spgt_partition_lba_size(u32 size)
  117. {
  118. sgpt_partition_lba_size = size;
  119. }
  120. static u32 get_spgt_partition_lba_size()
  121. {
  122. return sgpt_partition_lba_size;
  123. }
  124. static u64 get_gpt_header_last_usable_lba()
  125. {
  126. part_dev_t *dev = mt_part_get_device();
  127. return (last_lba(dev->blkdev->part_user)-get_spgt_partition_lba_size());
  128. }
  129. static u32 entries_crc32;
  130. static void set_entries_crc32(u32 crc32)
  131. {
  132. entries_crc32 = crc32;
  133. }
  134. static u32 get_entries_crc32(void)
  135. {
  136. return entries_crc32;
  137. }
  138. static int read_data(u8 *buf, u32 part_id, u64 lba, u64 size)
  139. {
  140. int err;
  141. part_dev_t *dev;
  142. dev = mt_part_get_device();
  143. if (!dev) {
  144. efi_err("%sread data, err(no dev)\n", TAG);
  145. return 1;
  146. }
  147. err = dev->read(dev, lba * dev->blkdev->blksz, buf, (int)size, part_id);
  148. if (err != (int)size) {
  149. efi_err("%sread data, err(%d)\n", TAG, err);
  150. return err;
  151. }
  152. return 0;
  153. }
  154. static int write_data(u64 lba, u8 *buf, u64 size, u32 part_id)
  155. {
  156. int err;
  157. part_dev_t *dev;
  158. dev = mt_part_get_device();
  159. if (!dev) {
  160. efi_err("%swrite data, err(no dev)\n", TAG);
  161. return 1;
  162. }
  163. err = dev->write(dev, buf, lba * dev->blkdev->blksz, (int)size, part_id);
  164. if (err != (int)size) {
  165. efi_err("%s write data, err(%d)\n", TAG, err);
  166. return err;
  167. }
  168. return 0;
  169. }
  170. const char hex_asc[] = "0123456789abcdef";
  171. #define hex_asc_lo(x) hex_asc[((x)&0x0f)];
  172. #define hex_asc_hi(x) hex_asc[((x)&0xf0)>>4];
  173. static inline char *hex_byte_pack(char *buf, u8 byte)
  174. {
  175. *buf++ = hex_asc_hi(byte);
  176. *buf++ = hex_asc_lo(byte);
  177. return buf;
  178. }
  179. static u8 *string(u8 *buf, u8 *end, const char *s)
  180. {
  181. int len, i;
  182. len = strnlen(s, PART_META_INFO_UUIDLEN);
  183. for (i = 0; i < len; ++i) {
  184. if (buf < end)
  185. *buf = *s;
  186. ++buf;
  187. ++s;
  188. }
  189. if (buf < end)
  190. *buf = 0;
  191. return buf;
  192. }
  193. static u8 *uuid_string(u8 *buf, u8 *args)
  194. {
  195. /* uuid format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx, which contains 16*2 + 4('-') + 1 ('\0') = 37 bytes*/
  196. char uuid[PART_META_INFO_UUIDLEN];
  197. char *p = uuid;
  198. int i;
  199. static const u8 index[16] = {3,2,1,0,5,4,7,6,8,9,10,11,12,13,14,15};
  200. u8 *end;
  201. end = buf + PART_META_INFO_UUIDLEN;
  202. for (i = 0; i < 16; i++) {
  203. p = hex_byte_pack(p, args[index[i]]);
  204. switch(i) {
  205. case 3:
  206. case 5:
  207. case 7:
  208. case 9:
  209. *p++ = '-';
  210. break;
  211. default:
  212. break;
  213. }
  214. }
  215. *p = 0;
  216. return string(buf, end, uuid);
  217. }
  218. static inline u8 *efi_guid_unparse(efi_guid_t *guid, u8 *out)
  219. {
  220. if (NULL == uuid_string(out, guid->b)) {
  221. efi_err("parse uuid string format fail!\n");
  222. return NULL;
  223. }
  224. return out;
  225. }
  226. static int parse_gpt_header(u32 part_id, u64 header_lba, u8 *header_buf, u8 *entries_buf)
  227. {
  228. int i;
  229. int err;
  230. u32 calc_crc, orig_header_crc;
  231. u64 entries_real_size, entries_read_size, num_block_entry;
  232. part_dev_t *dev = mt_part_get_device();
  233. gpt_header *header = (gpt_header *)header_buf;
  234. gpt_entry *entries = (gpt_entry *)entries_buf;
  235. struct part_meta_info *info;
  236. if (!dev) {
  237. efi_err("%s%s, err(no dev)\n", TAG, __func__);
  238. return 1;
  239. }
  240. if (g_part_ptr == NULL) {
  241. efi_err("%sg_part_ptr is NULL, partition table was not initialized\n", TAG);
  242. return 1;
  243. }
  244. if (header_buf == NULL) {
  245. efi_err("%sheader_buf is NULL\n", TAG);
  246. return 1;
  247. }
  248. if (entries_buf == NULL) {
  249. efi_err("%sentries_buf is NULL\n", TAG);
  250. return 1;
  251. }
  252. err = read_data(header_buf, part_id, header_lba, dev->blkdev->blksz);
  253. if (err) {
  254. efi_err("%sread header(part_id=%d,lba=%llx), err(%d)\n",
  255. TAG, part_id, header_lba, err);
  256. return err;
  257. }
  258. if (header->signature != GPT_HEADER_SIGNATURE) {
  259. efi_err("%scheck header, err(signature 0x%llx!=0x%llx)\n",
  260. TAG, header->signature, GPT_HEADER_SIGNATURE);
  261. return 1;
  262. }
  263. orig_header_crc = header->header_crc32;
  264. header->header_crc32 = 0;
  265. calc_crc = efi_crc32((u8 *)header, header->header_size);
  266. if (orig_header_crc != calc_crc) {
  267. efi_err("%scheck header, err(crc 0x%x!=0x%x(calc))\n",
  268. TAG, orig_header_crc, calc_crc);
  269. return 1;
  270. }
  271. header->header_crc32 = orig_header_crc;
  272. if (header->my_lba != header_lba) {
  273. efi_err("%scheck header, err(my_lba 0x%llx!=0x%llx)\n",
  274. TAG, header->my_lba, header_lba);
  275. return 1;
  276. }
  277. entries_real_size = (u64)header->num_partition_entries * header->sizeof_partition_entry;
  278. num_block_entry = (u64)(dev->blkdev->blksz / header->sizeof_partition_entry);
  279. entries_read_size = (u64)((header->num_partition_entries + (num_block_entry -1)) / num_block_entry) * dev->blkdev->blksz;
  280. err = read_data(entries_buf, part_id, header->partition_entry_lba, entries_read_size);
  281. if (err) {
  282. efi_err("%sread entries(part_id=%d,lba=%llx), err(%d)\n",
  283. TAG, part_id, header->partition_entry_lba, err);
  284. return err;
  285. }
  286. calc_crc = efi_crc32((u8 *)entries, (u32)entries_real_size);
  287. if (header->partition_entry_array_crc32 != calc_crc) {
  288. efi_err("%scheck header, err(entries crc 0x%x!=0x%x(calc))\n",
  289. TAG, header->partition_entry_array_crc32, calc_crc);
  290. return 1;
  291. }
  292. efi_critical("%s user part id = %d\n", TAG, dev->blkdev->part_user);
  293. for (i = 0; (u32)i < header->num_partition_entries; i++) {
  294. /* break if the partition entry is empty */
  295. if (!entries[i].starting_lba) {
  296. break;
  297. }
  298. g_part_ptr[i].start_sect = (unsigned long)entries[i].starting_lba;
  299. g_part_ptr[i].nr_sects = (unsigned long)(entries[i].ending_lba - entries[i].starting_lba + 1);
  300. g_part_ptr[i].part_attr = (unsigned long)entries[i].attributes;
  301. g_part_ptr[i].part_id = dev->blkdev->part_user;
  302. info = malloc(sizeof(*info));
  303. if (!info) {
  304. continue;
  305. }
  306. g_part_ptr[i].info = info;
  307. if ((entries[i].partition_name[0] & 0xFF00) == 0) {
  308. w2s(g_part_ptr[i].info->name, PART_META_INFO_NAMELEN, entries[i].partition_name, GPT_ENTRY_NAME_LEN);
  309. } else {
  310. memcpy(g_part_ptr[i].info->name, entries[i].partition_name, 64);
  311. }
  312. if (NULL == efi_guid_unparse(&entries[i].unique_partition_guid, g_part_ptr[i].info->uuid)) {
  313. efi_err("efi parse uuid string fail!\n");
  314. return 1;
  315. }
  316. efi_critical("%s[%d]name=%s, start_sect=0x%lx, nr_sects=0x%lx, uuid=%s\n", TAG, i,
  317. g_part_ptr[i].info ? (char *)g_part_ptr[i].info->name : "unknown",
  318. g_part_ptr[i].start_sect, g_part_ptr[i].nr_sects,
  319. g_part_ptr[i].info ? (char *)g_part_ptr[i].info->uuid : "");
  320. }
  321. // record the total entry count
  322. g_gpt_entry_cnt = i;
  323. return 0;
  324. }
  325. int read_gpt(part_t *part)
  326. {
  327. int err;
  328. u64 lba;
  329. u8 *pgpt_header, *pgpt_entries;
  330. u8 *sgpt_header, *sgpt_entries;
  331. u32 part_id, gpt_entries_size;
  332. part_dev_t *dev = mt_part_get_device();
  333. if (!dev) {
  334. efi_err("%s%s, err(no dev)\n", TAG, __func__);
  335. return 1;
  336. }
  337. part_id = dev->blkdev->part_user;
  338. gpt_entries_size = sizeof(gpt_entry) * PART_MAX_COUNT;
  339. g_part_ptr = part;
  340. efi_critical("%sParsing Primary GPT now...\n", TAG);
  341. pgpt_header = (u8 *)malloc(dev->blkdev->blksz);
  342. if (!pgpt_header) {
  343. efi_err("%smalloc memory(pgpt header), err\n", TAG);
  344. goto next_try;
  345. }
  346. memset(pgpt_header, 0, dev->blkdev->blksz);
  347. pgpt_entries = (u8 *)malloc(gpt_entries_size);
  348. if (!pgpt_entries) {
  349. free(pgpt_header);
  350. efi_err("%smalloc memory(pgpt entries), err\n", TAG);
  351. goto next_try;
  352. }
  353. memset(pgpt_entries, 0, gpt_entries_size);
  354. err = parse_gpt_header(part_id, 1, pgpt_header, pgpt_entries);
  355. /* Free pgpt buffers after using it */
  356. free(pgpt_header);
  357. free(pgpt_entries);
  358. if (!err) {
  359. goto find;
  360. }
  361. next_try:
  362. efi_critical("%sParsing Secondary GPT now...\n", TAG);
  363. sgpt_header = (u8 *)malloc(dev->blkdev->blksz);
  364. if (!sgpt_header) {
  365. efi_err("%smalloc memory(sgpt header), err\n", TAG);
  366. return 1;
  367. }
  368. memset(sgpt_header, 0, dev->blkdev->blksz);
  369. sgpt_entries = (u8 *)malloc(gpt_entries_size);
  370. if (!sgpt_entries) {
  371. free(sgpt_header);
  372. efi_err("%smalloc memory(sgpt entries), err\n", TAG);
  373. return 1;
  374. }
  375. memset(sgpt_entries, 0, gpt_entries_size);
  376. lba = last_lba(part_id);
  377. if (!lba) {
  378. free(sgpt_header);
  379. free(sgpt_entries);
  380. efi_err("%sFailure to find last lba.\n", TAG);
  381. return 1;
  382. }
  383. err = parse_gpt_header(part_id, lba, sgpt_header, sgpt_entries);
  384. /* Free sgpt buffers after using it */
  385. free(sgpt_header);
  386. free(sgpt_entries);
  387. if (!err) {
  388. goto find;
  389. }
  390. efi_err("%sFailure to find valid GPT.\n", TAG);
  391. return err;
  392. find:
  393. efi_critical("%sSuccess to find valid GPT.\n", TAG);
  394. return 0;
  395. }
  396. static void pack_pmbr_data(void *ptr)
  397. {
  398. pmbr *mbr = (pmbr *)ptr;
  399. u64 nr_sects;
  400. u16 nr_sects_split[2];
  401. u16 *nr_sects_split_ptr;
  402. part_dev_t *dev = mt_part_get_device();
  403. if (!dev) {
  404. efi_err("%s%s, err(no dev)\n", TAG, __func__);
  405. return;
  406. }
  407. nr_sects = last_lba(dev->blkdev->part_user) + 1;
  408. mbr->partition_record[0].sys_ind = GPT_PROTECTIVE_MBR;
  409. mbr->partition_record[0].start_sector = 0x1;
  410. /* Suffer from mbr->partition_record[0].nr_sects address not 4-byte aligned(data abort will occur if directly write u32 data), split it into two 2-byte */
  411. nr_sects_split[0] = ((nr_sects < 0xFFFFFFFF) ? (nr_sects - 1) : 0xFFFFFFFF) & 0xFFFF;
  412. nr_sects_split[1] = (((nr_sects < 0xFFFFFFFF) ? (nr_sects - 1) : 0xFFFFFFFF) >> 16) & 0xFFFF;
  413. nr_sects_split_ptr = (u16 *)(&((mbr->partition_record[0].nr_sects)));
  414. *nr_sects_split_ptr = nr_sects_split[0];
  415. *(nr_sects_split_ptr +1) = nr_sects_split[1];
  416. mbr->signature = 0xAA55;
  417. }
  418. static void pack_pheader_data(void *data)
  419. {
  420. part_dev_t *dev = mt_part_get_device();
  421. if (!dev) {
  422. efi_err("%s%s, err(no dev)\n", TAG, __func__);
  423. return;
  424. }
  425. gpt_header *header = (gpt_header *)data;
  426. header->reserved = 0;
  427. header->alternate_lba = last_lba(dev->blkdev->part_user);
  428. header->last_usable_lba = get_gpt_header_last_usable_lba();
  429. header->partition_entry_array_crc32 = get_entries_crc32();
  430. header->header_crc32 = 0;
  431. header->header_crc32 = efi_crc32(data, sizeof(gpt_header));
  432. }
  433. static void pack_entries_data(void *data)
  434. {
  435. int i;
  436. int nr_parts = 0;
  437. part_dev_t *dev = mt_part_get_device();
  438. gpt_entry *entries = (gpt_entry *)data;
  439. if (!dev) {
  440. efi_err("%s%s, err(no dev)\n", TAG, __func__);
  441. return;
  442. }
  443. //calculate how many partitions
  444. for (i = 0; i < PART_MAX_COUNT; i++) {
  445. if (!entries[i].partition_name[0]) {
  446. nr_parts = i;
  447. break;
  448. }
  449. }
  450. efi_err("%snumber of partitions: %d.\n", TAG, nr_parts);
  451. /* Update gpt entries */
  452. for (i = nr_parts-1; i >= 0; i--) {
  453. /* it's last partition (do not have reserved partition ex: no flashinfo, otp), only need to update last partition */
  454. /* may not go to here unless customer remove flashinfo partition */
  455. if (i == nr_parts-1 && !entries[i].starting_lba && !entries[i].ending_lba) {
  456. entries[i].ending_lba = last_lba(dev->blkdev->part_user) - get_spgt_partition_lba_size() ;
  457. entries[i].starting_lba = entries[i-1].ending_lba + 1;
  458. break;
  459. }
  460. /* Process reserved partitions(flashinfo, otp) and last partition before reserved partition(ex: userdata or intsd) */
  461. /* Reserved partition size is stored in ending_lba, sgpt partition size can be retrived from get_spgt_partition_size()(stored in header->reserved)*/
  462. if (!entries[i].starting_lba) {
  463. /* it's a reserved partition and it's last partition, entries[i].ending_lba not empty(partition size is here) */
  464. if (i == nr_parts-1 && entries[i].ending_lba) {
  465. entries[i].starting_lba = last_lba(dev->blkdev->part_user) - get_spgt_partition_lba_size() - entries[i].ending_lba + 1;
  466. entries[i].ending_lba = last_lba(dev->blkdev->part_user) - get_spgt_partition_lba_size() ;
  467. }
  468. /* reserved parttiion but not last one */
  469. /* may not go to here uless there exists more than one reserved partitions (ex: otp + flashinfo)*/
  470. else if (entries[i].ending_lba) {
  471. entries[i].starting_lba = entries[i+1].starting_lba - entries[i].ending_lba;
  472. entries[i].ending_lba = entries[i+1].starting_lba - 1;
  473. }
  474. /* userdata or intsed */
  475. else {
  476. entries[i].starting_lba = entries[i-1].ending_lba + 1;
  477. entries[i].ending_lba = entries[i+1].starting_lba - 1;
  478. }
  479. }
  480. }
  481. set_entries_crc32(efi_crc32(data, PART_MAX_COUNT * sizeof(gpt_entry)));
  482. }
  483. static void pack_sheader_data(void *data)
  484. {
  485. gpt_header *header = (gpt_header *)data;
  486. header->header_crc32 = 0;
  487. header->my_lba = header->alternate_lba;
  488. header->alternate_lba = 1;
  489. header->partition_entry_lba = get_gpt_header_last_usable_lba() + 1;
  490. header->partition_entry_array_crc32 = get_entries_crc32();
  491. header->header_crc32 = efi_crc32(data, sizeof(gpt_header));
  492. }
  493. int write_primary_gpt(void *data, unsigned sz)
  494. {
  495. int err, part_entries_cnt_per_block;
  496. u64 pentries_write_size;
  497. gpt_header *header;
  498. gpt_entry *entries;
  499. pmbr *mbr;
  500. int with_pmbr; /* 0: data is without pmbr, 1: data is with pmbr*/
  501. part_dev_t *dev = mt_part_get_device();
  502. if (!dev) {
  503. efi_err("%s%s, err(no dev)\n", TAG, __func__);
  504. return -1;
  505. }
  506. /* fastboot PGPT image check */
  507. if (sz == (PART_MAX_COUNT*sizeof(gpt_entry)+dev->blkdev->blksz)) {
  508. with_pmbr = 0;
  509. mbr = NULL;
  510. header = (gpt_header *)data;
  511. entries = (gpt_entry *)(data + dev->blkdev->blksz);
  512. } else if (sz == (PART_MAX_COUNT*sizeof(gpt_entry)+dev->blkdev->blksz * 2)) {
  513. with_pmbr = 1;
  514. mbr = (pmbr *)data;
  515. header = (gpt_header *)(data + dev->blkdev->blksz);
  516. entries = (gpt_entry *)(data + dev->blkdev->blksz * 2);
  517. } else {
  518. err = -1;
  519. efi_err("[GPT_Update]PGPT size not correct, err(%d), expect: 0x%lx read: 0x%x\n", err, (PART_MAX_COUNT*sizeof(gpt_entry)+dev->blkdev->blksz), sz);
  520. return err;
  521. }
  522. if (header->signature != GPT_HEADER_SIGNATURE) {
  523. err = -1;
  524. efi_err("[GPT_Update] %scheck header, err(signature 0x%llx!=0x%llx)\n",
  525. TAG, header->signature, GPT_HEADER_SIGNATURE);
  526. return err;
  527. }
  528. if (!with_pmbr) {
  529. mbr = (pmbr *)malloc(dev->blkdev->blksz);
  530. if (!mbr) {
  531. err = -1;
  532. efi_err("%s malloc memory(pmbr header), err\n", TAG);
  533. return err;
  534. }
  535. memset(mbr, 0, dev->blkdev->blksz);
  536. }
  537. if (header->alternate_lba != last_lba(dev->blkdev->part_user)) {
  538. set_spgt_partition_lba_size(header->alternate_lba); //sgpt partition size is hrere
  539. } else {
  540. set_spgt_partition_lba_size(last_lba(dev->blkdev->part_user) - header->last_usable_lba);
  541. }
  542. pack_entries_data((void *)entries); //move to gpt entries
  543. pack_pheader_data((void *)header); //update pheader
  544. pack_pmbr_data((void *)mbr);
  545. /* Write pmbr */
  546. err = write_data(0, (u8 *)mbr, (u64)dev->blkdev->blksz, dev->blkdev->part_user);
  547. if (!with_pmbr)
  548. free(mbr); /* Free pmbr after use it */
  549. if (err) {
  550. efi_err("[GPT_Update]write pmbr, err(%d)\n", err);
  551. return err;
  552. }
  553. /* Write pheader */
  554. err = write_data(1, (u8 *)header, (u64)dev->blkdev->blksz, dev->blkdev->part_user);
  555. if (err) {
  556. efi_err("[GPT_Update]write pheader, err(%d)\n", err);
  557. return err;
  558. }
  559. /* Write gpt entries */
  560. part_entries_cnt_per_block = dev->blkdev->blksz / header->sizeof_partition_entry;
  561. pentries_write_size = (u64)((PART_MAX_COUNT + part_entries_cnt_per_block - 1) / part_entries_cnt_per_block) * dev->blkdev->blksz;
  562. err = write_data(2, (u8 *)entries, pentries_write_size, dev->blkdev->part_user);
  563. if (err) {
  564. efi_err("[GPT_Update]write pentries, err(%d)\n", err);
  565. return err;
  566. }
  567. return 0;
  568. }
  569. int write_secondary_gpt(void *data, unsigned sz)
  570. {
  571. int err, part_entries_cnt_per_block;
  572. u64 pentries_write_size;
  573. u64 sentries_start_lba;
  574. gpt_header *header;
  575. gpt_entry *entries;
  576. part_dev_t *dev = mt_part_get_device();
  577. if (!dev) {
  578. efi_err("%s%s, err(no dev)\n", TAG, __func__);
  579. return -1;
  580. }
  581. /* fastboot PGPT image check */
  582. if (sz == (PART_MAX_COUNT*sizeof(gpt_entry)+dev->blkdev->blksz)) {
  583. header = (gpt_header *)data;
  584. entries = (gpt_entry *)(data + dev->blkdev->blksz);
  585. } else if (sz == (PART_MAX_COUNT*sizeof(gpt_entry)+dev->blkdev->blksz * 2)) {
  586. header = (gpt_header *)(data + dev->blkdev->blksz);
  587. entries = (gpt_entry *)(data + dev->blkdev->blksz * 2);
  588. } else {
  589. err = -1;
  590. efi_err("[GPT_Update]SGPT size not correct, err(%d), expect: 0x%lx read: 0x%x\n", err, (PART_MAX_COUNT*sizeof(gpt_entry)+dev->blkdev->blksz), sz);
  591. return err;
  592. }
  593. if (header->signature != GPT_HEADER_SIGNATURE) {
  594. err = -1;
  595. efi_err("[GPT_Update] %s check header, err(signature 0x%llx!=0x%llx)\n",
  596. TAG, header->signature, GPT_HEADER_SIGNATURE);
  597. return err;
  598. }
  599. pack_sheader_data(header); //update sheader
  600. /* Write sheader */
  601. err = write_data(last_lba(dev->blkdev->part_user), (u8 *)header, (u64)dev->blkdev->blksz, dev->blkdev->part_user);
  602. if (err) {
  603. efi_err("[GPT_Update]write sheader, err(%d)\n", err);
  604. return err;
  605. }
  606. /* Write gpt entries */
  607. sentries_start_lba = get_gpt_header_last_usable_lba() + 1;
  608. part_entries_cnt_per_block = dev->blkdev->blksz / header->sizeof_partition_entry;
  609. pentries_write_size = (u64)((PART_MAX_COUNT + part_entries_cnt_per_block - 1) / part_entries_cnt_per_block) * dev->blkdev->blksz;
  610. err = write_data(sentries_start_lba, (u8 *)entries, pentries_write_size, dev->blkdev->part_user);
  611. if (err) {
  612. efi_err("[GPT_Update]write pentries, err(%d)\n", err);
  613. return err;
  614. }
  615. return 0;
  616. }
  617. unsigned int *target_commandline_force_gpt(char *cmd)
  618. {
  619. cmdline_append("gpt=1");
  620. return 0;
  621. }