1a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 2a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// Use of this source code is governed by a BSD-style license that can be 3a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// found in the LICENSE file. 4a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 5a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#include <string.h> 6a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 75fed2a667096341160db8643a4a057e328953a1dBill Richardson#define _STUB_IMPLEMENTATION_ 80c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson 90c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson#include "cgpt.h" 100c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson#include "cgpt_params.h" 110c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson#include "cgptlib_internal.h" 125fed2a667096341160db8643a4a057e328953a1dBill Richardson#include "utility.h" 130c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson#include "vboot_host.h" 1466b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo 1566b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lostatic const char* DumpCgptAddParams(const CgptAddParams *params) { 1666b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo static char buf[256]; 1766b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo char tmp[64]; 1866b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo 1966b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo buf[0] = 0; 2066b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo snprintf(tmp, sizeof(tmp), "-i %d ", params->partition); 215fed2a667096341160db8643a4a057e328953a1dBill Richardson StrnAppend(buf, tmp, sizeof(buf)); 2266b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo if (params->label) { 2366b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo snprintf(tmp, sizeof(tmp), "-l %s ", params->label); 245fed2a667096341160db8643a4a057e328953a1dBill Richardson StrnAppend(buf, tmp, sizeof(buf)); 2566b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo } 2666b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo if (params->set_begin) { 2766b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo snprintf(tmp, sizeof(tmp), "-b %llu ", (unsigned long long)params->begin); 285fed2a667096341160db8643a4a057e328953a1dBill Richardson StrnAppend(buf, tmp, sizeof(buf)); 2966b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo } 3066b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo if (params->set_size) { 3166b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo snprintf(tmp, sizeof(tmp), "-s %llu ", (unsigned long long)params->size); 325fed2a667096341160db8643a4a057e328953a1dBill Richardson StrnAppend(buf, tmp, sizeof(buf)); 3366b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo } 3466b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo if (params->set_type) { 3566b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo GuidToStr(¶ms->type_guid, tmp, sizeof(tmp)); 365fed2a667096341160db8643a4a057e328953a1dBill Richardson StrnAppend(buf, "-t ", sizeof(buf)); 375fed2a667096341160db8643a4a057e328953a1dBill Richardson StrnAppend(buf, tmp, sizeof(buf)); 385fed2a667096341160db8643a4a057e328953a1dBill Richardson StrnAppend(buf, " ", sizeof(buf)); 3966b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo } 4066b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo if (params->set_unique) { 4166b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo GuidToStr(¶ms->unique_guid, tmp, sizeof(tmp)); 425fed2a667096341160db8643a4a057e328953a1dBill Richardson StrnAppend(buf, "-u ", sizeof(buf)); 435fed2a667096341160db8643a4a057e328953a1dBill Richardson StrnAppend(buf, tmp, sizeof(buf)); 445fed2a667096341160db8643a4a057e328953a1dBill Richardson StrnAppend(buf, " ", sizeof(buf)); 4566b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo } 4666b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo if (params->set_successful) { 4766b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo snprintf(tmp, sizeof(tmp), "-S %d ", params->successful); 485fed2a667096341160db8643a4a057e328953a1dBill Richardson StrnAppend(buf, tmp, sizeof(buf)); 4966b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo } 5066b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo if (params->set_tries) { 5166b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo snprintf(tmp, sizeof(tmp), "-T %d ", params->tries); 525fed2a667096341160db8643a4a057e328953a1dBill Richardson StrnAppend(buf, tmp, sizeof(buf)); 5366b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo } 5466b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo if (params->set_priority) { 5566b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo snprintf(tmp, sizeof(tmp), "-P %d ", params->priority); 565fed2a667096341160db8643a4a057e328953a1dBill Richardson StrnAppend(buf, tmp, sizeof(buf)); 5766b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo } 5866b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo if (params->set_raw) { 5966b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo snprintf(tmp, sizeof(tmp), "-A 0x%x ", params->raw_value); 605fed2a667096341160db8643a4a057e328953a1dBill Richardson StrnAppend(buf, tmp, sizeof(buf)); 6166b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo } 6266b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo 635fed2a667096341160db8643a4a057e328953a1dBill Richardson StrnAppend(buf, "\n", sizeof(buf)); 6466b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo return buf; 6566b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo} 6666b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo 67fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk// This is the implementation-specific helper function. 68fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulkstatic int GptSetEntryAttributes(struct drive *drive, 69250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan uint32_t index, 70250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan CgptAddParams *params) { 71fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk GptEntry *entry; 72fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk 73fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk entry = GetEntry(&drive->gpt, PRIMARY, index); 74fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk if (params->set_begin) 75fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk entry->starting_lba = params->begin; 76fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk if (params->set_size) 77fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk entry->ending_lba = entry->starting_lba + params->size - 1; 78fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk if (params->set_unique) { 79fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk memcpy(&entry->unique, ¶ms->unique_guid, sizeof(Guid)); 80fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk } else if (GuidIsZero(&entry->type)) { 814cb5497984642b8cbd592c14cb1912a787b2d4d7Bill Richardson if (CGPT_OK != GenerateGuid(&entry->unique)) { 824cb5497984642b8cbd592c14cb1912a787b2d4d7Bill Richardson Error("Unable to generate new GUID.\n"); 834cb5497984642b8cbd592c14cb1912a787b2d4d7Bill Richardson return -1; 84fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk } 85fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk } 86fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk if (params->set_type) 87fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk memcpy(&entry->type, ¶ms->type_guid, sizeof(Guid)); 88fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk if (params->label) { 89fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk if (CGPT_OK != UTF8ToUTF16((uint8_t *)params->label, entry->name, 90fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk sizeof(entry->name) / sizeof(entry->name[0]))) { 91fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk Error("The label cannot be converted to UTF16.\n"); 92fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk return -1; 93fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk } 94fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk } 95fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk return 0; 96fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk} 97fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk 98fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk// This is an internal helper function which assumes no NULL args are passed. 99fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk// It sets the given attribute values for a single entry at the given index. 100fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulkstatic int SetEntryAttributes(struct drive *drive, 101fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk uint32_t index, 102fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk CgptAddParams *params) { 103250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan if (params->set_raw) { 104fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk SetRaw(drive, PRIMARY, index, params->raw_value); 105250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan } else { 106250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan if (params->set_successful) 107fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk SetSuccessful(drive, PRIMARY, index, params->successful); 108250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan if (params->set_tries) 109fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk SetTries(drive, PRIMARY, index, params->tries); 110250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan if (params->set_priority) 111fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk SetPriority(drive, PRIMARY, index, params->priority); 112250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan } 113a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 114fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk // New partitions must specify type, begin, and size. 115fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk if (IsUnused(drive, PRIMARY, index)) { 116fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk if (!params->set_begin || !params->set_size || !params->set_type) { 117fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk Error("-t, -b, and -s options are required for new partitions\n"); 118fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk return -1; 119fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk } 120fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk if (GuidIsZero(¶ms->type_guid)) { 121fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk Error("New partitions must have a type other than \"unused\"\n"); 122fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk return -1; 123fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk } 124fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk } 125a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 126fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk return 0; 127fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk} 128a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 129fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulkstatic int CgptCheckAddValidity(struct drive *drive) { 1308577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen int gpt_retval; 1318577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive->gpt))) { 1328577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen Error("GptSanityCheck() returned %d: %s\n", 1338577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen gpt_retval, GptError(gpt_retval)); 1348577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen return -1; 1358577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen } 136a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 1378577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen if (((drive->gpt.valid_headers & MASK_BOTH) != MASK_BOTH) || 1388577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen ((drive->gpt.valid_entries & MASK_BOTH) != MASK_BOTH)) { 1398577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen Error("one of the GPT header/entries is invalid.\n" 1408577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen "please run 'cgpt repair' before adding anything.\n"); 1418577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen return -1; 142250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan } 1438577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen 144fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk return 0; 145fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk} 146250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan 147fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulkstatic int CgptGetUnusedPartition(struct drive *drive, uint32_t *index, 148fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk CgptAddParams *params) { 149fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk uint32_t i; 150fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk uint32_t max_part = GetNumberOfEntries(drive); 151fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk if (params->partition) { 152fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk if (params->partition > max_part) { 153fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk Error("invalid partition number: %d\n", params->partition); 154fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk return -1; 155fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk } 156fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk *index = params->partition - 1; 157fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk return 0; 158fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk } else { 159fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk // Find next empty partition. 160fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk for (i = 0; i < max_part; i++) { 161fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk if (IsUnused(drive, PRIMARY, i)) { 162fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk params->partition = i + 1; 163fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk *index = i; 164fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk return 0; 165fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk } 166fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk } 167fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk Error("no unused partitions available\n"); 168fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk return -1; 169fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk } 170fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk} 171fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk 172fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulkint CgptSetAttributes(CgptAddParams *params) { 173fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk struct drive drive; 174fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk 175fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk if (params == NULL) 176fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk return CGPT_FAILED; 177fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk 178ab899591808dd3e5f955ab7693b54a83389cd35fNam T. Nguyen if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDWR, 179ab899591808dd3e5f955ab7693b54a83389cd35fNam T. Nguyen params->drive_size)) 180fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk return CGPT_FAILED; 181fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk 182fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk if (CgptCheckAddValidity(&drive)) { 183250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan goto bad; 184250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan } 185250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan 186fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk if (params->partition == 0 || 187fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk params->partition >= GetNumberOfEntries(&drive)) { 188250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan Error("invalid partition number: %d\n", params->partition); 189250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan goto bad; 190250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan } 191250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan 192fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk SetEntryAttributes(&drive, params->partition - 1, params); 193250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan 194fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk UpdateAllEntries(&drive); 195250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan 196250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan // Write it all out. 197250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan return DriveClose(&drive, 1); 198250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan 199250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasanbad: 200250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan DriveClose(&drive, 0); 201250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan return CGPT_FAILED; 202250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan} 203250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan 204250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan// This method gets the partition details such as the attributes, the 205250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan// guids of the partitions, etc. Input is the partition number or the 206250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan// unique id of the partition. Output is populated in the respective 207250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan// fields of params. 2083f806a2abf07d7b801852a4a6f3a9080a4b5c427Bill Richardsonint CgptGetPartitionDetails(CgptAddParams *params) { 209250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan struct drive drive; 210250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan int result = CGPT_FAILED; 211fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk int index; 212250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan 213250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan if (params == NULL) 214fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk return CGPT_FAILED; 215250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan 216ab899591808dd3e5f955ab7693b54a83389cd35fNam T. Nguyen if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDWR, 217ab899591808dd3e5f955ab7693b54a83389cd35fNam T. Nguyen params->drive_size)) 218fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk return CGPT_FAILED; 219250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan 220fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk if (CgptCheckAddValidity(&drive)) { 221250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan goto bad; 222250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan } 223250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan 224fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk int max_part = GetNumberOfEntries(&drive); 225fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk if (params->partition > 0) { 226fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk if (params->partition >= max_part) { 227250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan Error("invalid partition number: %d\n", params->partition); 228250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan goto bad; 229250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan } 230250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan } else { 231250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan if (!params->set_unique) { 232250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan Error("either partition or unique_id must be specified\n"); 233250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan goto bad; 234250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan } 235250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan for (index = 0; index < max_part; index++) { 236fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk GptEntry *entry = GetEntry(&drive.gpt, PRIMARY, index); 237250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan if (GuidEqual(&entry->unique, ¶ms->unique_guid)) { 238250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan params->partition = index + 1; 239250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan break; 240250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan } 241250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan } 242250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan if (index >= max_part) { 243250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan Error("no partitions with the given unique id available\n"); 244250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan goto bad; 245250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan } 246250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan } 247fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk index = params->partition - 1; 248250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan 2498577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen // GPT-specific code 2508577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen GptEntry *entry = GetEntry(&drive.gpt, PRIMARY, index); 2518577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen params->begin = entry->starting_lba; 2528577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen params->size = entry->ending_lba - entry->starting_lba + 1; 2538577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen memcpy(¶ms->type_guid, &entry->type, sizeof(Guid)); 2548577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen memcpy(¶ms->unique_guid, &entry->unique, sizeof(Guid)); 2558577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen params->raw_value = entry->attrs.fields.gpt_att; 256250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan 257fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk params->successful = GetSuccessful(&drive, PRIMARY, index); 258fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk params->tries = GetTries(&drive, PRIMARY, index); 259fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk params->priority = GetPriority(&drive, PRIMARY, index); 260250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan result = CGPT_OK; 261250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan 262250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasanbad: 263250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan DriveClose(&drive, 0); 264250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan return result; 265250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan} 266250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan 26718e03706df6ab4256a89f4e578ecf0f165641c8aBill Richardsonstatic int GptAdd(struct drive *drive, CgptAddParams *params, uint32_t index) { 2687d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk GptEntry *entry, backup; 2697d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk int rv; 2707d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk 2717d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk entry = GetEntry(&drive->gpt, PRIMARY, index); 2727d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk memcpy(&backup, entry, sizeof(backup)); 2737d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk 2747d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk if (SetEntryAttributes(drive, index, params) || 2757d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk GptSetEntryAttributes(drive, index, params)) { 2767d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk memcpy(entry, &backup, sizeof(*entry)); 2777d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk return -1; 2787d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk } 2797d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk 2807d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk UpdateAllEntries(drive); 2817d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk 2827d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk rv = CheckEntries((GptEntry*)drive->gpt.primary_entries, 2837d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk (GptHeader*)drive->gpt.primary_header); 2847d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk 2857d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk if (0 != rv) { 2867d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk // If the modified entry is illegal, recover it and return error. 2877d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk memcpy(entry, &backup, sizeof(*entry)); 2887d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk Error("%s\n", GptErrorText(rv)); 2897d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk Error(DumpCgptAddParams(params)); 2907d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk return -1; 2917d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk } 2927d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk 2937d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk return 0; 2947d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk} 2957d401c5cd58ec422e239b28c334fc2e94778f565Albert Chaulk 2963f806a2abf07d7b801852a4a6f3a9080a4b5c427Bill Richardsonint CgptAdd(CgptAddParams *params) { 297250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan struct drive drive; 298250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan uint32_t index; 299250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan 300250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan if (params == NULL) 301250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan return CGPT_FAILED; 302250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan 303ab899591808dd3e5f955ab7693b54a83389cd35fNam T. Nguyen if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDWR, 304ab899591808dd3e5f955ab7693b54a83389cd35fNam T. Nguyen params->drive_size)) 305a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan return CGPT_FAILED; 306250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan 307fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk if (CgptCheckAddValidity(&drive)) { 308250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan goto bad; 309250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan } 310250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan 311fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk if (CgptGetUnusedPartition(&drive, &index, params)) { 312250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan goto bad; 313a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan } 314a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 3158577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen if (GptAdd(&drive, params, index)) 3168577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen goto bad; 31766b47ba37d3658cceecf30d25edc3becbb692c4aLouis Yung-Chieh Lo 318250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan // Write it all out. 319a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan return DriveClose(&drive, 1); 320a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 321a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasanbad: 322250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan DriveClose(&drive, 0); 323a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan return CGPT_FAILED; 324a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan} 325