summaryrefslogtreecommitdiff
path: root/memdisk
diff options
context:
space:
mode:
authorShao Miller <shao.miller@yrdsb.edu.on.ca>2009-08-03 21:45:34 -0400
committerShao Miller <shao.miller@yrdsb.edu.on.ca>2009-08-03 23:50:20 -0400
commit3369a18e1a3eae71a8b37bd91cff61dbbe389a2b (patch)
treefb0db869d0a1a5e1314762c5c4676769840a17a4 /memdisk
parent1275c1535315174f355b4bf74e69e572d8b38fc6 (diff)
downloadsyslinux-3369a18e1a3eae71a8b37bd91cff61dbbe389a2b.tar.gz
[memdisk] Add El Torito emulation for .ISO images
With this patch, users can now boot El Torito-bootable .ISO (CD/DVD) images. The user should specify "iso" on the kernel command-line.
Diffstat (limited to 'memdisk')
-rw-r--r--memdisk/Makefile4
-rw-r--r--memdisk/eltorito.c58
-rw-r--r--memdisk/eltorito.h83
-rw-r--r--memdisk/memdisk.inc69
-rw-r--r--memdisk/memdisk_chs_512.asm1
-rw-r--r--memdisk/memdisk_edd_512.asm1
-rw-r--r--memdisk/memdisk_iso_2048.asm1
-rw-r--r--memdisk/memdisk_iso_512.asm1
-rw-r--r--memdisk/setup.c147
9 files changed, 347 insertions, 18 deletions
diff --git a/memdisk/Makefile b/memdisk/Makefile
index 8e76f3d2..f397c979 100644
--- a/memdisk/Makefile
+++ b/memdisk/Makefile
@@ -38,11 +38,11 @@ endif
# Important: init.o16 must be first!!
OBJS16 = init.o16 init32.o
OBJS32 = start32.o setup.o msetup.o e820func.o conio.o memcpy.o memset.o \
- memmove.o unzip.o dskprobe.o \
+ memmove.o unzip.o dskprobe.o eltorito.o \
memdisk_chs_512.o memdisk_edd_512.o \
memdisk_iso_512.o memdisk_iso_2048.o
-CSRC = setup.c msetup.c e820func.c conio.c unzip.c dskprobe.c
+CSRC = setup.c msetup.c e820func.c conio.c unzip.c dskprobe.c eltorito.c
SSRC = start32.S memcpy.S memset.S memmove.S
NASMSRC = memdisk_chs_512.asm memdisk_edd_512.asm \
memdisk_iso_512.asm memdisk_iso_2048.asm \
diff --git a/memdisk/eltorito.c b/memdisk/eltorito.c
new file mode 100644
index 00000000..7e0ba89b
--- /dev/null
+++ b/memdisk/eltorito.c
@@ -0,0 +1,58 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2009 Shao Miller - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * eltorito.c
+ *
+ * EDD-4 El Torito structures and debugging routines
+ */
+
+#include <stdint.h>
+#include "memdisk.h"
+#include "conio.h"
+#include "eltorito.h"
+
+#ifdef DBG_ELTORITO
+void eltorito_dump(uint32_t image)
+{
+ printf("-- El Torito dump --\n", image);
+
+ /* BVD starts at sector 17. */
+ struct edd4_bvd *bvd = (struct edd4_bvd *)(image + 17 * 2048);
+
+ printf("bvd.boot_rec_ind: 0x%02x\n", bvd->boot_rec_ind);
+ printf("bvd.iso9660_id: %c%c%c%c%c\n", bvd->iso9660_id[0],
+ bvd->iso9660_id[1], bvd->iso9660_id[2], bvd->iso9660_id[3],
+ bvd->iso9660_id[4]);
+ printf("bvd.ver: 0x%02x\n", bvd->ver);
+ printf("bvd.eltorito: %s\n", bvd->eltorito);
+ printf("bvd.boot_cat: 0x%08x\n", bvd->boot_cat);
+
+ struct edd4_bootcat *boot_cat =
+ (struct edd4_bootcat *)(image + bvd->boot_cat * 2048);
+
+ printf("boot_cat.validation_entry\n");
+ printf(" .header_id: 0x%02x\n", boot_cat->validation_entry.header_id);
+ printf(" .platform_id: 0x%02x\n", boot_cat->validation_entry.platform_id);
+ printf(" .id_string: %s\n", boot_cat->validation_entry.id_string);
+ printf(" .checksum: 0x%04x\n", boot_cat->validation_entry.checksum);
+ printf(" .key55: 0x%02x\n", boot_cat->validation_entry.key55);
+ printf(" .keyAA: 0x%02x\n", boot_cat->validation_entry.keyAA);
+ printf("boot_cat.initial_entry\n");
+ printf(" .header_id: 0x%02x\n", boot_cat->initial_entry.header_id);
+ printf(" .media_type: 0x%02x\n", boot_cat->initial_entry.media_type);
+ printf(" .load_seg: 0x%04x\n", boot_cat->initial_entry.load_seg);
+ printf(" .system_type: 0x%02x\n", boot_cat->initial_entry.system_type);
+ printf(" .sect_count: %d\n", boot_cat->initial_entry.sect_count);
+ printf(" .load_block: 0x%08x\n", boot_cat->initial_entry.load_block);
+}
+#endif
diff --git a/memdisk/eltorito.h b/memdisk/eltorito.h
new file mode 100644
index 00000000..7d46e1d9
--- /dev/null
+++ b/memdisk/eltorito.h
@@ -0,0 +1,83 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2009 Shao Miller - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * eltorito.h
+ *
+ * EDD-4 El Torito structures and debugging routines
+ */
+
+#include <stdint.h>
+
+/*
+ * Uncomment for El Torito debugging
+ *
+ * #define DBG_ELTORITO 1
+ */
+
+#ifdef DBG_ELTORITO
+extern void eltorito_dump(uint32_t);
+#endif
+
+/* EDD-4 Bootable Optical Disc Drive Boot Volume Descriptor */
+struct edd4_bvd {
+ uint8_t boot_rec_ind; /* Boot Record Indicator */
+ uint8_t iso9660_id[5]; /* ISO9660 ID */
+ uint8_t ver; /* Descriptor Version */
+ uint8_t eltorito[32]; /* "EL TORITO" etc. */
+ uint8_t res1[32]; /* Reserved */
+ uint32_t boot_cat; /* Boot catalog sector */
+ uint8_t res2[1973]; /* Reserved */
+} __attribute__ ((packed));
+
+struct validation_entry {
+ uint8_t header_id; /* Header ID */
+ uint8_t platform_id; /* Platform ID */
+ uint16_t res1; /* Reserved */
+ uint8_t id_string[24]; /* Manufacturer */
+ uint16_t checksum; /* Sums with whole record to zero */
+ uint8_t key55; /* Key byte 0x55 */
+ uint8_t keyAA; /* Key byte 0xAA */
+} __attribute__ ((packed));
+
+struct initial_entry {
+ uint8_t header_id; /* Header ID */
+ uint8_t media_type; /* Media type */
+ uint16_t load_seg; /* Load segment */
+ uint8_t system_type; /* (Filesystem ID) */
+ uint8_t res1; /* Reserved */
+ uint16_t sect_count; /* Emulated sectors to load */
+ uint32_t load_block; /* Starting sector of image */
+ uint8_t res2[4]; /* Reserved */
+} __attribute__ ((packed));
+
+/* EDD-4 Bootable Optical Disc Drive Boot Catalog (fixed-size portions) */
+struct edd4_bootcat {
+ struct validation_entry validation_entry;
+ struct initial_entry initial_entry;
+} __attribute__ ((packed));
+
+/* EDD-4 CD Specification Packet */
+struct edd4_cd_pkt {
+ uint8_t size; /* Packet size */
+ uint8_t type; /* Boot media type (flags) */
+ uint8_t driveno; /* INT 13h drive number */
+ uint8_t controller; /* Controller index */
+ uint32_t start; /* Starting LBA of image */
+ uint16_t devno; /* Device number */
+ uint16_t userbuf; /* User buffer segment */
+ uint16_t load_seg; /* Load segment */
+ uint16_t sect_count; /* Emulated sectors to load */
+ uint8_t geom1; /* Cylinders bits 0 thru 7 */
+ uint8_t geom2; /* Sects/track 0 thru 5, cyls 8, 9 */
+ uint8_t geom3; /* Heads */
+} __attribute__ ((packed));
diff --git a/memdisk/memdisk.inc b/memdisk/memdisk.inc
index 14f077ab..98ad52b7 100644
--- a/memdisk/memdisk.inc
+++ b/memdisk/memdisk.inc
@@ -8,6 +8,7 @@
;
; Copyright 2001-2009 H. Peter Anvin - All Rights Reserved
; Copyright 2009 Intel Corporation; author: H. Peter Anvin
+; Portions copyright 2009 Shao Miller [El Torito code]
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
@@ -135,6 +136,10 @@ Int13Start:
mov ss,ax
mov sp,[cs:MyStack]
+%if ELTORITO
+ cmp word [cs:SavedAX],4a00h ; El Torito function?
+ jae our_drive ; We grab it
+%endif
; See if DL points to our class of device (FD, HD)
push dx
push dx
@@ -205,6 +210,14 @@ our_drive:
; Note: AX == P_AX here
cmp ah,Int13FuncsCnt-1
ja Invalid_jump
+%if ELTORITO
+ mov al,[CD_PKT.type] ; Check if we are in
+ cmp al,0 ; El Torito no emulation mode
+ ja .emulation ; No. We support the function
+ cmp ah,3fh ; Yes. We must not support functions
+ jbe Invalid_jump ; 0 through 3Fh. Check and decide
+.emulation:
+%endif
xor al,al ; AL = 0 is standard entry condition
mov di,ax
shr di,7 ; Convert AH to an offset in DI
@@ -393,8 +406,9 @@ EDDPresence:
jne Invalid
mov P_BX,0AA55h ; EDD signature
mov P_AX,03000h ; EDD 3.0
- mov P_CX,0003h ; Bit 0 - Fixed disk access subset
+ mov P_CX,0007h ; Bit 0 - Fixed disk access subset
; Bit 1 - Locking and ejecting subset
+ ; Bit 2 - EDD subset
pop ax ; Drop return address
xor ax,ax ; Success
jmp DoneWeird ; Success, but AH != 0, sigh...
@@ -575,10 +589,31 @@ edd_setup_regs:
EDDEject:
mov ax,0B200h ; Volume Not Removable
ret
-
+%if ELTORITO
+ElToritoTerminate:
+ TRACER 'T'
+ mov ax,[cs:SavedAX]
+ cmp al,1 ; We only support query, not terminate
+ jne ElToritoErr ; Fail
+ mov es,P_DS ; Caller's DS:SI pointed to packet
+ mov di,P_SI ; We'll use ES:DI
+ mov si,CD_PKT.size ; First byte is packet size
+ xor cx,0 ; Empty our count
+ ;mov cl,[ds:si] ; We'll copy that many bytes
+ mov cl,13h
+ rep movsb ; Copy until CX is zero
+ mov ax,0 ; Success
+ ret
+ElToritoEmulate:
+ElToritoBoot:
+ElToritoCatalog:
+ElToritoErr:
+ TRACER '!'
+ mov ax,100h ; Invalid parameter
+ ret
+%endif ; ELTORITO
%endif ; EDD
-
;
; INT 15h intercept routines
;
@@ -960,7 +995,14 @@ Int13Funcs dw Reset ; 00h - RESET
dw EDDSeek ; 47h - EDD SEEK
dw EDDGetParms ; 48h - EDD GET PARAMETERS
dw EDDDetectChange ; 49h - EDD MEDIA CHANGE STATUS
-%endif
+%if ELTORITO ; EDD El Torito Functions
+ ; ELTORITO _must_ also have EDD
+ dw ElToritoEmulate ; 4Ah - Initiate Disk Emulation
+ dw ElToritoTerminate ; 4Bh - Terminate Disk Emulation
+ dw ElToritoBoot ; 4Ch - Initiate Disk Emu. and Reboot
+ dw ElToritoCatalog ; 4Dh - Return Boot Catalog
+%endif ; ELTORITO
+%endif ; EDD
Int13FuncsEnd equ $
Int13FuncsCnt equ (Int13FuncsEnd-Int13Funcs) >> 1
@@ -1070,7 +1112,24 @@ EDD_DPT:
.res3 db 0 ; Reserved
.chksum db 0 ; DPI checksum
-%endif
+%if ELTORITO
+; El Torito CD Specification Packet - mostly filled in by installer
+CD_PKT:
+.size db 13h ; Packet size (19 bytes)
+.type db 0 ; Boot media type (flags)
+.driveno db 0E0h ; INT 13h drive number
+.controller db 0 ; Controller index
+.start dd 0 ; Starting LBA of image
+.devno dw 0 ; Device number
+.user_buf dw 0 ; User buffer segment
+.load_seg dw 0 ; Load segment
+.sect_count dw 0 ; Emulated sectors to load
+.geom1 db 0 ; Cylinders bits 0 thru 7
+.geom2 db 0 ; Sects/track 0 thru 5, cyls 8, 9
+.geom3 db 0 ; Heads
+%endif ; ELTORITO
+
+%endif ; EDD
; End patch area
alignb 4, db 0
diff --git a/memdisk/memdisk_chs_512.asm b/memdisk/memdisk_chs_512.asm
index 35acbbd8..d4b0f753 100644
--- a/memdisk/memdisk_chs_512.asm
+++ b/memdisk/memdisk_chs_512.asm
@@ -1,3 +1,4 @@
%define EDD 0
+%define ELTORITO 0
%define SECTORSIZE_LG2 9 ; log2(sector size)
%include "memdisk.inc"
diff --git a/memdisk/memdisk_edd_512.asm b/memdisk/memdisk_edd_512.asm
index fbd90c15..02d1737f 100644
--- a/memdisk/memdisk_edd_512.asm
+++ b/memdisk/memdisk_edd_512.asm
@@ -1,3 +1,4 @@
%define EDD 1
+%define ELTORITO 0
%define SECTORSIZE_LG2 9 ; log2(sector size)
%include "memdisk.inc"
diff --git a/memdisk/memdisk_iso_2048.asm b/memdisk/memdisk_iso_2048.asm
index 84a05542..0a444976 100644
--- a/memdisk/memdisk_iso_2048.asm
+++ b/memdisk/memdisk_iso_2048.asm
@@ -1,3 +1,4 @@
%define EDD 1
+%define ELTORITO 1
%define SECTORSIZE_LG2 11 ; log2(sector size)
%include "memdisk.inc"
diff --git a/memdisk/memdisk_iso_512.asm b/memdisk/memdisk_iso_512.asm
index fbd90c15..e49b449d 100644
--- a/memdisk/memdisk_iso_512.asm
+++ b/memdisk/memdisk_iso_512.asm
@@ -1,3 +1,4 @@
%define EDD 1
+%define ELTORITO 1
%define SECTORSIZE_LG2 9 ; log2(sector size)
%include "memdisk.inc"
diff --git a/memdisk/setup.c b/memdisk/setup.c
index 9fd5c9e8..41e87c12 100644
--- a/memdisk/setup.c
+++ b/memdisk/setup.c
@@ -2,6 +2,7 @@
*
* Copyright 2001-2009 H. Peter Anvin - All Rights Reserved
* Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ * Portions copyright 2009 Shao Miller [El Torito code]
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,6 +16,7 @@
#include "bda.h"
#include "dskprobe.h"
#include "e820.h"
+#include "eltorito.h"
#include "conio.h"
#include "version.h"
#include "memdisk.h"
@@ -143,8 +145,19 @@ struct patch_area {
dpt_t dpt;
struct edd_dpt edd_dpt;
+ struct edd4_cd_pkt cd_pkt; /* Only really in a memdisk_iso_* hook */
} __attribute__((packed));
+/* An EDD disk packet */
+struct edd_dsk_pkt {
+ uint8_t size; /* Packet size */
+ uint8_t res1; /* Reserved */
+ uint16_t count; /* Count to transfer */
+ uint32_t buf; /* Buffer pointer */
+ uint64_t start; /* LBA to start from */
+ uint64_t buf64; /* 64-bit buf pointer */
+} __attribute__ ((packed));
+
/*
* Routine to seek for a command-line item and return a pointer
* to the data portion, if present
@@ -322,11 +335,12 @@ void unzip_if_needed(uint32_t * where_p, uint32_t * size_p)
* Figure out the "geometry" of the disk in question
*/
struct geometry {
- uint32_t sectors; /* 512-byte sector count */
+ uint32_t sectors; /* Sector count */
uint32_t c, h, s; /* C/H/S geometry */
uint32_t offset; /* Byte offset for disk */
uint8_t type; /* Type byte for INT 13h AH=08h */
uint8_t driveno; /* Drive no */
+ uint16_t sector_size; /* Sector size in bytes (512 vs. 2048) */
const char *hsrc, *ssrc; /* Origins of H and S geometries */
};
@@ -406,6 +420,8 @@ static const struct geometry *get_disk_image_geometry(uint32_t where,
printf("command line: %s\n", shdr->cmdline);
+ hd_geometry.sector_size = 512; /* Assume floppy/HDD at first */
+
offset = 0;
if (CMD_HASDATA(p = getcmditem("offset")) && (v = atou(p)))
offset = v;
@@ -417,6 +433,71 @@ static const struct geometry *get_disk_image_geometry(uint32_t where,
hd_geometry.sectors = sectors;
hd_geometry.offset = offset;
+ if ((p = getcmditem("iso")) != CMD_NOTFOUND) {
+#ifdef DBG_ELTORITO
+ eltorito_dump(where);
+#endif
+ struct edd4_bvd *bvd = (struct edd4_bvd *)(where + 17 * 2048);
+ /* Tiny sanity check */
+ if ((bvd->boot_rec_ind != 0) || (bvd->ver != 1))
+ printf("El Torito BVD sanity check failed.\n");
+ struct edd4_bootcat *boot_cat =
+ (struct edd4_bootcat *)(where + bvd->boot_cat * 2048);
+ /* Another tiny sanity check */
+ if ((boot_cat->validation_entry.platform_id != 0) ||
+ (boot_cat->validation_entry.key55 != 0x55) ||
+ (boot_cat->validation_entry.keyAA != 0xAA))
+ printf("El Torito boot catalog sanity check failed.\n");
+ /* If we have an emulation mode, set the offset to the image */
+ if (boot_cat->initial_entry.media_type)
+ hd_geometry.offset += boot_cat->initial_entry.load_block * 2048;
+ if (boot_cat->initial_entry.media_type < 4) {
+ /* We're a floppy emulation mode or our params will be
+ * overwritten by the no emulation mode case
+ */
+ hd_geometry.driveno = 0x00;
+ hd_geometry.c = 80;
+ hd_geometry.h = 2;
+ }
+ switch (boot_cat->initial_entry.media_type) {
+ case 0: /* No emulation */
+ hd_geometry.driveno = 0xE0;
+ hd_geometry.type = 10; /* ATAPI removable media device */
+ hd_geometry.c = 65535;
+ hd_geometry.h = 255;
+ hd_geometry.s = 15;
+ /* 2048-byte sectors, so adjust the size and count */
+ hd_geometry.sector_size = 2048;
+ sectors = (size - hd_geometry.offset) >> 11;
+ break;
+ case 1: /* 1.2 MB floppy */
+ hd_geometry.s = 15;
+ hd_geometry.type = 2;
+ sectors = 2400;
+ break;
+ case 2: /* 1.44 MB floppy */
+ hd_geometry.s = 18;
+ hd_geometry.type = 4;
+ sectors = 2880;
+ break;
+ case 3: /* 2.88 MB floppy */
+ hd_geometry.s = 36;
+ hd_geometry.type = 6;
+ sectors = 5760;
+ break;
+ case 4:
+ hd_geometry.driveno = 0x80;
+ hd_geometry.type = 0;
+ sectors = (size - hd_geometry.offset) >> 9;
+ break;
+ }
+ /* For HDD emulation, we figure out the geometry later. Otherwise: */
+ if (hd_geometry.s) {
+ hd_geometry.hsrc = hd_geometry.ssrc = "El Torito";
+ }
+ hd_geometry.sectors = sectors;
+ }
+
/* Do we have a DOSEMU header? */
memcpy(&dosemu, (char *)where + hd_geometry.offset, sizeof dosemu);
if (!memcmp("DOSEMU", dosemu.magic, 7)) {
@@ -480,7 +561,7 @@ static const struct geometry *get_disk_image_geometry(uint32_t where,
if (!(max_h | max_s)) {
/* No FAT filesystem found to steal geometry from... */
- if (sectors < 4096 * 2) {
+ if ((sectors < 4096 * 2) && (hd_geometry.sector_size == 512)) {
int ok = 0;
unsigned int xsectors = sectors;
@@ -541,7 +622,9 @@ static const struct geometry *get_disk_image_geometry(uint32_t where,
const struct ptab_entry *ptab = (const struct ptab_entry *)
((char *)where + hd_geometry.offset + (512 - 2 - 4 * 16));
- hd_geometry.driveno = 0x80; /* Assume hard disk */
+ /* Assume hard disk */
+ if (!hd_geometry.driveno)
+ hd_geometry.driveno = 0x80;
if (*(uint16_t *) ((char *)where + 512 - 2) == 0xaa55) {
for (i = 0; i < 4; i++) {
@@ -718,12 +801,15 @@ void setup(const struct real_mode_args *rm_args_ptr)
uint16_t dosmem_k;
uint32_t stddosmem;
const struct geometry *geometry;
+ const struct edd4_bvd *bvd;
+ const struct edd4_bootcat *boot_cat = 0;
int total_size, cmdlinelen;
com32sys_t regs;
uint32_t ramdisk_image, ramdisk_size;
uint32_t boot_base, rm_base;
int bios_drives;
int do_edd = 1; /* 0 = no, 1 = yes, default is yes */
+ int do_eltorito = 0; /* default is no */
int no_bpt; /* No valid BPT presented */
uint32_t boot_seg = 0; /* Meaning 0000:7C00 */
uint32_t boot_len = 512; /* One sector */
@@ -762,13 +848,28 @@ void setup(const struct real_mode_args *rm_args_ptr)
else
do_edd = (geometry->driveno & 0x80) ? 1 : 0;
+ if (getcmditem("iso") != CMD_NOTFOUND) {
+ do_eltorito = 1;
+ do_edd = 1; /* Mandatory */
+ }
+
/* Choose the appropriate installable memdisk hook */
- if (do_edd) {
- bin_size = (int)&_binary_memdisk_edd_512_bin_size;
- memdisk_hook = (char *)&_binary_memdisk_edd_512_bin_start;
+ if (do_eltorito) {
+ if (geometry->sector_size == 2048) {
+ bin_size = (int)&_binary_memdisk_iso_2048_bin_size;
+ memdisk_hook = (char *)&_binary_memdisk_iso_2048_bin_start;
+ } else {
+ bin_size = (int)&_binary_memdisk_iso_512_bin_size;
+ memdisk_hook = (char *)&_binary_memdisk_iso_512_bin_start;
+ }
} else {
- bin_size = (int)&_binary_memdisk_chs_512_bin_size;
- memdisk_hook = (char *)&_binary_memdisk_chs_512_bin_start;
+ if (do_edd) {
+ bin_size = (int)&_binary_memdisk_edd_512_bin_size;
+ memdisk_hook = (char *)&_binary_memdisk_edd_512_bin_start;
+ } else {
+ bin_size = (int)&_binary_memdisk_chs_512_bin_size;
+ memdisk_hook = (char *)&_binary_memdisk_chs_512_bin_start;
+ }
}
/* Reserve the ramdisk memory */
@@ -788,7 +889,7 @@ void setup(const struct real_mode_args *rm_args_ptr)
pptr->driveno = geometry->driveno;
pptr->drivetype = geometry->type;
- pptr->cylinders = geometry->c;
+ pptr->cylinders = geometry->c; /* Possible precision loss */
pptr->heads = geometry->h;
pptr->sectors = geometry->s;
pptr->disksize = geometry->sectors;
@@ -884,7 +985,12 @@ void setup(const struct real_mode_args *rm_args_ptr)
pptr->edd_dpt.c = geometry->c;
pptr->edd_dpt.h = geometry->h;
pptr->edd_dpt.s = geometry->s;
- pptr->edd_dpt.flags |= 0x0002; /* Geometry valid */
+ /* EDD-4 states that invalid geometry should be returned
+ * for INT 0x13, AH=0x48 "EDD Get Disk Parameters" call on an
+ * El Torito ODD. Check for 2048-byte sector size
+ */
+ if (geometry->sector_size != 2048)
+ pptr->edd_dpt.flags |= 0x0002; /* Geometry valid */
}
if (!(geometry->driveno & 0x80)) {
/* Floppy drive. Mark it as a removable device with
@@ -896,6 +1002,21 @@ void setup(const struct real_mode_args *rm_args_ptr)
pptr->edd_dpt.chksum = -checksum_buf(&pptr->edd_dpt.dpikey, 73 - 30);
}
+ if (do_eltorito) {
+ bvd = (struct edd4_bvd *)(ramdisk_image + 17 * 2048);
+ boot_cat =
+ (struct edd4_bootcat *)(ramdisk_image + bvd->boot_cat * 2048);
+ pptr->cd_pkt.type = boot_cat->initial_entry.media_type; /* Cheat */
+ pptr->cd_pkt.driveno = geometry->driveno;
+ pptr->cd_pkt.start = boot_cat->initial_entry.load_block;
+ pptr->cd_pkt.load_seg = boot_cat->initial_entry.load_seg;
+ pptr->cd_pkt.sect_count = boot_cat->initial_entry.sect_count;
+ boot_len = pptr->cd_pkt.sect_count * 2048;
+ pptr->cd_pkt.geom1 = (uint8_t)(pptr->cylinders) & 0xFF;
+ pptr->cd_pkt.geom2 = (uint8_t)(pptr->sectors) | (uint8_t)((pptr->cylinders >> 2) & 0xC0);
+ pptr->cd_pkt.geom3 = (uint8_t)(pptr->heads);
+ }
+
/* The size is given by hptr->total_size plus the size of the E820
map -- 12 bytes per range; we may need as many as 2 additional
ranges (each insertrange() can worst-case turn 1 area into 3)
@@ -1041,7 +1162,7 @@ void setup(const struct real_mode_args *rm_args_ptr)
if (nhd > 128)
nhd = 128;
- wrz_8(BIOS_HD_COUNT, nhd);
+ if (!do_eltorito) wrz_8(BIOS_HD_COUNT, nhd);
} else {
/* Update BIOS floppy disk count */
uint8_t equip = rdz_8(BIOS_EQUIP);
@@ -1097,6 +1218,10 @@ void setup(const struct real_mode_args *rm_args_ptr)
/* Reboot into the new "disk" */
puts("Loading boot sector... ");
+ if (do_eltorito) {
+ /* 4 times as many 512-byte sectors in a 2048-byte sector */
+ boot_lba = pptr->cd_pkt.start * 4;
+ }
memcpy((void *)boot_base, (char *)pptr->diskbuf + boot_lba * 512, boot_len);
if (getcmditem("pause") != CMD_NOTFOUND) {