i2c: i2c_phy_v0: remove the debug message
[profile/mobile/platform/kernel/u-boot-tm1.git] / disk / part_efi.c
1 /*
2  * Copyright (C) 2008 RuggedCom, Inc.
3  * Richard Retanubun <RichardRetanubun@RuggedCom.com>
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 /*
25  * Problems with CONFIG_SYS_64BIT_LBA:
26  *
27  * struct disk_partition.start in include/part.h is sized as ulong.
28  * When CONFIG_SYS_64BIT_LBA is activated, lbaint_t changes from ulong to uint64_t.
29  * For now, it is cast back to ulong at assignment.
30  *
31  * This limits the maximum size of addressable storage to < 2 Terra Bytes
32  */
33  #include <linux/ctype.h>
34 #include <common.h>
35 #include <command.h>
36 #include <ide.h>
37 #include <malloc.h>
38 #include "part_efi.h"
39 #include "part_uefi.h"
40
41 #if defined(CONFIG_CMD_IDE) || \
42     defined(CONFIG_CMD_MG_DISK) || \
43     defined(CONFIG_CMD_SATA) || \
44     defined(CONFIG_CMD_SCSI) || \
45     defined(CONFIG_CMD_USB) || \
46     defined(CONFIG_MMC) || \
47     defined(CONFIG_SYSTEMACE)
48
49 /* Convert char[2] in little endian format to the host format integer
50  */
51 static inline unsigned short le16_to_int(unsigned char *le16)
52 {
53         return ((le16[1] << 8) + le16[0]);
54 }
55
56 /* Convert char[4] in little endian format to the host format integer
57  */
58 static inline unsigned long le32_to_int(unsigned char *le32)
59 {
60         return ((le32[3] << 24) + (le32[2] << 16) + (le32[1] << 8) + le32[0]);
61 }
62
63 /* Convert char[8] in little endian format to the host format integer
64  */
65 static inline unsigned long long le64_to_int(unsigned char *le64)
66 {
67         return (((unsigned long long)le64[7] << 56) +
68                 ((unsigned long long)le64[6] << 48) +
69                 ((unsigned long long)le64[5] << 40) +
70                 ((unsigned long long)le64[4] << 32) +
71                 ((unsigned long long)le64[3] << 24) +
72                 ((unsigned long long)le64[2] << 16) +
73                 ((unsigned long long)le64[1] << 8) +
74                 (unsigned long long)le64[0]);
75 }
76
77 /**
78  * efi_crc32() - EFI version of crc32 function
79  * @buf: buffer to calculate crc32 of
80  * @len - length of buf
81  *
82  * Description: Returns EFI-style CRC32 value for @buf
83  */
84 static inline unsigned long efi_crc32(const void *buf, unsigned long len)
85 {
86         return crc32(0, buf, len);
87 }
88
89 /*
90  * Private function prototypes
91  */
92
93 static int pmbr_part_valid(struct partition *part);
94 static int is_pmbr_valid(legacy_mbr * mbr);
95
96 static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,
97                                 gpt_header * pgpt_head, gpt_entry ** pgpt_pte);
98 #ifdef CONFIG_GPT_FORMAT_VALID
99 #ifdef CONFIG_EMMC_BOOT
100 static int format_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,
101                                 gpt_header * pgpt_head, gpt_entry ** pgpt_pte);
102 #endif
103 #endif  /* CONFIG_GPT_FORMAT_VALID */
104 static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,
105                                 gpt_header * pgpt_head);
106
107 static int is_pte_valid(gpt_entry * pte);
108
109 #define PARTNAME_SZ     (72 / sizeof(efi_char16_t))
110 static char *print_efiname(gpt_entry *pte)
111 {
112         static char name[PARTNAME_SZ + 1];
113         int i;
114         for (i = 0; i < PARTNAME_SZ; i++) {
115                 u8 c;
116                 c = pte->partition_name[i] & 0xff;
117                 c = (c && !isprint(c)) ? '.' : c;
118                 name[i] = c;
119         }
120         name[PARTNAME_SZ] = 0;
121         return name;
122 }
123
124
125 /*
126  * Public Functions (include/part.h)
127  */
128
129 void print_part_efi(block_dev_desc_t * dev_desc)
130 {
131         gpt_header gpt_head;
132         gpt_entry *pgpt_pte = NULL;
133         int i = 0;
134
135         if (!dev_desc) {
136                 debug("%s: Invalid Argument(s)\n", __FUNCTION__);
137                 return;
138         }
139         /* This function validates AND fills in the GPT header and PTE */
140         if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
141                          &(gpt_head), &pgpt_pte) != 1) {
142                 debug("%s: *** ERROR: Invalid GPT ***\n", __FUNCTION__);
143                 return;
144         }
145
146         debug("%s: gpt-entry at 0x%08X\n", __FUNCTION__, (unsigned int)pgpt_pte);
147
148         debug("Part  Start LBA  End LBA\n");
149         for (i = 0; i < le32_to_int(gpt_head.num_partition_entries); i++) {
150
151                 if (is_pte_valid(&(pgpt_pte)[i])) {
152                         debug("%s%d  0x%llX    0x%llX\n", GPT_ENTRY_NAME,
153                                 (i + 1),
154                                 le64_to_int((pgpt_pte)[i].starting_lba),
155                                 le64_to_int((pgpt_pte)[i].ending_lba));
156                 } else {
157                         break;  /* Stop at the first non valid PTE */
158                 }
159         }
160
161         /* Remember to free pte */
162         if (pgpt_pte != NULL) {
163                 debug("%s: Freeing pgpt_pte\n", __FUNCTION__);
164                 free(pgpt_pte);
165         }
166         return;
167 }
168
169 int get_partition_info_efi(block_dev_desc_t * dev_desc, int part,
170                                 disk_partition_t * info)
171 {
172         gpt_header gpt_head;
173         gpt_entry *pgpt_pte = NULL;
174
175         /* "part" argument must be at least 1 */
176         if (!dev_desc || !info || part < 1) {
177                 debug("%s: Invalid Argument(s)\n", __FUNCTION__);
178                 return -1;
179         }
180
181         /* This function validates AND fills in the GPT header and PTE */
182         if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
183                         &(gpt_head), &pgpt_pte) != 1) {
184                 debug("%s: *** ERROR: Invalid Main GPT ***\n", __FUNCTION__);
185                 if(is_gpt_valid(dev_desc, dev_desc->lba -1, &(gpt_head), &pgpt_pte) != 1){
186                         debug("%s: *** ERROR: Invalid alternate GPT ***\n", __FUNCTION__);
187                         return -1;
188
189                 }
190         }
191
192         /* The ulong casting limits the maximum disk size to 2 TB */
193         info->start = (ulong) le64_to_int((pgpt_pte)[part - 1].starting_lba);
194         /* The ending LBA is inclusive, to calculate size, add 1 to it */
195         info->size = ((ulong)le64_to_int((pgpt_pte)[part - 1].ending_lba) + 1)
196                      - info->start;
197         info->blksz = GPT_BLOCK_SIZE;
198
199         sprintf((char *)info->name, "%s", print_efiname(&((pgpt_pte)[part - 1])));
200         sprintf((char *)info->type, "U-Boot");
201
202         debug("%s: start 0x%lX, size 0x%lX, name %s", __FUNCTION__,
203                 info->start, info->size, info->name);
204
205         /* Remember to free pte */
206         if (pgpt_pte != NULL) {
207                 debug("%s: Freeing pgpt_pte\n", __FUNCTION__);
208                 free(pgpt_pte);
209         }
210         return 0;
211 }
212
213 int get_partition_info_by_name_efi(block_dev_desc_t * dev_desc, wchar_t* partition_name,
214                                 disk_partition_t * info)
215 {
216         gpt_header gpt_head;
217         gpt_entry *pgpt_pte = NULL;
218         int ret = -1;
219         unsigned int i,j,partition_nums=0;
220         wchar_t disk_parition[MAX_UTF_PARTITION_NAME_LEN];
221
222         if (!dev_desc || !info || !partition_name) {
223                 debug("%s: Invalid Argument(s)\n", __FUNCTION__);
224                 return -1;
225         }
226
227         /* This function validates AND fills in the GPT header and PTE */
228         if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
229                         &(gpt_head), &pgpt_pte) != 1) {
230                 debug("%s: *** ERROR: Invalid Main GPT ***\n", __FUNCTION__);
231                 if(is_gpt_valid(dev_desc, dev_desc->lba -1, &(gpt_head), &pgpt_pte) != 1){
232                         debug("%s: *** ERROR: Invalid alternate GPT ***\n", __FUNCTION__);
233                         return -1;
234
235                 }
236         }
237
238         /*Get the partition info*/
239         partition_nums = le32_to_int(gpt_head.num_partition_entries);
240         for(i=0;i<partition_nums;i++)
241         {
242                 for(j=0;j<MAX_UTF_PARTITION_NAME_LEN;j++)
243                 {
244                         disk_parition[j] = (wchar_t)pgpt_pte[i].partition_name[j];
245                 }
246
247                 if(0 == wcscmp(disk_parition, partition_name))
248                 {
249                         /* The ulong casting limits the maximum disk size to 2 TB */
250                         info->start = (ulong) le64_to_int((pgpt_pte)[i].starting_lba);
251                         /* The ending LBA is inclusive, to calculate size, add 1 to it */
252                         info->size = ((ulong)le64_to_int((pgpt_pte)[i].ending_lba) + 1) - info->start;
253                         info->blksz = GPT_BLOCK_SIZE;
254
255                         sprintf((char *)info->name, "%s", print_efiname(&((pgpt_pte)[i])));
256                         sprintf((char *)info->type, "U-Boot");
257
258                         debug("%s: start 0x%lX, size 0x%lX, name %s", __FUNCTION__,
259                                 info->start, info->size, info->name);
260                         ret = 0;
261                         break;
262                 }
263         }
264
265         /* Remember to free pte */
266         if (pgpt_pte != NULL) {
267                 debug("%s: Freeing pgpt_pte\n", __FUNCTION__);
268                 free(pgpt_pte);
269         }
270
271         return ret;
272 }
273
274 int get_partition_num_by_name_efi(block_dev_desc_t *dev_desc, const char *partition_name)
275 {
276         gpt_header gpt_head;
277         gpt_entry *pgpt_pte = NULL;
278         int ret = -1;
279         unsigned int i, j, partition_nums = 0;
280         int part_name_len = (72 / sizeof(efi_char16_t));
281
282         if (!dev_desc || !partition_name) {
283                 debug("%s: Invalid Argument(s)\n", __FUNCTION__);
284                 return -1;
285         }
286
287         /* This function validates AND fills in the GPT header and PTE */
288         if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
289                         &(gpt_head), &pgpt_pte) != 1) {
290                 debug("%s: *** ERROR: Invalid Main GPT ***\n", __FUNCTION__);
291                 if (is_gpt_valid(dev_desc, dev_desc->lba -1, &(gpt_head), &pgpt_pte) != 1){
292                         debug("%s: *** ERROR: Invalid alternate GPT ***\n", __FUNCTION__);
293                         return -1;
294
295                 }
296         }
297
298         partition_nums = le32_to_int(gpt_head.num_partition_entries);
299         for (i = 0; i < partition_nums; i++) {
300                 for (j = 0; j < part_name_len; j++) {
301                         if (partition_name[j] != pgpt_pte[i].partition_name[j])
302                                 break;
303                         if (partition_name[j] == 0 && pgpt_pte[i].partition_name[j] == 0) {
304                                 ret = i + 1;
305                                 goto free;
306                         }
307                 }
308         }
309
310 free:
311         /* Remember to free pte */
312         if (pgpt_pte != NULL) {
313                 debug("%s: Freeing pgpt_pte\n", __FUNCTION__);
314                 free(pgpt_pte);
315         }
316
317         return ret;
318 }
319
320 int get_all_partition_info_efi(block_dev_desc_t * dev_desc, PARTITION_CFG * info, unsigned int *total_partition_num)
321 {
322         gpt_header gpt_head;
323         gpt_entry *pgpt_pte = NULL;
324         unsigned int i,j, partition_nums = 0;
325
326         if (!dev_desc || !info) {
327                 debug("%s: Invalid Argument(s)\n", __FUNCTION__);
328                 return -1;
329         }
330
331         /* This function validates AND fills in the GPT header and PTE */
332         if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
333                         &(gpt_head), &pgpt_pte) != 1) {
334                 debug("%s: *** ERROR: Invalid Main GPT ***\n", __FUNCTION__);
335                 if(is_gpt_valid(dev_desc, dev_desc->lba -1, &(gpt_head), &pgpt_pte) != 1){
336                         debug("%s: *** ERROR: Invalid alternate GPT ***\n", __FUNCTION__);
337                         return -1;
338
339                 }
340         }
341
342         partition_nums = le32_to_int(gpt_head.num_partition_entries);
343
344         //TODO:partitions shuld beyond MAX PARTITION NUM
345         for(i=0;i<partition_nums;i++)
346         {
347                 /* The ulong casting limits the maximum disk size to 2 TB */
348                 info[i].partition_offset = (ulong) le64_to_int((pgpt_pte)[i].starting_lba);
349                 /* The ending LBA is inclusive, to calculate size, add 1 to it */
350                 info[i].partition_size = ((ulong)le64_to_int((pgpt_pte)[i].ending_lba) + 1) - info[i].partition_offset;
351                 //TODO: We write partition index at unique_partition_guid.b[15]
352                 info[i].partition_index = pgpt_pte[i].unique_partition_guid.b[15];
353
354                 for(j=0;j<MAX_UTF_PARTITION_NAME_LEN;j++)
355                 {
356                         info[i].partition_name[j] = (wchar_t)pgpt_pte[i].partition_name[j];
357                 }
358
359                 debug("%s: start 0x%lX, size 0x%lX, name %S", __FUNCTION__,
360                         info[i].partition_offset, info[i].partition_size, info[i].partition_name);
361         }
362
363         *total_partition_num = partition_nums;
364
365         /* Remember to free pte */
366         if (pgpt_pte != NULL) {
367                 debug("%s: Freeing pgpt_pte\n", __FUNCTION__);
368                 free(pgpt_pte);
369         }
370         return 0;
371 }
372
373
374 int get_partition_info_efi_with_partnum(block_dev_desc_t * dev_desc, int part,
375                 disk_partition_t * info, unsigned long total, unsigned long sdidx, int sdpart, disk_partition_t *sdinfo)
376 {
377         gpt_header gpt_head;
378         gpt_entry *pgpt_pte = NULL;
379
380         /* "part" argument must be at least 1 */
381         if (!dev_desc || !info || part < 1) {
382                 debug("%s: Invalid Argument(s)\n", __FUNCTION__);
383                 return -1;
384         }
385
386         /* This function validates AND fills in the GPT header and PTE */
387         if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
388                         &(gpt_head), &pgpt_pte) != 1) {
389                 debug("%s: *** ERROR: Invalid Main GPT ***\n", __FUNCTION__);
390                 if(is_gpt_valid(dev_desc, dev_desc->lba -1, &(gpt_head), &pgpt_pte) != 1){
391                         debug("%s: *** ERROR: Invalid alternate GPT ***\n", __FUNCTION__);
392                         return -1;
393
394                 }
395         }
396
397         /* The ulong casting limits the maximum disk size to 2 TB */
398         info->start = (ulong) le64_to_int((pgpt_pte)[part - 1].starting_lba);
399         /* The ending LBA is inclusive, to calculate size, add 1 to it */
400         info->size = ((ulong)le64_to_int((pgpt_pte)[part - 1].ending_lba) + 1)
401                      - info->start;
402         info->blksz = GPT_BLOCK_SIZE;
403
404         sprintf((char *)info->name, "%s",
405                         print_efiname(&((pgpt_pte)[part - 1])));
406         sprintf((char *)info->type, "U-Boot");
407
408         debug("%s: start 0x%lX, size 0x%lX, name %s\n", __FUNCTION__,
409                 info->start, info->size, info->name);
410
411         /* copy sd info */
412         if (sdidx < (le32_to_int(gpt_head.num_partition_entries))) {
413                 sdinfo->start = (ulong) le64_to_int((pgpt_pte)[sdpart - 1].starting_lba);
414                 sdinfo->size = ((ulong)le64_to_int((pgpt_pte)[sdpart - 1].ending_lba) + 1) - sdinfo->start;
415         }
416
417         /* Remember to free pte */
418         if (pgpt_pte != NULL) {
419                 debug("%s: Freeing pgpt_pte\n", __FUNCTION__);
420                 free(pgpt_pte);
421         }
422
423         if (total == 0)
424                 return 0;
425         else if (total != le32_to_int(gpt_head.num_partition_entries))
426                 return -1;
427         else
428                 return 0;
429 }
430
431 int test_part_efi(block_dev_desc_t * dev_desc)
432 {
433         legacy_mbr legacymbr;
434
435         /* Read legacy MBR from block 0 and validate it */
436         if ((dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *) & legacymbr) != 1)
437                 || (is_pmbr_valid(&legacymbr) != 1)) {
438                 return -1;
439         }
440         return 0;
441 }
442
443 /*
444  * Private functions
445  */
446 /*
447  * pmbr_part_valid(): Check for EFI partition signature
448  *
449  * Returns: 1 if EFI GPT partition type is found.
450  */
451 static int pmbr_part_valid(struct partition *part)
452 {
453         if (part->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT &&
454                 le32_to_int(part->start_sect) == 1UL) {
455                 return 1;
456         }
457
458         return 0;
459 }
460
461 /*
462  * is_pmbr_valid(): test Protective MBR for validity
463  *
464  * Returns: 1 if PMBR is valid, 0 otherwise.
465  * Validity depends on two things:
466  *  1) MSDOS signature is in the last two bytes of the MBR
467  *  2) One partition of type 0xEE is found, checked by pmbr_part_valid()
468  */
469 static int is_pmbr_valid(legacy_mbr * mbr)
470 {
471         int i = 0;
472
473         if (!mbr || le16_to_int(mbr->signature) != MSDOS_MBR_SIGNATURE) {
474                 return 0;
475         }
476
477         for (i = 0; i < 4; i++) {
478                 if (pmbr_part_valid(&mbr->partition_record[i])) {
479                         return 1;
480                 }
481         }
482         return 0;
483 }
484
485 /**
486  * is_gpt_valid() - tests one GPT header and PTEs for validity
487  *
488  * lba is the logical block address of the GPT header to test
489  * gpt is a GPT header ptr, filled on return.
490  * ptes is a PTEs ptr, filled on return.
491  *
492  * Description: returns 1 if valid,  0 on error.
493  * If valid, returns pointers to PTEs.
494  */
495 static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,
496                         gpt_header * pgpt_head, gpt_entry ** pgpt_pte)
497 {
498         unsigned char crc32_backup[4] = { 0 };
499         unsigned long calc_crc32;
500         unsigned long long lastlba;
501         //debug("Enter is_gpt_valid 0x%16Lx \n", lba);
502         if (!dev_desc || !pgpt_head) {
503                 debug("%s: Invalid Argument(s)\n", __FUNCTION__);
504                 return 0;
505         }
506
507         /* Read GPT Header from device */
508         if (dev_desc->block_read(dev_desc->dev, lba, 1, pgpt_head) != 1) {
509                 debug("*** ERROR: Can't read GPT header ***\n");
510                 return 0;
511         }
512
513         /* Check the GPT header signature */
514         if (le64_to_int(pgpt_head->signature) != GPT_HEADER_SIGNATURE) {
515                 debug("GUID Partition Table Header signature is wrong:"
516                         "0x%llX != 0x%llX\n",
517                         (unsigned long long)le64_to_int(pgpt_head->signature),
518                         (unsigned long long)GPT_HEADER_SIGNATURE);
519                 return 0;
520         }
521
522         /* Check the GUID Partition Table CRC */
523         memcpy(crc32_backup, pgpt_head->header_crc32, sizeof(crc32_backup));
524         memset(pgpt_head->header_crc32, 0, sizeof(pgpt_head->header_crc32));
525
526         calc_crc32 = efi_crc32((const unsigned char *)pgpt_head,
527                 le32_to_int(pgpt_head->header_size));
528
529         memcpy(pgpt_head->header_crc32, crc32_backup, sizeof(crc32_backup));
530
531         if (calc_crc32 != le32_to_int(crc32_backup)) {
532                 debug("GUID Partition Table Header CRC is wrong:"
533                         "0x%08lX != 0x%08lX\n",
534                         le32_to_int(crc32_backup), calc_crc32);
535                 return 0;
536         }
537
538         /* Check that the my_lba entry points to the LBA that contains the GPT */
539         if (le64_to_int(pgpt_head->my_lba) != lba) {
540                 debug("GPT: my_lba incorrect: %llX != %llX\n",
541                         (unsigned long long)le64_to_int(pgpt_head->my_lba),
542                         (unsigned long long)lba);
543                 return 0;
544         }
545
546         /* Check the first_usable_lba and last_usable_lba are within the disk. */
547         lastlba = (unsigned long long)dev_desc->lba;
548         if (le64_to_int(pgpt_head->first_usable_lba) > lastlba) {
549                 debug("GPT: first_usable_lba incorrect: %llX > %llX\n",
550                         le64_to_int(pgpt_head->first_usable_lba), lastlba);
551                 return 0;
552         }
553         if (le64_to_int(pgpt_head->last_usable_lba) > lastlba) {
554                 debug("GPT: last_usable_lba incorrect: %llX > %llX\n",
555                         le64_to_int(pgpt_head->last_usable_lba), lastlba);
556                 return 0;
557         }
558
559         debug("GPT: first_usable_lba: %llX last_usable_lba %llX last lba %llX\n",
560                 le64_to_int(pgpt_head->first_usable_lba),
561                 le64_to_int(pgpt_head->last_usable_lba), lastlba);
562
563         /* Read and allocate Partition Table Entries */
564         *pgpt_pte = alloc_read_gpt_entries(dev_desc, pgpt_head);
565         if (*pgpt_pte == NULL) {
566                 debug("GPT: Failed to allocate memory for PTE\n");
567                 return 0;
568         }
569
570         /* Check the GUID Partition Table Entry Array CRC */
571         calc_crc32 = efi_crc32((const unsigned char *)*pgpt_pte,
572                 le32_to_int(pgpt_head->num_partition_entries) *
573                 le32_to_int(pgpt_head->sizeof_partition_entry));
574
575         if (calc_crc32 != le32_to_int(pgpt_head->partition_entry_array_crc32)) {
576                 debug("GUID Partition Table Entry Array CRC is wrong:"
577                         "0x%08lX != 0x%08lX\n",
578                         le32_to_int(pgpt_head->partition_entry_array_crc32),
579                         calc_crc32);
580
581                 if (*pgpt_pte != NULL) {
582                         free(*pgpt_pte);
583                 }
584                 return 0;
585         }
586
587         /* We're done, all's well */
588         return 1;
589 }
590
591 #ifdef CONFIG_GPT_FORMAT_VALID
592 #ifdef CONFIG_EMMC_BOOT
593 /**
594  * format_gpt_valid() - tests one GPT header and PTEs for validity
595  *
596  * lba is the logical block address of the GPT header to test
597  * gpt is a GPT header ptr, filled on return.
598  * ptes is a PTEs ptr, filled on return.
599  *
600  * Description: returns 1 if valid,  0 on error.
601  * If valid, returns pointers to PTEs.
602  */
603 static int format_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,
604                         gpt_header * pgpt_head, gpt_entry ** pgpt_pte)
605 {
606         unsigned char crc32_backup[4] = { 0 };
607         unsigned long calc_crc32;
608         unsigned long long lastlba;
609         int idx;
610
611         if (!dev_desc || !pgpt_head) {
612                 debug("%s: Invalid Argument(s)\n", __FUNCTION__);
613                 return 0;
614         }
615         
616         memset(pgpt_head, 0, sizeof(gpt_header));
617
618         /* set GPT Header from device */
619         for (idx = 0; idx < 8; idx ++) {
620                 pgpt_head->signature[idx] = (GPT_HEADER_SIGNATURE >> (8 * idx)) & 0xff;
621                 debug("signature[%d] = 0x%02x\n", idx, pgpt_head->signature[idx]);
622         }
623
624         if (dev_desc->block_write(dev_desc->dev, lba, 1, pgpt_head) != 1) {
625                 debug("*** ERROR: Can't write GPT header ***\n");
626                 return 0;
627         }
628 #if 1
629         //richardfeng mask
630         /* Check the GPT header signature */
631         if (le64_to_int(pgpt_head->signature) != GPT_HEADER_SIGNATURE) {
632                 debug("GUID Partition Table Header signature is wrong:"
633                         "0x%llX != 0x%llX\n",
634                         (unsigned long long)le64_to_int(pgpt_head->signature),
635                         (unsigned long long)GPT_HEADER_SIGNATURE);
636                 return 0;
637         }
638
639         /* Check the GUID Partition Table CRC */
640         memcpy(crc32_backup, pgpt_head->header_crc32, sizeof(crc32_backup));
641         memset(pgpt_head->header_crc32, 0, sizeof(pgpt_head->header_crc32));
642
643         calc_crc32 = efi_crc32((const unsigned char *)pgpt_head,
644                 le32_to_int(pgpt_head->header_size));
645
646         memcpy(pgpt_head->header_crc32, crc32_backup, sizeof(crc32_backup));
647
648         if (calc_crc32 != le32_to_int(crc32_backup)) {
649                 debug("GUID Partition Table Header CRC is wrong:"
650                         "0x%08lX != 0x%08lX\n",
651                         le32_to_int(crc32_backup), calc_crc32);
652                 return 0;
653         }
654
655         /* Check that the my_lba entry points to the LBA that contains the GPT */
656         if (le64_to_int(pgpt_head->my_lba) != lba) {
657                 debug("GPT: my_lba incorrect: %llX != %llX\n",
658                         (unsigned long long)le64_to_int(pgpt_head->my_lba),
659                         (unsigned long long)lba);
660                 return 0;
661         }
662
663         /* Check the first_usable_lba and last_usable_lba are within the disk. */
664         lastlba = (unsigned long long)dev_desc->lba;
665         if (le64_to_int(pgpt_head->first_usable_lba) > lastlba) {
666                 debug("GPT: first_usable_lba incorrect: %llX > %llX\n",
667                         le64_to_int(pgpt_head->first_usable_lba), lastlba);
668                 return 0;
669         }
670         if (le64_to_int(pgpt_head->last_usable_lba) > lastlba) {
671                 debug("GPT: last_usable_lba incorrect: %llX > %llX\n",
672                         le64_to_int(pgpt_head->last_usable_lba), lastlba);
673                 return 0;
674         }
675
676         debug("GPT: first_usable_lba: %llX last_usable_lba %llX last lba %llX\n",
677                 le64_to_int(pgpt_head->first_usable_lba),
678                 le64_to_int(pgpt_head->last_usable_lba), lastlba);
679
680         /* Read and allocate Partition Table Entries */
681         *pgpt_pte = alloc_read_gpt_entries(dev_desc, pgpt_head);
682         if (*pgpt_pte == NULL) {
683                 debug("GPT: Failed to allocate memory for PTE\n");
684                 return 0;
685         }
686
687         /* Check the GUID Partition Table Entry Array CRC */
688         calc_crc32 = efi_crc32((const unsigned char *)*pgpt_pte,
689                 le32_to_int(pgpt_head->num_partition_entries) *
690                 le32_to_int(pgpt_head->sizeof_partition_entry));
691
692         if (calc_crc32 != le32_to_int(pgpt_head->partition_entry_array_crc32)) {
693                 debug("GUID Partition Table Entry Array CRC is wrong:"
694                         "0x%08lX != 0x%08lX\n",
695                         le32_to_int(pgpt_head->partition_entry_array_crc32),
696                         calc_crc32);
697
698                 if (*pgpt_pte != NULL) {
699                         free(*pgpt_pte);
700                 }
701                 return 0;
702         }
703 #endif
704         /* We're done, all's well */
705         return 1;
706 }
707 #endif
708 #endif  /* CONFIG_GPT_FORMAT_VALID */
709
710 /**
711  * alloc_read_gpt_entries(): reads partition entries from disk
712  * @dev_desc
713  * @gpt - GPT header
714  *
715  * Description: Returns ptes on success,  NULL on error.
716  * Allocates space for PTEs based on information found in @gpt.
717  * Notes: remember to free pte when you're done!
718  */
719 static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,
720                                          gpt_header * pgpt_head)
721 {
722         size_t count = 0;
723         gpt_entry *pte = NULL;
724
725         if (!dev_desc || !pgpt_head) {
726                 debug("%s: Invalid Argument(s)\n", __FUNCTION__);
727                 return NULL;
728         }
729
730         count = le32_to_int(pgpt_head->num_partition_entries) *
731                 le32_to_int(pgpt_head->sizeof_partition_entry);
732
733         debug("%s: count = %lu * %lu = %u\n", __FUNCTION__,
734                 le32_to_int(pgpt_head->num_partition_entries),
735                 le32_to_int(pgpt_head->sizeof_partition_entry), count);
736         if(count % GPT_BLOCK_SIZE){
737                 size_t ntemp;
738                 ntemp = count/GPT_BLOCK_SIZE +1;
739                 count = ntemp * GPT_BLOCK_SIZE;
740         }
741         /* Allocate memory for PTE, remember to FREE */
742         if (count != 0) {
743                 pte = malloc(count);
744         }
745
746         if (count == 0 || pte == NULL) {
747                 debug("%s: ERROR: Can't allocate 0x%X bytes for GPT Entries\n",
748                         __FUNCTION__, count);
749                 return NULL;
750         }
751
752         /* Read GPT Entries from device */
753         if (dev_desc->block_read (dev_desc->dev,
754                 (unsigned long)le64_to_int(pgpt_head->partition_entry_lba),
755                 (lbaint_t) (count / GPT_BLOCK_SIZE), pte)
756                 != (count / GPT_BLOCK_SIZE)) {
757
758                 debug("*** ERROR: Can't read GPT Entries ***\n");
759                 free(pte);
760                 return NULL;
761         }
762         return pte;
763 }
764
765 /**
766  * is_pte_valid(): validates a single Partition Table Entry
767  * @gpt_entry - Pointer to a single Partition Table Entry
768  *
769  * Description: returns 1 if valid,  0 on error.
770  */
771 static int is_pte_valid(gpt_entry * pte)
772 {
773         efi_guid_t unused_guid;
774
775         if (!pte) {
776                 debug("%s: Invalid Argument(s)\n", __FUNCTION__);
777                 return 0;
778         }
779
780         /* Only one validation for now:
781          * The GUID Partition Type != Unused Entry (ALL-ZERO)
782          */
783         memset(unused_guid.b, 0, sizeof(unused_guid.b));
784
785         if (memcmp(pte->partition_type_guid.b, unused_guid.b,
786                 sizeof(unused_guid.b)) == 0) {
787
788                 debug("%s: Found an unused PTE GUID at 0x%08X\n", __FUNCTION__,
789                 (unsigned int)pte);
790
791                 return 0;
792         } else {
793                 return 1;
794         }
795 }
796 #endif