mirror of
https://github.com/ventoy/Ventoy.git
synced 2025-05-19 01:35:15 -04:00
add support for linux vdisk(vhd/vdi/raw)
This commit is contained in:
parent
3c649b281f
commit
d02f184a8d
26 changed files with 1043 additions and 135 deletions
|
@ -25,6 +25,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||
#include <ventoy.h>
|
||||
|
||||
int g_debug = 0;
|
||||
int g_hddmode = 0;
|
||||
char *g_cmdline_copy;
|
||||
void *g_initrd_addr;
|
||||
size_t g_initrd_len;
|
||||
|
@ -55,6 +56,40 @@ uint64 g_fixup_iso9660_secover_tot_secs = 0;
|
|||
static struct int13_disk_address __bss16 ( ventoy_address );
|
||||
#define ventoy_address __use_data16 ( ventoy_address )
|
||||
|
||||
static uint64_t ventoy_remap_lba_hdd(uint64_t lba, uint32_t *count)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t max_sectors;
|
||||
ventoy_img_chunk *cur;
|
||||
|
||||
if ((NULL == g_cur_chunk) || (lba < g_cur_chunk->img_start_sector) ||
|
||||
(lba > g_cur_chunk->img_end_sector))
|
||||
{
|
||||
g_cur_chunk = NULL;
|
||||
for (i = 0; i < g_img_chunk_num; i++)
|
||||
{
|
||||
cur = g_chunk + i;
|
||||
if (lba >= cur->img_start_sector && lba <= cur->img_end_sector)
|
||||
{
|
||||
g_cur_chunk = cur;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (g_cur_chunk)
|
||||
{
|
||||
max_sectors = g_cur_chunk->img_end_sector - lba + 1;
|
||||
if (*count > max_sectors)
|
||||
{
|
||||
*count = max_sectors;
|
||||
}
|
||||
|
||||
return g_cur_chunk->disk_start_sector + (lba - g_cur_chunk->img_start_sector);
|
||||
}
|
||||
return lba;
|
||||
}
|
||||
|
||||
static uint64_t ventoy_remap_lba(uint64_t lba, uint32_t *count)
|
||||
{
|
||||
uint32_t i;
|
||||
|
@ -92,6 +127,72 @@ static uint64_t ventoy_remap_lba(uint64_t lba, uint32_t *count)
|
|||
return lba;
|
||||
}
|
||||
|
||||
static int ventoy_vdisk_read_real_hdd(uint64_t lba, unsigned int count, unsigned long buffer)
|
||||
{
|
||||
uint32_t left = 0;
|
||||
uint32_t readcount = 0;
|
||||
uint32_t tmpcount = 0;
|
||||
uint16_t status = 0;
|
||||
uint64_t curlba = 0;
|
||||
uint64_t maplba = 0;
|
||||
unsigned long phyaddr;
|
||||
|
||||
curlba = lba;
|
||||
left = count;
|
||||
|
||||
#if VTOY_DEBUG
|
||||
printf("ventoy_vdisk_read_real_hdd: %llu %u\n", lba, count);
|
||||
#endif
|
||||
|
||||
while (left > 0)
|
||||
{
|
||||
readcount = left;
|
||||
maplba = ventoy_remap_lba_hdd(curlba, &readcount);
|
||||
|
||||
tmpcount = readcount;
|
||||
|
||||
phyaddr = user_to_phys(buffer, 0);
|
||||
|
||||
while (tmpcount > 0)
|
||||
{
|
||||
/* Use INT 13, 42 to read the data from real disk */
|
||||
ventoy_address.lba = maplba;
|
||||
ventoy_address.buffer.segment = (uint16_t)(phyaddr >> 4);
|
||||
ventoy_address.buffer.offset = (uint16_t)(phyaddr & 0x0F);
|
||||
|
||||
if (tmpcount >= 64) /* max sectors per transmit */
|
||||
{
|
||||
ventoy_address.count = 64;
|
||||
tmpcount -= 64;
|
||||
maplba += 64;
|
||||
phyaddr += 32768;
|
||||
}
|
||||
else
|
||||
{
|
||||
ventoy_address.count = tmpcount;
|
||||
tmpcount = 0;
|
||||
}
|
||||
|
||||
__asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
|
||||
"sti\n\t"
|
||||
"int $0x13\n\t"
|
||||
"sti\n\t" /* BIOS bugs */
|
||||
"jc 1f\n\t"
|
||||
"xorw %%ax, %%ax\n\t"
|
||||
"\n1:\n\t" )
|
||||
: "=a" ( status )
|
||||
: "a" ( 0x4200 ), "d" ( VENTOY_BIOS_FAKE_DRIVE ),
|
||||
"S" ( __from_data16 ( &ventoy_address ) ) );
|
||||
}
|
||||
|
||||
curlba += readcount;
|
||||
left -= readcount;
|
||||
buffer += (readcount * 512);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_vdisk_read_real(uint64_t lba, unsigned int count, unsigned long buffer)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
|
@ -297,6 +398,13 @@ int ventoy_vdisk_read(struct san_device *sandev, uint64_t lba, unsigned int coun
|
|||
|
||||
ix86 = (struct i386_all_regs *)sandev->x86_regptr;
|
||||
|
||||
if (g_hddmode)
|
||||
{
|
||||
ventoy_vdisk_read_real_hdd(lba, count, buffer);
|
||||
ix86->regs.dl = sandev->drive;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Workaround for SSTR PE loader error */
|
||||
if (g_fixup_iso9660_secover_start)
|
||||
{
|
||||
|
@ -441,9 +549,12 @@ static void ventoy_dump_chain(ventoy_chain_head *chain)
|
|||
uint32_t i = 0;
|
||||
uint8_t chksum = 0;
|
||||
uint8_t *guid;
|
||||
uint8_t *sig;
|
||||
uint8_t *vtoy_reserve;
|
||||
|
||||
guid = chain->os_param.vtoy_disk_guid;
|
||||
sig = chain->os_param.vtoy_disk_signature;
|
||||
|
||||
for (i = 0; i < sizeof(ventoy_os_param); i++)
|
||||
{
|
||||
chksum += *((uint8_t *)(&(chain->os_param)) + i);
|
||||
|
@ -457,6 +568,7 @@ static void ventoy_dump_chain(ventoy_chain_head *chain)
|
|||
|
||||
printf("os_param->chksum=0x%x (%s)\n", chain->os_param.chksum, chksum ? "FAILED" : "SUCCESS");
|
||||
printf("os_param->vtoy_disk_guid=%02x%02x%02x%02x\n", guid[0], guid[1], guid[2], guid[3]);
|
||||
printf("os_param->vtoy_disk_signature=%02x%02x%02x%02x\n", sig[0], sig[1], sig[2], sig[3]);
|
||||
printf("os_param->vtoy_disk_size=%llu\n", chain->os_param.vtoy_disk_size);
|
||||
printf("os_param->vtoy_disk_part_id=%u\n", chain->os_param.vtoy_disk_part_id);
|
||||
printf("os_param->vtoy_disk_part_type=%u\n", chain->os_param.vtoy_disk_part_type);
|
||||
|
@ -530,19 +642,33 @@ static int ventoy_update_image_location(ventoy_os_param *param)
|
|||
}
|
||||
|
||||
memcpy(&location->guid, ¶m->guid, sizeof(ventoy_guid));
|
||||
location->image_sector_size = 2048;
|
||||
location->image_sector_size = g_hddmode ? 512 : 2048;
|
||||
location->disk_sector_size = g_chain->disk_sector_size;
|
||||
location->region_count = g_img_chunk_num;
|
||||
|
||||
region = location->regions;
|
||||
|
||||
for (i = 0; i < g_img_chunk_num; i++)
|
||||
if (g_hddmode)
|
||||
{
|
||||
region->image_sector_count = chunk->img_end_sector - chunk->img_start_sector + 1;
|
||||
region->image_start_sector = chunk->img_start_sector;
|
||||
region->disk_start_sector = chunk->disk_start_sector;
|
||||
region++;
|
||||
chunk++;
|
||||
for (i = 0; i < g_img_chunk_num; i++)
|
||||
{
|
||||
region->image_sector_count = chunk->disk_end_sector - chunk->disk_start_sector + 1;
|
||||
region->image_start_sector = chunk->img_start_sector * 4;
|
||||
region->disk_start_sector = chunk->disk_start_sector;
|
||||
region++;
|
||||
chunk++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < g_img_chunk_num; i++)
|
||||
{
|
||||
region->image_sector_count = chunk->img_end_sector - chunk->img_start_sector + 1;
|
||||
region->image_start_sector = chunk->img_start_sector;
|
||||
region->disk_start_sector = chunk->disk_start_sector;
|
||||
region++;
|
||||
chunk++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -553,6 +679,7 @@ int ventoy_boot_vdisk(void *data)
|
|||
uint8_t chksum = 0;
|
||||
unsigned int i;
|
||||
unsigned int drive;
|
||||
ventoy_img_chunk *cur;
|
||||
|
||||
(void)data;
|
||||
|
||||
|
@ -562,8 +689,14 @@ int ventoy_boot_vdisk(void *data)
|
|||
{
|
||||
g_debug = 1;
|
||||
printf("### ventoy chain boot begin... ###\n");
|
||||
printf("cmdline: <%s>\n", g_cmdline_copy);
|
||||
ventoy_debug_pause();
|
||||
}
|
||||
|
||||
if (strstr(g_cmdline_copy, "sector512"))
|
||||
{
|
||||
g_hddmode = 1;
|
||||
}
|
||||
|
||||
g_chain = (ventoy_chain_head *)g_initrd_addr;
|
||||
g_chunk = (ventoy_img_chunk *)((char *)g_chain + g_chain->img_chunk_offset);
|
||||
|
@ -601,6 +734,16 @@ int ventoy_boot_vdisk(void *data)
|
|||
ventoy_dump_chain(g_chain);
|
||||
}
|
||||
|
||||
if (g_hddmode)
|
||||
{
|
||||
for (i = 0; i < g_img_chunk_num; i++)
|
||||
{
|
||||
cur = g_chunk + i;
|
||||
cur->img_start_sector *= 4;
|
||||
cur->img_end_sector = cur->img_end_sector * 4 + 3;
|
||||
}
|
||||
}
|
||||
|
||||
drive = ventoy_int13_hook(g_chain);
|
||||
|
||||
if (g_debug)
|
||||
|
|
|
@ -1051,6 +1051,10 @@ static __asmcall void int13 ( struct i386_all_regs *ix86 ) {
|
|||
/* We simulate a cdrom, so no need to sync hd drive number */
|
||||
//int13_check_num_drives();
|
||||
|
||||
#if VTOY_DEBUG
|
||||
printf("int13 0x%x 0x%x\n", bios_drive, command); sleep(1);
|
||||
#endif
|
||||
|
||||
if (bios_drive == VENTOY_BIOS_FAKE_DRIVE)
|
||||
{
|
||||
ix86->regs.dl = g_sandev->exdrive;
|
||||
|
@ -1255,39 +1259,15 @@ static void int13_hook_vector ( void ) {
|
|||
* @ret rc Return status code
|
||||
*/
|
||||
static int int13_load_mbr ( unsigned int drive, struct segoff *address ) {
|
||||
uint16_t status;
|
||||
int discard_b, discard_c, discard_d;
|
||||
uint16_t magic;
|
||||
|
||||
/* Use INT 13, 02 to read the MBR */
|
||||
address->segment = 0;
|
||||
address->offset = 0x7c00;
|
||||
__asm__ __volatile__ ( REAL_CODE ( "pushw %%es\n\t"
|
||||
"pushl %%ebx\n\t"
|
||||
"popw %%bx\n\t"
|
||||
"popw %%es\n\t"
|
||||
"stc\n\t"
|
||||
"sti\n\t"
|
||||
"int $0x13\n\t"
|
||||
"sti\n\t" /* BIOS bugs */
|
||||
"jc 1f\n\t"
|
||||
"xorw %%ax, %%ax\n\t"
|
||||
"\n1:\n\t"
|
||||
"popw %%es\n\t" )
|
||||
: "=a" ( status ), "=b" ( discard_b ),
|
||||
"=c" ( discard_c ), "=d" ( discard_d )
|
||||
: "a" ( 0x0201 ), "b" ( *address ),
|
||||
"c" ( 1 ), "d" ( drive ) );
|
||||
if ( status ) {
|
||||
DBG ( "INT13 drive %02x could not read MBR (status %04x)\n",
|
||||
drive, status );
|
||||
return -EIO;
|
||||
}
|
||||
address->segment = 0;
|
||||
address->offset = 0x7c00;
|
||||
copy_to_real(address->segment, address->offset, g_sandev->boot_catalog_sector, 512);
|
||||
|
||||
/* Check magic signature */
|
||||
get_real ( magic, address->segment,
|
||||
( address->offset +
|
||||
offsetof ( struct master_boot_record, magic ) ) );
|
||||
get_real ( magic, address->segment, (address->offset + offsetof ( struct master_boot_record, magic ) ) );
|
||||
|
||||
if ( magic != INT13_MBR_MAGIC ) {
|
||||
DBG ( "INT13 drive %02x does not contain a valid MBR\n",
|
||||
drive );
|
||||
|
@ -1443,8 +1423,14 @@ unsigned int ventoy_int13_hook (ventoy_chain_head *chain)
|
|||
/* hook will copy num_drives to dl when int13 08 was called, so must initialize it's value */
|
||||
get_real(num_drives, BDA_SEG, BDA_NUM_DRIVES);
|
||||
|
||||
//natural_drive = num_drives | 0x80;
|
||||
natural_drive = 0xE0; /* just set a cdrom drive number 224 */
|
||||
if (g_hddmode)
|
||||
{
|
||||
natural_drive = num_drives | 0x80;
|
||||
}
|
||||
else
|
||||
{
|
||||
natural_drive = 0xE0; /* just set a cdrom drive number 224 */
|
||||
}
|
||||
|
||||
if (chain->disk_drive >= 0x80 && chain->drive_map >= 0x80)
|
||||
{
|
||||
|
@ -1456,8 +1442,8 @@ unsigned int ventoy_int13_hook (ventoy_chain_head *chain)
|
|||
g_sandev = zalloc(sizeof(struct san_device) + sizeof(struct int13_data));
|
||||
g_sandev->priv = int13 = (struct int13_data *)(g_sandev + 1);
|
||||
g_sandev->drive = int13->natural_drive = natural_drive;
|
||||
g_sandev->is_cdrom = 1;
|
||||
g_sandev->blksize_shift = 2;
|
||||
g_sandev->is_cdrom = g_hddmode ? 0 : 1;
|
||||
g_sandev->blksize_shift = g_hddmode ? 0 : 2;
|
||||
g_sandev->capacity.blksize = 512;
|
||||
g_sandev->capacity.blocks = chain->virt_img_size_in_bytes / 512;
|
||||
g_sandev->exdrive = chain->disk_drive;
|
||||
|
@ -1521,9 +1507,20 @@ int ventoy_int13_boot ( unsigned int drive, void *imginfo, const char *cmdline)
|
|||
struct ibft_table *ibft = NULL;
|
||||
|
||||
/* Look for a usable boot sector */
|
||||
if ( ( ( rc = int13_load_eltorito ( drive, &address ) ) != 0 ) &&
|
||||
( ( rc = int13_load_mbr ( drive, &address ) ) != 0 ))
|
||||
if (g_hddmode)
|
||||
{
|
||||
if ((rc = int13_load_mbr(drive, &address)) != 0)
|
||||
{
|
||||
printf("int13_load_mbr %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ( ( rc = int13_load_eltorito ( drive, &address ) ) != 0 ) &&
|
||||
( ( rc = int13_load_mbr ( drive, &address ) ) != 0 ))
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (imginfo)
|
||||
{
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
//#define VTOY_DEBUG 1
|
||||
|
||||
#define grub_uint64_t uint64_t
|
||||
#define grub_uint32_t uint32_t
|
||||
#define grub_uint16_t uint16_t
|
||||
|
@ -43,7 +45,7 @@ typedef struct ventoy_image_location
|
|||
{
|
||||
ventoy_guid guid;
|
||||
|
||||
/* image sector size, currently this value is always 2048 */
|
||||
/* image sector size, 2048/512 */
|
||||
grub_uint32_t image_sector_size;
|
||||
|
||||
/* disk sector size, normally the value is 512 */
|
||||
|
@ -86,7 +88,9 @@ typedef struct ventoy_os_param
|
|||
|
||||
grub_uint64_t vtoy_reserved[4]; // Internal use by ventoy
|
||||
|
||||
grub_uint8_t reserved[31];
|
||||
grub_uint8_t vtoy_disk_signature[4];
|
||||
|
||||
grub_uint8_t reserved[27];
|
||||
}ventoy_os_param;
|
||||
|
||||
typedef struct ventoy_iso9660_override
|
||||
|
@ -182,6 +186,7 @@ typedef struct ventoy_sector_flag
|
|||
#define VENTOY_BOOT_FIXBIN_DRIVE 0xFD
|
||||
|
||||
extern int g_debug;
|
||||
extern int g_hddmode;
|
||||
extern char *g_cmdline_copy;
|
||||
extern void *g_initrd_addr;
|
||||
extern size_t g_initrd_len;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue