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 50fe71a61e5b0cb666675900d206251a7c18ed944bSteve Block ALOGI("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) 6501dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("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) { 7801dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Maximum number of primary partition exceeded."); 79a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 80a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 81a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 82a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (!(item = alloc_wl(sizeof(struct pc_partition)))) { 8301dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("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. */ 9135539affd81eae1d8734a5c4f7a148108068d7fdAshok Bhat item->offset = (loff_t)((uintptr_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)))) { 14901dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("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 */ 1550b344e7f111d845f9cbb8d284f62d546645c733eAndrew Boie item->offset = ((loff_t)(*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) { 16601dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("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 2115e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yaostatic struct write_list * 2125e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yaomk_mbr_sig() 2135e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao{ 2145e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao struct write_list *item; 2155e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao if (!(item = alloc_wl(sizeof(uint16_t)))) { 2165e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao ALOGE("Unable to allocate memory for MBR signature."); 2175e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao return NULL; 2185e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao } 2195e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao 2205e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao { 2215e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao /* DO NOT DEREFERENCE */ 2225e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao struct pc_boot_record *mbr = (void *)PC_MBR_DISK_OFFSET; 2235e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao /* grab the offset in mbr where to write mbr signature. */ 224283540147877ca3c5f7ecb280a6b5778ab63366cJP Abgrall item->offset = (loff_t)((uintptr_t)((uint8_t *)(&mbr->mbr_sig))); 2255e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao } 2265e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao 2275e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao *((uint16_t*)item->data) = PC_BIOS_BOOT_SIG; 2285e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao return item; 2295e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao} 2305e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao 231a6391f1006b961ca89d1c79a826375380684a4deSan Mehatstruct write_list * 232a6391f1006b961ca89d1c79a826375380684a4deSan Mehatconfig_mbr(struct disk_info *dinfo) 233a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{ 234a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct part_info *pinfo; 235a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t cur_lba = dinfo->skip_lba; 236a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t ext_lba = 0; 237a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct write_list *wr_list = NULL; 238a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct write_list *temp_wr = NULL; 239a6391f1006b961ca89d1c79a826375380684a4deSan Mehat int cnt = 0; 240a6391f1006b961ca89d1c79a826375380684a4deSan Mehat int extended = 0; 241a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 242a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (!dinfo->part_lst) 243a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 244a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 245a6391f1006b961ca89d1c79a826375380684a4deSan Mehat for (cnt = 0; cnt < dinfo->num_parts; ++cnt) { 246a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pinfo = &dinfo->part_lst[cnt]; 247a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 248a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* Should we create an extedned partition? */ 249a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (cnt == (PC_NUM_BOOT_RECORD_PARTS - 1)) { 250a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (cnt + 1 < dinfo->num_parts) { 251a6391f1006b961ca89d1c79a826375380684a4deSan Mehat extended = 1; 252a6391f1006b961ca89d1c79a826375380684a4deSan Mehat ext_lba = cur_lba; 253a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if ((temp_wr = mk_pri_pentry(dinfo, NULL, cnt, &cur_lba))) 254a6391f1006b961ca89d1c79a826375380684a4deSan Mehat wlist_add(&wr_list, temp_wr); 255a6391f1006b961ca89d1c79a826375380684a4deSan Mehat else { 25601dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Cannot create primary extended partition."); 257a6391f1006b961ca89d1c79a826375380684a4deSan Mehat goto fail; 258a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 259a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 260a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 261a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 262a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* if extended, need 1 lba for ebr */ 263a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if ((cur_lba + extended) >= dinfo->num_lba) 264a6391f1006b961ca89d1c79a826375380684a4deSan Mehat goto nospace; 265a6391f1006b961ca89d1c79a826375380684a4deSan Mehat else if (pinfo->len_kb != (uint32_t)-1) { 266a6391f1006b961ca89d1c79a826375380684a4deSan Mehat uint32_t sz_lba = (pinfo->len_kb / dinfo->sect_size) * 1024; 267a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if ((cur_lba + sz_lba + extended) > dinfo->num_lba) 268a6391f1006b961ca89d1c79a826375380684a4deSan Mehat goto nospace; 269a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 270a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 271a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (!extended) 272a6391f1006b961ca89d1c79a826375380684a4deSan Mehat temp_wr = mk_pri_pentry(dinfo, pinfo, cnt, &cur_lba); 273a6391f1006b961ca89d1c79a826375380684a4deSan Mehat else { 274a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct part_info *pnext; 275a6391f1006b961ca89d1c79a826375380684a4deSan Mehat pnext = cnt + 1 < dinfo->num_parts ? &dinfo->part_lst[cnt+1] : NULL; 276a6391f1006b961ca89d1c79a826375380684a4deSan Mehat temp_wr = mk_ext_pentry(dinfo, pinfo, &cur_lba, ext_lba, pnext); 277a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 278a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 279a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (temp_wr) 280a6391f1006b961ca89d1c79a826375380684a4deSan Mehat wlist_add(&wr_list, temp_wr); 281a6391f1006b961ca89d1c79a826375380684a4deSan Mehat else { 28201dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Cannot create partition %d (%s).", cnt, pinfo->name); 283a6391f1006b961ca89d1c79a826375380684a4deSan Mehat goto fail; 284a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 285a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 286a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 287a6391f1006b961ca89d1c79a826375380684a4deSan Mehat /* fill in the rest of the MBR with empty parts (if needed). */ 288a6391f1006b961ca89d1c79a826375380684a4deSan Mehat for (; cnt < PC_NUM_BOOT_RECORD_PARTS; ++cnt) { 289a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct part_info blank; 290a6391f1006b961ca89d1c79a826375380684a4deSan Mehat cur_lba = 0; 291a6391f1006b961ca89d1c79a826375380684a4deSan Mehat memset(&blank, 0, sizeof(struct part_info)); 292a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (!(temp_wr = mk_pri_pentry(dinfo, &blank, cnt, &cur_lba))) { 29301dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Cannot create blank partition %d.", cnt); 294a6391f1006b961ca89d1c79a826375380684a4deSan Mehat goto fail; 295a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 296a6391f1006b961ca89d1c79a826375380684a4deSan Mehat wlist_add(&wr_list, temp_wr); 297a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 298a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 2995e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao if ((temp_wr = mk_mbr_sig())) 3005e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao wlist_add(&wr_list, temp_wr); 3015e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao else { 3025e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao ALOGE("Cannot set MBR signature"); 3035e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao goto fail; 3045e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao } 3055e0db82858387ba8c529a8fbc667a58b29b79706Cylen Yao 306a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return wr_list; 307a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 308a6391f1006b961ca89d1c79a826375380684a4deSan Mehatnospace: 30901dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Not enough space to add parttion '%s'.", pinfo->name); 310a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 311a6391f1006b961ca89d1c79a826375380684a4deSan Mehatfail: 312a6391f1006b961ca89d1c79a826375380684a4deSan Mehat wlist_free(wr_list); 313a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 314a6391f1006b961ca89d1c79a826375380684a4deSan Mehat} 315a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 316a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 317a6391f1006b961ca89d1c79a826375380684a4deSan Mehat/* Returns the device path of the partition referred to by 'name' 318a6391f1006b961ca89d1c79a826375380684a4deSan Mehat * Must be freed by the caller. 319a6391f1006b961ca89d1c79a826375380684a4deSan Mehat */ 320a6391f1006b961ca89d1c79a826375380684a4deSan Mehatchar * 321a6391f1006b961ca89d1c79a826375380684a4deSan Mehatfind_mbr_part(struct disk_info *dinfo, const char *name) 322a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{ 323a6391f1006b961ca89d1c79a826375380684a4deSan Mehat struct part_info *plist = dinfo->part_lst; 324a6391f1006b961ca89d1c79a826375380684a4deSan Mehat int num = 0; 325a6391f1006b961ca89d1c79a826375380684a4deSan Mehat char *dev_name = NULL; 326a6391f1006b961ca89d1c79a826375380684a4deSan Mehat int has_extended = (dinfo->num_parts > PC_NUM_BOOT_RECORD_PARTS); 327a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 328a6391f1006b961ca89d1c79a826375380684a4deSan Mehat for(num = 1; num <= dinfo->num_parts; ++num) { 329a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (!strcmp(plist[num-1].name, name)) 330a6391f1006b961ca89d1c79a826375380684a4deSan Mehat break; 331a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 332a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 333a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (num > dinfo->num_parts) 334a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 335a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 336a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (has_extended && (num >= PC_NUM_BOOT_RECORD_PARTS)) 337a6391f1006b961ca89d1c79a826375380684a4deSan Mehat num++; 338a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 339a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (!(dev_name = malloc(MAX_NAME_LEN))) { 34001dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Cannot allocate memory."); 341a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 342a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 343a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 344a6391f1006b961ca89d1c79a826375380684a4deSan Mehat num = snprintf(dev_name, MAX_NAME_LEN, "%s%d", dinfo->device, num); 345a6391f1006b961ca89d1c79a826375380684a4deSan Mehat if (num >= MAX_NAME_LEN) { 34601dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Device name is too long?!"); 347a6391f1006b961ca89d1c79a826375380684a4deSan Mehat free(dev_name); 348a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return NULL; 349a6391f1006b961ca89d1c79a826375380684a4deSan Mehat } 350a6391f1006b961ca89d1c79a826375380684a4deSan Mehat 351a6391f1006b961ca89d1c79a826375380684a4deSan Mehat return dev_name; 352a6391f1006b961ca89d1c79a826375380684a4deSan Mehat} 353