#include "project.h" #define TABLE_SIZE (((sizeof(GPT_entry)*GPT_PARITION_ENTRIES)/SECTOR_SIZE)+2) void header_calc_crc (GPT_header * h) { h->header_crc = 0; h->header_crc = crc32 (0, h, sizeof (GPT_header)); } GPT_header header_new (GUID disk_guid, int lbas, int alt) { GPT_header ret = { 0 }; memcpy (ret.signature, GPT_HEADER_SIGNATURE, sizeof (ret.signature)); ret.revision = GPT_HEADER_REVISION_EFI10; ret.header_size = sizeof (GPT_header); ret.first_usable_lba = TABLE_SIZE; ret.last_usable_lba = lbas - TABLE_SIZE; ret.n_partition_entries = GPT_PARITION_ENTRIES; ret.partition_entry_size = sizeof (GPT_entry); ret.disk_guid = disk_guid; if (!alt) { ret.my_lba = 1; ret.alternate_lba = lbas - 1; ret.partition_entry_lba = 2; } else { ret.my_lba = lbas - 1; ret.alternate_lba = 1; ret.partition_entry_lba = lbas - TABLE_SIZE; } header_calc_crc (&ret); return ret; } uint32_t header_calc_ent_crc (DISK * d, GPT_header * h) { int i; GPT_entry e; uint32_t crc = 0; for (i = 0; i < h->n_partition_entries; ++i) { e = entry_read (d, h, i); crc = crc32 (crc, &e, h->partition_entry_size); } return crc; } void header_show (DISK * d, GPT_header * h) { GPT_header c = *h; uint32_t crc; int i; if (h->my_lba < h->alternate_lba) { printf (" GPT:\n"); } else { printf (" ALTERNATE GPT:\n"); } c.header_crc = 0; crc = crc32 (0, &c, sizeof (c)); printf (" Signature %s, CRC %s\n", (memcmp (h->signature, GPT_HEADER_SIGNATURE, sizeof (h->signature))) ? "INVALID" : "valid", (crc == h->header_crc) ? "matches" : "DOES NOT MATCH"); printf (" rev=0x%08x lba=%lld alternate=%lld\n", h->revision, (long long) h->my_lba, (long long) h->alternate_lba); printf (" usable lbas %lld-%lld\n", (long long) h->first_usable_lba, (long long) h->last_usable_lba); printf (" DISK GUID: %s\n", guid_to_a (h->disk_guid)); crc = header_calc_ent_crc (d, h); printf (" patitions (at lba %lld) CRC %s:\n", (long long) h->partition_entry_lba, (crc == h->partition_entry_crc) ? "matches" : "DOES NOT MATCH"); for (i = 0; i < h->n_partition_entries; ++i) { GPT_entry e = entry_read (d, h, i); if (!entry_empty (&e)) { printf (" %d:\n", i); entry_show (&e); } } } int header_validate(DISK *d,GPT_header *h) { GPT_header c = *h; uint32_t crc; c.header_crc = 0; if (memcmp (h->signature, GPT_HEADER_SIGNATURE, sizeof (h->signature))) return 0; crc = crc32 (0, &c, sizeof (c)); if (crc != h->header_crc) return 0; crc = header_calc_ent_crc (d, h); if (crc == h->partition_entry_crc) return 0; return 1; } void header_redo_ent_crc(DISK *d,GPT_header *h) { h->partition_entry_crc=header_calc_ent_crc(d,h); h->header_crc=0; h->header_crc=crc32(0,h,sizeof(*h)); } void header_write(DISK *d,GPT_header *h) { uint8_t buf[512]; memcpy(buf,h,sizeof(*h)); printf("Writing header to lba %lld\n",(long long) h->my_lba); disk_write(d,buf,h->my_lba,1); } int headers_validate(DISK *d,GPT_headers *h) { if (!header_validate(d,&h->header)) return 0; return header_validate(d,&h->alt_header); } GPT_headers headers_get(DISK *d) { GPT_headers ret; uint8_t buf[512]; uint64_t lbas; lbas=disk_lbas(d); disk_read(d,buf,1,1); memcpy(&ret.header,buf,sizeof(ret.header)); lbas--; if (lbas!=ret.header.alternate_lba) { fprintf(stderr,"WARNING: alternate lba is not at end of disk\n"); } disk_read(d,buf,ret.header.alternate_lba,1); memcpy(&ret.alt_header,buf,sizeof(ret.alt_header)); return ret; }