* [Qemu-devel] updated block-partition driver
@ 2007-01-31 2:53 jbrown105
0 siblings, 0 replies; only message in thread
From: jbrown105 @ 2007-01-31 2:53 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 505 bytes --]
This edition is finally able to construct a real partition table. Still
buggy
(linux fdisk complains about it) but partitions are mountable inside the
VM.
The full syntax is:
qemu -hda
partition:boot=1,bootloader=bootmbr.bin,/dev/hda1,sysid=0xC,partition.raw,sysid=ox82,/dev/sda2,sysid=0x83
You can simplify it though (assuming /dev/hda1 holds a FAT32
filesystem):
qemu -hda partition:/dev/hda1
Good luck.
--
jbrown105@speedymail.org
--
http://www.fastmail.fm - Send your email first class
[-- Attachment #2: block_composite.h --]
[-- Type: text/plain, Size: 1508 bytes --]
/*
* Block driver to use composite images
*
* Copyright (c) 2007 Jim Brown
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef BLOCK_COMPOSITE_H
#define BLOCK_COMPOSITE_H
#include "vl.h"
#include "block_int.h"
typedef struct SlaveDriverState {
BlockDriverState * bs;
int start_sector;
int end_sector;
} SlaveDriverState;
typedef struct BDRVPartState {
SlaveDriverState * slave_bs;
int slave_count;
} BDRVPartState;
#endif /*BLOCK_COMPOSITE_H*/
[-- Attachment #3: block-composite.c --]
[-- Type: text/plain, Size: 6155 bytes --]
/*
* Block driver to use composite images
*
* Copyright (c) 2007 Jim Brown
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "block_composite.h"
static int composite_probe(const uint8_t *buf, int buf_size, const char *filename)
{
if (strstart(filename, "composite:", NULL))
return 100;
return 0;
}
static int composite_open(BlockDriverState *bs, const char *nfilename, int flags)
{
BDRVPartState *s = bs->opaque;
BlockDriverState * slave_bs;
int previous_start, file_count = 1, i;
const char * zfilename = &(nfilename[10]), * nptr = zfilename;
char * filename;
bs->read_only = 0;
s->slave_count = 0;
previous_start = 0;
while (nptr != NULL)
{
nptr = strchr(nptr, ',')+1;
if ((nptr-1) != NULL)
{
file_count++;
}
else
{
nptr = NULL;
}
}
s->slave_bs = qemu_mallocz(sizeof(SlaveDriverState)*file_count);
if (s->slave_bs == NULL) return -1;
nptr = zfilename;
while (nptr != NULL)
{
nptr = strchr(zfilename, ',')+1;
if ((nptr-1) != NULL)
{
filename = strndup(zfilename, (size_t)((nptr-1)-zfilename));
zfilename = nptr;
}
else
{
filename = strdup(zfilename);
nptr = NULL;
}
slave_bs = qemu_mallocz(sizeof(BlockDriverState));
if ((slave_bs == NULL) || (bdrv_open2(slave_bs, filename, 0, NULL) != 0))
{
for (i = 0; i < s->slave_count; i++)
{
bdrv_close(s->slave_bs[i].bs);
qemu_free(s->slave_bs[i].bs);
}
qemu_free(s->slave_bs);
return -1;
}
free(filename);
s->slave_bs[s->slave_count].bs = slave_bs;
s->slave_bs[s->slave_count].start_sector = previous_start;
previous_start = previous_start + s->slave_bs[s->slave_count].bs->total_sectors;
s->slave_count++;
if (slave_bs->read_only)
{
bs->read_only = 1;
}
}
bs->total_sectors = previous_start;
return 0;
}
static int composite_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVPartState *s = bs->opaque;
int ret,sstart,send,i;
sstart = -1;
for (i = 0; i < s->slave_count; i++)
{
if ((s->slave_bs[i].start_sector +
s->slave_bs[i].bs->total_sectors > sector_num)
&& (s->slave_bs[i].start_sector <= sector_num))
{
sstart = i;
break;
}
}
if (sstart == -1) return -1;
send = -1;
for (i = 0; i < s->slave_count; i++)
{
if((s->slave_bs[i].start_sector + s->slave_bs[i].bs->total_sectors
> sector_num+nb_sectors)
&& (s->slave_bs[i].start_sector
<= sector_num+nb_sectors))
{
send = i;
break;
}
}
if (send == -1) return -1;
if (sstart > send) return -2; //wtf???
int a = 0, b = 0, bufpos = 0;
i = sstart;
while (i < send)
{
a = s->slave_bs[i].bs->total_sectors;
ret = bdrv_read(s->slave_bs[i].bs, sector_num+b, &(buf[bufpos]), a);
if (ret != 0) return ret;
b = b+a;
bufpos = bufpos + (a * 512);
i++;
}
return bdrv_read(s->slave_bs[send].bs, sector_num+b, &(buf[bufpos]), nb_sectors-b);
}
static int composite_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVPartState *s = bs->opaque;
int ret,sstart,send,i;
sstart = -1;
for (i = 0; i < s->slave_count; i++)
{
if ((s->slave_bs[i].start_sector +
s->slave_bs[i].bs->total_sectors > sector_num)
&& (s->slave_bs[i].start_sector <= sector_num))
{
sstart = i;
break;
}
}
if (sstart == -1) return -1;
send = -1;
for (i = 0; i < s->slave_count; i++)
{
if((s->slave_bs[i].start_sector + s->slave_bs[i].bs->total_sectors
> sector_num+nb_sectors)
&& (s->slave_bs[i].start_sector
<= sector_num+nb_sectors))
{
send = i;
break;
}
}
if (send == -1) return -1;
if (sstart > send) return -2; //wtf???
int a = 0, b = 0, bufpos = 0;
i = sstart;
while (i < send)
{
a = s->slave_bs[i].bs->total_sectors;
ret = bdrv_write(s->slave_bs[i].bs, sector_num+b, &(buf[bufpos]), a);
if (ret != 0) return ret;
b = b+a;
bufpos = bufpos + (a * 512);
i++;
}
i= bdrv_write(s->slave_bs[send].bs, sector_num+b, &(buf[bufpos]), nb_sectors-b);
return i;
}
static void composite_close(BlockDriverState *bs)
{
BDRVPartState *s = bs->opaque;
int i;
for (i = 0; i < s->slave_count; i++)
{
bdrv_close(s->slave_bs[i].bs);
qemu_free(s->slave_bs[i].bs);
}
qemu_free(s->slave_bs);
s->slave_bs = NULL;
}
static int composite_create(const char *filename, int64_t total_size,
const char *backing_file, int flags)
{
/* what would be the point... just make a raw or qcow */
return -ENOTSUP;
}
BlockDriver bdrv_composite = {
"composite",
sizeof(BDRVPartState),
composite_probe,
composite_open,
composite_read,
composite_write,
composite_close,
composite_create,
.protocol_name = "composite",
};
[-- Attachment #4: block-ram.c --]
[-- Type: text/plain, Size: 3070 bytes --]
/*
* Block driver in RAM
*
* Copyright (c) 2007 Jim Boown
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "vl.h"
#include "block_int.h"
#include <assert.h>
#ifndef QEMU_TOOL
#include "exec-all.h"
#endif
typedef struct BDRVRamState {
char * ram_data;
} BDRVRamState;
static int ram_probe(const uint8_t *buf, int buf_size, const char *filename)
{
if (strstart(filename, "ram:", NULL))
return 100;
return 0;
}
static int ram_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVRamState *s = bs->opaque;
if (!strstart(filename, "ram:", NULL))
return -1;
int sectnum = atoi(filename+4);
if (sectnum == 0) return -2;
s->ram_data = qemu_mallocz(sectnum*512);
if (s->ram_data == NULL) return -2;
memset(s->ram_data, ' ', sectnum*512);
bs->total_sectors = sectnum;
return 0;
}
static int ram_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVRamState *s = bs->opaque;
if (sector_num+nb_sectors > bs->total_sectors)
return -1;
memcpy(buf, &(s->ram_data[sector_num*512]), nb_sectors*512);
return 0;
}
static int ram_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVRamState *s = bs->opaque;
if (sector_num+nb_sectors > bs->total_sectors)
return -1;
memcpy(&(s->ram_data[sector_num*512]), buf, nb_sectors*512);
return 0;
}
static void ram_close(BlockDriverState *bs)
{
BDRVRamState *s = bs->opaque;
qemu_free(s->ram_data);
}
static int ram_is_allocated(BlockDriverState *bs,
int64_t sector_num, int nb_sectors, int* n)
{
*n = bs->total_sectors - sector_num;
if (*n > nb_sectors)
*n = nb_sectors;
else if (*n < 0)
return 0;
return 1;
}
BlockDriver bdrv_ram = {
"ram",
sizeof(BDRVRamState),
ram_probe,
ram_open,
ram_read,
ram_write,
ram_close,
NULL,
NULL,
ram_is_allocated,
.protocol_name = "ram",
};
[-- Attachment #5: block-partition.c --]
[-- Type: text/plain, Size: 8225 bytes --]
/*
* Block driver to use partitions as hard disks
*
* Copyright (c) 2007 Jim Brown
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/* we need this in order to be able to figure out the sizes of the individual partitions */
#include "block_composite.h"
/* in sectors */
#define MBR_SIZE 63
/* ideally this would be dynamically allocated */
#define MAX_PART_STRING 4096
typedef struct CompositeDriverState {
BlockDriverState * bs;
} CompositeDriverState;
static int partition_probe(const uint8_t *buf, int buf_size, const char *filename)
{
if (strstart(filename, "partition:", NULL))
return 100;
return 0;
}
static int partition_open(BlockDriverState *bs, const char *nfilename, int flags)
{
CompositeDriverState *s = bs->opaque;
BlockDriverState * bbs;
int64_t size, totalsectors;
int boot_fd, i, bootid = 1, partition_count = 0;
int head, cylinder, sector, oldstart;
int oldhead, oldcylinder, oldsector;
int sysid[10]; /* probably only need 4 */
const char * zfilename = &(nfilename[10]), * nptr = zfilename;
char * filename, * strerr = NULL, * bootloader;
char mbr_data[MBR_SIZE*512], partition_string[MAX_PART_STRING];
partition_string[0] = '\0';
strcat(partition_string, "composite:ram:63,"); /*63 == MBR_SIZE */
bootloader = strdup("bootmbr.bin");
bs->read_only = 0;
int n = 0;
while (nptr != NULL)
{
nptr = strchr(zfilename, ',')+1;
if ((nptr-1) != NULL)
{
filename = strndup(zfilename, (size_t)((nptr-1)-zfilename));
zfilename = nptr;
}
else
{
filename = strdup(zfilename);
nptr = NULL;
}
if (strncmp(filename, "sysid=", 6) == 0)
{
/* just pass in any sysid, e.g. 0x82 or 0x0C */
char ffd[strlen(filename)];
ffd[0] = ' ';
ffd[1] = '\0';
strcat(ffd, filename+6);
sysid[partition_count] = (int)strtol(ffd, &strerr, 0);
if (*strerr != '\0') /* detect error in conversion */
sysid[partition_count-1] = 0x0C; /* default to win98 FAT32 */
}
else if (strncmp(filename, "boot=", 5) == 0)
{
/* between 1 and 4, 1 selects the first partition, 4 selects the last partition (if you are making a hard disk with 4 partitions in it) */
char ffd[strlen(filename)];
int bootidf;
ffd[0] = ' ';
ffd[1] = '\0';
strcat(ffd, filename+5);
bootidf = (int)strtol(ffd, &strerr, 0);
if (*strerr == '\0') /* no detect error in conversion */
bootid = bootidf;
}
else if (strncmp(filename, "bootloader=", 11) == 0)
{
free(bootloader);
bootloader = strdup(filename+11);
}
else
{
/* the string shouldn't start with a ',' */
if (n)
strcat(partition_string, ",");
else
n = 1;
strcat(partition_string, filename);
partition_count ++;
sysid[partition_count-1] = 0x0C; /* default to win98 FAT32 */
}
free(filename);
}
s->bs = qemu_mallocz(sizeof(BlockDriverState));
if ((s->bs == NULL) || (bdrv_open2(s->bs, partition_string, 0, NULL) != 0))
{
free(bootloader);
return -1;
}
bs->total_sectors = s->bs->total_sectors;
bs->read_only = s->bs->read_only;
/* get the fake MBR */
memset(mbr_data, 0, MBR_SIZE*512);
boot_fd = open(bootloader, O_RDONLY);
if (boot_fd == -1)
{
printf("Warning: failed to open bootmbr.bin - MBR will not be bootable\n");
}
else
{
if (read(boot_fd, mbr_data, MBR_SIZE*512) == -1)
{
printf("Warning: failed to read bootmbr.bin - MBR will not be bootable\n");
}
close(boot_fd);
}
oldstart = 0x3F; //3F == 63
oldhead = 0x01;
oldsector = 0x01;
oldcylinder = 0x00;
/* remember that the very first slave in the composite is the ram image **
* that we're using to store the MBR, so the second slave in the composite
* is the first partition */
for (i = 1; i <= partition_count; i++)
{
/* set up c/h/s */
if (i == partition_count)
{
totalsectors = bs->total_sectors;
}
else
{
bbs = ((BDRVPartState*)s->bs->opaque)->slave_bs[i+1].bs;
totalsectors = bbs->total_sectors;
}
size = totalsectors * 512;
cylinder = size/(63*16);
head = 16;
sector = 63;
/* some bit twiddling here */
sector = (((cylinder >> 8) & 3) << 6) + sector;
/* set up fake MBR - each partition entry is 16 bytes long */
/* start 446 */
/* set which partition is meant to be bootable (that we'll boot from) */
if (i == bootid)
mbr_data[446+((i-1)*16)] = 0x80;
else
mbr_data[446+((i-1)*16)] = 0x00;
/* start head */
mbr_data[447+((i-1)*16)] = oldhead;
/* start sector - only first 6 bits */
mbr_data[448+((i-1)*16)] = oldsector;
/* start cylinder - this byte plus 2 bits from mbr_data[447] */
mbr_data[449+((i-1)*16)] = oldcylinder;
/* system ID */
mbr_data[450+((i-1)*16)] = sysid[i-1];
/* ending head */
mbr_data[451+((i-1)*16)] = head;
/* ending sector */
mbr_data[452+((i-1)*16)] = sector;
/* ending cylinder */
mbr_data[453+((i-1)*16)] = cylinder;
/* absolute start sector - 4 bytes/DWORD */
//mbr_data[454+(i*16)] = 0x3F; // 3F = 63
*((uint32_t*)(mbr_data+454+((i-1)*16))) = cpu_to_le32(oldstart);
/* absolute total number of sectors - 4 bytes/DWORD */
*((uint32_t*)(mbr_data+458+((i-1)*16))) = cpu_to_le32(totalsectors);
/* end 462 */
oldstart = oldstart + totalsectors;
oldhead = head;
oldcylinder = cylinder;
oldsector = sector;
oldsector++;
if (oldsector > 63)
{
oldhead++;
oldsector = 0x01;
if (oldhead > 16)
{
oldcylinder++;
oldhead = 0x01;
}
}
}
/* set the MBR sector signature */
mbr_data[510] = 0x55;
mbr_data[511] = 0xAA;
/* now write it to the ram image */
/*
bs->boot_sector_enabled = 0;
s->bs->boot_sector_enabled = 0;
bbs = ((BDRVPartState*)s->bs->opaque)->slave_bs[0].bs; the ram image
bbs->boot_sector_enabled = 0;
*/
if (bdrv_write(s->bs, 0, mbr_data, MBR_SIZE) != 0)
printf("Warning: failed to commit MBR and partition table to fake hard disk\n");
return 0;
}
static int partition_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
CompositeDriverState *s = bs->opaque;
return bdrv_read(s->bs, sector_num, buf, nb_sectors);
}
static int partition_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
CompositeDriverState *s = bs->opaque;
return bdrv_write(s->bs, sector_num, buf, nb_sectors);
}
static void partition_close(BlockDriverState *bs)
{
CompositeDriverState *s = bs->opaque;
bdrv_close(s->bs);
qemu_free(s->bs);
s->bs = NULL;
}
static int partition_create(const char *filename, int64_t total_size,
const char *backing_file, int flags)
{
/* what would be the point... just make a raw or qcow */
return -ENOTSUP;
}
BlockDriver bdrv_partition = {
"partition",
sizeof(CompositeDriverState),
partition_probe,
partition_open,
partition_read,
partition_write,
partition_close,
partition_create,
.protocol_name = "partition",
};
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2007-01-31 2:53 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-01-31 2:53 [Qemu-devel] updated block-partition driver jbrown105
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).