1*201b66b7SHaojian Zhuang /* 2*201b66b7SHaojian Zhuang * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. 3*201b66b7SHaojian Zhuang * 4*201b66b7SHaojian Zhuang * Redistribution and use in source and binary forms, with or without 5*201b66b7SHaojian Zhuang * modification, are permitted provided that the following conditions are met: 6*201b66b7SHaojian Zhuang * 7*201b66b7SHaojian Zhuang * Redistributions of source code must retain the above copyright notice, this 8*201b66b7SHaojian Zhuang * list of conditions and the following disclaimer. 9*201b66b7SHaojian Zhuang * 10*201b66b7SHaojian Zhuang * Redistributions in binary form must reproduce the above copyright notice, 11*201b66b7SHaojian Zhuang * this list of conditions and the following disclaimer in the documentation 12*201b66b7SHaojian Zhuang * and/or other materials provided with the distribution. 13*201b66b7SHaojian Zhuang * 14*201b66b7SHaojian Zhuang * Neither the name of ARM nor the names of its contributors may be used 15*201b66b7SHaojian Zhuang * to endorse or promote products derived from this software without specific 16*201b66b7SHaojian Zhuang * prior written permission. 17*201b66b7SHaojian Zhuang * 18*201b66b7SHaojian Zhuang * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19*201b66b7SHaojian Zhuang * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20*201b66b7SHaojian Zhuang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21*201b66b7SHaojian Zhuang * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22*201b66b7SHaojian Zhuang * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23*201b66b7SHaojian Zhuang * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24*201b66b7SHaojian Zhuang * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25*201b66b7SHaojian Zhuang * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26*201b66b7SHaojian Zhuang * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27*201b66b7SHaojian Zhuang * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28*201b66b7SHaojian Zhuang * POSSIBILITY OF SUCH DAMAGE. 29*201b66b7SHaojian Zhuang */ 30*201b66b7SHaojian Zhuang 31*201b66b7SHaojian Zhuang #include <assert.h> 32*201b66b7SHaojian Zhuang #include <debug.h> 33*201b66b7SHaojian Zhuang #include <io_storage.h> 34*201b66b7SHaojian Zhuang #include <gpt.h> 35*201b66b7SHaojian Zhuang #include <mbr.h> 36*201b66b7SHaojian Zhuang #include <partition.h> 37*201b66b7SHaojian Zhuang #include <platform.h> 38*201b66b7SHaojian Zhuang #include <string.h> 39*201b66b7SHaojian Zhuang 40*201b66b7SHaojian Zhuang static uint8_t mbr_sector[PARTITION_BLOCK_SIZE]; 41*201b66b7SHaojian Zhuang partition_entry_list_t list; 42*201b66b7SHaojian Zhuang 43*201b66b7SHaojian Zhuang #if LOG_LEVEL >= LOG_LEVEL_VERBOSE 44*201b66b7SHaojian Zhuang static void dump_entries(int num) 45*201b66b7SHaojian Zhuang { 46*201b66b7SHaojian Zhuang char name[EFI_NAMELEN]; 47*201b66b7SHaojian Zhuang int i, j, len; 48*201b66b7SHaojian Zhuang 49*201b66b7SHaojian Zhuang VERBOSE("Partition table with %d entries:\n", num); 50*201b66b7SHaojian Zhuang for (i = 0; i < num; i++) { 51*201b66b7SHaojian Zhuang len = snprintf(name, EFI_NAMELEN, "%s", list.list[i].name); 52*201b66b7SHaojian Zhuang for (j = 0; j < EFI_NAMELEN - len - 1; j++) { 53*201b66b7SHaojian Zhuang name[len + j] = ' '; 54*201b66b7SHaojian Zhuang } 55*201b66b7SHaojian Zhuang name[EFI_NAMELEN - 1] = '\0'; 56*201b66b7SHaojian Zhuang VERBOSE("%d: %s %lx-%lx\n", i + 1, name, list.list[i].start, 57*201b66b7SHaojian Zhuang list.list[i].start + list.list[i].length - 4); 58*201b66b7SHaojian Zhuang } 59*201b66b7SHaojian Zhuang } 60*201b66b7SHaojian Zhuang #else 61*201b66b7SHaojian Zhuang #define dump_entries(num) ((void)num) 62*201b66b7SHaojian Zhuang #endif 63*201b66b7SHaojian Zhuang 64*201b66b7SHaojian Zhuang /* 65*201b66b7SHaojian Zhuang * Load the first sector that carries MBR header. 66*201b66b7SHaojian Zhuang * The MBR boot signature should be always valid whether it's MBR or GPT. 67*201b66b7SHaojian Zhuang */ 68*201b66b7SHaojian Zhuang static int load_mbr_header(uintptr_t image_handle, mbr_entry_t *mbr_entry) 69*201b66b7SHaojian Zhuang { 70*201b66b7SHaojian Zhuang size_t bytes_read; 71*201b66b7SHaojian Zhuang uintptr_t offset; 72*201b66b7SHaojian Zhuang int result; 73*201b66b7SHaojian Zhuang 74*201b66b7SHaojian Zhuang assert(mbr_entry != NULL); 75*201b66b7SHaojian Zhuang /* MBR partition table is in LBA0. */ 76*201b66b7SHaojian Zhuang result = io_seek(image_handle, IO_SEEK_SET, MBR_OFFSET); 77*201b66b7SHaojian Zhuang if (result != 0) { 78*201b66b7SHaojian Zhuang WARN("Failed to seek (%i)\n", result); 79*201b66b7SHaojian Zhuang return result; 80*201b66b7SHaojian Zhuang } 81*201b66b7SHaojian Zhuang result = io_read(image_handle, (uintptr_t)&mbr_sector, 82*201b66b7SHaojian Zhuang PARTITION_BLOCK_SIZE, &bytes_read); 83*201b66b7SHaojian Zhuang if (result != 0) { 84*201b66b7SHaojian Zhuang WARN("Failed to read data (%i)\n", result); 85*201b66b7SHaojian Zhuang return result; 86*201b66b7SHaojian Zhuang } 87*201b66b7SHaojian Zhuang 88*201b66b7SHaojian Zhuang /* Check MBR boot signature. */ 89*201b66b7SHaojian Zhuang if ((mbr_sector[PARTITION_BLOCK_SIZE - 2] != MBR_SIGNATURE_FIRST) || 90*201b66b7SHaojian Zhuang (mbr_sector[PARTITION_BLOCK_SIZE - 1] != MBR_SIGNATURE_SECOND)) { 91*201b66b7SHaojian Zhuang return -ENOENT; 92*201b66b7SHaojian Zhuang } 93*201b66b7SHaojian Zhuang offset = (uintptr_t)&mbr_sector + MBR_PRIMARY_ENTRY_OFFSET; 94*201b66b7SHaojian Zhuang memcpy(mbr_entry, (void *)offset, sizeof(mbr_entry_t)); 95*201b66b7SHaojian Zhuang return 0; 96*201b66b7SHaojian Zhuang } 97*201b66b7SHaojian Zhuang 98*201b66b7SHaojian Zhuang /* 99*201b66b7SHaojian Zhuang * Load GPT header and check the GPT signature. 100*201b66b7SHaojian Zhuang * If partiton numbers could be found, check & update it. 101*201b66b7SHaojian Zhuang */ 102*201b66b7SHaojian Zhuang static int load_gpt_header(uintptr_t image_handle) 103*201b66b7SHaojian Zhuang { 104*201b66b7SHaojian Zhuang gpt_header_t header; 105*201b66b7SHaojian Zhuang size_t bytes_read; 106*201b66b7SHaojian Zhuang int result; 107*201b66b7SHaojian Zhuang 108*201b66b7SHaojian Zhuang result = io_seek(image_handle, IO_SEEK_SET, GPT_HEADER_OFFSET); 109*201b66b7SHaojian Zhuang if (result != 0) { 110*201b66b7SHaojian Zhuang return result; 111*201b66b7SHaojian Zhuang } 112*201b66b7SHaojian Zhuang result = io_read(image_handle, (uintptr_t)&header, 113*201b66b7SHaojian Zhuang sizeof(gpt_header_t), &bytes_read); 114*201b66b7SHaojian Zhuang if ((result != 0) || (sizeof(gpt_header_t) != bytes_read)) { 115*201b66b7SHaojian Zhuang return result; 116*201b66b7SHaojian Zhuang } 117*201b66b7SHaojian Zhuang if (memcmp(header.signature, GPT_SIGNATURE, 118*201b66b7SHaojian Zhuang sizeof(header.signature)) != 0) { 119*201b66b7SHaojian Zhuang return -EINVAL; 120*201b66b7SHaojian Zhuang } 121*201b66b7SHaojian Zhuang 122*201b66b7SHaojian Zhuang /* partition numbers can't exceed PLAT_PARTITION_MAX_ENTRIES */ 123*201b66b7SHaojian Zhuang list.entry_count = header.list_num; 124*201b66b7SHaojian Zhuang if (list.entry_count > PLAT_PARTITION_MAX_ENTRIES) { 125*201b66b7SHaojian Zhuang list.entry_count = PLAT_PARTITION_MAX_ENTRIES; 126*201b66b7SHaojian Zhuang } 127*201b66b7SHaojian Zhuang return 0; 128*201b66b7SHaojian Zhuang } 129*201b66b7SHaojian Zhuang 130*201b66b7SHaojian Zhuang static int load_gpt_entry(uintptr_t image_handle, gpt_entry_t *entry) 131*201b66b7SHaojian Zhuang { 132*201b66b7SHaojian Zhuang size_t bytes_read; 133*201b66b7SHaojian Zhuang int result; 134*201b66b7SHaojian Zhuang 135*201b66b7SHaojian Zhuang assert(entry != NULL); 136*201b66b7SHaojian Zhuang result = io_read(image_handle, (uintptr_t)entry, sizeof(gpt_entry_t), 137*201b66b7SHaojian Zhuang &bytes_read); 138*201b66b7SHaojian Zhuang if (sizeof(gpt_entry_t) != bytes_read) 139*201b66b7SHaojian Zhuang return -EINVAL; 140*201b66b7SHaojian Zhuang return result; 141*201b66b7SHaojian Zhuang } 142*201b66b7SHaojian Zhuang 143*201b66b7SHaojian Zhuang static int verify_partition_gpt(uintptr_t image_handle) 144*201b66b7SHaojian Zhuang { 145*201b66b7SHaojian Zhuang gpt_entry_t entry; 146*201b66b7SHaojian Zhuang int result, i; 147*201b66b7SHaojian Zhuang 148*201b66b7SHaojian Zhuang for (i = 0; i < list.entry_count; i++) { 149*201b66b7SHaojian Zhuang result = load_gpt_entry(image_handle, &entry); 150*201b66b7SHaojian Zhuang assert(result == 0); 151*201b66b7SHaojian Zhuang result = parse_gpt_entry(&entry, &list.list[i]); 152*201b66b7SHaojian Zhuang if (result != 0) { 153*201b66b7SHaojian Zhuang break; 154*201b66b7SHaojian Zhuang } 155*201b66b7SHaojian Zhuang } 156*201b66b7SHaojian Zhuang if (i == 0) { 157*201b66b7SHaojian Zhuang return -EINVAL; 158*201b66b7SHaojian Zhuang } 159*201b66b7SHaojian Zhuang /* 160*201b66b7SHaojian Zhuang * Only records the valid partition number that is loaded from 161*201b66b7SHaojian Zhuang * partition table. 162*201b66b7SHaojian Zhuang */ 163*201b66b7SHaojian Zhuang list.entry_count = i; 164*201b66b7SHaojian Zhuang dump_entries(list.entry_count); 165*201b66b7SHaojian Zhuang 166*201b66b7SHaojian Zhuang return 0; 167*201b66b7SHaojian Zhuang } 168*201b66b7SHaojian Zhuang 169*201b66b7SHaojian Zhuang int load_partition_table(unsigned int image_id) 170*201b66b7SHaojian Zhuang { 171*201b66b7SHaojian Zhuang uintptr_t dev_handle, image_handle, image_spec = 0; 172*201b66b7SHaojian Zhuang mbr_entry_t mbr_entry; 173*201b66b7SHaojian Zhuang int result; 174*201b66b7SHaojian Zhuang 175*201b66b7SHaojian Zhuang result = plat_get_image_source(image_id, &dev_handle, &image_spec); 176*201b66b7SHaojian Zhuang if (result != 0) { 177*201b66b7SHaojian Zhuang WARN("Failed to obtain reference to image id=%u (%i)\n", 178*201b66b7SHaojian Zhuang image_id, result); 179*201b66b7SHaojian Zhuang return result; 180*201b66b7SHaojian Zhuang } 181*201b66b7SHaojian Zhuang 182*201b66b7SHaojian Zhuang result = io_open(dev_handle, image_spec, &image_handle); 183*201b66b7SHaojian Zhuang if (result != 0) { 184*201b66b7SHaojian Zhuang WARN("Failed to access image id=%u (%i)\n", image_id, result); 185*201b66b7SHaojian Zhuang return result; 186*201b66b7SHaojian Zhuang } 187*201b66b7SHaojian Zhuang 188*201b66b7SHaojian Zhuang result = load_mbr_header(image_handle, &mbr_entry); 189*201b66b7SHaojian Zhuang if (result != 0) { 190*201b66b7SHaojian Zhuang WARN("Failed to access image id=%u (%i)\n", image_id, result); 191*201b66b7SHaojian Zhuang return result; 192*201b66b7SHaojian Zhuang } 193*201b66b7SHaojian Zhuang if (mbr_entry.type == PARTITION_TYPE_GPT) { 194*201b66b7SHaojian Zhuang result = load_gpt_header(image_handle); 195*201b66b7SHaojian Zhuang assert(result == 0); 196*201b66b7SHaojian Zhuang result = io_seek(image_handle, IO_SEEK_SET, GPT_ENTRY_OFFSET); 197*201b66b7SHaojian Zhuang assert(result == 0); 198*201b66b7SHaojian Zhuang result = verify_partition_gpt(image_handle); 199*201b66b7SHaojian Zhuang } else { 200*201b66b7SHaojian Zhuang /* MBR type isn't supported yet. */ 201*201b66b7SHaojian Zhuang result = -EINVAL; 202*201b66b7SHaojian Zhuang goto exit; 203*201b66b7SHaojian Zhuang } 204*201b66b7SHaojian Zhuang exit: 205*201b66b7SHaojian Zhuang io_close(image_handle); 206*201b66b7SHaojian Zhuang return result; 207*201b66b7SHaojian Zhuang } 208*201b66b7SHaojian Zhuang 209*201b66b7SHaojian Zhuang const partition_entry_t *get_partition_entry(const char *name) 210*201b66b7SHaojian Zhuang { 211*201b66b7SHaojian Zhuang int i; 212*201b66b7SHaojian Zhuang 213*201b66b7SHaojian Zhuang for (i = 0; i < list.entry_count; i++) { 214*201b66b7SHaojian Zhuang if (strcmp(name, list.list[i].name) == 0) { 215*201b66b7SHaojian Zhuang return &list.list[i]; 216*201b66b7SHaojian Zhuang } 217*201b66b7SHaojian Zhuang } 218*201b66b7SHaojian Zhuang return NULL; 219*201b66b7SHaojian Zhuang } 220*201b66b7SHaojian Zhuang 221*201b66b7SHaojian Zhuang const partition_entry_list_t *get_partition_entry_list(void) 222*201b66b7SHaojian Zhuang { 223*201b66b7SHaojian Zhuang return &list; 224*201b66b7SHaojian Zhuang } 225*201b66b7SHaojian Zhuang 226*201b66b7SHaojian Zhuang void partition_init(unsigned int image_id) 227*201b66b7SHaojian Zhuang { 228*201b66b7SHaojian Zhuang load_partition_table(image_id); 229*201b66b7SHaojian Zhuang } 230