1 /* 2 * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <inttypes.h> 9 #include <stdio.h> 10 #include <string.h> 11 12 #include <common/debug.h> 13 #include <common/tf_crc32.h> 14 #include <drivers/io/io_storage.h> 15 #include <drivers/partition/efi.h> 16 #include <drivers/partition/partition.h> 17 #include <drivers/partition/gpt.h> 18 #include <drivers/partition/mbr.h> 19 #include <plat/common/platform.h> 20 21 static uint8_t mbr_sector[PLAT_PARTITION_BLOCK_SIZE]; 22 static partition_entry_list_t list; 23 24 #if LOG_LEVEL >= LOG_LEVEL_VERBOSE 25 static void dump_entries(int num) 26 { 27 char name[EFI_NAMELEN]; 28 int i, j, len; 29 30 VERBOSE("Partition table with %d entries:\n", num); 31 for (i = 0; i < num; i++) { 32 len = snprintf(name, EFI_NAMELEN, "%s", list.list[i].name); 33 for (j = 0; j < EFI_NAMELEN - len - 1; j++) { 34 name[len + j] = ' '; 35 } 36 name[EFI_NAMELEN - 1] = '\0'; 37 VERBOSE("%d: %s %" PRIx64 "-%" PRIx64 "\n", i + 1, name, list.list[i].start, 38 list.list[i].start + list.list[i].length - 4); 39 } 40 } 41 #else 42 #define dump_entries(num) ((void)num) 43 #endif 44 45 /* 46 * Load the first sector that carries MBR header. 47 * The MBR boot signature should be always valid whether it's MBR or GPT. 48 */ 49 static int load_mbr_header(uintptr_t image_handle, mbr_entry_t *mbr_entry) 50 { 51 size_t bytes_read; 52 uintptr_t offset; 53 int result; 54 55 assert(mbr_entry != NULL); 56 /* MBR partition table is in LBA0. */ 57 result = io_seek(image_handle, IO_SEEK_SET, MBR_OFFSET); 58 if (result != 0) { 59 WARN("Failed to seek (%i)\n", result); 60 return result; 61 } 62 result = io_read(image_handle, (uintptr_t)&mbr_sector, 63 PLAT_PARTITION_BLOCK_SIZE, &bytes_read); 64 if (result != 0) { 65 WARN("Failed to read data (%i)\n", result); 66 return result; 67 } 68 69 /* Check MBR boot signature. */ 70 if ((mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 2] != MBR_SIGNATURE_FIRST) || 71 (mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 1] != MBR_SIGNATURE_SECOND)) { 72 return -ENOENT; 73 } 74 offset = (uintptr_t)&mbr_sector + MBR_PRIMARY_ENTRY_OFFSET; 75 memcpy(mbr_entry, (void *)offset, sizeof(mbr_entry_t)); 76 return 0; 77 } 78 79 /* 80 * Load GPT header and check the GPT signature and header CRC. 81 * If partition numbers could be found, check & update it. 82 */ 83 static int load_gpt_header(uintptr_t image_handle) 84 { 85 gpt_header_t header; 86 size_t bytes_read; 87 int result; 88 uint32_t header_crc, calc_crc; 89 90 result = io_seek(image_handle, IO_SEEK_SET, GPT_HEADER_OFFSET); 91 if (result != 0) { 92 return result; 93 } 94 result = io_read(image_handle, (uintptr_t)&header, 95 sizeof(gpt_header_t), &bytes_read); 96 if ((result != 0) || (sizeof(gpt_header_t) != bytes_read)) { 97 return result; 98 } 99 if (memcmp(header.signature, GPT_SIGNATURE, 100 sizeof(header.signature)) != 0) { 101 return -EINVAL; 102 } 103 104 /* 105 * UEFI Spec 2.8 March 2019 Page 119: HeaderCRC32 value is 106 * computed by setting this field to 0, and computing the 107 * 32-bit CRC for HeaderSize bytes. 108 */ 109 header_crc = header.header_crc; 110 header.header_crc = 0U; 111 112 calc_crc = tf_crc32(0U, (uint8_t *)&header, DEFAULT_GPT_HEADER_SIZE); 113 if (header_crc != calc_crc) { 114 ERROR("Invalid GPT Header CRC: Expected 0x%x but got 0x%x.\n", 115 header_crc, calc_crc); 116 return -EINVAL; 117 } 118 119 header.header_crc = header_crc; 120 121 /* partition numbers can't exceed PLAT_PARTITION_MAX_ENTRIES */ 122 list.entry_count = header.list_num; 123 if (list.entry_count > PLAT_PARTITION_MAX_ENTRIES) { 124 list.entry_count = PLAT_PARTITION_MAX_ENTRIES; 125 } 126 return 0; 127 } 128 129 static int load_mbr_entry(uintptr_t image_handle, mbr_entry_t *mbr_entry, 130 int part_number) 131 { 132 size_t bytes_read; 133 uintptr_t offset; 134 int result; 135 136 assert(mbr_entry != NULL); 137 /* MBR partition table is in LBA0. */ 138 result = io_seek(image_handle, IO_SEEK_SET, MBR_OFFSET); 139 if (result != 0) { 140 WARN("Failed to seek (%i)\n", result); 141 return result; 142 } 143 result = io_read(image_handle, (uintptr_t)&mbr_sector, 144 PLAT_PARTITION_BLOCK_SIZE, &bytes_read); 145 if (result != 0) { 146 WARN("Failed to read data (%i)\n", result); 147 return result; 148 } 149 150 /* Check MBR boot signature. */ 151 if ((mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 2] != MBR_SIGNATURE_FIRST) || 152 (mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 1] != MBR_SIGNATURE_SECOND)) { 153 return -ENOENT; 154 } 155 offset = (uintptr_t)&mbr_sector + 156 MBR_PRIMARY_ENTRY_OFFSET + 157 MBR_PRIMARY_ENTRY_SIZE * part_number; 158 memcpy(mbr_entry, (void *)offset, sizeof(mbr_entry_t)); 159 160 return 0; 161 } 162 163 static int load_mbr_entries(uintptr_t image_handle) 164 { 165 mbr_entry_t mbr_entry; 166 int i; 167 168 list.entry_count = MBR_PRIMARY_ENTRY_NUMBER; 169 170 for (i = 0; i < list.entry_count; i++) { 171 load_mbr_entry(image_handle, &mbr_entry, i); 172 list.list[i].start = mbr_entry.first_lba * 512; 173 list.list[i].length = mbr_entry.sector_nums * 512; 174 list.list[i].name[0] = mbr_entry.type; 175 } 176 177 return 0; 178 } 179 180 static int load_gpt_entry(uintptr_t image_handle, gpt_entry_t *entry) 181 { 182 size_t bytes_read; 183 int result; 184 185 assert(entry != NULL); 186 result = io_read(image_handle, (uintptr_t)entry, sizeof(gpt_entry_t), 187 &bytes_read); 188 if (sizeof(gpt_entry_t) != bytes_read) 189 return -EINVAL; 190 return result; 191 } 192 193 static int verify_partition_gpt(uintptr_t image_handle) 194 { 195 gpt_entry_t entry; 196 int result, i; 197 198 for (i = 0; i < list.entry_count; i++) { 199 result = load_gpt_entry(image_handle, &entry); 200 assert(result == 0); 201 result = parse_gpt_entry(&entry, &list.list[i]); 202 if (result != 0) { 203 break; 204 } 205 } 206 if (i == 0) { 207 return -EINVAL; 208 } 209 /* 210 * Only records the valid partition number that is loaded from 211 * partition table. 212 */ 213 list.entry_count = i; 214 dump_entries(list.entry_count); 215 216 return 0; 217 } 218 219 int load_partition_table(unsigned int image_id) 220 { 221 uintptr_t dev_handle, image_handle, image_spec = 0; 222 mbr_entry_t mbr_entry; 223 int result; 224 225 result = plat_get_image_source(image_id, &dev_handle, &image_spec); 226 if (result != 0) { 227 WARN("Failed to obtain reference to image id=%u (%i)\n", 228 image_id, result); 229 return result; 230 } 231 232 result = io_open(dev_handle, image_spec, &image_handle); 233 if (result != 0) { 234 WARN("Failed to access image id=%u (%i)\n", image_id, result); 235 return result; 236 } 237 238 result = load_mbr_header(image_handle, &mbr_entry); 239 if (result != 0) { 240 WARN("Failed to access image id=%u (%i)\n", image_id, result); 241 return result; 242 } 243 if (mbr_entry.type == PARTITION_TYPE_GPT) { 244 result = load_gpt_header(image_handle); 245 assert(result == 0); 246 result = io_seek(image_handle, IO_SEEK_SET, GPT_ENTRY_OFFSET); 247 assert(result == 0); 248 result = verify_partition_gpt(image_handle); 249 } else { 250 result = load_mbr_entries(image_handle); 251 } 252 253 io_close(image_handle); 254 return result; 255 } 256 257 const partition_entry_t *get_partition_entry(const char *name) 258 { 259 int i; 260 261 for (i = 0; i < list.entry_count; i++) { 262 if (strcmp(name, list.list[i].name) == 0) { 263 return &list.list[i]; 264 } 265 } 266 return NULL; 267 } 268 269 const partition_entry_t *get_partition_entry_by_type(const uuid_t *type_uuid) 270 { 271 int i; 272 273 for (i = 0; i < list.entry_count; i++) { 274 if (guidcmp(type_uuid, &list.list[i].type_guid) == 0) { 275 return &list.list[i]; 276 } 277 } 278 279 return NULL; 280 } 281 282 const partition_entry_t *get_partition_entry_by_uuid(const uuid_t *part_uuid) 283 { 284 int i; 285 286 for (i = 0; i < list.entry_count; i++) { 287 if (guidcmp(part_uuid, &list.list[i].part_guid) == 0) { 288 return &list.list[i]; 289 } 290 } 291 292 return NULL; 293 } 294 295 const partition_entry_list_t *get_partition_entry_list(void) 296 { 297 return &list; 298 } 299 300 void partition_init(unsigned int image_id) 301 { 302 load_partition_table(image_id); 303 } 304