1a6391f1006b961ca89d1c79a826375380684a4deSan Mehat/* libs/diskconfig/diskconfig.c 2a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * 3a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * Copyright 2008, The Android Open Source Project 4a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * 5a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * Licensed under the Apache License, Version 2.0 (the "License"); 6a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * you may not use this file except in compliance with the License. 7a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * You may obtain a copy of the License at 8a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * 9a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * http://www.apache.org/licenses/LICENSE-2.0 10a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * 11a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * Unless required by applicable law or agreed to in writing, software 12a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * distributed under the License is distributed on an "AS IS" BASIS, 13a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * See the License for the specific language governing permissions and 15a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * limitations under the License. 16a6391f1006b961ca89d1c79a826375380684a4deSan Mehat */ 17a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 18a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#define LOG_TAG "config_mbr" 19a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <stdint.h> 20a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <stdlib.h> 21a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <string.h> 22a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <stdio.h> 23a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 24a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <cutils/log.h> 25a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 26a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <diskconfig/diskconfig.h> 27a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 28a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 29a6391f1006b961ca89d1c79a826375380684a4deSan Mehat/* start and len are in LBA units */ 30a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstatic void 31a6391f1006b961ca89d1c79a826375380684a4deSan Mehatcfg_pentry(struct pc_partition *pentry, uint8_t status, uint8_t type, 32a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t start, uint32_t len) 33a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{ 34a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (len > 0) { 35a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* seems that somes BIOSens can get wedged on boot while verifying 36a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * the mbr if these are 0 */ 37a6391f1006b961ca89d1c79a826375380684a4deSan Mehat memset(&pentry->start, 0xff, sizeof(struct chs)); 38a6391f1006b961ca89d1c79a826375380684a4deSan Mehat memset(&pentry->end, 0xff, sizeof(struct chs)); 39a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } else { 40a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* zero out the c/h/s entries.. they are not used */ 41a6391f1006b961ca89d1c79a826375380684a4deSan Mehat memset(&pentry->start, 0, sizeof(struct chs)); 42a6391f1006b961ca89d1c79a826375380684a4deSan Mehat memset(&pentry->end, 0, sizeof(struct chs)); 43a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 44a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 45a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pentry->status = status; 46a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pentry->type = type; 47a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pentry->start_lba = start; 48a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pentry->len_lba = len; 49a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 50a6391f1006b961ca89d1c79a826375380684a4deSan Mehat LOGI("Configuring pentry. status=0x%x type=0x%x start_lba=%u len_lba=%u", 51a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pentry->status, pentry->type, pentry->start_lba, pentry->len_lba); 52a6391f1006b961ca89d1c79a826375380684a4deSan Mehat} 53a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 54a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 55a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstatic inline uint32_t 56a6391f1006b961ca89d1c79a826375380684a4deSan Mehatkb_to_lba(uint32_t len_kb, uint32_t sect_size) 57a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{ 58a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint64_t lba; 59a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 60a6391f1006b961ca89d1c79a826375380684a4deSan Mehat lba = (uint64_t)len_kb * 1024; 61a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* bump it up to the next LBA boundary just in case */ 62a6391f1006b961ca89d1c79a826375380684a4deSan Mehat lba = (lba + (uint64_t)sect_size - 1) & ~((uint64_t)sect_size - 1); 63a6391f1006b961ca89d1c79a826375380684a4deSan Mehat lba /= (uint64_t)sect_size; 64a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (lba >= 0xffffffffULL) 65a6391f1006b961ca89d1c79a826375380684a4deSan Mehat LOGE("Error converting kb -> lba. 32bit overflow, expect weirdness"); 66a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return (uint32_t)(lba & 0xffffffffULL); 67a6391f1006b961ca89d1c79a826375380684a4deSan Mehat} 68a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 69a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 70a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstatic struct write_list * 71a6391f1006b961ca89d1c79a826375380684a4deSan Mehatmk_pri_pentry(struct disk_info *dinfo, struct part_info *pinfo, int pnum, 72a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t *lba) 73a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{ 74a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct write_list *item; 75a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct pc_partition *pentry; 76a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 77a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (pnum >= PC_NUM_BOOT_RECORD_PARTS) { 78a6391f1006b961ca89d1c79a826375380684a4deSan Mehat LOGE("Maximum number of primary partition exceeded."); 79a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 80a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 81a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 82a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (!(item = alloc_wl(sizeof(struct pc_partition)))) { 83a6391f1006b961ca89d1c79a826375380684a4deSan Mehat LOGE("Unable to allocate memory for partition entry."); 84a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 85a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 86a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 87a6391f1006b961ca89d1c79a826375380684a4deSan Mehat { 88a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* DO NOT DEREFERENCE */ 89a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct pc_boot_record *mbr = (void *)PC_MBR_DISK_OFFSET; 90a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* grab the offset in mbr where to write this partition entry. */ 91a6391f1006b961ca89d1c79a826375380684a4deSan Mehat item->offset = (loff_t)((uint32_t)((uint8_t *)(&mbr->ptable[pnum]))); 92a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 93a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 94a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pentry = (struct pc_partition *) &item->data; 95a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 96a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* need a standard primary partition entry */ 97a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (pinfo) { 98a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* need this to be 64 bit in case len_kb is large */ 99a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint64_t len_lba; 100a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 101a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (pinfo->len_kb != (uint32_t)-1) { 102a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* bump it up to the next LBA boundary just in case */ 103a6391f1006b961ca89d1c79a826375380684a4deSan Mehat len_lba = ((uint64_t)pinfo->len_kb * 1024); 104a6391f1006b961ca89d1c79a826375380684a4deSan Mehat len_lba += ((uint64_t)dinfo->sect_size - 1); 105a6391f1006b961ca89d1c79a826375380684a4deSan Mehat len_lba &= ~((uint64_t)dinfo->sect_size - 1); 106a6391f1006b961ca89d1c79a826375380684a4deSan Mehat len_lba /= (uint64_t)dinfo->sect_size; 107a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } else { 108a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* make it fill the rest of disk */ 109a6391f1006b961ca89d1c79a826375380684a4deSan Mehat len_lba = dinfo->num_lba - *lba; 110a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 111a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 112a6391f1006b961ca89d1c79a826375380684a4deSan Mehat cfg_pentry(pentry, ((pinfo->flags & PART_ACTIVE_FLAG) ? 113a6391f1006b961ca89d1c79a826375380684a4deSan Mehat PC_PART_ACTIVE : PC_PART_NORMAL), 114a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pinfo->type, *lba, (uint32_t)len_lba); 115a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 116a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pinfo->start_lba = *lba; 117a6391f1006b961ca89d1c79a826375380684a4deSan Mehat *lba += (uint32_t)len_lba; 118a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } else { 119a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* this should be made an extended partition, and should take 120a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * up the rest of the disk as a primary partition */ 121a6391f1006b961ca89d1c79a826375380684a4deSan Mehat cfg_pentry(pentry, PC_PART_NORMAL, PC_PART_TYPE_EXTENDED, 122a6391f1006b961ca89d1c79a826375380684a4deSan Mehat *lba, dinfo->num_lba - *lba); 123a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 124a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* note that we do not update the *lba because we now have to 125a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * create a chain of extended partition tables, and first one is at 126a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * *lba */ 127a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 128a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 129a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return item; 130a6391f1006b961ca89d1c79a826375380684a4deSan Mehat} 131a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 132a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 133a6391f1006b961ca89d1c79a826375380684a4deSan Mehat/* This function configures an extended boot record at the beginning of an 134a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * extended partition. This creates a logical partition and a pointer to 135a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * the next EBR. 136a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * 137a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * ext_lba == The start of the toplevel extended partition (pointed to by the 138a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * entry in the MBR). 139a6391f1006b961ca89d1c79a826375380684a4deSan Mehat */ 140a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstatic struct write_list * 141a6391f1006b961ca89d1c79a826375380684a4deSan Mehatmk_ext_pentry(struct disk_info *dinfo, struct part_info *pinfo, uint32_t *lba, 142a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t ext_lba, struct part_info *pnext) 143a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{ 144a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct write_list *item; 145a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct pc_boot_record *ebr; 146a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t len; /* in lba units */ 147a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 148a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (!(item = alloc_wl(sizeof(struct pc_boot_record)))) { 149a6391f1006b961ca89d1c79a826375380684a4deSan Mehat LOGE("Unable to allocate memory for EBR."); 150a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 151a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 152a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 153a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* we are going to write the ebr at the current LBA, and then bump the 154a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * lba counter since that is where the logical data partition will start */ 155a6391f1006b961ca89d1c79a826375380684a4deSan Mehat item->offset = (*lba) * dinfo->sect_size; 156a6391f1006b961ca89d1c79a826375380684a4deSan Mehat (*lba)++; 157a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 158a6391f1006b961ca89d1c79a826375380684a4deSan Mehat ebr = (struct pc_boot_record *) &item->data; 159a6391f1006b961ca89d1c79a826375380684a4deSan Mehat memset(ebr, 0, sizeof(struct pc_boot_record)); 160a6391f1006b961ca89d1c79a826375380684a4deSan Mehat ebr->mbr_sig = PC_BIOS_BOOT_SIG; 161a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 162a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (pinfo->len_kb != (uint32_t)-1) 163a6391f1006b961ca89d1c79a826375380684a4deSan Mehat len = kb_to_lba(pinfo->len_kb, dinfo->sect_size); 164a6391f1006b961ca89d1c79a826375380684a4deSan Mehat else { 165a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (pnext) { 166a6391f1006b961ca89d1c79a826375380684a4deSan Mehat LOGE("Only the last partition can be specified to fill the disk " 167a6391f1006b961ca89d1c79a826375380684a4deSan Mehat "(name = '%s')", pinfo->name); 168a6391f1006b961ca89d1c79a826375380684a4deSan Mehat goto fail; 169a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 170a6391f1006b961ca89d1c79a826375380684a4deSan Mehat len = dinfo->num_lba - *lba; 171a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* update the pinfo structure to reflect the new size, for 172a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * bookkeeping */ 173a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pinfo->len_kb = 174a6391f1006b961ca89d1c79a826375380684a4deSan Mehat (uint32_t)(((uint64_t)len * (uint64_t)dinfo->sect_size) / 175a6391f1006b961ca89d1c79a826375380684a4deSan Mehat ((uint64_t)1024)); 176a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 177a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 178a6391f1006b961ca89d1c79a826375380684a4deSan Mehat cfg_pentry(&ebr->ptable[PC_EBR_LOGICAL_PART], PC_PART_NORMAL, 179a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pinfo->type, 1, len); 180a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 181a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pinfo->start_lba = *lba; 182a6391f1006b961ca89d1c79a826375380684a4deSan Mehat *lba += len; 183a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 184a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* If this is not the last partition, we have to create a link to the 185a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * next extended partition. 186a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * 187a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * Otherwise, there's nothing to do since the "pointer entry" is 188a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * already zero-filled. 189a6391f1006b961ca89d1c79a826375380684a4deSan Mehat */ 190a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (pnext) { 191a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* The start lba for next partition is an offset from the beginning 192a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * of the top-level extended partition */ 193a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t next_start_lba = *lba - ext_lba; 194a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t next_len_lba; 195a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (pnext->len_kb != (uint32_t)-1) 196a6391f1006b961ca89d1c79a826375380684a4deSan Mehat next_len_lba = 1 + kb_to_lba(pnext->len_kb, dinfo->sect_size); 197a6391f1006b961ca89d1c79a826375380684a4deSan Mehat else 198a6391f1006b961ca89d1c79a826375380684a4deSan Mehat next_len_lba = dinfo->num_lba - *lba; 199a6391f1006b961ca89d1c79a826375380684a4deSan Mehat cfg_pentry(&ebr->ptable[PC_EBR_NEXT_PTR_PART], PC_PART_NORMAL, 200a6391f1006b961ca89d1c79a826375380684a4deSan Mehat PC_PART_TYPE_EXTENDED, next_start_lba, next_len_lba); 201a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 202a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 203a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return item; 204a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 205a6391f1006b961ca89d1c79a826375380684a4deSan Mehatfail: 206a6391f1006b961ca89d1c79a826375380684a4deSan Mehat free_wl(item); 207a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 208a6391f1006b961ca89d1c79a826375380684a4deSan Mehat} 209a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 210a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 211a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstruct write_list * 212a6391f1006b961ca89d1c79a826375380684a4deSan Mehatconfig_mbr(struct disk_info *dinfo) 213a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{ 214a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct part_info *pinfo; 215a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t cur_lba = dinfo->skip_lba; 216a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t ext_lba = 0; 217a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct write_list *wr_list = NULL; 218a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct write_list *temp_wr = NULL; 219a6391f1006b961ca89d1c79a826375380684a4deSan Mehat int cnt = 0; 220a6391f1006b961ca89d1c79a826375380684a4deSan Mehat int extended = 0; 221a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 222a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (!dinfo->part_lst) 223a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 224a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 225a6391f1006b961ca89d1c79a826375380684a4deSan Mehat for (cnt = 0; cnt < dinfo->num_parts; ++cnt) { 226a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pinfo = &dinfo->part_lst[cnt]; 227a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 228a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* Should we create an extedned partition? */ 229a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (cnt == (PC_NUM_BOOT_RECORD_PARTS - 1)) { 230a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (cnt + 1 < dinfo->num_parts) { 231a6391f1006b961ca89d1c79a826375380684a4deSan Mehat extended = 1; 232a6391f1006b961ca89d1c79a826375380684a4deSan Mehat ext_lba = cur_lba; 233a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if ((temp_wr = mk_pri_pentry(dinfo, NULL, cnt, &cur_lba))) 234a6391f1006b961ca89d1c79a826375380684a4deSan Mehat wlist_add(&wr_list, temp_wr); 235a6391f1006b961ca89d1c79a826375380684a4deSan Mehat else { 236a6391f1006b961ca89d1c79a826375380684a4deSan Mehat LOGE("Cannot create primary extended partition."); 237a6391f1006b961ca89d1c79a826375380684a4deSan Mehat goto fail; 238a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 239a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 240a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 241a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 242a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* if extended, need 1 lba for ebr */ 243a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if ((cur_lba + extended) >= dinfo->num_lba) 244a6391f1006b961ca89d1c79a826375380684a4deSan Mehat goto nospace; 245a6391f1006b961ca89d1c79a826375380684a4deSan Mehat else if (pinfo->len_kb != (uint32_t)-1) { 246a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t sz_lba = (pinfo->len_kb / dinfo->sect_size) * 1024; 247a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if ((cur_lba + sz_lba + extended) > dinfo->num_lba) 248a6391f1006b961ca89d1c79a826375380684a4deSan Mehat goto nospace; 249a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 250a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 251a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (!extended) 252a6391f1006b961ca89d1c79a826375380684a4deSan Mehat temp_wr = mk_pri_pentry(dinfo, pinfo, cnt, &cur_lba); 253a6391f1006b961ca89d1c79a826375380684a4deSan Mehat else { 254a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct part_info *pnext; 255a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pnext = cnt + 1 < dinfo->num_parts ? &dinfo->part_lst[cnt+1] : NULL; 256a6391f1006b961ca89d1c79a826375380684a4deSan Mehat temp_wr = mk_ext_pentry(dinfo, pinfo, &cur_lba, ext_lba, pnext); 257a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 258a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 259a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (temp_wr) 260a6391f1006b961ca89d1c79a826375380684a4deSan Mehat wlist_add(&wr_list, temp_wr); 261a6391f1006b961ca89d1c79a826375380684a4deSan Mehat else { 262a6391f1006b961ca89d1c79a826375380684a4deSan Mehat LOGE("Cannot create partition %d (%s).", cnt, pinfo->name); 263a6391f1006b961ca89d1c79a826375380684a4deSan Mehat goto fail; 264a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 265a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 266a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 267a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* fill in the rest of the MBR with empty parts (if needed). */ 268a6391f1006b961ca89d1c79a826375380684a4deSan Mehat for (; cnt < PC_NUM_BOOT_RECORD_PARTS; ++cnt) { 269a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct part_info blank; 270a6391f1006b961ca89d1c79a826375380684a4deSan Mehat cur_lba = 0; 271a6391f1006b961ca89d1c79a826375380684a4deSan Mehat memset(&blank, 0, sizeof(struct part_info)); 272a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (!(temp_wr = mk_pri_pentry(dinfo, &blank, cnt, &cur_lba))) { 273a6391f1006b961ca89d1c79a826375380684a4deSan Mehat LOGE("Cannot create blank partition %d.", cnt); 274a6391f1006b961ca89d1c79a826375380684a4deSan Mehat goto fail; 275a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 276a6391f1006b961ca89d1c79a826375380684a4deSan Mehat wlist_add(&wr_list, temp_wr); 277a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 278a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 279a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return wr_list; 280a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 281a6391f1006b961ca89d1c79a826375380684a4deSan Mehatnospace: 282a6391f1006b961ca89d1c79a826375380684a4deSan Mehat LOGE("Not enough space to add parttion '%s'.", pinfo->name); 283a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 284a6391f1006b961ca89d1c79a826375380684a4deSan Mehatfail: 285a6391f1006b961ca89d1c79a826375380684a4deSan Mehat wlist_free(wr_list); 286a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 287a6391f1006b961ca89d1c79a826375380684a4deSan Mehat} 288a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 289a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 290a6391f1006b961ca89d1c79a826375380684a4deSan Mehat/* Returns the device path of the partition referred to by 'name' 291a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * Must be freed by the caller. 292a6391f1006b961ca89d1c79a826375380684a4deSan Mehat */ 293a6391f1006b961ca89d1c79a826375380684a4deSan Mehatchar * 294a6391f1006b961ca89d1c79a826375380684a4deSan Mehatfind_mbr_part(struct disk_info *dinfo, const char *name) 295a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{ 296a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct part_info *plist = dinfo->part_lst; 297a6391f1006b961ca89d1c79a826375380684a4deSan Mehat int num = 0; 298a6391f1006b961ca89d1c79a826375380684a4deSan Mehat char *dev_name = NULL; 299a6391f1006b961ca89d1c79a826375380684a4deSan Mehat int has_extended = (dinfo->num_parts > PC_NUM_BOOT_RECORD_PARTS); 300a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 301a6391f1006b961ca89d1c79a826375380684a4deSan Mehat for(num = 1; num <= dinfo->num_parts; ++num) { 302a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (!strcmp(plist[num-1].name, name)) 303a6391f1006b961ca89d1c79a826375380684a4deSan Mehat break; 304a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 305a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 306a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (num > dinfo->num_parts) 307a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 308a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 309a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (has_extended && (num >= PC_NUM_BOOT_RECORD_PARTS)) 310a6391f1006b961ca89d1c79a826375380684a4deSan Mehat num++; 311a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 312a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (!(dev_name = malloc(MAX_NAME_LEN))) { 313a6391f1006b961ca89d1c79a826375380684a4deSan Mehat LOGE("Cannot allocate memory."); 314a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 315a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 316a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 317a6391f1006b961ca89d1c79a826375380684a4deSan Mehat num = snprintf(dev_name, MAX_NAME_LEN, "%s%d", dinfo->device, num); 318a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (num >= MAX_NAME_LEN) { 319a6391f1006b961ca89d1c79a826375380684a4deSan Mehat LOGE("Device name is too long?!"); 320a6391f1006b961ca89d1c79a826375380684a4deSan Mehat free(dev_name); 321a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 322a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 323a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 324a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return dev_name; 325a6391f1006b961ca89d1c79a826375380684a4deSan Mehat} 326