| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- #include "typedefs.h"
- #include "print.h"
- #include "blkdev.h"
- #include "dram_buffer.h"
- #include "partition_api.h"
- #include "pal_log.h"
- #include "storage_api.h"
- typedef struct {
- u8 b[16];
- } __attribute__((packed)) efi_guid_t;
- typedef struct {
- u64 signature;
- u32 revision;
- u32 header_size;
- u32 header_crc32;
- u32 reserved;
- u64 my_lba;
- u64 alternate_lba;
- u64 first_usable_lba;
- u64 last_usable_lba;
- efi_guid_t disk_guid;
- u64 partition_entry_lba;
- u32 num_partition_entries;
- u32 sizeof_partition_entry;
- u32 partition_entry_array_crc32;
- } __attribute__((packed)) gpt_header;
- #define GPT_ENTRY_NAME_LEN (72 / sizeof(u16))
- typedef struct {
- efi_guid_t partition_type_guid;
- efi_guid_t unique_partition_guid;
- u64 starting_lba;
- u64 ending_lba;
- u64 attributes;
- u16 partition_name[GPT_ENTRY_NAME_LEN];
- } __attribute__((packed))gpt_entry;
- static part_t *part_ptr = NULL;
- /*
- ********** Definition of Debug Macro **********
- */
- #define TAG "[GPT_PL]"
- /*
- ********** Definition of GPT buffer **********
- */
- #define GPT_HEADER_BUF g_dram_buf->gpt_header_buf
- #define GPT_ENTRIES_BUF g_dram_buf->gpt_entries_buf
- /*
- ********** Definition of CRC32 Calculation **********
- */
- #define gpt_dram_crc32_table g_dram_buf->crc32_table
- #define GPT_HEADER_SIGNATURE 0x5452415020494645ULL
- #ifdef EARLY_PARTITION_ACCESS
- #define GPT_SRAM_BUF_SIZE 4096
- unsigned char __NOBITS_SECTION__(.gpt_sram_buf) gpt_sram_buf[GPT_SRAM_BUF_SIZE];
- u32 __NOBITS_SECTION__(.gpt_sram_crc32_table) gpt_sram_crc32_table[256];
- part_t __NOBITS_SECTION__(.gpt_sram_part_info) gpt_sram_part_info;
- struct part_meta_info __NOBITS_SECTION__(.gpt_sram_part_meta_info) gpt_sram_part_meta_info;
- #endif
- static void init_crc32_table(u32* crc32_table)
- {
- int i, j;
- u32 crc;
- for (i = 0; i < 256; i++) {
- crc = i;
- for (j = 0; j < 8; j++) {
- if (crc & 1) {
- crc = (crc >> 1) ^ 0xEDB88320;
- } else {
- crc >>= 1;
- }
- }
- crc32_table[i] = crc;
- }
- }
- static u32 crc32(u32 crc, u8 *p, u32 len, u32* crc32_table)
- {
- while (len--) {
- crc ^= *p++;
- crc = (crc >> 8) ^ crc32_table[crc & 255];
- }
- return crc;
- }
- static u32 efi_crc32(u32 crc, u8 *p, u32 len, u32* crc32_table)
- {
- return crc32(crc, p, len, crc32_table);
- }
- static u32 efi_crc32_finalize(u32 crc)
- {
- return crc ^ ~0L;
- }
- static void get_part_name(u8 *dst, u16 *src, int len)
- {
- int i = 0;
- if ((src[0] & 0xFF00) == 0) { // word to ascii string
- while (i < len - 1) {
- if (!src[i])
- break;
- dst[i] = src[i] & 0xFF;
- i++;
- }
- dst[i] = 0;
- } else {
- memcpy(dst, src, len - 1);
- dst[len-1] = 0;
- }
- }
- static void get_part_info(u32 part_id, part_t *part_ptr, gpt_entry *entry)
- {
- get_part_name(part_ptr->info->name, entry->partition_name, min(PART_META_INFO_NAMELEN, GPT_ENTRY_NAME_LEN));
- part_ptr->start_sect = (unsigned long)entry->starting_lba;
- part_ptr->nr_sects = (unsigned long)(entry->ending_lba - entry->starting_lba + 1);
- part_ptr->part_id = part_id;
- part_ptr->part_attr = (unsigned long)entry->attributes;
- pal_log_debug("%sname=%s, start_sect=0x%x, nr_sects=0x%x\n", TAG, part_ptr->info->name,
- (unsigned long)entry->starting_lba, (unsigned long)(entry->ending_lba - entry->starting_lba + 1));
- }
- extern u64 g_emmc_user_size;
- static u64 last_lba(u32 part_id)
- {
- #if !defined(BOOTDEV_SDMMC_UFS_COMBO)
- /* Only support USER region now */
- #if (CFG_BOOT_DEV == BOOTDEV_SDMMC)
- return g_emmc_user_size / 512 - 1;
- #elif (CFG_BOOT_DEV == BOOTDEV_UFS)
- {
- blkdev_t *dev;
- u64 bytes;
- dev = blkdev_get(CFG_BOOT_DEV);
- if (dev == NULL)
- return 0;
- bytes = dev->get_part_size(dev, part_id);
- if (bytes)
- return bytes / dev->blksz - 1;
- else
- return 0;
- }
- #endif
- #else
- #if (CFG_BOOT_DEV == BOOTDEV_SDMMC) || (CFG_BOOT_DEV == BOOTDEV_UFS)
- blkdev_t *dev;
- u64 bytes;
- dev = blkdev_get(CFG_BOOT_DEV);
- if (dev == NULL)
- return 0;
- if (dev->type == BOOTDEV_SDMMC) {
- return g_emmc_user_size / 512 - 1;
- } else if (dev->type == BOOTDEV_UFS) {
- bytes = dev->get_part_size(dev, part_id);
- if (bytes)
- return bytes / dev->blksz - 1;
- else
- return 0;
- }
- #endif
- #endif
- return 0;
- }
- static int read_data(u8 *buf, u32 part_id, u64 lba, u64 size)
- {
- int err;
- blkdev_t *dev;
- dev = blkdev_get(CFG_BOOT_DEV);
- if (!dev) {
- pal_log_err("%sread data, err(no dev)\n", TAG);
- return 1;
- }
- err = blkdev_read(dev, lba * dev->blksz, (u32)size, buf, part_id);
- if (err) {
- pal_log_err("%sread data, err(%d)\n", TAG, err);
- return err;
- }
- return 0;
- }
- static int get_gpt_header(u32 part_id, u64 header_lba, u8 *header_buf, u32 len, u32 *crc32_table)
- {
- int err;
- u32 calc_crc, orig_header_crc;
- gpt_header *header = (gpt_header *)header_buf;
- err = read_data(header_buf, part_id, header_lba, len);
- if (err) {
- pal_log_err("%sread header(part_id=%d,lba=%llx), err(%d)\n",
- TAG, part_id, header_lba, err);
- return err;
- }
- if (header->signature != GPT_HEADER_SIGNATURE) {
- pal_log_err("%scheck header, err(signature 0x%llx!=0x%llx)\n",
- TAG, header->signature, GPT_HEADER_SIGNATURE);
- return 1;
- }
- orig_header_crc = header->header_crc32;
- header->header_crc32 = 0;
- calc_crc = efi_crc32(~0L, (u8 *)header, header->header_size, crc32_table);
- calc_crc = efi_crc32_finalize(calc_crc);
- if (orig_header_crc != calc_crc) {
- pal_log_err("%scheck header, err(crc 0x%x!=0x%x(calc))\n",
- TAG, orig_header_crc, calc_crc);
- return 1;
- }
- header->header_crc32 = orig_header_crc;
- if (header->my_lba != header_lba) {
- pal_log_err("%scheck header, err(my_lba 0x%llx!=0x%llx)\n",
- TAG, header->my_lba, header_lba);
- return 1;
- }
- return 0;
- }
- #ifdef EARLY_PARTITION_ACCESS
- 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) {
- int err, i, found;
- int entries_cnt, cur_entry_idx;
- u32 calc_crc, orig_header_crc;
- u64 entries_read_size, num_block_entry, read_lba;
- gpt_header gpt_header_buf;
- gpt_header *header = &gpt_header_buf;
- gpt_entry *entries = (gpt_entry *)entries_buf;
- init_crc32_table(gpt_sram_crc32_table);
- part_ptr->start_sect = 0;
- if (get_gpt_header(part_id, header_lba, (u8*) &gpt_header_buf, sizeof(gpt_header_buf), gpt_sram_crc32_table)) {
- pal_log_err("%s get_gpt_header fail\n", TAG);
- return 1;
- }
- num_block_entry = (u64)(blksz / header->sizeof_partition_entry);
- entries_read_size = (u64)((header->num_partition_entries + (num_block_entry - 1)) / num_block_entry) * blksz;
- calc_crc = ~0L;
- read_lba = header->partition_entry_lba;
- found = 0;
- while (entries_read_size > 0) {
- err = read_data((u8*)entries_buf, part_id, read_lba, GPT_SRAM_BUF_SIZE);
- read_lba = read_lba + GPT_SRAM_BUF_SIZE/blksz;
- calc_crc = efi_crc32(calc_crc, (u8 *)entries_buf, (u32)GPT_SRAM_BUF_SIZE, gpt_sram_crc32_table);
- entries_read_size -= GPT_SRAM_BUF_SIZE;
- entries_cnt = GPT_SRAM_BUF_SIZE/header->sizeof_partition_entry;
- for (i = 0; i < entries_cnt && found == 0; i++) {
- if(!entries[i].starting_lba)
- break;
- get_part_info(part_id, part_ptr, &entries[i]);
- if (!strcmp(part_ptr->info->name, part_name)) {
- found = 1;
- break;
- }
- }
- }
- calc_crc = efi_crc32_finalize(calc_crc);
- if (header->partition_entry_array_crc32 != calc_crc) {
- pal_log_err("%scheck header, err(entries crc 0x%x!=0x%x(calc))\n",
- TAG, header->partition_entry_array_crc32, calc_crc);
- memset(part_ptr, 0, sizeof(part_t));
- return 1;
- }
- if (found == 0)
- memset(part_ptr, 0, sizeof(part_t));
- return 0;
- }
- part_t *mt_get_part_sram(const char *name)
- {
- u32 part_id;
- part_id = storage_get_part_id(STORAGE_PHYS_PART_USER);
- if (name == NULL) {
- pal_log_err("%s[%s]invalid argument\n", TAG, __func__);
- return NULL;
- }
- blkdev_t *dev = blkdev_get(CFG_BOOT_DEV);
- if (!dev) {
- pal_log_err("%s%s fail, err(no dev)\n", TAG, __func__);
- return NULL;
- }
- gpt_sram_part_info.info = &gpt_sram_part_meta_info;
- if (get_part_ptr_by_gpt(part_id, 1, gpt_sram_buf, &gpt_sram_part_info, name, dev->blksz) != 0) {
- if (get_part_ptr_by_gpt(part_id, last_lba(part_id), gpt_sram_buf, &gpt_sram_part_info, name, dev->blksz) != 0) {
- pal_log_err("%sFailure to find valid GPT.\n", TAG);
- return NULL;
- }
- }
- if (gpt_sram_part_info.start_sect == 0 && gpt_sram_part_info.nr_sects == 0)
- return NULL;
- else
- return &gpt_sram_part_info;
- }
- int mt_get_part_info_by_name(const char *name, struct part_info_t *part_info)
- {
- part_t *part;
- blkdev_t *dev = blkdev_get(CFG_BOOT_DEV);
- if (!dev) {
- pal_log_err("%s%s fail, err(no dev)\n", TAG, __func__);
- return 1;
- }
- part = mt_get_part_sram(name);
- if (part != NULL && part_info != NULL) {
- part_info->addr = (u64)part->start_sect * (u64)dev->blksz;
- part_info->active = (part->part_attr & PART_ATTR_LEGACY_BIOS_BOOTABLE);
- return 0;
- }
- return 1;
- }
- u64 get_part_addr(const char *name) {
- struct part_info_t part_info;
- if (mt_get_part_info_by_name(name, &part_info) != 0) {
- pal_log_err("%smt_get_part_info_by_name fail\n", TAG);
- return 0;
- } else {
- return (u64)part_info.addr;
- }
- }
- #endif
- static int parse_gpt_header(u32 part_id, u64 header_lba, u8 *header_buf, u8 *entries_buf)
- {
- int i;
- blkdev_t *dev;
- int err;
- u32 calc_crc, orig_header_crc;
- u64 entries_real_size, entries_read_size, num_block_entry;
- gpt_header *header = (gpt_header *)header_buf;
- gpt_entry *entries = (gpt_entry *)entries_buf;
- init_crc32_table(gpt_dram_crc32_table);
- dev = blkdev_get(CFG_BOOT_DEV);
- if (!dev) {
- pal_log_err("%sparse_gpt_header fail, err(no dev)\n", TAG);
- return 1;
- }
- if (get_gpt_header(part_id, header_lba, header_buf, dev->blksz, gpt_dram_crc32_table)) {
- pal_log_err("%s get_gpt_header fail\n", TAG);
- return 1;
- }
- entries_real_size = (u64)header->num_partition_entries * header->sizeof_partition_entry;
- num_block_entry = (u64)(dev->blksz / header->sizeof_partition_entry);
- entries_read_size = (u64)((header->num_partition_entries + (num_block_entry - 1)) / num_block_entry) * dev->blksz;
- err = read_data(entries_buf, part_id, header->partition_entry_lba, entries_read_size);
- if (err) {
- pal_log_err("%sread entries(part_id=%d,lba=%llx), err(%d)\n",
- TAG, part_id, header->partition_entry_lba, err);
- return err;
- }
- calc_crc = efi_crc32(~0L, (u8 *)entries, (u32)entries_real_size, gpt_dram_crc32_table);
- calc_crc = efi_crc32_finalize(calc_crc);
- if (header->partition_entry_array_crc32 != calc_crc) {
- pal_log_err("%scheck header, err(entries crc 0x%x!=0x%x(calc))\n",
- TAG, header->partition_entry_array_crc32, calc_crc);
- return 1;
- }
- for (i = 0; i < header->num_partition_entries; i++) {
- /* break if partition entry is empty */
- if(!entries[i].starting_lba)
- break;
- part_ptr[i].info = &g_dram_buf->meta_info[i];
- get_part_info(part_id, &part_ptr[i], &entries[i]);
- }
- return 0;
- }
- int read_gpt(part_t *part)
- {
- int err;
- u64 lba;
- u32 part_id;
- part_id = storage_get_part_id(STORAGE_PHYS_PART_USER);
- part_ptr = part;
- pal_log_debug("%sParsing Primary GPT now...\n", TAG);
- err = parse_gpt_header(part_id, 1, GPT_HEADER_BUF, GPT_ENTRIES_BUF);
- if (!err) {
- goto find;
- }
- pal_log_debug("%sParsing Secondary GPT now...\n", TAG);
- lba = last_lba(part_id);
- if (!lba){
- pal_log_err("%sFailure to find last lba.\n", TAG);
- return 1;
- }
- err = parse_gpt_header(part_id, lba, GPT_HEADER_BUF, GPT_ENTRIES_BUF);
- if (!err) {
- goto find;
- }
- pal_log_err("%sFailure to find valid GPT.\n", TAG);
- return err;
- find:
- pal_log_err("%sSuccess to find valid GPT.\n", TAG);
- return 0;
- }
|