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" 1966ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn 20a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <stdint.h> 2166ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn#include <stdio.h> 22a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <stdlib.h> 23a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <string.h> 24a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 25a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <diskconfig/diskconfig.h> 2630f991f251940be3ed11566fb71139852286f68aMark Salyzyn#include <log/log.h> 27a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 28a6391f1006b961ca89d1c79a826375380684a4deSan Mehat/* start and len are in LBA units */ 29a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstatic void 30a6391f1006b961ca89d1c79a826375380684a4deSan Mehatcfg_pentry(struct pc_partition *pentry, uint8_t status, uint8_t type, 31a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t start, uint32_t len) 32a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{ 33a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (len > 0) { 34a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* seems that somes BIOSens can get wedged on boot while verifying 35a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * the mbr if these are 0 */ 36a6391f1006b961ca89d1c79a826375380684a4deSan Mehat memset(&pentry->start, 0xff, sizeof(struct chs)); 37a6391f1006b961ca89d1c79a826375380684a4deSan Mehat memset(&pentry->end, 0xff, sizeof(struct chs)); 38a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } else { 39a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* zero out the c/h/s entries.. they are not used */ 40a6391f1006b961ca89d1c79a826375380684a4deSan Mehat memset(&pentry->start, 0, sizeof(struct chs)); 41a6391f1006b961ca89d1c79a826375380684a4deSan Mehat memset(&pentry->end, 0, sizeof(struct chs)); 42a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 43a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 44a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pentry->status = status; 45a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pentry->type = type; 46a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pentry->start_lba = start; 47a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pentry->len_lba = len; 48a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 49fe71a61e5b0cb666675900d206251a7c18ed944bSteve Block ALOGI("Configuring pentry. status=0x%x type=0x%x start_lba=%u len_lba=%u", 50a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pentry->status, pentry->type, pentry->start_lba, pentry->len_lba); 51a6391f1006b961ca89d1c79a826375380684a4deSan Mehat} 52a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 53a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 54a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstatic inline uint32_t 55a6391f1006b961ca89d1c79a826375380684a4deSan Mehatkb_to_lba(uint32_t len_kb, uint32_t sect_size) 56a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{ 57a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint64_t lba; 58a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 59a6391f1006b961ca89d1c79a826375380684a4deSan Mehat lba = (uint64_t)len_kb * 1024; 60a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* bump it up to the next LBA boundary just in case */ 61a6391f1006b961ca89d1c79a826375380684a4deSan Mehat lba = (lba + (uint64_t)sect_size - 1) & ~((uint64_t)sect_size - 1); 62a6391f1006b961ca89d1c79a826375380684a4deSan Mehat lba /= (uint64_t)sect_size; 63a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (lba >= 0xffffffffULL) 6401dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Error converting kb -> lba. 32bit overflow, expect weirdness"); 65a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return (uint32_t)(lba & 0xffffffffULL); 66a6391f1006b961ca89d1c79a826375380684a4deSan Mehat} 67a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 68a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 69a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstatic struct write_list * 70a6391f1006b961ca89d1c79a826375380684a4deSan Mehatmk_pri_pentry(struct disk_info *dinfo, struct part_info *pinfo, int pnum, 71a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t *lba) 72a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{ 73a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct write_list *item; 74a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct pc_partition *pentry; 75a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 76a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (pnum >= PC_NUM_BOOT_RECORD_PARTS) { 7701dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Maximum number of primary partition exceeded."); 78a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 79a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 80a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 81a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (!(item = alloc_wl(sizeof(struct pc_partition)))) { 8201dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Unable to allocate memory for partition entry."); 83a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 84a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 85a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 86a6391f1006b961ca89d1c79a826375380684a4deSan Mehat { 87a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* DO NOT DEREFERENCE */ 88a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct pc_boot_record *mbr = (void *)PC_MBR_DISK_OFFSET; 89a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* grab the offset in mbr where to write this partition entry. */ 9035539affd81eae1d8734a5c4f7a148108068d7fdAshok Bhat item->offset = (loff_t)((uintptr_t)((uint8_t *)(&mbr->ptable[pnum]))); 91a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 92a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 93a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pentry = (struct pc_partition *) &item->data; 94a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 95a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* need a standard primary partition entry */ 96a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (pinfo) { 97a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* need this to be 64 bit in case len_kb is large */ 98a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint64_t len_lba; 99a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 100a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (pinfo->len_kb != (uint32_t)-1) { 101a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* bump it up to the next LBA boundary just in case */ 102a6391f1006b961ca89d1c79a826375380684a4deSan Mehat len_lba = ((uint64_t)pinfo->len_kb * 1024); 103a6391f1006b961ca89d1c79a826375380684a4deSan Mehat len_lba += ((uint64_t)dinfo->sect_size - 1); 104a6391f1006b961ca89d1c79a826375380684a4deSan Mehat len_lba &= ~((uint64_t)dinfo->sect_size - 1); 105a6391f1006b961ca89d1c79a826375380684a4deSan Mehat len_lba /= (uint64_t)dinfo->sect_size; 106a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } else { 107a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* make it fill the rest of disk */ 108a6391f1006b961ca89d1c79a826375380684a4deSan Mehat len_lba = dinfo->num_lba - *lba; 109a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 110a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 111a6391f1006b961ca89d1c79a826375380684a4deSan Mehat cfg_pentry(pentry, ((pinfo->flags & PART_ACTIVE_FLAG) ? 112a6391f1006b961ca89d1c79a826375380684a4deSan Mehat PC_PART_ACTIVE : PC_PART_NORMAL), 113a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pinfo->type, *lba, (uint32_t)len_lba); 114a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 115a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pinfo->start_lba = *lba; 116a6391f1006b961ca89d1c79a826375380684a4deSan Mehat *lba += (uint32_t)len_lba; 117a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } else { 118a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* this should be made an extended partition, and should take 119a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * up the rest of the disk as a primary partition */ 120a6391f1006b961ca89d1c79a826375380684a4deSan Mehat cfg_pentry(pentry, PC_PART_NORMAL, PC_PART_TYPE_EXTENDED, 121a6391f1006b961ca89d1c79a826375380684a4deSan Mehat *lba, dinfo->num_lba - *lba); 122a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 123a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* note that we do not update the *lba because we now have to 124a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * create a chain of extended partition tables, and first one is at 125a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * *lba */ 126a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 127a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 128a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return item; 129a6391f1006b961ca89d1c79a826375380684a4deSan Mehat} 130a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 131a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 132a6391f1006b961ca89d1c79a826375380684a4deSan Mehat/* This function configures an extended boot record at the beginning of an 133a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * extended partition. This creates a logical partition and a pointer to 134a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * the next EBR. 135a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * 136a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * ext_lba == The start of the toplevel extended partition (pointed to by the 137a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * entry in the MBR). 138a6391f1006b961ca89d1c79a826375380684a4deSan Mehat */ 139a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstatic struct write_list * 140a6391f1006b961ca89d1c79a826375380684a4deSan Mehatmk_ext_pentry(struct disk_info *dinfo, struct part_info *pinfo, uint32_t *lba, 141a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t ext_lba, struct part_info *pnext) 142a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{ 143a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct write_list *item; 144a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct pc_boot_record *ebr; 145a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t len; /* in lba units */ 146a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 147a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (!(item = alloc_wl(sizeof(struct pc_boot_record)))) { 14801dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Unable to allocate memory for EBR."); 149a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 150a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 151a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 152a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* we are going to write the ebr at the current LBA, and then bump the 153a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * lba counter since that is where the logical data partition will start */ 1540b344e7f111d845f9cbb8d284f62d546645c733eAndrew Boie item->offset = ((loff_t)(*lba)) * dinfo->sect_size; 155a6391f1006b961ca89d1c79a826375380684a4deSan Mehat (*lba)++; 156a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 157a6391f1006b961ca89d1c79a826375380684a4deSan Mehat ebr = (struct pc_boot_record *) &item->data; 158a6391f1006b961ca89d1c79a826375380684a4deSan Mehat memset(ebr, 0, sizeof(struct pc_boot_record)); 159a6391f1006b961ca89d1c79a826375380684a4deSan Mehat ebr->mbr_sig = PC_BIOS_BOOT_SIG; 160a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 161a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (pinfo->len_kb != (uint32_t)-1) 162a6391f1006b961ca89d1c79a826375380684a4deSan Mehat len = kb_to_lba(pinfo->len_kb, dinfo->sect_size); 163a6391f1006b961ca89d1c79a826375380684a4deSan Mehat else { 164a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (pnext) { 16501dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Only the last partition can be specified to fill the disk " 166a6391f1006b961ca89d1c79a826375380684a4deSan Mehat "(name = '%s')", pinfo->name); 167a6391f1006b961ca89d1c79a826375380684a4deSan Mehat goto fail; 168a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 169a6391f1006b961ca89d1c79a826375380684a4deSan Mehat len = dinfo->num_lba - *lba; 170a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* update the pinfo structure to reflect the new size, for 171a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * bookkeeping */ 172a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pinfo->len_kb = 173a6391f1006b961ca89d1c79a826375380684a4deSan Mehat (uint32_t)(((uint64_t)len * (uint64_t)dinfo->sect_size) / 174a6391f1006b961ca89d1c79a826375380684a4deSan Mehat ((uint64_t)1024)); 175a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 176a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 177a6391f1006b961ca89d1c79a826375380684a4deSan Mehat cfg_pentry(&ebr->ptable[PC_EBR_LOGICAL_PART], PC_PART_NORMAL, 178a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pinfo->type, 1, len); 179a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 180a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pinfo->start_lba = *lba; 181a6391f1006b961ca89d1c79a826375380684a4deSan Mehat *lba += len; 182a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 183a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* If this is not the last partition, we have to create a link to the 184a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * next extended partition. 185a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * 186a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * Otherwise, there's nothing to do since the "pointer entry" is 187a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * already zero-filled. 188a6391f1006b961ca89d1c79a826375380684a4deSan Mehat */ 189a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (pnext) { 190a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* The start lba for next partition is an offset from the beginning 191a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * of the top-level extended partition */ 192a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t next_start_lba = *lba - ext_lba; 193a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t next_len_lba; 194a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (pnext->len_kb != (uint32_t)-1) 195a6391f1006b961ca89d1c79a826375380684a4deSan Mehat next_len_lba = 1 + kb_to_lba(pnext->len_kb, dinfo->sect_size); 196a6391f1006b961ca89d1c79a826375380684a4deSan Mehat else 197a6391f1006b961ca89d1c79a826375380684a4deSan Mehat next_len_lba = dinfo->num_lba - *lba; 198a6391f1006b961ca89d1c79a826375380684a4deSan Mehat cfg_pentry(&ebr->ptable[PC_EBR_NEXT_PTR_PART], PC_PART_NORMAL, 199a6391f1006b961ca89d1c79a826375380684a4deSan Mehat PC_PART_TYPE_EXTENDED, next_start_lba, next_len_lba); 200a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 201a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 202a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return item; 203a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 204a6391f1006b961ca89d1c79a826375380684a4deSan Mehatfail: 205a6391f1006b961ca89d1c79a826375380684a4deSan Mehat free_wl(item); 206a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 207a6391f1006b961ca89d1c79a826375380684a4deSan Mehat} 208a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 209a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 2105e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yaostatic struct write_list * 2115e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yaomk_mbr_sig() 2125e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao{ 2135e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao struct write_list *item; 2145e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao if (!(item = alloc_wl(sizeof(uint16_t)))) { 2155e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao ALOGE("Unable to allocate memory for MBR signature."); 2165e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao return NULL; 2175e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao } 2185e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao 2195e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao { 2205e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao /* DO NOT DEREFERENCE */ 2215e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao struct pc_boot_record *mbr = (void *)PC_MBR_DISK_OFFSET; 2225e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao /* grab the offset in mbr where to write mbr signature. */ 223283540147877ca3c5f7ecb280a6b5778ab63366cJP Abgrall item->offset = (loff_t)((uintptr_t)((uint8_t *)(&mbr->mbr_sig))); 2245e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao } 2255e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao 2265e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao *((uint16_t*)item->data) = PC_BIOS_BOOT_SIG; 2275e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao return item; 2285e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao} 2295e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao 230a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstruct write_list * 231a6391f1006b961ca89d1c79a826375380684a4deSan Mehatconfig_mbr(struct disk_info *dinfo) 232a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{ 233a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct part_info *pinfo; 234a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t cur_lba = dinfo->skip_lba; 235a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t ext_lba = 0; 236a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct write_list *wr_list = NULL; 237a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct write_list *temp_wr = NULL; 238a6391f1006b961ca89d1c79a826375380684a4deSan Mehat int cnt = 0; 239a6391f1006b961ca89d1c79a826375380684a4deSan Mehat int extended = 0; 240a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 241a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (!dinfo->part_lst) 242a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 243a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 244a6391f1006b961ca89d1c79a826375380684a4deSan Mehat for (cnt = 0; cnt < dinfo->num_parts; ++cnt) { 245a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pinfo = &dinfo->part_lst[cnt]; 246a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 247a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* Should we create an extedned partition? */ 248a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (cnt == (PC_NUM_BOOT_RECORD_PARTS - 1)) { 249a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (cnt + 1 < dinfo->num_parts) { 250a6391f1006b961ca89d1c79a826375380684a4deSan Mehat extended = 1; 251a6391f1006b961ca89d1c79a826375380684a4deSan Mehat ext_lba = cur_lba; 252a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if ((temp_wr = mk_pri_pentry(dinfo, NULL, cnt, &cur_lba))) 253a6391f1006b961ca89d1c79a826375380684a4deSan Mehat wlist_add(&wr_list, temp_wr); 254a6391f1006b961ca89d1c79a826375380684a4deSan Mehat else { 25501dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Cannot create primary extended partition."); 256a6391f1006b961ca89d1c79a826375380684a4deSan Mehat goto fail; 257a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 258a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 259a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 260a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 261a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* if extended, need 1 lba for ebr */ 262a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if ((cur_lba + extended) >= dinfo->num_lba) 263a6391f1006b961ca89d1c79a826375380684a4deSan Mehat goto nospace; 264a6391f1006b961ca89d1c79a826375380684a4deSan Mehat else if (pinfo->len_kb != (uint32_t)-1) { 265a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t sz_lba = (pinfo->len_kb / dinfo->sect_size) * 1024; 266a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if ((cur_lba + sz_lba + extended) > dinfo->num_lba) 267a6391f1006b961ca89d1c79a826375380684a4deSan Mehat goto nospace; 268a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 269a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 270a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (!extended) 271a6391f1006b961ca89d1c79a826375380684a4deSan Mehat temp_wr = mk_pri_pentry(dinfo, pinfo, cnt, &cur_lba); 272a6391f1006b961ca89d1c79a826375380684a4deSan Mehat else { 273a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct part_info *pnext; 274a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pnext = cnt + 1 < dinfo->num_parts ? &dinfo->part_lst[cnt+1] : NULL; 275a6391f1006b961ca89d1c79a826375380684a4deSan Mehat temp_wr = mk_ext_pentry(dinfo, pinfo, &cur_lba, ext_lba, pnext); 276a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 277a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 278a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (temp_wr) 279a6391f1006b961ca89d1c79a826375380684a4deSan Mehat wlist_add(&wr_list, temp_wr); 280a6391f1006b961ca89d1c79a826375380684a4deSan Mehat else { 28101dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Cannot create partition %d (%s).", cnt, pinfo->name); 282a6391f1006b961ca89d1c79a826375380684a4deSan Mehat goto fail; 283a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 284a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 285a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 286a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* fill in the rest of the MBR with empty parts (if needed). */ 287a6391f1006b961ca89d1c79a826375380684a4deSan Mehat for (; cnt < PC_NUM_BOOT_RECORD_PARTS; ++cnt) { 288a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct part_info blank; 289a6391f1006b961ca89d1c79a826375380684a4deSan Mehat cur_lba = 0; 290a6391f1006b961ca89d1c79a826375380684a4deSan Mehat memset(&blank, 0, sizeof(struct part_info)); 291a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (!(temp_wr = mk_pri_pentry(dinfo, &blank, cnt, &cur_lba))) { 29201dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Cannot create blank partition %d.", cnt); 293a6391f1006b961ca89d1c79a826375380684a4deSan Mehat goto fail; 294a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 295a6391f1006b961ca89d1c79a826375380684a4deSan Mehat wlist_add(&wr_list, temp_wr); 296a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 297a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 2985e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao if ((temp_wr = mk_mbr_sig())) 2995e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao wlist_add(&wr_list, temp_wr); 3005e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao else { 3015e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao ALOGE("Cannot set MBR signature"); 3025e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao goto fail; 3035e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao } 3045e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao 305a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return wr_list; 306a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 307a6391f1006b961ca89d1c79a826375380684a4deSan Mehatnospace: 30801dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Not enough space to add parttion '%s'.", pinfo->name); 309a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 310a6391f1006b961ca89d1c79a826375380684a4deSan Mehatfail: 311a6391f1006b961ca89d1c79a826375380684a4deSan Mehat wlist_free(wr_list); 312a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 313a6391f1006b961ca89d1c79a826375380684a4deSan Mehat} 314a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 315a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 316a6391f1006b961ca89d1c79a826375380684a4deSan Mehat/* Returns the device path of the partition referred to by 'name' 317a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * Must be freed by the caller. 318a6391f1006b961ca89d1c79a826375380684a4deSan Mehat */ 319a6391f1006b961ca89d1c79a826375380684a4deSan Mehatchar * 320a6391f1006b961ca89d1c79a826375380684a4deSan Mehatfind_mbr_part(struct disk_info *dinfo, const char *name) 321a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{ 322a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct part_info *plist = dinfo->part_lst; 323a6391f1006b961ca89d1c79a826375380684a4deSan Mehat int num = 0; 324a6391f1006b961ca89d1c79a826375380684a4deSan Mehat char *dev_name = NULL; 325a6391f1006b961ca89d1c79a826375380684a4deSan Mehat int has_extended = (dinfo->num_parts > PC_NUM_BOOT_RECORD_PARTS); 326a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 327a6391f1006b961ca89d1c79a826375380684a4deSan Mehat for(num = 1; num <= dinfo->num_parts; ++num) { 328a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (!strcmp(plist[num-1].name, name)) 329a6391f1006b961ca89d1c79a826375380684a4deSan Mehat break; 330a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 331a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 332a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (num > dinfo->num_parts) 333a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 334a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 335a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (has_extended && (num >= PC_NUM_BOOT_RECORD_PARTS)) 336a6391f1006b961ca89d1c79a826375380684a4deSan Mehat num++; 337a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 338a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (!(dev_name = malloc(MAX_NAME_LEN))) { 33901dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Cannot allocate memory."); 340a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 341a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 342a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 343a6391f1006b961ca89d1c79a826375380684a4deSan Mehat num = snprintf(dev_name, MAX_NAME_LEN, "%s%d", dinfo->device, num); 344a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (num >= MAX_NAME_LEN) { 34501dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Device name is too long?!"); 346a6391f1006b961ca89d1c79a826375380684a4deSan Mehat free(dev_name); 347a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 348a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 349a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 350a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return dev_name; 351a6391f1006b961ca89d1c79a826375380684a4deSan Mehat} 352