1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2013 The ChromiumOS Authors 2*8617a60dSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 3*8617a60dSAndroid Build Coastguard Worker * found in the LICENSE file. 4*8617a60dSAndroid Build Coastguard Worker */ 5*8617a60dSAndroid Build Coastguard Worker 6*8617a60dSAndroid Build Coastguard Worker #ifndef VBOOT_REFERENCE_GPT_MISC_H_ 7*8617a60dSAndroid Build Coastguard Worker #define VBOOT_REFERENCE_GPT_MISC_H_ 8*8617a60dSAndroid Build Coastguard Worker 9*8617a60dSAndroid Build Coastguard Worker #include "gpt.h" 10*8617a60dSAndroid Build Coastguard Worker #include "vboot_api.h" 11*8617a60dSAndroid Build Coastguard Worker 12*8617a60dSAndroid Build Coastguard Worker #ifdef __cplusplus 13*8617a60dSAndroid Build Coastguard Worker extern "C" { 14*8617a60dSAndroid Build Coastguard Worker #endif /* __cplusplus */ 15*8617a60dSAndroid Build Coastguard Worker 16*8617a60dSAndroid Build Coastguard Worker enum { 17*8617a60dSAndroid Build Coastguard Worker GPT_SUCCESS = 0, 18*8617a60dSAndroid Build Coastguard Worker GPT_ERROR_NO_VALID_KERNEL, 19*8617a60dSAndroid Build Coastguard Worker GPT_ERROR_INVALID_HEADERS, 20*8617a60dSAndroid Build Coastguard Worker GPT_ERROR_INVALID_ENTRIES, 21*8617a60dSAndroid Build Coastguard Worker GPT_ERROR_INVALID_SECTOR_SIZE, 22*8617a60dSAndroid Build Coastguard Worker GPT_ERROR_INVALID_SECTOR_NUMBER, 23*8617a60dSAndroid Build Coastguard Worker GPT_ERROR_INVALID_UPDATE_TYPE, 24*8617a60dSAndroid Build Coastguard Worker GPT_ERROR_CRC_CORRUPTED, 25*8617a60dSAndroid Build Coastguard Worker GPT_ERROR_OUT_OF_REGION, 26*8617a60dSAndroid Build Coastguard Worker GPT_ERROR_START_LBA_OVERLAP, 27*8617a60dSAndroid Build Coastguard Worker GPT_ERROR_END_LBA_OVERLAP, 28*8617a60dSAndroid Build Coastguard Worker GPT_ERROR_DUP_GUID, 29*8617a60dSAndroid Build Coastguard Worker GPT_ERROR_INVALID_FLASH_GEOMETRY, 30*8617a60dSAndroid Build Coastguard Worker GPT_ERROR_NO_SUCH_ENTRY, 31*8617a60dSAndroid Build Coastguard Worker /* Number of errors */ 32*8617a60dSAndroid Build Coastguard Worker GPT_ERROR_COUNT 33*8617a60dSAndroid Build Coastguard Worker }; 34*8617a60dSAndroid Build Coastguard Worker 35*8617a60dSAndroid Build Coastguard Worker /* Bit masks for GptData.modified field. */ 36*8617a60dSAndroid Build Coastguard Worker #define GPT_MODIFIED_HEADER1 0x01 37*8617a60dSAndroid Build Coastguard Worker #define GPT_MODIFIED_HEADER2 0x02 38*8617a60dSAndroid Build Coastguard Worker #define GPT_MODIFIED_ENTRIES1 0x04 39*8617a60dSAndroid Build Coastguard Worker #define GPT_MODIFIED_ENTRIES2 0x08 40*8617a60dSAndroid Build Coastguard Worker 41*8617a60dSAndroid Build Coastguard Worker /* 42*8617a60dSAndroid Build Coastguard Worker * The 'update_type' of GptUpdateKernelEntry(). We expose TRY and BAD only 43*8617a60dSAndroid Build Coastguard Worker * because those are what verified boot needs. For more precise control on GPT 44*8617a60dSAndroid Build Coastguard Worker * attribute bits, please refer to gpt_internal.h. 45*8617a60dSAndroid Build Coastguard Worker */ 46*8617a60dSAndroid Build Coastguard Worker enum { 47*8617a60dSAndroid Build Coastguard Worker /* 48*8617a60dSAndroid Build Coastguard Worker * System will be trying to boot the currently selected kernel 49*8617a60dSAndroid Build Coastguard Worker * partition. Update its try count if necessary. 50*8617a60dSAndroid Build Coastguard Worker */ 51*8617a60dSAndroid Build Coastguard Worker GPT_UPDATE_ENTRY_TRY = 1, 52*8617a60dSAndroid Build Coastguard Worker /* 53*8617a60dSAndroid Build Coastguard Worker * The currently selected kernel partition failed validation. Mark 54*8617a60dSAndroid Build Coastguard Worker * entry as invalid. 55*8617a60dSAndroid Build Coastguard Worker */ 56*8617a60dSAndroid Build Coastguard Worker GPT_UPDATE_ENTRY_BAD = 2, 57*8617a60dSAndroid Build Coastguard Worker /* 58*8617a60dSAndroid Build Coastguard Worker * Used for fastboot mode. If kernel partition slot is marked active, 59*8617a60dSAndroid Build Coastguard Worker * its GPT entry is marked with S1,P2,T0. 60*8617a60dSAndroid Build Coastguard Worker */ 61*8617a60dSAndroid Build Coastguard Worker GPT_UPDATE_ENTRY_ACTIVE = 3, 62*8617a60dSAndroid Build Coastguard Worker /* 63*8617a60dSAndroid Build Coastguard Worker * Used for fastboot mode. If kernel partition slot is marked invalid, 64*8617a60dSAndroid Build Coastguard Worker * its GPT entry is marked with S0,P0,T0. 65*8617a60dSAndroid Build Coastguard Worker */ 66*8617a60dSAndroid Build Coastguard Worker GPT_UPDATE_ENTRY_INVALID = 4, 67*8617a60dSAndroid Build Coastguard Worker }; 68*8617a60dSAndroid Build Coastguard Worker 69*8617a60dSAndroid Build Coastguard Worker /* If this bit is 1, the GPT is stored in another from the streaming data */ 70*8617a60dSAndroid Build Coastguard Worker #define GPT_FLAG_EXTERNAL 0x1 71*8617a60dSAndroid Build Coastguard Worker 72*8617a60dSAndroid Build Coastguard Worker /* 73*8617a60dSAndroid Build Coastguard Worker * A note about stored_on_device and gpt_drive_sectors: 74*8617a60dSAndroid Build Coastguard Worker * 75*8617a60dSAndroid Build Coastguard Worker * This code is used by both the "cgpt" utility and depthcharge/vboot. ATM, 76*8617a60dSAndroid Build Coastguard Worker * depthcharge does not have logic to properly setup stored_on_device and 77*8617a60dSAndroid Build Coastguard Worker * gpt_drive_sectors, but it does do a memset(gpt, 0, sizeof(GptData)). And so, 78*8617a60dSAndroid Build Coastguard Worker * GPT_STORED_ON_DEVICE should be 0 to make stored_on_device compatible with 79*8617a60dSAndroid Build Coastguard Worker * present behavior. At the same time, in vb2api_load_kernel() and GptLoad(), 80*8617a60dSAndroid Build Coastguard Worker * we need to have simple shims to set gpt_drive_sectors to drive_sectors. 81*8617a60dSAndroid Build Coastguard Worker * 82*8617a60dSAndroid Build Coastguard Worker * TODO(namnguyen): Remove those shims when the firmware can set these fields. 83*8617a60dSAndroid Build Coastguard Worker */ 84*8617a60dSAndroid Build Coastguard Worker typedef struct { 85*8617a60dSAndroid Build Coastguard Worker /* Fill in the following fields before calling GptInit() */ 86*8617a60dSAndroid Build Coastguard Worker /* GPT primary header, from sector 1 of disk (size: 512 bytes) */ 87*8617a60dSAndroid Build Coastguard Worker uint8_t *primary_header; 88*8617a60dSAndroid Build Coastguard Worker /* GPT secondary header, from last sector of disk (size: 512 bytes) */ 89*8617a60dSAndroid Build Coastguard Worker uint8_t *secondary_header; 90*8617a60dSAndroid Build Coastguard Worker /* Primary GPT table, follows primary header */ 91*8617a60dSAndroid Build Coastguard Worker uint8_t *primary_entries; 92*8617a60dSAndroid Build Coastguard Worker /* Secondary GPT table, precedes secondary header */ 93*8617a60dSAndroid Build Coastguard Worker uint8_t *secondary_entries; 94*8617a60dSAndroid Build Coastguard Worker /* Size of a LBA sector, in bytes */ 95*8617a60dSAndroid Build Coastguard Worker uint32_t sector_bytes; 96*8617a60dSAndroid Build Coastguard Worker /* Size of drive (that the partitions are on) in LBA sectors */ 97*8617a60dSAndroid Build Coastguard Worker uint64_t streaming_drive_sectors; 98*8617a60dSAndroid Build Coastguard Worker /* Size of the device that holds the GPT structures, 512-byte sectors */ 99*8617a60dSAndroid Build Coastguard Worker uint64_t gpt_drive_sectors; 100*8617a60dSAndroid Build Coastguard Worker /* Flags */ 101*8617a60dSAndroid Build Coastguard Worker uint32_t flags; 102*8617a60dSAndroid Build Coastguard Worker 103*8617a60dSAndroid Build Coastguard Worker /* Outputs */ 104*8617a60dSAndroid Build Coastguard Worker /* Which inputs have been modified? GPT_MODIFIED_* */ 105*8617a60dSAndroid Build Coastguard Worker uint8_t modified; 106*8617a60dSAndroid Build Coastguard Worker /* 107*8617a60dSAndroid Build Coastguard Worker * The current chromeos kernel index in partition table. -1 means not 108*8617a60dSAndroid Build Coastguard Worker * found on drive. Note that GPT partition numbers are traditionally 109*8617a60dSAndroid Build Coastguard Worker * 1-based, but we're using a zero-based index here. 110*8617a60dSAndroid Build Coastguard Worker */ 111*8617a60dSAndroid Build Coastguard Worker int current_kernel; 112*8617a60dSAndroid Build Coastguard Worker 113*8617a60dSAndroid Build Coastguard Worker /* Internal variables */ 114*8617a60dSAndroid Build Coastguard Worker uint8_t valid_headers, valid_entries, ignored; 115*8617a60dSAndroid Build Coastguard Worker int current_priority; 116*8617a60dSAndroid Build Coastguard Worker } GptData; 117*8617a60dSAndroid Build Coastguard Worker 118*8617a60dSAndroid Build Coastguard Worker /** 119*8617a60dSAndroid Build Coastguard Worker * Initializes the GPT data structure's internal state. 120*8617a60dSAndroid Build Coastguard Worker * 121*8617a60dSAndroid Build Coastguard Worker * The following fields must be filled before calling this function: 122*8617a60dSAndroid Build Coastguard Worker * 123*8617a60dSAndroid Build Coastguard Worker * primary_header 124*8617a60dSAndroid Build Coastguard Worker * secondary_header 125*8617a60dSAndroid Build Coastguard Worker * primary_entries 126*8617a60dSAndroid Build Coastguard Worker * secondary_entries 127*8617a60dSAndroid Build Coastguard Worker * sector_bytes 128*8617a60dSAndroid Build Coastguard Worker * drive_sectors 129*8617a60dSAndroid Build Coastguard Worker * stored_on_device 130*8617a60dSAndroid Build Coastguard Worker * gpt_device_sectors 131*8617a60dSAndroid Build Coastguard Worker * 132*8617a60dSAndroid Build Coastguard Worker * On return the modified field may be set, if the GPT data has been modified 133*8617a60dSAndroid Build Coastguard Worker * and should be written to disk. 134*8617a60dSAndroid Build Coastguard Worker * 135*8617a60dSAndroid Build Coastguard Worker * Returns GPT_SUCCESS if successful, non-zero if error: 136*8617a60dSAndroid Build Coastguard Worker * GPT_ERROR_INVALID_HEADERS, both partition table headers are invalid, enters 137*8617a60dSAndroid Build Coastguard Worker * recovery mode, 138*8617a60dSAndroid Build Coastguard Worker * GPT_ERROR_INVALID_ENTRIES, both partition table entries are invalid, enters 139*8617a60dSAndroid Build Coastguard Worker * recovery mode, 140*8617a60dSAndroid Build Coastguard Worker * GPT_ERROR_INVALID_SECTOR_SIZE, size of a sector is not supported, 141*8617a60dSAndroid Build Coastguard Worker * GPT_ERROR_INVALID_SECTOR_NUMBER, number of sectors in drive is invalid (too 142*8617a60dSAndroid Build Coastguard Worker * small) */ 143*8617a60dSAndroid Build Coastguard Worker int GptInit(GptData *gpt); 144*8617a60dSAndroid Build Coastguard Worker 145*8617a60dSAndroid Build Coastguard Worker /** 146*8617a60dSAndroid Build Coastguard Worker * Return the nth instance of parition entry matching the partition type guid 147*8617a60dSAndroid Build Coastguard Worker * from the gpt table. Instance value starts from 0. If the entry is not found, 148*8617a60dSAndroid Build Coastguard Worker * it returns NULL. 149*8617a60dSAndroid Build Coastguard Worker */ 150*8617a60dSAndroid Build Coastguard Worker GptEntry *GptFindNthEntry(GptData *gpt, const Guid *guid, unsigned int n); 151*8617a60dSAndroid Build Coastguard Worker 152*8617a60dSAndroid Build Coastguard Worker /** 153*8617a60dSAndroid Build Coastguard Worker * Allocate and read GPT data from the drive. The sector_bytes and 154*8617a60dSAndroid Build Coastguard Worker * drive_sectors fields should be filled on input. The primary and secondary 155*8617a60dSAndroid Build Coastguard Worker * header and entries are filled on output. 156*8617a60dSAndroid Build Coastguard Worker * 157*8617a60dSAndroid Build Coastguard Worker * Returns 0 if successful, 1 if error. 158*8617a60dSAndroid Build Coastguard Worker */ 159*8617a60dSAndroid Build Coastguard Worker int AllocAndReadGptData(vb2ex_disk_handle_t disk_handle, GptData *gptdata); 160*8617a60dSAndroid Build Coastguard Worker 161*8617a60dSAndroid Build Coastguard Worker /** 162*8617a60dSAndroid Build Coastguard Worker * Write any changes for the GPT data back to the drive, then free the buffers. 163*8617a60dSAndroid Build Coastguard Worker */ 164*8617a60dSAndroid Build Coastguard Worker int WriteAndFreeGptData(vb2ex_disk_handle_t disk_handle, GptData *gptdata); 165*8617a60dSAndroid Build Coastguard Worker 166*8617a60dSAndroid Build Coastguard Worker /** 167*8617a60dSAndroid Build Coastguard Worker * Return 1 if the entry is unused, 0 if it is used. 168*8617a60dSAndroid Build Coastguard Worker */ 169*8617a60dSAndroid Build Coastguard Worker int IsUnusedEntry(const GptEntry *e); 170*8617a60dSAndroid Build Coastguard Worker 171*8617a60dSAndroid Build Coastguard Worker /** 172*8617a60dSAndroid Build Coastguard Worker * Return size(in lba) of a partition represented by given GPT entry. 173*8617a60dSAndroid Build Coastguard Worker */ 174*8617a60dSAndroid Build Coastguard Worker uint64_t GptGetEntrySizeLba(const GptEntry *e); 175*8617a60dSAndroid Build Coastguard Worker 176*8617a60dSAndroid Build Coastguard Worker /** 177*8617a60dSAndroid Build Coastguard Worker * Return size(in bytes) of a partition represented by given GPT entry. 178*8617a60dSAndroid Build Coastguard Worker */ 179*8617a60dSAndroid Build Coastguard Worker uint64_t GptGetEntrySizeBytes(const GptData *gpt, const GptEntry *e); 180*8617a60dSAndroid Build Coastguard Worker 181*8617a60dSAndroid Build Coastguard Worker /** 182*8617a60dSAndroid Build Coastguard Worker * Updates the kernel entry with the specified index, using the specified type 183*8617a60dSAndroid Build Coastguard Worker * of update (GPT_UPDATE_ENTRY_*). 184*8617a60dSAndroid Build Coastguard Worker * 185*8617a60dSAndroid Build Coastguard Worker * On return the modified field may be set, if the GPT data has been modified 186*8617a60dSAndroid Build Coastguard Worker * and should be written to disk. 187*8617a60dSAndroid Build Coastguard Worker * 188*8617a60dSAndroid Build Coastguard Worker * Returns GPT_SUCCESS if successful, else 189*8617a60dSAndroid Build Coastguard Worker * GPT_ERROR_INVALID_UPDATE_TYPE, invalid 'update_type' is given. 190*8617a60dSAndroid Build Coastguard Worker */ 191*8617a60dSAndroid Build Coastguard Worker int GptUpdateKernelWithEntry(GptData *gpt, GptEntry *e, uint32_t update_type); 192*8617a60dSAndroid Build Coastguard Worker 193*8617a60dSAndroid Build Coastguard Worker /** 194*8617a60dSAndroid Build Coastguard Worker * Updates the kernel entry identified by current_kernel field. If 195*8617a60dSAndroid Build Coastguard Worker * current_kernel is not set it returns an error. 196*8617a60dSAndroid Build Coastguard Worker * 197*8617a60dSAndroid Build Coastguard Worker * Returns GPT_SUCCESS if successful, else 198*8617a60dSAndroid Build Coastguard Worker * GPT_ERROR_INVALID_UPDATE_TYPE, invalid 'update_type' is given. 199*8617a60dSAndroid Build Coastguard Worker */ 200*8617a60dSAndroid Build Coastguard Worker int GptUpdateKernelEntry(GptData *gpt, uint32_t update_type); 201*8617a60dSAndroid Build Coastguard Worker 202*8617a60dSAndroid Build Coastguard Worker /* Getters and setters for partition attribute fields. */ 203*8617a60dSAndroid Build Coastguard Worker 204*8617a60dSAndroid Build Coastguard Worker int GetEntryRequired(const GptEntry *e); 205*8617a60dSAndroid Build Coastguard Worker int GetEntryLegacyBoot(const GptEntry *e); 206*8617a60dSAndroid Build Coastguard Worker int GetEntrySuccessful(const GptEntry *e); 207*8617a60dSAndroid Build Coastguard Worker int GetEntryPriority(const GptEntry *e); 208*8617a60dSAndroid Build Coastguard Worker int GetEntryTries(const GptEntry *e); 209*8617a60dSAndroid Build Coastguard Worker int GetEntryErrorCounter(const GptEntry *e); 210*8617a60dSAndroid Build Coastguard Worker void SetEntryRequired(GptEntry *e, int required); 211*8617a60dSAndroid Build Coastguard Worker void SetEntryLegacyBoot(GptEntry *e, int legacy_boot); 212*8617a60dSAndroid Build Coastguard Worker void SetEntrySuccessful(GptEntry *e, int successful); 213*8617a60dSAndroid Build Coastguard Worker void SetEntryPriority(GptEntry *e, int priority); 214*8617a60dSAndroid Build Coastguard Worker void SetEntryTries(GptEntry *e, int tries); 215*8617a60dSAndroid Build Coastguard Worker void SetEntryErrorCounter(GptEntry *e, int error_counter); 216*8617a60dSAndroid Build Coastguard Worker 217*8617a60dSAndroid Build Coastguard Worker #ifdef __cplusplus 218*8617a60dSAndroid Build Coastguard Worker } 219*8617a60dSAndroid Build Coastguard Worker #endif /* __cplusplus */ 220*8617a60dSAndroid Build Coastguard Worker 221*8617a60dSAndroid Build Coastguard Worker #endif /* VBOOT_REFERENCE_GPT_MISC_H_ */ 222