From c73c832ade109dc19a33c74550a573c8a1cc84de Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Tue, 6 Mar 2018 18:18:53 +0900 Subject: [PATCH] Functioning bootloader --- Makefile | 2 +- ata.h | 154 +++++++++++++++++++++++++++++ atapi_imp.h | 223 ++++++++++++++++++++++++++++++++++++++++++ boot.s | 10 ++ cstuff.c | 271 ++++++++++++++++++++++++++++++++++++++++++++-------- elf.h | 157 ++++++++++++++++++++++++++++++ iso9660.h | 165 ++++++++++++++++++++++++++++++++ multiboot.h | 89 +++++++++++++++++ text.h | 63 ++++++++++++ types.h | 10 ++ util.h | 70 ++++++++++++++ 11 files changed, 1175 insertions(+), 39 deletions(-) create mode 100644 ata.h create mode 100644 atapi_imp.h create mode 100644 elf.h create mode 100644 iso9660.h create mode 100644 multiboot.h create mode 100644 text.h create mode 100644 types.h create mode 100644 util.h diff --git a/Makefile b/Makefile index dc4f3176..e0d55202 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ KLD = $(KERNEL_TARGET)-ld all: image.iso image.iso: stuff/boot/boot.sys - xorriso -as mkisofs -R -J -c boot/bootcat -b boot/boot.sys -no-emul-boot -boot-load-size 4 -o image.iso stuff + xorriso -as mkisofs -R -J -c boot/bootcat -b boot/boot.sys -no-emul-boot -boot-load-size 16 -o image.iso stuff cstuff.o: cstuff.c ${KCC} -c -Os -o cstuff.o cstuff.c diff --git a/ata.h b/ata.h new file mode 100644 index 00000000..303dadc1 --- /dev/null +++ b/ata.h @@ -0,0 +1,154 @@ +/* vim: tabstop=4 shiftwidth=4 noexpandtab + * + * Values for ATA / PATA devices + */ + +#pragma once + +#define ATA_SR_BSY 0x80 +#define ATA_SR_DRDY 0x40 +#define ATA_SR_DF 0x20 +#define ATA_SR_DSC 0x10 +#define ATA_SR_DRQ 0x08 +#define ATA_SR_CORR 0x04 +#define ATA_SR_IDX 0x02 +#define ATA_SR_ERR 0x01 + +#define ATA_ER_BBK 0x80 +#define ATA_ER_UNC 0x40 +#define ATA_ER_MC 0x20 +#define ATA_ER_IDNF 0x10 +#define ATA_ER_MCR 0x08 +#define ATA_ER_ABRT 0x04 +#define ATA_ER_TK0NF 0x02 +#define ATA_ER_AMNF 0x01 + +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +#define ATAPI_CMD_READ 0xA8 +#define ATAPI_CMD_EJECT 0x1B + +#define ATA_IDENT_DEVICETYPE 0 +#define ATA_IDENT_CYLINDERS 2 +#define ATA_IDENT_HEADS 6 +#define ATA_IDENT_SECTORS 12 +#define ATA_IDENT_SERIAL 20 +#define ATA_IDENT_MODEL 54 +#define ATA_IDENT_CAPABILITIES 98 +#define ATA_IDENT_FIELDVALID 106 +#define ATA_IDENT_MAX_LBA 120 +#define ATA_IDENT_COMMANDSETS 164 +#define ATA_IDENT_MAX_LBA_EXT 200 + +#define IDE_ATA 0x00 +#define IDE_ATAPI 0x01 + +#define ATA_MASTER 0x00 +#define ATA_SLAVE 0x01 + +#define ATA_REG_DATA 0x00 +#define ATA_REG_ERROR 0x01 +#define ATA_REG_FEATURES 0x01 +#define ATA_REG_SECCOUNT0 0x02 +#define ATA_REG_LBA0 0x03 +#define ATA_REG_LBA1 0x04 +#define ATA_REG_LBA2 0x05 +#define ATA_REG_HDDEVSEL 0x06 +#define ATA_REG_COMMAND 0x07 +#define ATA_REG_STATUS 0x07 +#define ATA_REG_SECCOUNT1 0x08 +#define ATA_REG_LBA3 0x09 +#define ATA_REG_LBA4 0x0A +#define ATA_REG_LBA5 0x0B +#define ATA_REG_CONTROL 0x0C +#define ATA_REG_ALTSTATUS 0x0C +#define ATA_REG_DEVADDRESS 0x0D + +// Channels: +#define ATA_PRIMARY 0x00 +#define ATA_SECONDARY 0x01 + +// Directions: +#define ATA_READ 0x00 +#define ATA_WRITE 0x01 + +typedef struct { + uint16_t base; + uint16_t ctrl; + uint16_t bmide; + uint16_t nien; +} ide_channel_regs_t; + +typedef struct { + uint8_t reserved; + uint8_t channel; + uint8_t drive; + uint16_t type; + uint16_t signature; + uint16_t capabilities; + uint32_t command_sets; + uint32_t size; + uint8_t model[41]; +} ide_device_t; + +typedef struct { + uint8_t status; + uint8_t chs_first_sector[3]; + uint8_t type; + uint8_t chs_last_sector[3]; + uint32_t lba_first_sector; + uint32_t sector_count; +} partition_t; + +typedef struct { + uint16_t flags; + uint16_t unused1[9]; + char serial[20]; + uint16_t unused2[3]; + char firmware[8]; + char model[40]; + uint16_t sectors_per_int; + uint16_t unused3; + uint16_t capabilities[2]; + uint16_t unused4[2]; + uint16_t valid_ext_data; + uint16_t unused5[5]; + uint16_t size_of_rw_mult; + uint32_t sectors_28; + uint16_t unused6[38]; + uint64_t sectors_48; + uint16_t unused7[152]; +} __attribute__((packed)) ata_identify_t; + +typedef struct { + uint8_t boostrap[446]; + partition_t partitions[4]; + uint8_t signature[2]; +} __attribute__((packed)) mbr_t; + +struct ata_device { + int io_base; + int control; + int slave; + int is_atapi; + ata_identify_t identity; + unsigned int atapi_lba; + unsigned int atapi_sector_size; +}; + +typedef union { + uint8_t command_bytes[12]; + uint16_t command_words[6]; +} atapi_command_t; diff --git a/atapi_imp.h b/atapi_imp.h new file mode 100644 index 00000000..11cec1a0 --- /dev/null +++ b/atapi_imp.h @@ -0,0 +1,223 @@ +#pragma once + +static struct ata_device ata_primary_master = {.io_base = 0x1F0, .control = 0x3F6, .slave = 0}; +static struct ata_device ata_primary_slave = {.io_base = 0x1F0, .control = 0x3F6, .slave = 1}; +static struct ata_device ata_secondary_master = {.io_base = 0x170, .control = 0x376, .slave = 0}; +static struct ata_device ata_secondary_slave = {.io_base = 0x170, .control = 0x376, .slave = 1}; + +static void ata_io_wait(struct ata_device * dev) { + inportb(dev->io_base + ATA_REG_ALTSTATUS); + inportb(dev->io_base + ATA_REG_ALTSTATUS); + inportb(dev->io_base + ATA_REG_ALTSTATUS); + inportb(dev->io_base + ATA_REG_ALTSTATUS); +} + +static int ata_status_wait(struct ata_device * dev, int timeout) { + int status; + if (timeout > 0) { + int i = 0; + while ((status = inportb(dev->io_base + ATA_REG_STATUS)) & ATA_SR_BSY && (i < timeout)) i++; + } else { + while ((status = inportb(dev->io_base + ATA_REG_STATUS)) & ATA_SR_BSY); + } + return status; +} + +static void ata_soft_reset(struct ata_device * dev) { + outportb(dev->control, 0x04); + ata_io_wait(dev); + outportb(dev->control, 0x00); +} + +static int ata_wait(struct ata_device * dev, int advanced) { + uint8_t status = 0; + + ata_io_wait(dev); + + status = ata_status_wait(dev, -1); + + if (advanced) { + status = inportb(dev->io_base + ATA_REG_STATUS); + if (status & ATA_SR_ERR) return 1; + if (status & ATA_SR_DF) return 1; + if (!(status & ATA_SR_DRQ)) return 1; + } + + return 0; +} + +static void atapi_device_init(struct ata_device * dev) { + + dev->is_atapi = 1; + + outportb(dev->io_base + 1, 1); + outportb(dev->control, 0); + + outportb(dev->io_base + ATA_REG_HDDEVSEL, 0xA0 | dev->slave << 4); + ata_io_wait(dev); + + outportb(dev->io_base + ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET); + ata_io_wait(dev); + + ata_wait(dev, 0); + + uint16_t * buf = (uint16_t *)&dev->identity; + + for (int i = 0; i < 256; ++i) { + buf[i] = inports(dev->io_base); + } + + uint8_t * ptr = (uint8_t *)&dev->identity.model; + for (int i = 0; i < 39; i+=2) { + uint8_t tmp = ptr[i+1]; + ptr[i+1] = ptr[i]; + ptr[i] = tmp; + } + + /* Detect medium */ + atapi_command_t command; + memset(&command, 0, sizeof(command)); + command.command_bytes[0] = 0x25; + + uint16_t bus = dev->io_base; + + outportb(bus + ATA_REG_FEATURES, 0x00); + outportb(bus + ATA_REG_LBA1, 0x08); + outportb(bus + ATA_REG_LBA2, 0x08); + outportb(bus + ATA_REG_COMMAND, ATA_CMD_PACKET); + + /* poll */ + while (1) { + uint8_t status = inportb(dev->io_base + ATA_REG_STATUS); + if ((status & ATA_SR_ERR)) goto atapi_error; + if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRDY)) break; + } + + for (int i = 0; i < 6; ++i) { + outports(bus, command.command_words[i]); + } + + /* poll */ + while (1) { + uint8_t status = inportb(dev->io_base + ATA_REG_STATUS); + if ((status & ATA_SR_ERR)) goto atapi_error_read; + if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRDY)) break; + if ((status & ATA_SR_DRQ)) break; + } + + uint16_t data[4]; + + for (int i = 0; i < 4; ++i) { + data[i] = inports(bus); + } + +#define htonl(l) ( (((l) & 0xFF) << 24) | (((l) & 0xFF00) << 8) | (((l) & 0xFF0000) >> 8) | (((l) & 0xFF000000) >> 24)) + uint32_t lba, blocks;; + memcpy(&lba, &data[0], sizeof(uint32_t)); + lba = htonl(lba); + memcpy(&blocks, &data[2], sizeof(uint32_t)); + blocks = htonl(blocks); + + dev->atapi_lba = lba; + dev->atapi_sector_size = blocks; + + return; + +atapi_error_read: + return; + +atapi_error: + return; +} + +static int ata_device_detect(struct ata_device * dev) { + ata_soft_reset(dev); + ata_io_wait(dev); + outportb(dev->io_base + ATA_REG_HDDEVSEL, 0xA0 | dev->slave << 4); + ata_io_wait(dev); + ata_status_wait(dev, 10000); + + unsigned char cl = inportb(dev->io_base + ATA_REG_LBA1); /* CYL_LO */ + unsigned char ch = inportb(dev->io_base + ATA_REG_LBA2); /* CYL_HI */ + + if (cl == 0xFF && ch == 0xFF) { + /* Nothing here */ + return 0; + } + if ((cl == 0x00 && ch == 0x00) || + (cl == 0x3C && ch == 0xC3)) { + return 1; + } else if ((cl == 0x14 && ch == 0xEB) || + (cl == 0x69 && ch == 0x96)) { + atapi_device_init(dev); + return 2; + } + + return 0; +} + +static void ata_device_read_sector_atapi(struct ata_device * dev, uint32_t lba, uint8_t * buf) { + + if (!dev->is_atapi) return; + + uint16_t bus = dev->io_base; + + outportb(dev->io_base + ATA_REG_HDDEVSEL, 0xA0 | dev->slave << 4); + ata_io_wait(dev); + + outportb(bus + ATA_REG_FEATURES, 0x00); + outportb(bus + ATA_REG_LBA1, dev->atapi_sector_size & 0xFF); + outportb(bus + ATA_REG_LBA2, dev->atapi_sector_size >> 8); + outportb(bus + ATA_REG_COMMAND, ATA_CMD_PACKET); + + /* poll */ + while (1) { + uint8_t status = inportb(dev->io_base + ATA_REG_STATUS); + if ((status & ATA_SR_ERR)) goto atapi_error_on_read_setup; + if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRQ)) break; + } + + atapi_command_t command; + command.command_bytes[0] = 0xA8; + command.command_bytes[1] = 0; + command.command_bytes[2] = (lba >> 0x18) & 0xFF; + command.command_bytes[3] = (lba >> 0x10) & 0xFF; + command.command_bytes[4] = (lba >> 0x08) & 0xFF; + command.command_bytes[5] = (lba >> 0x00) & 0xFF; + command.command_bytes[6] = 0; + command.command_bytes[7] = 0; + command.command_bytes[8] = 0; /* bit 0 = PMI (0, last sector) */ + command.command_bytes[9] = 1; /* control */ + command.command_bytes[10] = 0; + command.command_bytes[11] = 0; + + for (int i = 0; i < 6; ++i) { + outports(bus, command.command_words[i]); + } + + while (1) { + uint8_t status = inportb(dev->io_base + ATA_REG_STATUS); + if ((status & ATA_SR_ERR)) goto atapi_error_on_read_setup; + if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRQ)) break; + } + + uint16_t size_to_read = inportb(bus + ATA_REG_LBA2) << 8; + size_to_read = size_to_read | inportb(bus + ATA_REG_LBA1); + + + inportsm(bus,buf,size_to_read/2); + + while (1) { + uint8_t status = inportb(dev->io_base + ATA_REG_STATUS); + if ((status & ATA_SR_ERR)) goto atapi_error_on_read_setup; + if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRDY)) break; + } + + return; + +atapi_error_on_read_setup: + print("error on setup\n"); + return; +} + + diff --git a/boot.s b/boot.s index b8379840..9a4f5955 100644 --- a/boot.s +++ b/boot.s @@ -124,3 +124,13 @@ gdt_end global mmap_ent mmap_ent db 0, 0 +[bits 32] +global jump_to_main +jump_to_main: + extern _eax + extern _ebx + extern _xmain + mov eax, [_eax] + mov ebx, [_ebx] + jmp [_xmain] + diff --git a/cstuff.c b/cstuff.c index d2f50f9f..4b5d2037 100644 --- a/cstuff.c +++ b/cstuff.c @@ -1,54 +1,249 @@ -#define __DEBUG__ -#ifdef __DEBUG__ -unsigned short * textmemptr = (unsigned short *)0xB8000; -static void placech(unsigned char c, int x, int y, int attr) { - unsigned short *where; - unsigned att = attr << 8; - where = textmemptr + (y * 80 + x); - *where = c | att; +#include "types.h" +#include "ata.h" +#include "text.h" +#include "util.h" +#include "atapi_imp.h" +#include "iso9660.h" +#include "elf.h" +#include "multiboot.h" + +static void restore_root(void) { + memcpy(dir_entry, (iso_9660_directory_entry_t *)&root->root, sizeof(iso_9660_directory_entry_t)); + +#if 1 + print("Root restored."); + print("\n Entry len: "); print_hex( dir_entry->length); + print("\n File start: "); print_hex( dir_entry->extent_start_LSB); + print("\n File len: "); print_hex( dir_entry->extent_length_LSB); + print("\n"); +#endif } -static int x = 0; -static int y = 0; -static void print(char * str) { - while (*str) { - if (*str == '\n') { - x = 0; - y += 1; - if (y == 24) { - y = 0; +static void restore_mod(void) { + memcpy(dir_entry, (iso_9660_directory_entry_t *)mod_dir, sizeof(iso_9660_directory_entry_t)); +#if 0 + print("mod restored."); + print("\n Entry len: "); print_hex( dir_entry->length); + print("\n File start: "); print_hex( dir_entry->extent_start_LSB); + print("\n File len: "); print_hex( dir_entry->extent_length_LSB); + print("\n"); +#endif +} + +#define KERNEL_LOAD_START 0x300000 + +static char * modules[] = { + "ZERO.KO", + "RANDOM.KO", + "SERIAL.KO", + "DEBUG_SH.KO", + "PROCFS.KO", + "TMPFS.KO", + "ATA.KO", + "EXT2.KO", + "ISO9660.KO", + "PS2KBD.KO", + "PS2MOUSE.KO", + "LFBVIDEO.KO", + "VBOXGUES.KO", + "VMWARE.KO", + "VIDSET.KO", + "PACKETFS.KO", + "SND.KO", + "AC97.KO", + "NET.KO", + "PCNET.KO", + "RTL.KO", + "E1000.KO", + 0 +}; + +static mboot_mod_t modules_mboot[23] = { + {0,0,0,1} +}; + +static struct multiboot multiboot_header = { + /* flags; */ (1 << 3), + /* mem_lower; */ 0x100000, + /* mem_upper; */ 0x640000, + /* boot_device; */ 0, + /* cmdline; */ (uintptr_t)"vid=auto,1024,768 root=/dev/ram0,nocache start=session", + /* mods_count; */ 23, + /* mods_addr; */ &modules_mboot, + /* num; */ 0, + /* size; */ 0, + /* addr; */ 0, + /* shndx; */ 0, + /* mmap_length; */ 0, + /* mmap_addr; */ 0, + /* drives_length; */ 0, + /* drives_addr; */ 0, + /* config_table; */ 0, + /* boot_loader_name; */ 0, + /* apm_table; */ 0, + /* vbe_control_info; */ 0, + /* vbe_mode_info; */ 0, + /* vbe_mode; */ 0, + /* vbe_interface_seg; */ 0, + /* vbe_interface_off; */ 0, + /* vbe_interface_len; */ 0, +}; + +static long ramdisk_off = 1; +static long ramdisk_len = 1; + +extern void jump_to_main(void); + +int _eax = 1; +int _ebx = 1; +int _xmain = 1; + +static void move_kernel(void) { + clear(); + print("Relocating kernel...\n"); + + Elf32_Header * header = (Elf32_Header *)KERNEL_LOAD_START; + + if (header->e_ident[0] != ELFMAG0 || + header->e_ident[1] != ELFMAG1 || + header->e_ident[2] != ELFMAG2 || + header->e_ident[3] != ELFMAG3) { + print("Kernel is invalid?\n"); + } + + uintptr_t entry = (uintptr_t)header->e_entry; + + for (uintptr_t x = 0; x < (uint32_t)header->e_phentsize * header->e_phnum; x += header->e_phentsize) { + Elf32_Phdr * phdr = (Elf32_Phdr *)((uint8_t*)KERNEL_LOAD_START + header->e_phoff + x); + if (phdr->p_type == PT_LOAD) { + //read_fs(file, phdr->p_offset, phdr->p_filesz, (uint8_t *)phdr->p_vaddr); + print("Loading a Phdr... "); + print_hex(phdr->p_vaddr); + print(" "); + print_hex(phdr->p_offset); + print(" "); + print_hex(phdr->p_filesz); + print("\n"); + memcpy((uint8_t*)phdr->p_vaddr, (uint8_t*)KERNEL_LOAD_START + phdr->p_offset, phdr->p_filesz); + long r = phdr->p_filesz; + while (r < phdr->p_memsz) { + *(char *)(phdr->p_vaddr + r) = 0; + r++; + } + } + } + + int foo; + //__asm__ __volatile__("jmp %1" : "=a"(foo) : "a" (MULTIBOOT_EAX_MAGIC), "b"((unsigned int)multiboot_header), "r"((unsigned int)entry)); + _eax = MULTIBOOT_EAX_MAGIC; + _ebx = &multiboot_header; + _xmain = entry; + jump_to_main(); +} + +static void do_it(struct ata_device * _device) { + device = _device; + if (device->atapi_sector_size != 2048) { + print_hex(device->atapi_sector_size); + print("\n - bad sector size\n"); + return; + } + print("Locating stage2...\n"); + for (int i = 0x10; i < 0x15; ++i) { + ata_device_read_sector_atapi(device, i, (uint8_t *)root); + switch (root->type) { + case 1: + root_sector = i; + goto done; + case 0xFF: + return; + } + } + return; +done: + restore_root(); + + if (navigate("KERNEL.")) { + print("Found kernel.\n"); + print_hex(dir_entry->extent_start_LSB); print(" "); + print_hex(dir_entry->extent_length_LSB); print("\n"); + long offset = 0; + for (int i = dir_entry->extent_start_LSB; i < dir_entry->extent_start_LSB + dir_entry->extent_length_LSB / 2048 + 1; ++i, offset += 2048) { + ata_device_read_sector_atapi(device, i, (uint8_t *)KERNEL_LOAD_START + offset); + } + restore_root(); + if (navigate("MOD")) { + memcpy(mod_dir, dir_entry, sizeof(iso_9660_directory_entry_t)); + print("Scanning modules...\n"); + char ** c = modules; + int j = 0; + while (*c) { + print("load "); print(*c); print("\n"); + if (!navigate(*c)) { + print("Failed to locate module! ["); + print(*c); + print("]\n"); + break; + } + modules_mboot[j].mod_start = KERNEL_LOAD_START + offset; + modules_mboot[j].mod_end = KERNEL_LOAD_START + offset + dir_entry->extent_length_LSB; + for (int i = dir_entry->extent_start_LSB; i < dir_entry->extent_start_LSB + dir_entry->extent_length_LSB / 2048 + 1; ++i, offset += 2048) { + ata_device_read_sector_atapi(device, i, (uint8_t *)KERNEL_LOAD_START + offset); + } + restore_mod(); + c++; + j++; + } + print("Done.\n"); + restore_root(); + if (navigate("RAMDISK.IMG")) { + print("Loading ramdisk...\n"); + ramdisk_off = KERNEL_LOAD_START + offset; + ramdisk_len = dir_entry->extent_length_LSB; + modules_mboot[22].mod_start = ramdisk_off; + modules_mboot[22].mod_end = ramdisk_off + ramdisk_len; + for (int i = dir_entry->extent_start_LSB; i < dir_entry->extent_start_LSB + dir_entry->extent_length_LSB / 2048 + 1; ++i, offset += 2048) { + if (i % 32 == 0) { + print("."); + } + ata_device_read_sector_atapi(device, i, (uint8_t *)KERNEL_LOAD_START + offset); + } + print("Done.\n"); + move_kernel(); } } else { - placech(*str, x, y, 0x07); - x++; - if (x == 80) { - x = 0; - y += 1; - if (y == 24) { - y = 0; - } - } + print("No mod directory?\n"); } - str++; + } else { + print("boo\n"); } -} -static void clear() { - for (int y = 0; y < 24; ++y) { - for (int x = 0; x < 80; ++x) { - placech(' ', x, y, 0x00); - } - } + return; } -#else -#define print(...) -#define clear() -#endif int kmain() { clear(); print("ToaruOS-NIH Bootloader v0.1\n\n"); print("Scanning ATA devices.\n"); + ata_device_detect(&ata_primary_master); + ata_device_detect(&ata_primary_slave); + ata_device_detect(&ata_secondary_master); + ata_device_detect(&ata_secondary_slave); + + if (ata_primary_master.is_atapi) { + do_it(&ata_primary_master); + } + if (ata_primary_slave.is_atapi) { + do_it(&ata_primary_slave); + } + if (ata_secondary_master.is_atapi) { + do_it(&ata_secondary_master); + } + if (ata_secondary_slave.is_atapi) { + do_it(&ata_secondary_slave); + } + + while (1); } diff --git a/elf.h b/elf.h new file mode 100644 index 00000000..6deb9987 --- /dev/null +++ b/elf.h @@ -0,0 +1,157 @@ +#pragma once +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define EI_NIDENT 16 + +typedef uint32_t Elf32_Word; +typedef uint32_t Elf32_Addr; +typedef uint32_t Elf32_Off; +typedef uint32_t Elf32_Sword; +typedef uint16_t Elf32_Half; + +/* + * ELF Header + */ +typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Header; + +/* + * e_type + */ + +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Relocatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_LOPROC 0xff0 /* [Processor Specific] */ +#define ET_HIPROC 0xfff /* [Processor Specific] */ + +/* + * Machine types + */ +#define EM_NONE 0 +#define EM_386 3 + +#define EV_NONE 0 +#define EV_CURRENT 1 + +/** Program Header */ +typedef struct { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +/* p_type values */ +#define PT_NULL 0 /* Unused, skip me */ +#define PT_LOAD 1 /* Loadable segment */ +#define PT_DYNAMIC 2 /* Dynamic linking information */ +#define PT_INTERP 3 /* Interpreter (null-terminated string, pathname) */ +#define PT_NOTE 4 /* Auxillary information */ +#define PT_SHLIB 5 /* Reserved. */ +#define PT_PHDR 6 /* Oh, it's me. Hello! Back-reference to the header table itself */ +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7FFFFFFF + + +/** Section Header */ +typedef struct { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +typedef struct { + uint32_t id; + uintptr_t ptr; +} Elf32_auxv; + +typedef struct { + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct { + Elf32_Sword d_tag; + union { + Elf32_Word d_val; + Elf32_Addr d_ptr; + Elf32_Off d_off; + } d_un; +} Elf32_Dyn; + +/* sh_type values */ +#define SHT_NONE 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_NOBITS 8 +#define SHT_REL 9 + +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) +#define ELF32_R_INFO(s,t) (((s) << 8) + (unsigned char)(t)) + +#define ELF32_ST_BIND(i) ((i) >> 4) +#define ELF32_ST_TYPE(i) ((i) & 0xf) +#define ELF32_ST_INFO(b,t) (((b) << 4) + ((t) & 0xf)) + +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 +#define STB_NUM 3 + +#define STB_LOPROC 13 +#define STB_HIPROC 15 + +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_COMMON 5 +#define STT_TLS 6 +#define STT_NUM 7 + +#define STT_LOPROC 13 +#define STT_HIPROC 15 + + diff --git a/iso9660.h b/iso9660.h new file mode 100644 index 00000000..0daf6248 --- /dev/null +++ b/iso9660.h @@ -0,0 +1,165 @@ +#pragma once + +typedef struct { + char year[4]; + char month[2]; + char day[2]; + char hour[2]; + char minute[2]; + char second[2]; + char hundredths[2]; + int8_t timezone; +} __attribute__((packed)) iso_9660_datetime_t; + +typedef struct { + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + int8_t timezone; +} __attribute__((packed)) iso_9660_rec_date_t; + +typedef struct { + uint8_t length; + uint8_t ext_length; + + uint32_t extent_start_LSB; + uint32_t extent_start_MSB; + + uint32_t extent_length_LSB; + uint32_t extent_length_MSB; + + iso_9660_rec_date_t record_date; + + uint8_t flags; + uint8_t interleave_units; + uint8_t interleave_gap; + + uint16_t volume_seq_LSB; + uint16_t volume_seq_MSB; + + uint8_t name_len; + char name[]; +} __attribute__((packed)) iso_9660_directory_entry_t; + +typedef struct { + uint8_t type; /* 0x01 */ + char id[5]; /* CD001 */ + + uint8_t version; + uint8_t _unused0; + + char system_id[32]; + char volume_id[32]; + + uint8_t _unused1[8]; + + uint32_t volume_space_LSB; + uint32_t volume_space_MSB; + + uint8_t _unused2[32]; + + uint16_t volume_set_LSB; + uint16_t volume_set_MSB; + + uint16_t volume_seq_LSB; + uint16_t volume_seq_MSB; + + uint16_t logical_block_size_LSB; + uint16_t logical_block_size_MSB; + + uint32_t path_table_size_LSB; + uint32_t path_table_size_MSB; + + uint32_t path_table_LSB; + uint32_t optional_path_table_LSB; + + uint32_t path_table_MSB; + uint32_t optional_path_table_MSB; + + /* iso_9660_directory_entry_t */ + char root[34]; + + char volume_set_id[128]; + char volume_publisher[128]; + char data_preparer[128]; + char application_id[128]; + + char copyright_file[38]; + char abstract_file[36]; + char bibliographic_file[37]; + + iso_9660_datetime_t creation; + iso_9660_datetime_t modification; + iso_9660_datetime_t expiration; + iso_9660_datetime_t effective; + + uint8_t file_structure_version; + uint8_t _unused_3; + + char application_use[]; +} __attribute__((packed)) iso_9660_volume_descriptor_t; + +#define ISO_SECTOR_SIZE 2048 + +#define FLAG_HIDDEN 0x01 +#define FLAG_DIRECTORY 0x02 +#define FLAG_ASSOCIATED 0x04 +#define FLAG_EXTENDED 0x08 +#define FLAG_PERMISSIONS 0x10 +#define FLAG_CONTINUES 0x80 + +static int root_sector = 0; +static iso_9660_volume_descriptor_t * root = (iso_9660_volume_descriptor_t *)((uint8_t *)0x20000); +static iso_9660_directory_entry_t * dir_entry = (iso_9660_directory_entry_t *)((uint8_t *)0x20800); +static uint8_t * mod_dir = (uint8_t *)0x21000; +static uint8_t * dir_entries = (uint8_t *)(0x30000); +static struct ata_device * device = 0; + +static int navigate(char * name) { + memset(dir_entries, 2048, 0xA5); + //print("reading from sector "); + //print_hex(dir_entry->extent_start_LSB); + //print("\n"); + ata_device_read_sector_atapi(device, dir_entry->extent_start_LSB, dir_entries); + ata_device_read_sector_atapi(device, dir_entry->extent_start_LSB+1, dir_entries + 2048); + ata_device_read_sector_atapi(device, dir_entry->extent_start_LSB+2, dir_entries + 4096); + + long offset = 0; + while (1) { + iso_9660_directory_entry_t * dir = (iso_9660_directory_entry_t *)(dir_entries + offset); + if (dir->length == 0) { + if (offset < dir_entry->extent_length_LSB) { + offset += 1; // this->block_size - ((uintptr_t)offset % this->block_size); + goto try_again; + } + break; + } + if (!(dir->flags & FLAG_HIDDEN)) { + char file_name[dir->name_len + 1]; + memcpy(file_name, dir->name, dir->name_len); + file_name[dir->name_len] = 0; + char * s = strchr(file_name,';'); + if (s) { + *s = '\0'; + } +#if 0 + print("Found a file: "); + print(" Name: "); + print(file_name); print("\n"); +#endif + if (!strcmp(file_name, name)) { + memcpy(dir_entry, dir, sizeof(iso_9660_directory_entry_t)); + return 1; + } + } + offset += dir->length; +try_again: + if ((long)(offset) > dir_entry->extent_length_LSB) break; + } + + return 0; +} + diff --git a/multiboot.h b/multiboot.h new file mode 100644 index 00000000..92d6a7a8 --- /dev/null +++ b/multiboot.h @@ -0,0 +1,89 @@ +#pragma once + +#define MULTIBOOT_MAGIC 0x1BADB002 +#define MULTIBOOT_EAX_MAGIC 0x2BADB002 +#define MULTIBOOT_FLAG_MEM 0x001 +#define MULTIBOOT_FLAG_DEVICE 0x002 +#define MULTIBOOT_FLAG_CMDLINE 0x004 +#define MULTIBOOT_FLAG_MODS 0x008 +#define MULTIBOOT_FLAG_AOUT 0x010 +#define MULTIBOOT_FLAG_ELF 0x020 +#define MULTIBOOT_FLAG_MMAP 0x040 +#define MULTIBOOT_FLAG_CONFIG 0x080 +#define MULTIBOOT_FLAG_LOADER 0x100 +#define MULTIBOOT_FLAG_APM 0x200 +#define MULTIBOOT_FLAG_VBE 0x400 + +struct multiboot +{ + uintptr_t flags; + uintptr_t mem_lower; + uintptr_t mem_upper; + uintptr_t boot_device; + uintptr_t cmdline; + uintptr_t mods_count; + uintptr_t mods_addr; + uintptr_t num; + uintptr_t size; + uintptr_t addr; + uintptr_t shndx; + uintptr_t mmap_length; + uintptr_t mmap_addr; + uintptr_t drives_length; + uintptr_t drives_addr; + uintptr_t config_table; + uintptr_t boot_loader_name; + uintptr_t apm_table; + uintptr_t vbe_control_info; + uintptr_t vbe_mode_info; + uintptr_t vbe_mode; + uintptr_t vbe_interface_seg; + uintptr_t vbe_interface_off; + uintptr_t vbe_interface_len; +} __attribute__ ((packed)); + +typedef struct { + uint16_t attributes; + uint8_t winA, winB; + uint16_t granularity; + uint16_t winsize; + uint16_t segmentA, segmentB; + uint32_t realFctPtr; + uint16_t pitch; + + uint16_t Xres, Yres; + uint8_t Wchar, Ychar, planes, bpp, banks; + uint8_t memory_model, bank_size, image_pages; + uint8_t reserved0; + + uint8_t red_mask, red_position; + uint8_t green_mask, green_position; + uint8_t blue_mask, blue_position; + uint8_t rsv_mask, rsv_position; + uint8_t directcolor_attributes; + + uint32_t physbase; + uint32_t reserved1; + uint16_t reserved2; +} __attribute__ ((packed)) vbe_info_t; + +typedef struct { + uintptr_t mod_start; + uintptr_t mod_end; + uintptr_t cmdline; + uintptr_t reserved; +} __attribute__ ((packed)) mboot_mod_t; + +typedef struct { + uint32_t size; + uint64_t base_addr; + uint64_t length; + uint32_t type; +} __attribute__ ((packed)) mboot_memmap_t; + +extern struct multiboot *copy_multiboot(struct multiboot *mboot_ptr); +extern void dump_multiboot(struct multiboot *mboot_ptr); +extern char * ramdisk; +extern struct multiboot * mboot_ptr; + + diff --git a/text.h b/text.h new file mode 100644 index 00000000..0ec7445c --- /dev/null +++ b/text.h @@ -0,0 +1,63 @@ +#pragma once + +#define __DEBUG__ +#ifdef __DEBUG__ +unsigned short * textmemptr = (unsigned short *)0xB8000; +static void placech(unsigned char c, int x, int y, int attr) { + unsigned short *where; + unsigned att = attr << 8; + where = textmemptr + (y * 80 + x); + *where = c | att; +} + +static int x = 0; +static int y = 0; +static void print(char * str) { + while (*str) { + if (*str == '\n') { + for (; x < 80; ++x) { + placech(' ', x, y, 0x00); + } + x = 0; + y += 1; + if (y == 24) { + y = 0; + } + } else { + placech(*str, x, y, 0x07); + x++; + if (x == 80) { + x = 0; + y += 1; + if (y == 24) { + y = 0; + } + } + } + str++; + } +} + +static void print_hex(unsigned int value) { + char out[9] = {0}; + for (int i = 7; i > -1; i--) { + out[i] = "0123456789abcdef"[(value >> (4 * (7 - i))) & 0xF]; + } + print(out); +} + +static void clear() { + x = 0; + y = 0; + for (int y = 0; y < 24; ++y) { + for (int x = 0; x < 80; ++x) { + placech(' ', x, y, 0x00); + } + } +} +#else +#define print(...) +#define clear() +#define print_hex(...) +#endif + diff --git a/types.h b/types.h new file mode 100644 index 00000000..14e7a5c4 --- /dev/null +++ b/types.h @@ -0,0 +1,10 @@ +#pragma once + +typedef unsigned long long uint64_t; +typedef unsigned long uint32_t; +typedef unsigned short uint16_t; +typedef unsigned char uint8_t; +typedef signed char int8_t; +typedef unsigned long uintptr_t; + + diff --git a/util.h b/util.h new file mode 100644 index 00000000..c2a29ce5 --- /dev/null +++ b/util.h @@ -0,0 +1,70 @@ +#pragma once + +#define _inline inline __attribute__((always_inline)) + +static _inline unsigned short inports(unsigned short _port) { + unsigned short rv; + asm volatile ("inw %1, %0" : "=a" (rv) : "dN" (_port)); + return rv; +} + +static _inline void outports(unsigned short _port, unsigned short _data) { + asm volatile ("outw %1, %0" : : "dN" (_port), "a" (_data)); +} + +static _inline unsigned int inportl(unsigned short _port) { + unsigned int rv; + asm volatile ("inl %%dx, %%eax" : "=a" (rv) : "dN" (_port)); + return rv; +} + +static _inline void outportl(unsigned short _port, unsigned int _data) { + asm volatile ("outl %%eax, %%dx" : : "dN" (_port), "a" (_data)); +} + +static _inline unsigned char inportb(unsigned short _port) { + unsigned char rv; + asm volatile ("inb %1, %0" : "=a" (rv) : "dN" (_port)); + return rv; +} + +static _inline void outportb(unsigned short _port, unsigned char _data) { + asm volatile ("outb %1, %0" : : "dN" (_port), "a" (_data)); +} + + +static _inline void inportsm(unsigned short port, unsigned char * data, unsigned long size) { + asm volatile ("rep insw" : "+D" (data), "+c" (size) : "d" (port) : "memory"); +} + +static _inline void * memcpy(void * restrict dest, const void * restrict src, long n) { + asm volatile("cld; rep movsb" + : "=c"((int){0}) + : "D"(dest), "S"(src), "c"(n) + : "flags", "memory"); + return dest; +} + +static _inline void * memset(void * dest, int c, long n) { + asm volatile("cld; rep stosb" + : "=c"((int){0}) + : "D"(dest), "a"(c), "c"(n) + : "flags", "memory"); + return dest; +} + +static int strcmp(const char * l, const char * r) { + for (; *l == *r && *l; l++, r++); + return *(unsigned char *)l - *(unsigned char *)r; +} + +static char * strchr(const char * s, int c) { + while (*s) { + if (*s == c) { + return (char *)s; + } + s++; + } + return 0; +} +