iso9660
diff --git a/.gitignore b/.gitignore
index 67b4bf89..ac2046e4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,11 +7,14 @@
/**/*.bin.gz
/**/*.elf
/**/*.hdd
+/**/*.iso
/bochsout.txt
/bx_enh_dbg.ini
.vscode
/limine-install
!/limine.bin
!/limine-pxe.bin
+!/limine-cd.bin
!/stage2.map
/stivale
+/test_image
diff --git a/Makefile b/Makefile
index 63edae00..a6f66170 100644
--- a/Makefile
+++ b/Makefile
@@ -29,6 +29,7 @@ install: all
bootloader: | decompressor stage2
gzip -n -9 < stage2/stage2.bin > stage2/stage2.bin.gz
cd bootsect && nasm bootsect.asm -fbin -o ../limine.bin
+ cd cdboot && nasm bootsect.asm -fbin -o ../limine-cd.bin
cd pxeboot && nasm bootsect.asm -fbin -o ../limine-pxe.bin
cp stage2/stage2.map ./
cp stage2/stage3.bin ./limine.sys
@@ -118,3 +119,12 @@ fat32-test: test.hdd bootloader | all
rm -rf test_image loopback_dev
./limine-install ./ test.hdd
qemu-system-x86_64 -net none -smp 4 -enable-kvm -cpu host -hda test.hdd -debugcon stdio
+
+iso9660-test: bootloader
+ $(MAKE) -C test
+ cp stage2.map test/
+ rm -rf test_image/
+ mkdir -p test_image/boot
+ cp -rv limine-cd.bin limine.sys stage2/stages.bin test/* test_image/boot/
+ genisoimage -no-emul-boot -b boot/limine-cd.bin -o test.iso test_image/
+ qemu-system-x86_64 -net none -smp 4 -enable-kvm -cpu host -cdrom test.iso -debugcon stdio
diff --git a/cdboot/bootsect.asm b/cdboot/bootsect.asm
new file mode 100644
index 00000000..03a7ee60
--- /dev/null
+++ b/cdboot/bootsect.asm
@@ -0,0 +1,109 @@
+BITS 16
+ORG 0x7C00
+
+; Please read bootsect/bootsect.asm before this file
+
+%define ISO9660_BUFFER 0x8000
+%define ROOT_DIRECTORY 156
+%define ROOT_DIRECTORY_BUFFER (ISO9660_BUFFER + ROOT_DIRECTORY)
+
+%define DIRECTORY_RECORD_LENGTH 0
+%define DIRECTORY_RECORD_LBA 2
+%define DIRECTORY_RECORD_SIZE 10
+%define DIRECTORY_RECORD_FILENAME_LENGTH 32
+%define DIRECTORY_RECORD_FILENAME 33
+
+%define BOOT_FROM_CD 2
+
+jmp skip_bpb
+nop
+times 87 db 0
+
+skip_bpb:
+ cli
+ cld
+ jmp 0x0000:.initialise_cs
+ .initialise_cs:
+ xor ax, ax
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+ mov sp, 0x7C00
+ sti
+
+ ; int 13h?
+ mov ah, 0x41
+ mov bx, 0x55AA
+ int 0x13
+ jc err
+ cmp bx, 0xAA55
+ jne err
+
+ mov esp, 0x7C00
+
+ ; --- Load the stage 2 ---
+ ; Find and load the PVD
+ call findPVD
+ jc err
+
+ ; Load the root directory
+ mov eax, dword [ROOT_DIRECTORY_BUFFER + DIRECTORY_RECORD_LBA]
+ mov ecx, dword [ROOT_DIRECTORY_BUFFER + DIRECTORY_RECORD_SIZE]
+
+ mov esi, ecx ; Size, for read_file
+ add ecx, 2047
+ shr ecx, 11
+ call read_2k_sectors
+ jc err
+
+ ; Find and load '/BOOT'
+ mov ebx, TXT_BOOT
+ mov cl, TXT_BOOT_SZ
+ call read_file
+ jc err
+
+ ; Find and load '/BOOT/STAGES.BIN'
+ mov ebx, TXT_STAGES
+ mov cl, TXT_STAGES_SZ
+ call read_file ; esi is set from the last call
+ jc err
+
+ ; Enable GDT
+ lgdt [gdt]
+ cli
+ mov eax, cr0
+ or al, 1
+ mov cr0, eax
+
+ jmp 0x08:pmode
+
+err:
+ hlt
+ jmp err
+
+%include 'iso9660.asm'
+%include '../bootsect/gdt.inc'
+
+BITS 32
+pmode:
+ mov eax, 0x10
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+
+ ; Time to handle control over to the stage 2
+ push BOOT_FROM_CD
+ and edx, 0xFF
+ push edx ; Boot drive
+ call ISO9660_BUFFER
+ hlt
+
+TXT_BOOT: db "BOOT"
+TXT_BOOT_SZ equ $ - TXT_BOOT
+TXT_STAGES: db "STAGES.BIN;1"
+TXT_STAGES_SZ equ $ - TXT_STAGES
+
+; Just making sure the entry point (ISO9660_BUFFER) is not reached
+times (0x8000 - 0x7C00) - ($ - $$) db 0
diff --git a/cdboot/findFile.asm b/cdboot/findFile.asm
new file mode 100644
index 00000000..0a66a2d1
--- /dev/null
+++ b/cdboot/findFile.asm
@@ -0,0 +1,58 @@
+BITS 16
+
+; --- Find file in directory ---
+; IN:
+; eax <- directory extent
+; ebx <- ptr to filename
+; cl <- filename sz
+; esi <- size of directory extent
+
+; OUT:
+; eax <- LBA of the extent
+; ebx <- size in bytes
+; Carry if not found
+
+; SMASHES:
+; ch
+findFile:
+ push edx
+ push edi
+ push esi
+ mov edx, eax
+
+ .checkEntry:
+ ; Get the size of this entry
+ mov edi, dword [edx + DIRECTORY_RECORD_LENGTH]
+ and edi, 0xFF
+
+ ; Check filename size
+ mov al, byte [edx + DIRECTORY_RECORD_FILENAME_LENGTH]
+ cmp al, cl
+ jnz .gonext
+
+ ; Sizes match, check filename
+ lea eax, dword [edx + DIRECTORY_RECORD_FILENAME]
+ call strcmp
+ jnc .found
+
+ ; Go to the next
+ .gonext:
+ add edx, edi
+ sub esi, edi
+ test esi, esi
+ jnz .checkEntry
+
+ .notfound:
+ stc
+ jmp .end
+ .found:
+ clc
+ mov eax, [edx + DIRECTORY_RECORD_LBA]
+ mov ebx, [edx + DIRECTORY_RECORD_SIZE]
+ .end:
+ pop esi
+ pop edi
+ pop edx
+ ret
+
+%include 'strcmp.asm'
diff --git a/cdboot/findPVD.asm b/cdboot/findPVD.asm
new file mode 100644
index 00000000..6f9b94d2
--- /dev/null
+++ b/cdboot/findPVD.asm
@@ -0,0 +1,51 @@
+BITS 16
+
+; --- Find primary volume descriptor ---
+; IN:
+; dl <- drive number
+
+; OUT:
+; [ISO9660_BUFFER] <- PVD
+; Carry if not found
+findPVD:
+ pusha
+ ; Just start reading volume descriptors
+
+ mov eax, 0x10 ; First volume descriptor's LBA
+ .checkVD:
+ mov cx, 1 ; Each volume descriptor is 2KB
+ call read_2k_sectors
+
+ ; Check identifier
+ mov ecx, ISO9660_BUFFER
+ inc ecx
+ mov bl, byte [ecx]
+ inc ecx
+ mov ecx, dword [ecx]
+ cmp bl, 'C'
+ jne .notfound
+ cmp ecx, 0x31303044
+ jne .notfound
+
+ ; Check type = 0xFF (final)
+ mov ecx, ISO9660_BUFFER
+ mov bl, byte [ecx]
+ cmp bl, 0xFF
+ jz .notfound
+
+ ; Check type = 0x01 (PVD)
+ cmp bl, 0x01
+ jz .found
+
+ ; Didn't match, go to the next
+ inc eax
+ jmp .checkVD
+
+ .found:
+ clc
+ jmp .end
+ .notfound:
+ stc
+ .end:
+ popa
+ ret
diff --git a/cdboot/iso9660.asm b/cdboot/iso9660.asm
new file mode 100644
index 00000000..28f1551f
--- /dev/null
+++ b/cdboot/iso9660.asm
@@ -0,0 +1,35 @@
+BITS 16
+
+%include 'read_2k_sectors.asm'
+%include 'findPVD.asm'
+%include 'findFile.asm'
+
+; --- Read file ---
+; IN:
+; ebx <- ptr to filename
+; cl <- filename sz
+; esi <- size of directory extent
+
+; OUT:
+; If found: [ISO9660_BUFFER] <- contents of the file
+; If not found: CF=1
+; esi <- size in bytes
+
+; SMASHES:
+; eax, ebx, ecx
+read_file:
+ mov eax, ISO9660_BUFFER
+ call findFile
+ jc .end
+
+ ; LBA of the extent is now @ eax
+ ; ebx is size in bytes
+ mov esi, ebx ; Return value
+
+ ; bytes to 2k sectors
+ mov ecx, ebx
+ add ecx, 2047
+ shr ecx, 11
+ call read_2k_sectors
+ .end:
+ ret
diff --git a/cdboot/read_2k_sectors.asm b/cdboot/read_2k_sectors.asm
new file mode 100644
index 00000000..f5d3dd16
--- /dev/null
+++ b/cdboot/read_2k_sectors.asm
@@ -0,0 +1,30 @@
+BITS 16
+
+; --- Read sectors from disk ---
+; IN:
+; eax <- start LBA (2k sectors)
+; cx <- number of 2k sectors
+; dl <- drive number
+; ds <- ZERO
+
+; OUT:
+; Carry if error
+
+align 8
+dapack:
+ dapack_size: db 0x10
+ dapack_null: db 0x00
+ dapack_nblocks: dw 0
+ dapack_buffer: dd ISO9660_BUFFER
+ dapack_LBA: dq 0
+
+read_2k_sectors:
+ pusha
+ mov dword [dapack_LBA], eax
+ mov word [dapack_nblocks], cx
+
+ mov ah, 0x42
+ mov si, dapack
+ int 0x13
+ popa
+ ret
diff --git a/cdboot/strcmp.asm b/cdboot/strcmp.asm
new file mode 100644
index 00000000..fd21186f
--- /dev/null
+++ b/cdboot/strcmp.asm
@@ -0,0 +1,34 @@
+BITS 16
+
+; --- Compare strings ---
+; IN:
+; eax <- ptr to first string
+; ebx <- ptr to second string
+; cl <- size of BOTH strings (must be the same)
+
+; OUT:
+; CF=0 if equal, CF=1 otherwise
+strcmp:
+ pusha
+ .nextchar:
+ mov dh, byte [eax]
+ mov dl, byte [ebx]
+ cmp dh, dl
+ jnz .notequal
+
+ ; Characters match
+ dec cl
+ test cl, cl
+ jz .equal
+ inc eax
+ inc ebx
+ jmp .nextchar
+
+ .equal:
+ clc
+ jmp .end
+ .notequal:
+ stc
+ .end:
+ popa
+ ret
diff --git a/limine-cd.bin b/limine-cd.bin
new file mode 100644
index 00000000..43f1e81e
Binary files /dev/null and b/limine-cd.bin differ
diff --git a/limine-pxe.bin b/limine-pxe.bin
index 7406f422..d99b96dd 100644
Binary files a/limine-pxe.bin and b/limine-pxe.bin differ
diff --git a/limine.bin b/limine.bin
index 06f1233e..11a45a41 100644
Binary files a/limine.bin and b/limine.bin differ
diff --git a/limine.sys b/limine.sys
index d560af4b..bdff02c2 100644
Binary files a/limine.sys and b/limine.sys differ
diff --git a/stage2/fs/file.c b/stage2/fs/file.c
index fc0ca148..8fbc65c4 100644
--- a/stage2/fs/file.c
+++ b/stage2/fs/file.c
@@ -4,6 +4,7 @@
#include <fs/echfs.h>
#include <fs/ext2.h>
#include <fs/fat32.h>
+#include <fs/iso9660.h>
#include <lib/blib.h>
#include <mm/pmm.h>
#include <lib/part.h>
@@ -23,6 +24,20 @@ bool fs_get_guid(struct guid *guid, struct volume *part) {
int fopen(struct file_handle *ret, struct volume *part, const char *filename) {
ret->is_memfile = false;
+ if (iso9660_check_signature(part)) {
+ struct iso9660_file_handle *fd = ext_mem_alloc(sizeof(struct iso9660_file_handle));
+
+ int r = iso9660_open(fd, part, filename);
+ if (r)
+ return r;
+
+ ret->fd = (void *)fd;
+ ret->read = (void *)iso9660_read;
+ ret->size = fd->size;
+
+ return 0;
+ }
+
if (echfs_check_signature(part)) {
struct echfs_file_handle *fd = ext_mem_alloc(sizeof(struct echfs_file_handle));
diff --git a/stage2/fs/iso9660.c b/stage2/fs/iso9660.c
new file mode 100644
index 00000000..5326a6d0
--- /dev/null
+++ b/stage2/fs/iso9660.c
@@ -0,0 +1,197 @@
+#include <fs/iso9660.h>
+#include <lib/blib.h>
+#include <lib/libc.h>
+#include <mm/pmm.h>
+
+#define ISO9660_FIRST_VOLUME_DESCRIPTOR 0x10
+#define ISO9660_VOLUME_DESCRIPTOR_SIZE ISO9660_SECTOR_SIZE
+#define ROCK_RIDGE_MAX_FILENAME 255
+
+// --- Both endian structures ---
+struct BE16_t { uint16_t little, big; } __attribute__((packed));
+struct BE32_t { uint32_t little, big; } __attribute__((packed));
+
+// --- Directory entries ---
+struct iso9660_directory_entry {
+ uint8_t length;
+ uint8_t extended_attribute_length;
+ struct BE32_t extent;
+ struct BE32_t extent_size;
+ uint8_t datetime[7];
+ uint8_t flags;
+ uint8_t interleaved_unit_size;
+ uint8_t interleaved_gap_size;
+ struct BE16_t volume_seq;
+ uint8_t filename_size;
+} __attribute__((packed));
+
+// --- Volume descriptors ---
+// VDT = Volume Descriptor Type
+enum {
+ ISO9660_VDT_BOOT_RECORD,
+ ISO9660_VDT_PRIMARY,
+ ISO9660_VDT_SUPPLEMENTARY,
+ ISO9660_VDT_PARTITION_DESCRIPTOR,
+ ISO9660_VDT_TERMINATOR = 255
+};
+
+struct iso9660_volume_descriptor {
+ uint8_t type;
+ char identifier[5];
+ uint8_t version;
+ uint8_t data[2041];
+} __attribute__((packed));
+
+struct iso9660_primary_volume {
+ uint8_t type;
+ char standard_identifier[5];
+ uint8_t version;
+ uint8_t unused0[1];
+ char system_identifier[32];
+ char volume_identifier[32];
+ uint8_t unused1[8];
+ struct BE32_t space_size;
+ uint8_t unused2[32];
+ struct BE16_t set_size;
+ struct BE16_t volume_seq;
+ struct BE16_t LBA_size;
+ struct BE32_t path_table_size;
+
+ uint32_t LBA_path_table_little;
+ uint32_t LBA_optional_path_table_little;
+ uint32_t LBA_path_table_big;
+ uint32_t LBA_optional_path_table_big;
+
+ struct iso9660_directory_entry root;
+ uint8_t no_one_cares[1858];
+} __attribute__((packed));
+
+
+// --- Implementation ---
+// Cached root
+static void *root = NULL;
+static uint32_t root_size = 0;
+
+static void iso9660_find_PVD(struct iso9660_volume_descriptor *desc, struct volume *vol) {
+ uint32_t lba = ISO9660_FIRST_VOLUME_DESCRIPTOR;
+ while (true) {
+ volume_read(vol, desc, lba * ISO9660_SECTOR_SIZE, ISO9660_SECTOR_SIZE);
+
+ switch (desc->type) {
+ case ISO9660_VDT_PRIMARY:
+ return;
+ case ISO9660_VDT_TERMINATOR:
+ panic("ISO9660: no primary volume descriptor");
+ break;
+ }
+
+ ++lba;
+ }
+}
+
+static void iso9660_cache_root(struct volume *vol) {
+ struct iso9660_primary_volume pv;
+ iso9660_find_PVD((struct iso9660_volume_descriptor *)&pv, vol);
+
+ root_size = pv.root.extent_size.little;
+ root = ext_mem_alloc(root_size);
+ volume_read(vol, root, pv.root.extent.little * ISO9660_SECTOR_SIZE, root_size);
+}
+
+static int iso9660_strcmp(const char *a, const char *b, size_t size) {
+ while (size--) {
+ char ca = *a++;
+ char cb = *b++;
+ if (!(ca == cb || (ca - ('a'-'A')) == cb))
+ return 1;
+ }
+
+ return 0;
+}
+
+static struct iso9660_directory_entry *iso9660_find(void *buffer, uint32_t size, const char *filename) {
+ // The file can be either FILENAME or FILENAME;1
+ uint32_t len = strlen(filename);
+ char finalfile[len + 2];
+ strcpy(finalfile, filename);
+ finalfile[len + 0] = ';';
+ finalfile[len + 1] = '1';
+
+ while (size) {
+ struct iso9660_directory_entry *entry = buffer;
+ char* entry_filename = (char*)entry + sizeof(struct iso9660_directory_entry);
+
+ if (!entry->length) {
+ return NULL;
+ } else if (entry->filename_size == len && !iso9660_strcmp(filename, entry_filename, len)) {
+ return buffer;
+ } else if (entry->filename_size == len+2 && !iso9660_strcmp(finalfile, entry_filename, len+2)) {
+ return buffer;
+ } else {
+ size -= entry->length;
+ buffer += entry->length;
+ }
+ }
+
+ return NULL;
+}
+
+
+// --- Public functions ---
+int iso9660_check_signature(struct volume *vol) {
+ char buf[6];
+ const uint64_t signature = ISO9660_FIRST_VOLUME_DESCRIPTOR * ISO9660_SECTOR_SIZE + 1;
+ volume_read(vol, buf, signature, 5);
+ buf[5] = '\0';
+ return !strcmp(buf, "CD001");
+}
+
+int iso9660_open(struct iso9660_file_handle *ret, struct volume *vol, const char *path) {
+ // Is the root directory cached?
+ if (!root)
+ iso9660_cache_root(vol);
+
+ ret->context.vol = *vol;
+ ret->context.root = root;
+ ret->context.root_size = root_size;
+
+ while (*path == '/')
+ ++path;
+
+ struct iso9660_directory_entry *current = root;
+ uint32_t current_size = root_size;
+
+ uint32_t next_sector = 0;
+ uint32_t next_size = 0;
+
+ char filename[ROCK_RIDGE_MAX_FILENAME];
+ while (true) {
+ char *aux = filename;
+ while (!(*path == '/' || *path == '\0'))
+ *aux++ = *path++;
+ *aux = '\0';
+
+ struct iso9660_directory_entry *entry = iso9660_find(current, current_size, filename);
+ if (!entry)
+ return 1; // Not found :(
+
+ next_sector = entry->extent.little;
+ next_size = entry->extent_size.little;
+
+ if (*path++ == '\0')
+ break; // Found :)
+
+ current_size = next_size;
+ current = ext_mem_alloc(current_size);
+ volume_read(vol, current, next_sector * ISO9660_SECTOR_SIZE, current_size);
+ }
+
+ ret->LBA = next_sector;
+ ret->size = next_size;
+ return 0;
+}
+
+int iso9660_read(struct iso9660_file_handle *file, void *buf, uint64_t loc, uint64_t count) {
+ volume_read(&file->context.vol, buf, file->LBA * ISO9660_SECTOR_SIZE + loc, count);
+ return 0;
+}
diff --git a/stage2/fs/iso9660.h b/stage2/fs/iso9660.h
new file mode 100644
index 00000000..ebd0cb5a
--- /dev/null
+++ b/stage2/fs/iso9660.h
@@ -0,0 +1,25 @@
+#ifndef __FS__ISO9660_H__
+#define __FS__ISO9660_H__
+
+#include <stdint.h>
+#include <lib/part.h>
+
+#define ISO9660_SECTOR_SIZE (2 << 10)
+
+struct iso9660_context {
+ struct volume vol;
+ void* root;
+ uint32_t root_size;
+};
+
+struct iso9660_file_handle {
+ struct iso9660_context context;
+ uint32_t LBA;
+ uint32_t size;
+};
+
+int iso9660_check_signature(struct volume *vol);
+int iso9660_open(struct iso9660_file_handle *ret, struct volume *vol, const char *path);
+int iso9660_read(struct iso9660_file_handle *file, void *buf, uint64_t loc, uint64_t count);
+
+#endif
diff --git a/stage2/lib/blib.c b/stage2/lib/blib.c
index fa391d9f..878c7f81 100644
--- a/stage2/lib/blib.c
+++ b/stage2/lib/blib.c
@@ -11,6 +11,8 @@ uint8_t boot_drive;
int boot_partition = -1;
bool booted_from_pxe = false;
+bool booted_from_cd = false;
+bool stage3_already_loaded = false;
bool parse_resolution(int *width, int *height, int *bpp, const char *buf) {
int res[3] = {0};
diff --git a/stage2/lib/blib.h b/stage2/lib/blib.h
index 5f8ddf44..70333094 100644
--- a/stage2/lib/blib.h
+++ b/stage2/lib/blib.h
@@ -9,6 +9,8 @@ extern uint8_t boot_drive;
extern int boot_partition;
extern bool booted_from_pxe;
+extern bool booted_from_cd;
+extern bool stage3_already_loaded;
bool parse_resolution(int *width, int *height, int *bpp, const char *buf);
diff --git a/stage2/lib/config.c b/stage2/lib/config.c
index df60239f..455701d4 100644
--- a/stage2/lib/config.c
+++ b/stage2/lib/config.c
@@ -19,14 +19,16 @@ static char *config_addr;
extern symbol stage3_addr;
int init_config_disk(struct volume *part) {
- struct file_handle stage3;
+ if (!stage3_already_loaded) {
+ struct file_handle stage3;
- if (fopen(&stage3, part, "/limine.sys")
- && fopen(&stage3, part, "/boot/limine.sys")) {
- panic("Could not open stage 3");
- }
+ if (fopen(&stage3, part, "/limine.sys")
+ && fopen(&stage3, part, "/boot/limine.sys")) {
+ panic("Could not open stage 3");
+ }
- fread(&stage3, stage3_addr, 0, stage3.size);
+ fread(&stage3, stage3_addr, 0, stage3.size);
+ }
struct file_handle f;
diff --git a/stage2/lib/part.c b/stage2/lib/part.c
index f88faf6c..4ef76441 100644
--- a/stage2/lib/part.c
+++ b/stage2/lib/part.c
@@ -254,7 +254,7 @@ static size_t volume_index_i = 0;
void volume_create_index(void) {
size_t volume_count = 0;
- for (uint8_t drive = 0x80; drive < 0x8f; drive++) {
+ for (uint8_t drive = 0x80; drive; drive++) {
struct rm_regs r = {0};
struct bios_drive_params drive_params;
@@ -298,7 +298,7 @@ void volume_create_index(void) {
volume_index = ext_mem_alloc(sizeof(struct volume) * volume_count);
- for (uint8_t drive = 0x80; drive < 0x8f; drive++) {
+ for (uint8_t drive = 0x80; drive; drive++) {
struct rm_regs r = {0};
struct bios_drive_params drive_params;
diff --git a/stage2/lib/uri.c b/stage2/lib/uri.c
index 0a495f9d..883dc09e 100644
--- a/stage2/lib/uri.c
+++ b/stage2/lib/uri.c
@@ -94,10 +94,10 @@ static bool parse_bios_partition(char *loc, uint8_t *drive, uint8_t *partition)
static bool uri_bios_dispatch(struct file_handle *fd, char *loc, char *path) {
uint8_t drive, partition;
+ struct volume volume;
if (!parse_bios_partition(loc, &drive, &partition))
return false;
- struct volume volume;
if (!volume_get_by_coord(&volume, drive, partition))
return false;
@@ -154,7 +154,7 @@ static bool uri_boot_dispatch(struct file_handle *fd, char *s_part, char *path)
if (booted_from_pxe)
return uri_tftp_dispatch(fd, s_part, path);
- uint8_t partition;
+ int partition;
if (s_part[0] != '\0') {
uint64_t val = strtoui(s_part, NULL, 10);
@@ -162,12 +162,10 @@ static bool uri_boot_dispatch(struct file_handle *fd, char *s_part, char *path)
panic("Partition number outside range 1-256");
}
partition = val - 1;
+ } else if (booted_from_cd || boot_partition != -1) {
+ partition = boot_partition;
} else {
- if (boot_partition != -1) {
- partition = boot_partition;
- } else {
- panic("Boot partition information is unavailable.");
- }
+ panic("Boot partition information is unavailable.");
}
struct volume part;
diff --git a/stage2/main.c b/stage2/main.c
index 1f3650a2..79c14b9f 100644
--- a/stage2/main.c
+++ b/stage2/main.c
@@ -20,10 +20,18 @@
#include <pxe/pxe.h>
#include <pxe/tftp.h>
-void entry(uint8_t _boot_drive, int pxe_boot) {
+enum {
+ BOOT_FROM_HDD,
+ BOOT_FROM_PXE,
+ BOOT_FROM_CD
+};
+
+void entry(uint8_t _boot_drive, int boot_from) {
boot_drive = _boot_drive;
- booted_from_pxe = pxe_boot;
+ booted_from_pxe = (boot_from == BOOT_FROM_PXE);
+ booted_from_cd = (boot_from == BOOT_FROM_CD);
+ stage3_already_loaded = booted_from_cd; // CD loads both stages
mtrr_save();
@@ -37,20 +45,15 @@ void entry(uint8_t _boot_drive, int pxe_boot) {
init_e820();
init_memmap();
+ struct volume part;
volume_create_index();
- if (pxe_boot) {
- pxe_init();
- if (init_config_pxe()) {
- panic("Failed to load config file");
- }
- print("Config loaded via PXE\n");
- } else {
+ switch (boot_from) {
+ case BOOT_FROM_HDD:
print("Boot drive: %x\n", boot_drive);
// Look for config file.
print("Searching for config file...\n");
for (int i = 0; ; i++) {
- struct volume part;
int ret = volume_get_by_coord(&part, boot_drive, i);
switch (ret) {
case INVALID_TABLE:
@@ -66,6 +69,22 @@ void entry(uint8_t _boot_drive, int pxe_boot) {
break;
}
}
+ break;
+
+ case BOOT_FROM_PXE:
+ pxe_init();
+ if (init_config_pxe()) {
+ panic("Failed to load config file");
+ }
+ print("Config loaded via PXE\n");
+ break;
+
+ case BOOT_FROM_CD:
+ boot_partition = -1; // raw device
+ volume_get_by_coord(&part, boot_drive, boot_partition);
+ if (init_config_disk(&part))
+ panic("Failed to load config file");
+ break;
}
trace_init();
@@ -81,7 +100,7 @@ void entry(uint8_t _boot_drive, int pxe_boot) {
if (!strcmp(proto, "stivale")) {
stivale_load(config, cmdline);
} else if (!strcmp(proto, "stivale2")) {
- stivale2_load(config, cmdline, pxe_boot);
+ stivale2_load(config, cmdline, boot_from);
} else if (!strcmp(proto, "linux")) {
linux_load(config, cmdline);
} else if (!strcmp(proto, "chainload")) {
diff --git a/test/limine.cfg b/test/limine.cfg
index 0af42a2c..93019355 100644
--- a/test/limine.cfg
+++ b/test/limine.cfg
@@ -5,48 +5,48 @@ GRAPHICS=yes
MENU_RESOLUTION=1024x768
MENU_FONT=boot:///boot/font.bin
E9_OUTPUT=yes
-STAGE2_MAP=bios://:1/boot/stage2.map
+STAGE2_MAP=boot:///boot/stage2.map
THEME_COLOURS=60000000;aa0000;00aaff;aa5500;0000aa;aa00aa;9076de;aaaaaa
THEME_MARGIN=64
-BACKGROUND_PATH=bios://:1/boot/bg.bmp
+BACKGROUND_PATH=boot:///boot/bg.bmp
:+Legacy
::Stivale Test
PROTOCOL=stivale
-KERNEL_PATH=boot://1/boot/test.elf
+KERNEL_PATH=boot:///boot/test.elf
KERNEL_CMDLINE=Hi! This is an example!
-MODULE_PATH=bios://:1/boot/test.elf
+MODULE_PATH=boot:///boot/test.elf
MODULE_STRING=yooooo
-MODULE_PATH=bios://:1/boot/bg.bmp
+MODULE_PATH=boot:///boot/bg.bmp
MODULE_STRING=yooooo
::Stivale Test (KASLR)
PROTOCOL=stivale
KASLR=yes
-KERNEL_PATH=boot://1/boot/test.elf
+KERNEL_PATH=boot:///boot/test.elf
KERNEL_CMDLINE=Hi! This is an example!
-MODULE_PATH=bios://:1/boot/test.elf
+MODULE_PATH=boot:///boot/test.elf
MODULE_STRING=yooooo
-MODULE_PATH=bios://:1/boot/bg.bmp
+MODULE_PATH=boot:///boot/bg.bmp
MODULE_STRING=yooooo
:Stivale2 Test
PROTOCOL=stivale2
RESOLUTION=640x480x16
-KERNEL_PATH=bios://:1/boot/test.elf
+KERNEL_PATH=boot:///boot/test.elf
KERNEL_CMDLINE=Woah! Another example!
-MODULE_PATH=bios://:1/boot/bg.bmp
+MODULE_PATH=boot:///boot/bg.bmp
MODULE_STRING=yooooo
:Stivale2 Test (KASLR)
@@ -54,8 +54,18 @@ MODULE_STRING=yooooo
PROTOCOL=stivale2
RESOLUTION=640x480x16
KASLR=yes
+KERNEL_PATH=boot:///boot/test.elf
+KERNEL_CMDLINE=Woah! Another example!
+
+MODULE_PATH=boot:///boot/bg.bmp
+MODULE_STRING=yooooo
+
+:Test bios://
+
+PROTOCOL=stivale2
+RESOLUTION=640x480x16
KERNEL_PATH=bios://:1/boot/test.elf
KERNEL_CMDLINE=Woah! Another example!
MODULE_PATH=bios://:1/boot/bg.bmp
-MODULE_STRING=yooooo
+MODULE_STRING=yooooo
\ No newline at end of file
