static int find_partition(BlockBackend *blk, int partition, off_t *offset, off_t *size) { struct partition_record mbr[4]; uint8_t data[MBR_SIZE]; int i; int ext_partnum = 4; int ret; ret = blk_pread(blk, 0, data, sizeof(data)); if (ret < 0) { error_report("error while reading: %s", strerror(-ret)); exit(EXIT_FAILURE); } if (data[510] != 0x55 || data[511] != 0xaa) { return -EINVAL; } for (i = 0; i < 4; i++) { read_partition(&data[446 + 16 * i], &mbr[i]); if (!mbr[i].system || !mbr[i].nb_sectors_abs) { continue; } if (mbr[i].system == 0xF || mbr[i].system == 0x5) { struct partition_record ext[4]; uint8_t data1[MBR_SIZE]; int j; ret = blk_pread(blk, mbr[i].start_sector_abs * MBR_SIZE, data1, sizeof(data1)); if (ret < 0) { error_report("error while reading: %s", strerror(-ret)); exit(EXIT_FAILURE); } for (j = 0; j < 4; j++) { read_partition(&data1[446 + 16 * j], &ext[j]); if (!ext[j].system || !ext[j].nb_sectors_abs) { continue; } if ((ext_partnum + j + 1) == partition) { *offset = (uint64_t)ext[j].start_sector_abs << 9; *size = (uint64_t)ext[j].nb_sectors_abs << 9; return 0; } } ext_partnum += 4; } else if ((i + 1) == partition) { *offset = (uint64_t)mbr[i].start_sector_abs << 9; *size = (uint64_t)mbr[i].nb_sectors_abs << 9; return 0; } } return -ENOENT; }
static int find_partition(BlockDriverState *bs, int partition, off_t *offset, off_t *size) { struct partition_record mbr[4]; uint8_t data[512]; int i; int ext_partnum = 4; int ret; if ((ret = bdrv_read(bs, 0, data, 1)) < 0) { errno = -ret; err(EXIT_FAILURE, "error while reading"); } if (data[510] != 0x55 || data[511] != 0xaa) { errno = -EINVAL; return -1; } for (i = 0; i < 4; i++) { read_partition(&data[446 + 16 * i], &mbr[i]); if (!mbr[i].nb_sectors_abs) continue; if (mbr[i].system == 0xF || mbr[i].system == 0x5) { struct partition_record ext[4]; uint8_t data1[512]; int j; if ((ret = bdrv_read(bs, mbr[i].start_sector_abs, data1, 1)) < 0) { errno = -ret; err(EXIT_FAILURE, "error while reading"); } for (j = 0; j < 4; j++) { read_partition(&data1[446 + 16 * j], &ext[j]); if (!ext[j].nb_sectors_abs) continue; if ((ext_partnum + j + 1) == partition) { *offset = (uint64_t)ext[j].start_sector_abs << 9; *size = (uint64_t)ext[j].nb_sectors_abs << 9; return 0; } } ext_partnum += 4; } else if ((i + 1) == partition) { *offset = (uint64_t)mbr[i].start_sector_abs << 9; *size = (uint64_t)mbr[i].nb_sectors_abs << 9; return 0; } } errno = -ENOENT; return -1; }
int main() { int s[MAXN+1]; /* dot thicknesses to partition */ int n; /* how many dots? */ int k; /* how many partitions? */ read_partition(s,&n,&k); partition(s,n,k); }
/* * Read MSC command */ void msc_cmd_read() { struct msc_command my_cmd; int msc_pt_handle; uint32_t processed_bytes; msc_pt_handle = 0; if (open_partition("MSC", PARTITION_OPEN_READ, &msc_pt_handle)) goto finish; if (read_partition(msc_pt_handle, &my_cmd, sizeof(my_cmd), &processed_bytes)) goto finish; if (processed_bytes != sizeof(my_cmd)) goto finish; memcpy(&msc_cmd, &my_cmd, sizeof(my_cmd)); finish: close_partition(msc_pt_handle); return; }
// prepares the verity enabled (MF_VERIFY / MF_VERIFYATBOOT) fstab record for // mount. The 'wait_for_verity_dev' parameter makes this function wait for the // verity device to get created before return int fs_mgr_setup_verity(FstabEntry* entry, bool wait_for_verity_dev) { int retval = FS_MGR_SETUP_VERITY_FAIL; int fd = -1; std::string verity_blk_name; struct fec_handle *f = NULL; struct fec_verity_metadata verity; struct verity_table_params params = { .table = NULL }; const std::string mount_point(basename(entry->mount_point.c_str())); bool verified_at_boot = false; android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance(); if (fec_open(&f, entry->blk_device.c_str(), O_RDONLY, FEC_VERITY_DISABLE, FEC_DEFAULT_ROOTS) < 0) { PERROR << "Failed to open '" << entry->blk_device << "'"; return retval; } // read verity metadata if (fec_verity_get_metadata(f, &verity) < 0) { PERROR << "Failed to get verity metadata '" << entry->blk_device << "'"; // Allow verity disabled when the device is unlocked without metadata if (fs_mgr_is_device_unlocked()) { retval = FS_MGR_SETUP_VERITY_SKIPPED; LWARNING << "Allow invalid metadata when the device is unlocked"; } goto out; } #ifdef ALLOW_ADBD_DISABLE_VERITY if (verity.disabled) { retval = FS_MGR_SETUP_VERITY_DISABLED; LINFO << "Attempt to cleanly disable verity - only works in USERDEBUG/ENG"; goto out; } #endif // read ecc metadata if (fec_ecc_get_metadata(f, ¶ms.ecc) < 0) { params.ecc.valid = false; } params.ecc_dev = entry->blk_device.c_str(); if (load_verity_state(*entry, ¶ms.mode) < 0) { /* if accessing or updating the state failed, switch to the default * safe mode. This makes sure the device won't end up in an endless * restart loop, and no corrupted data will be exposed to userspace * without a warning. */ params.mode = VERITY_MODE_EIO; } if (!verity.table) { goto out; } params.table = strdup(verity.table); if (!params.table) { goto out; } // verify the signature on the table if (verify_verity_signature(verity) < 0) { // Allow signature verification error when the device is unlocked if (fs_mgr_is_device_unlocked()) { retval = FS_MGR_SETUP_VERITY_SKIPPED; LWARNING << "Allow signature verification error when the device is unlocked"; goto out; } if (params.mode == VERITY_MODE_LOGGING) { // the user has been warned, allow mounting without dm-verity retval = FS_MGR_SETUP_VERITY_SKIPPED; goto out; } // invalidate root hash and salt to trigger device-specific recovery if (invalidate_table(params.table, verity.table_length) < 0) { goto out; } } LINFO << "Enabling dm-verity for " << mount_point.c_str() << " (mode " << params.mode << ")"; // Update the verity params using the actual block device path update_verity_table_blk_device(entry->blk_device, ¶ms.table, entry->fs_mgr_flags.slot_select); // load the verity mapping table if (load_verity_table(dm, mount_point, verity.data_size, ¶ms, format_verity_table) == 0) { goto loaded; } if (params.ecc.valid) { // kernel may not support error correction, try without LINFO << "Disabling error correction for " << mount_point.c_str(); params.ecc.valid = false; if (load_verity_table(dm, mount_point, verity.data_size, ¶ms, format_verity_table) == 0) { goto loaded; } } // try the legacy format for backwards compatibility if (load_verity_table(dm, mount_point, verity.data_size, ¶ms, format_legacy_verity_table) == 0) { goto loaded; } if (params.mode != VERITY_MODE_EIO) { // as a last resort, EIO mode should always be supported LINFO << "Falling back to EIO mode for " << mount_point.c_str(); params.mode = VERITY_MODE_EIO; if (load_verity_table(dm, mount_point, verity.data_size, ¶ms, format_legacy_verity_table) == 0) { goto loaded; } } LERROR << "Failed to load verity table for " << mount_point.c_str(); goto out; loaded: if (!dm.GetDmDevicePathByName(mount_point, &verity_blk_name)) { LERROR << "Couldn't get verity device number!"; goto out; } // mark the underlying block device as read-only fs_mgr_set_blk_ro(entry->blk_device); // Verify the entire partition in one go // If there is an error, allow it to mount as a normal verity partition. if (entry->fs_mgr_flags.verify_at_boot) { LINFO << "Verifying partition " << entry->blk_device << " at boot"; int err = read_partition(verity_blk_name.c_str(), verity.data_size); if (!err) { LINFO << "Verified verity partition " << entry->blk_device << " at boot"; verified_at_boot = true; } } // assign the new verity block device as the block device if (!verified_at_boot) { entry->blk_device = verity_blk_name; } else if (!dm.DeleteDevice(mount_point)) { LERROR << "Failed to remove verity device " << mount_point.c_str(); goto out; } // make sure we've set everything up properly if (wait_for_verity_dev && !fs_mgr_wait_for_file(entry->blk_device, 1s)) { goto out; } retval = FS_MGR_SETUP_VERITY_SUCCESS; out: if (fd != -1) { close(fd); } fec_close(f); free(params.table); return retval; }
// --------------------------------------------------------------------------- // // Read Master Boot Record (partitions) // static Cyg_ErrNo read_mbr(disk_channel *chan) { cyg_disk_info_t *info = chan->info; disk_funs *funs = chan->funs; disk_controller *ctlr = chan->controller; cyg_uint8 *buf = (cyg_uint8*)malloc(info->block_size); Cyg_ErrNo res = ENOERR; int i; D(("read MBR\n")); for (i = 0; i < info->partitions_num; i++) info->partitions[i].type = 0x00; cyg_drv_mutex_lock( &ctlr->lock ); while( ctlr->busy ) cyg_drv_cond_wait( &ctlr->queue ); ctlr->busy = true; ctlr->result = -EWOULDBLOCK; for( i = 0; i < sizeof(buf); i++ ) buf[i] = 0; //diag_printf("buf = %p\n",buf); res = (funs->read)(chan, (void *)buf, 1, 0); if( res == -EWOULDBLOCK ) { // If the driver replys EWOULDBLOCK, then the transfer is // being handled asynchronously and when it is finished it // will call disk_transfer_done(). This will wake us up here // to continue. while( ctlr->result == -EWOULDBLOCK ) cyg_drv_cond_wait( &ctlr->async ); res = ctlr->result; } ctlr->busy = false; cyg_drv_mutex_unlock( &ctlr->lock ); if (ENOERR != res) return res; #ifdef DEBUG diag_dump_buf_with_offset( buf, 512, buf ); #endif //for test //buf[MBR_SIG_ADDR+0]=0x55;buf[MBR_SIG_ADDR+1]=0xAA; if (MBR_SIG_BYTE0 == buf[MBR_SIG_ADDR+0] && MBR_SIG_BYTE1 == buf[MBR_SIG_ADDR+1]) { int npart; D(("disk MBR found\n")); npart = info->partitions_num < MBR_PART_NUM ? info->partitions_num : MBR_PART_NUM; for (i = 0; i < MBR_PART_NUM; i++) { cyg_disk_partition_t *part = &info->partitions[i]; part->index = i+1; read_partition(&buf[MBR_PART_ADDR+MBR_PART_SIZE*i], info, part); //read_partition(&buftest[MBR_PART_SIZE*i], info, part); #ifdef DEBUG if (0x00 != part->type) { D(("\ndisk MBR partition %d:\n", i)); D((" type = %02X\n", part->type)); D((" state = %02X\n", part->state)); D((" start = %d\n", part->start)); D((" end = %d\n", part->end)); D((" size = %d\n\n", part->size)); } #endif #if EBR if(part->type == 0x05 || part->type == 0x0F) read_ebr(chan,part); #endif } } free(buf); return ENOERR; }
static Cyg_ErrNo read_ebr(disk_channel *chan,cyg_disk_partition_t *part) { cyg_disk_info_t *info = chan->info; disk_funs *funs = chan->funs; disk_controller *ctlr = chan->controller; cyg_uint8 *buf = (cyg_uint8*)malloc(info->block_size); Cyg_ErrNo res = ENOERR; cyg_uint32 start=0; int i,index = 5; cyg_disk_partition_t *oldpart,*newpart=part; D(("read EBR\n")); while(1) { cyg_drv_mutex_lock( &ctlr->lock ); while( ctlr->busy ) cyg_drv_cond_wait( &ctlr->queue ); ctlr->busy = true; ctlr->result = -EWOULDBLOCK; res = (funs->read)(chan, (void *)buf, 1, newpart->start); if( res == -EWOULDBLOCK ) { // If the driver replys EWOULDBLOCK, then the transfer is // being handled asynchronously and when it is finished it // will call disk_transfer_done(). This will wake us up here // to continue. while( ctlr->result == -EWOULDBLOCK ) cyg_drv_cond_wait( &ctlr->async ); res = ctlr->result; } ctlr->busy = false; cyg_drv_mutex_unlock( &ctlr->lock ); if (ENOERR != res) return res; #ifdef DEBUG diag_dump_buf_with_offset( buf, 512, buf ); #endif if (MBR_SIG_BYTE0 == buf[MBR_SIG_ADDR+0] && MBR_SIG_BYTE1 == buf[MBR_SIG_ADDR+1]) { D(("disk EBR found\n")); start = newpart->start; read_partition(&buf[MBR_PART_ADDR+MBR_PART_SIZE*0], info, newpart); //read_partition(&buftest[MBR_PART_SIZE*0], info, newpart); newpart->start += start; newpart->end += start; #ifdef DEBUG if (0x00 != part->type) { // D(("\ndisk MBR partition %d:\n", i)); D((" type = %02X\n", newpart->type)); D((" state = %02X\n", newpart->state)); D((" start = %d\n", newpart->start)); D((" end = %d\n", newpart->end)); D((" size = %d\n\n", newpart->size)); } #endif if(0x00 != buf[MBR_PART_ADDR+MBR_PART_SIZE+4]) //if(0x00 != buftest[MBR_PART_SIZE*1+4]) { oldpart = newpart; newpart = (cyg_disk_partition_t *)malloc(sizeof(struct cyg_disk_partition_t)); memset(newpart,0,sizeof(struct cyg_disk_partition_t)); oldpart->pnext = newpart; newpart->index = index; index++; info->partitions_num++; newpart->pnext = NULL; read_partition(&buf[MBR_PART_ADDR+MBR_PART_SIZE], info, newpart); newpart->start += start; newpart->end += start; } else break; } else break; } free(buf); return res; }