Functioning bootloader

This commit is contained in:
K. Lange 2018-03-06 18:18:53 +09:00 committed by Kevin Lange
parent 2e3279350e
commit c73c832ade
11 changed files with 1175 additions and 39 deletions

View File

@ -6,7 +6,7 @@ KLD = $(KERNEL_TARGET)-ld
all: image.iso all: image.iso
image.iso: stuff/boot/boot.sys 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 cstuff.o: cstuff.c
${KCC} -c -Os -o cstuff.o cstuff.c ${KCC} -c -Os -o cstuff.o cstuff.c

154
ata.h Normal file
View File

@ -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;

223
atapi_imp.h Normal file
View File

@ -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;
}

10
boot.s
View File

@ -124,3 +124,13 @@ gdt_end
global mmap_ent global mmap_ent
mmap_ent db 0, 0 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]

271
cstuff.c
View File

@ -1,54 +1,249 @@
#define __DEBUG__ #include "types.h"
#ifdef __DEBUG__ #include "ata.h"
unsigned short * textmemptr = (unsigned short *)0xB8000; #include "text.h"
static void placech(unsigned char c, int x, int y, int attr) { #include "util.h"
unsigned short *where; #include "atapi_imp.h"
unsigned att = attr << 8; #include "iso9660.h"
where = textmemptr + (y * 80 + x); #include "elf.h"
*where = c | att; #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 void restore_mod(void) {
static int y = 0; memcpy(dir_entry, (iso_9660_directory_entry_t *)mod_dir, sizeof(iso_9660_directory_entry_t));
static void print(char * str) { #if 0
while (*str) { print("mod restored.");
if (*str == '\n') { print("\n Entry len: "); print_hex( dir_entry->length);
x = 0; print("\n File start: "); print_hex( dir_entry->extent_start_LSB);
y += 1; print("\n File len: "); print_hex( dir_entry->extent_length_LSB);
if (y == 24) { print("\n");
y = 0; #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 { } else {
placech(*str, x, y, 0x07); print("No mod directory?\n");
x++;
if (x == 80) {
x = 0;
y += 1;
if (y == 24) {
y = 0;
}
}
}
str++;
} }
} else {
print("boo\n");
} }
static void clear() { return;
for (int y = 0; y < 24; ++y) {
for (int x = 0; x < 80; ++x) {
placech(' ', x, y, 0x00);
} }
}
}
#else
#define print(...)
#define clear()
#endif
int kmain() { int kmain() {
clear(); clear();
print("ToaruOS-NIH Bootloader v0.1\n\n"); print("ToaruOS-NIH Bootloader v0.1\n\n");
print("Scanning ATA devices.\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); while (1);
} }

157
elf.h Normal file
View File

@ -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

165
iso9660.h Normal file
View File

@ -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;
}

89
multiboot.h Normal file
View File

@ -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;

63
text.h Normal file
View File

@ -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

10
types.h Normal file
View File

@ -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;

70
util.h Normal file
View File

@ -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;
}