static int initialize_gpt(struct drive *drive, const char *guid) { GptHeader *h = (GptHeader *)drive->gpt.primary_header; memcpy(h->signature, GPT_HEADER_SIGNATURE, GPT_HEADER_SIGNATURE_SIZE); h->revision = GPT_HEADER_REVISION; h->size = sizeof(GptHeader); h->my_lba = 1; h->alternate_lba = drive->gpt.drive_sectors - 1; h->first_usable_lba = 1 + 1 + GPT_ENTRIES_SECTORS; h->last_usable_lba = drive->gpt.drive_sectors - 1 - GPT_ENTRIES_SECTORS - 1; if (guid) { if (StrToGuid(guid, &h->disk_uuid) != CGPT_OK) { Error("Provided GUID is invalid: \"%s\"\n", guid); return CGPT_FAILED; } } else { if (!uuid_generator) { Error("Unable to generate new GUID. uuid_generator not set.\n"); return CGPT_FAILED; } (*uuid_generator)((uint8_t *)&h->disk_uuid); } h->entries_lba = 2; h->number_of_entries = 128; h->size_of_entry = sizeof(GptEntry); // Copy to secondary RepairHeader(&drive->gpt, MASK_PRIMARY); UpdateCrc(&drive->gpt); return CGPT_OK; }
int GptCreate(struct drive *drive, CgptCreateParams *params) { // Erase the data memset(drive->gpt.primary_header, 0, drive->gpt.sector_bytes * GPT_HEADER_SECTOR); memset(drive->gpt.secondary_header, 0, drive->gpt.sector_bytes * GPT_HEADER_SECTOR); memset(drive->gpt.primary_entries, 0, drive->gpt.sector_bytes * GPT_ENTRIES_SECTORS); memset(drive->gpt.secondary_entries, 0, drive->gpt.sector_bytes * GPT_ENTRIES_SECTORS); drive->gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 | GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2); // Initialize a blank set if (!params->zap) { GptHeader *h = (GptHeader *)drive->gpt.primary_header; memcpy(h->signature, GPT_HEADER_SIGNATURE, GPT_HEADER_SIGNATURE_SIZE); h->revision = GPT_HEADER_REVISION; h->size = sizeof(GptHeader); h->my_lba = 1; h->alternate_lba = drive->gpt.drive_sectors - 1; h->first_usable_lba = 1 + 1 + GPT_ENTRIES_SECTORS; h->last_usable_lba = drive->gpt.drive_sectors - 1 - GPT_ENTRIES_SECTORS - 1; if (!uuid_generator) { Error("Unable to generate new GUID. uuid_generator not set.\n"); return -1; } (*uuid_generator)((uint8_t *)&h->disk_uuid); h->entries_lba = 2; h->number_of_entries = 128; h->size_of_entry = sizeof(GptEntry); // Copy to secondary RepairHeader(&drive->gpt, MASK_PRIMARY); UpdateCrc(&drive->gpt); } return 0; }
static int GptCreate(struct drive *drive, CgptCreateParams *params) { // Allocate and/or erase the data. // We cannot assume the GPT headers or entry arrays have been allocated // by GptLoad() because those fields might have failed validation checks. AllocAndClear(&drive->gpt.primary_header, drive->gpt.sector_bytes * GPT_HEADER_SECTORS); AllocAndClear(&drive->gpt.secondary_header, drive->gpt.sector_bytes * GPT_HEADER_SECTORS); drive->gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 | GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2); // Initialize a blank set if (!params->zap) { GptHeader *h = (GptHeader *)drive->gpt.primary_header; memcpy(h->signature, GPT_HEADER_SIGNATURE, GPT_HEADER_SIGNATURE_SIZE); h->revision = GPT_HEADER_REVISION; h->size = sizeof(GptHeader); h->my_lba = GPT_PMBR_SECTORS; /* The second sector on drive. */ h->alternate_lba = drive->gpt.gpt_drive_sectors - GPT_HEADER_SECTORS; if (CGPT_OK != GenerateGuid(&h->disk_uuid)) { Error("Unable to generate new GUID.\n"); return -1; } /* Calculate number of entries */ h->size_of_entry = sizeof(GptEntry); h->number_of_entries = MAX_NUMBER_OF_ENTRIES; if (drive->gpt.flags & GPT_FLAG_EXTERNAL) { // We might have smaller space for the GPT table. Scale accordingly. // // +------+------------+---------------+-----+--------------+-----------+ // | PMBR | Prim. Head | Prim. Entries | ... | Sec. Entries | Sec. Head | // +------+------------+---------------+-----+--------------+-----------+ // // Half the size of gpt_drive_sectors must be big enough to hold PMBR + // GPT Header + Entries Table, though the secondary structures do not // contain PMBR. size_t required_headers_size = (GPT_PMBR_SECTORS + GPT_HEADER_SECTORS) * drive->gpt.sector_bytes; size_t min_entries_size = MIN_NUMBER_OF_ENTRIES * h->size_of_entry; size_t required_min_size = required_headers_size + min_entries_size; size_t half_size = (drive->gpt.gpt_drive_sectors / 2) * drive->gpt.sector_bytes; if (half_size < required_min_size) { Error("Not enough space to store GPT structures. Required %d bytes.\n", required_min_size * 2); return -1; } size_t max_entries = (half_size - required_headers_size) / h->size_of_entry; if (h->number_of_entries > max_entries) { h->number_of_entries = max_entries; } } /* Then use number of entries to calculate entries_lba. */ h->entries_lba = h->my_lba + GPT_HEADER_SECTORS; if (!(drive->gpt.flags & GPT_FLAG_EXTERNAL)) { h->entries_lba += params->padding; h->first_usable_lba = h->entries_lba + CalculateEntriesSectors(h); h->last_usable_lba = (drive->gpt.streaming_drive_sectors - GPT_HEADER_SECTORS - CalculateEntriesSectors(h) - 1); } else { h->first_usable_lba = params->padding; h->last_usable_lba = (drive->gpt.streaming_drive_sectors - 1); } size_t entries_size = h->number_of_entries * h->size_of_entry; AllocAndClear(&drive->gpt.primary_entries, entries_size); AllocAndClear(&drive->gpt.secondary_entries, entries_size); // Copy to secondary RepairHeader(&drive->gpt, MASK_PRIMARY); UpdateCrc(&drive->gpt); } return 0; }