Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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);
}
Esempio n. 4
0
/*
 * 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, &params.ecc) < 0) {
        params.ecc.valid = false;
    }

    params.ecc_dev = entry->blk_device.c_str();

    if (load_verity_state(*entry, &params.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, &params.table,
                                   entry->fs_mgr_flags.slot_select);

    // load the verity mapping table
    if (load_verity_table(dm, mount_point, verity.data_size, &params, 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, &params, format_verity_table) == 0) {
            goto loaded;
        }
    }

    // try the legacy format for backwards compatibility
    if (load_verity_table(dm, mount_point, verity.data_size, &params, 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, &params,
                              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;
}
Esempio n. 6
0
// ---------------------------------------------------------------------------
//
// 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;
}
Esempio n. 7
0
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;
}