printf and shitty paging

This commit is contained in:
Tunacan 2021-06-28 22:53:47 +03:00
parent e5f54a0cfb
commit e46c2dbf0a
21 changed files with 1013 additions and 486 deletions

1
.gitignore vendored
View file

@ -1,4 +1,5 @@
.vscode/
workspace.code-workspace
*.o
*.bin
*.iso

View file

@ -16,7 +16,8 @@ ISO = build/HhhOS.iso
DIRS = build build/boot build/std build/drivers build/drivers/terminal build/drivers/idt build/drivers/device build/drivers/keyboard build/drivers/pic build/drivers/ide
OBJS = build/boot/boot.o build/boot/kernel.o build/std/string.o build/drivers/terminal/terminal.o build/drivers/idt/idt.o \
build/drivers/idt/isr.o build/std/util.o build/drivers/device/device.o build/drivers/keyboard/keyboard.o build/drivers/pic/pic.o build/drivers/ide/ide.o
build/drivers/idt/isr.o build/std/util.o build/drivers/device/device.o build/drivers/keyboard/keyboard.o build/drivers/pic/pic.o \
build/drivers/ide/ide.o build/std/stdio.o
ARCHDIR = arch/$(ARCH)/
@ -34,7 +35,7 @@ $(ISO): dirs $(BIN)
grub-mkrescue -o $(ISO) sysroot
$(BIN): $(OBJS)
$(CC) -T linker.ld $(LDFLAGS) -o $@ $^
$(CC) -T linker.ld -o $@ $^ $(LDFLAGS)
build/%.o: $(ARCHDIR)%.c
$(CC) -c $(CFLAGS) -Iinclude -o $@ $<

View file

@ -63,7 +63,6 @@ data_segment equ gdt.data - gdt
; Declare _start as a function symbol with the given symbol size.
section .text
global _start:function (_start.end - _start)
global load_idt
gdt_load:
push eax
@ -79,6 +78,27 @@ gdt_load:
pop eax
ret
global load_page_directory
load_page_directory:
push ebp
mov ebp, esp
mov eax, [esp + 8]
mov cr3, eax
mov esp, ebp
pop ebp
ret
global enable_paging
enable_paging:
push ebp
mov ebp, esp
mov eax, cr0
or eax, 80000001h
mov cr0, eax
mov esp, ebp
pop ebp
ret
_start:
; The bootloader has loaded us into 32-bit protected mode on a x86
; machine. Interrupts are disabled. Paging is disabled. The processor
@ -95,6 +115,15 @@ _start:
; in assembly as languages such as C cannot function without a stack.
mov esp, stack_top
;now enable SSE and the like
mov eax, cr0
and ax, 0xFFFB ;clear coprocessor emulation CR0.EM
or ax, 0x2 ;set coprocessor monitoring CR0.MP
mov cr0, eax
mov eax, cr4
or ax, 3 << 9 ;set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
mov cr4, eax
; This is a good place to initialize crucial processor state before the
; high-level kernel is entered. It's best to minimize the early
; environment where crucial features are offline. Note that the

View file

@ -1,5 +1,6 @@
#include <stdbool.h>
#include <stddef.h>
#include <std/stdio.h>
#include <drivers/idt/isr.h>
#include <drivers/keyboard/keyboard.h>
#include <drivers/pic/pic.h>
@ -11,10 +12,10 @@ int keyboard_descriptor = 0;
int terminal_descriptor = 0;
void shell() {
terminal_writestring("hello yes");
printf("hello yes");
while (is_running) {
terminal_writestring("\n> ");
printf("\n> ");
while (true) {
unsigned char scancode = read(keyboard_descriptor, NULL);
@ -44,40 +45,66 @@ void shell() {
}
if (finished) break;
if (!special) terminal_putchar(keyboard_get_key_from_scancode(scancode));
if (!special) putchar(keyboard_get_key_from_scancode(scancode));
terminal_updatecursor();
}
}
}
extern void load_page_directory(uint32_t);
extern void enable_paging();
uint32_t page_directory[1024] __attribute__((aligned(4096)));
uint32_t first_page_table[1024] __attribute__((aligned(4096)));
void kmain() {
terminal_descriptor = terminal_initialize();
terminal_writestring("Initializing terminal... done, descriptor: ");
terminal_writeline(itoa(terminal_descriptor));
terminal_writestring("Preparing interrupts... ");
pic_init();
isr_install();
terminal_writeline("done");
terminal_writestring("Preparing keyboard... ");
keyboard_descriptor = keyboard_init();
terminal_writestring("done, descriptor: ");
terminal_writeline(itoa(keyboard_descriptor));
terminal_writeline("Preparing IDE driver... ");
terminal_writeline("Searching for IDE devices... ");
ide_init();
terminal_writestring("Are interrupts enabled? ");
if (are_interrupts_enabled() == 1) {
terminal_writeline("yes");
} else {
terminal_writeline("no");
//set each entry to not present
for (uint32_t i = 0; i < 1024; i++) {
// This sets the following flags to the pages:
// Supervisor: Only kernel-mode can access them
// Write Enabled: It can be both read from and written to
// Not Present: The page table is not present
page_directory[i] = 0x00000002;
}
terminal_writestring("kmain memory address: ");
terminal_writeline(itoa(kmain));
// i holds the physical address where we want to start mapping these pages to.
// in this case, we want to map these pages to the very beginning of memory.
// we will fill all 1024 entries in the table, mapping 4 megabytes
for (uint32_t i = 0; i < 1024; i++) {
// As the address is page aligned, it will always leave 12 bits zeroed.
// Those bits are used by the attributes ;)
first_page_table[i] = (i * 0x1000) | 3; // attributes: supervisor level, read/write, present.
}
terminal_writeline("----------");
// attributes: supervisor level, read/write, present
page_directory[0] = ((uint32_t)first_page_table) | 3;
load_page_directory(page_directory);
enable_paging();
terminal_descriptor = terminal_initialize();
printf("Terminal initialized, descriptor: %d\n", terminal_descriptor);
printf("Preparing interrupts... ");
pic_init();
isr_install();
printf("done\n");
keyboard_descriptor = keyboard_init();
printf("Keyboard ready, descriptor: %d\n", keyboard_descriptor);
printf("Preparing IDE driver... \n");
printf("Searching for IDE devices... \n");
ide_init();
printf("Are interrupts enabled? ");
if (are_interrupts_enabled() == 1) {
printf("yes\n");
} else {
printf("no\n");
}
printf("kmain memory address: %p\n", kmain);
printf("----------\n");
shell();
}

View file

@ -8,20 +8,20 @@
// NOTE(hippoz): The function below is actually a joke. It's temporary. I'll
// implement the timer soon.
uint8_t sleep(int h) {
if (h != 1)
return 1;
for (unsigned long long i = 0; i < 99999999999; i++)
;
return 0;
if (h != 1)
return 1;
for (unsigned long long i = 0; i < 99999999999; i++)
;
return 0;
}
// ---- IDE Channel Registers ----
struct IDEChannelRegisters {
unsigned short base; // I/O Base.
unsigned short ctrl; // Control Base
unsigned short bmide; // Bus Master IDE
unsigned char nIEN; // nIEN (No Interrupt);
unsigned short base; // I/O Base.
unsigned short ctrl; // Control Base
unsigned short bmide; // Bus Master IDE
unsigned char nIEN; // nIEN (No Interrupt);
} channels[2];
// ---- Variables ----
@ -32,264 +32,245 @@ unsigned static char ide_irq_invoked = 0;
// ---- IDE Device ----
struct ide_device {
unsigned char Reserved; // 0 (Empty) or 1 (This Drive really exists).
unsigned char Channel; // 0 (Primary Channel) or 1 (Secondary Channel).
unsigned char Drive; // 0 (Master Drive) or 1 (Slave Drive).
unsigned short Type; // 0: ATA, 1:ATAPI.
unsigned short Signature; // Drive Signature
unsigned short Capabilities; // Features.
unsigned int CommandSets; // Command Sets Supported.
unsigned int Size; // Size in Sectors.
unsigned char Model[41]; // Model in string.
unsigned char Reserved; // 0 (Empty) or 1 (This Drive really exists).
unsigned char Channel; // 0 (Primary Channel) or 1 (Secondary Channel).
unsigned char Drive; // 0 (Master Drive) or 1 (Slave Drive).
unsigned short Type; // 0: ATA, 1:ATAPI.
unsigned short Signature; // Drive Signature
unsigned short Capabilities; // Features.
unsigned int CommandSets; // Command Sets Supported.
unsigned int Size; // Size in Sectors.
unsigned char Model[41]; // Model in string.
} ide_devices[4];
// ---- Functions ----
void ide_write(unsigned char channel, unsigned char reg, unsigned char data) {
if (reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
if (reg < 0x08)
outportb(channels[channel].base + reg - 0x00, data);
else if (reg < 0x0C)
outportb(channels[channel].base + reg - 0x06, data);
else if (reg < 0x0E)
outportb(channels[channel].ctrl + reg - 0x0A, data);
else if (reg < 0x16)
outportb(channels[channel].bmide + reg - 0x0E, data);
if (reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
if (reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
if (reg < 0x08)
outportb(channels[channel].base + reg - 0x00, data);
else if (reg < 0x0C)
outportb(channels[channel].base + reg - 0x06, data);
else if (reg < 0x0E)
outportb(channels[channel].ctrl + reg - 0x0A, data);
else if (reg < 0x16)
outportb(channels[channel].bmide + reg - 0x0E, data);
if (reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
}
unsigned char ide_read(unsigned char channel, unsigned char reg) {
unsigned char result;
unsigned char result;
if (reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
if (reg < 0x08)
result = inportb(channels[channel].base + reg - 0x00);
else if (reg < 0x0C)
result = inportb(channels[channel].base + reg - 0x06);
else if (reg < 0x0E)
result = inportb(channels[channel].ctrl + reg - 0x0A);
else if (reg < 0x16)
result = inportb(channels[channel].bmide + reg - 0x0E);
if (reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
if (reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
if (reg < 0x08)
result = inportb(channels[channel].base + reg - 0x00);
else if (reg < 0x0C)
result = inportb(channels[channel].base + reg - 0x06);
else if (reg < 0x0E)
result = inportb(channels[channel].ctrl + reg - 0x0A);
else if (reg < 0x16)
result = inportb(channels[channel].bmide + reg - 0x0E);
if (reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
return result;
return result;
}
void ide_read_buffer(unsigned char channel, unsigned char reg,
unsigned int *buffer, unsigned int quads) {
/* WARNING: This code contains a serious bug. The inline assembly trashes ES
* and ESP for all of the code the compiler generates between the inline
* assembly blocks.
*/
if (reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
/* WARNING: This code contains a serious bug. The inline assembly trashes ES
* and ESP for all of the code the compiler generates between the inline
* assembly blocks.
*/
if (reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
asm("pushw %es; movw %ds, %ax; movw %ax, %es");
asm("pushw %es; movw %ds, %ax; movw %ax, %es");
if (reg < 0x08)
insl(channels[channel].base + reg - 0x00, buffer, quads);
else if (reg < 0x0C)
insl(channels[channel].base + reg - 0x06, buffer, quads);
else if (reg < 0x0E)
insl(channels[channel].ctrl + reg - 0x0A, buffer, quads);
else if (reg < 0x16)
insl(channels[channel].bmide + reg - 0x0E, buffer, quads);
if (reg < 0x08)
insl(channels[channel].base + reg - 0x00, buffer, quads);
else if (reg < 0x0C)
insl(channels[channel].base + reg - 0x06, buffer, quads);
else if (reg < 0x0E)
insl(channels[channel].ctrl + reg - 0x0A, buffer, quads);
else if (reg < 0x16)
insl(channels[channel].bmide + reg - 0x0E, buffer, quads);
asm("popw %es;");
asm("popw %es;");
if (reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
if (reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
}
unsigned char ide_polling(unsigned char channel, unsigned int advanced_check) {
// Delay 400 ns for BSY to be set:
for (int i = 0; i < 4; i++)
ide_read(channel, ATA_REG_ALTSTATUS); // Reading the Alternate Status port
// wastes 100ns; loop four times.
// Delay 400 ns for BSY to be set:
for (int i = 0; i < 4; i++)
ide_read(channel, ATA_REG_ALTSTATUS); // Reading the Alternate Status port
// wastes 100ns; loop four times.
// Wait for BSY to be 0:
while (ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY) {
if (advanced_check) {
unsigned char state = ide_read(channel, ATA_REG_STATUS); // Read Status Register.
// Wait for BSY to be 0:
while (ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY)
// Check For Errors:
if (state & ATA_SR_ERR)
return 2; // Error
if (advanced_check) {
unsigned char state =
ide_read(channel, ATA_REG_STATUS); // Read Status Register.
// Check If Device fault:
if (state & ATA_SR_DF)
return 1; // Device Fault.
// Check For Errors:
if (state & ATA_SR_ERR)
return 2; // Error
// Check If Device fault:
if (state & ATA_SR_DF)
return 1; // Device Fault.
// Check DRQ:
// BSY = 0; DF = 0; ERR = 0 so we should check for DRQ now.
if ((state & ATA_SR_DRQ) == 0)
return 3; // DRQ should be set
// Check DRQ:
// BSY = 0; DF = 0; ERR = 0 so we should check for DRQ now.
if ((state & ATA_SR_DRQ) == 0)
return 3; // DRQ should be set
}
}
return 0; // No Error.
return 0; // No Error.
}
unsigned char ide_print_error(unsigned int drive, unsigned char err) {
if (err == 0)
if (err == 0)
return err;
printf("IDE - ");
if (err == 1) {
printf("Device Fault");
err = 19;
} else if (err == 2) {
unsigned char st = ide_read(ide_devices[drive].Channel, ATA_REG_ERROR);
if (st & ATA_ER_AMNF) {
printf("No Address Mark Found");
err = 7;
}
if (st & ATA_ER_TK0NF) {
printf("No Media or Media Error");
err = 3;
}
if (st & ATA_ER_ABRT) {
printf("Command Aborted");
err = 20;
}
if (st & ATA_ER_MCR) {
printf("No Media or Media Error");
err = 3;
}
if (st & ATA_ER_IDNF) {
printf("ID mark not Found");
err = 21;
}
if (st & ATA_ER_MC) {
printf("No Media or Media Error");
err = 3;
}
if (st & ATA_ER_UNC) {
printf("Uncorrectable Data Error");
err = 22;
}
if (st & ATA_ER_BBK) {
printf("Bad Sectors");
err = 13;
}
} else if (err == 3) {
printf("Reads Nothing");
err = 23;
} else if (err == 4) {
printf("Write Protected");
err = 8;
}
printf(" - [%s %s %s\n", (const char *[]){"Primary", "Secondary"}[ide_devices[drive].Channel],
(const char *[]){"Master", "Slave"}[ide_devices[drive].Drive], ide_devices[drive].Model);
return err;
terminal_writestring("IDE:");
if (err == 1) {
terminal_writestring("- Device Fault\n ");
err = 19;
} else if (err == 2) {
unsigned char st = ide_read(ide_devices[drive].Channel, ATA_REG_ERROR);
if (st & ATA_ER_AMNF) {
terminal_writestring("- No Address Mark Found\n");
err = 7;
}
if (st & ATA_ER_TK0NF) {
terminal_writestring("- No Media or Media Error\n");
err = 3;
}
if (st & ATA_ER_ABRT) {
terminal_writestring("- Command Aborted\n");
err = 20;
}
if (st & ATA_ER_MCR) {
terminal_writestring("- No Media or Media Error\n");
err = 3;
}
if (st & ATA_ER_IDNF) {
terminal_writestring("- ID mark not Found\n");
err = 21;
}
if (st & ATA_ER_MC) {
terminal_writestring("- No Media or Media Error\n");
err = 3;
}
if (st & ATA_ER_UNC) {
terminal_writestring("- Uncorrectable Data Error\n");
err = 22;
}
if (st & ATA_ER_BBK) {
terminal_writestring("- Bad Sectors\n");
err = 13;
}
} else if (err == 3) {
terminal_writestring("- Reads Nothing\n");
err = 23;
} else if (err == 4) {
terminal_writestring("- Write Protected\n");
err = 8;
}
terminal_writestring("- [");
terminal_writestring(
(const char *[]){"Primary", "Secondary"}[ide_devices[drive].Channel]);
terminal_writestring(" ");
terminal_writestring(
(const char *[]){"Master", "Slave"}[ide_devices[drive].Drive]);
terminal_writestring(" ");
terminal_writeline(ide_devices[drive].Model);
return err;
}
void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2,
unsigned int BAR3, unsigned int BAR4) {
int j, k, count = 0;
int j, k, count = 0;
// Detect I/O Ports which interface IDE Controller:
channels[ATA_PRIMARY].base = (BAR0 & 0xFFFFFFFC) + 0x1F0 * (!BAR0);
channels[ATA_PRIMARY].ctrl = (BAR1 & 0xFFFFFFFC) + 0x3F6 * (!BAR1);
channels[ATA_SECONDARY].base = (BAR2 & 0xFFFFFFFC) + 0x170 * (!BAR2);
channels[ATA_SECONDARY].ctrl = (BAR3 & 0xFFFFFFFC) + 0x376 * (!BAR3);
channels[ATA_PRIMARY].bmide = (BAR4 & 0xFFFFFFFC) + 0; // Bus Master IDE
channels[ATA_SECONDARY].bmide = (BAR4 & 0xFFFFFFFC) + 8; // Bus Master IDE
// Detect I/O Ports which interface IDE Controller:
channels[ATA_PRIMARY].base = (BAR0 & 0xFFFFFFFC) + 0x1F0 * (!BAR0);
channels[ATA_PRIMARY].ctrl = (BAR1 & 0xFFFFFFFC) + 0x3F6 * (!BAR1);
channels[ATA_SECONDARY].base = (BAR2 & 0xFFFFFFFC) + 0x170 * (!BAR2);
channels[ATA_SECONDARY].ctrl = (BAR3 & 0xFFFFFFFC) + 0x376 * (!BAR3);
channels[ATA_PRIMARY].bmide = (BAR4 & 0xFFFFFFFC) + 0; // Bus Master IDE
channels[ATA_SECONDARY].bmide = (BAR4 & 0xFFFFFFFC) + 8; // Bus Master IDE
// Disable IRQs:
ide_write(ATA_PRIMARY, ATA_REG_CONTROL, 2);
ide_write(ATA_SECONDARY, ATA_REG_CONTROL, 2);
// Disable IRQs:
ide_write(ATA_PRIMARY, ATA_REG_CONTROL, 2);
ide_write(ATA_SECONDARY, ATA_REG_CONTROL, 2);
// Detect ATA-ATAPI Devices:
for (int i = 0; i < 2; i++)
for (j = 0; j < 2; j++) {
unsigned char err = 0, type = IDE_ATA, status;
ide_devices[count].Reserved = 0; // Assuming that no drive here.
// Detect ATA-ATAPI Devices:
for (int i = 0; i < 2; i++)
for (j = 0; j < 2; j++) {
unsigned char err = 0, type = IDE_ATA, status;
ide_devices[count].Reserved = 0; // Assuming that no drive here.
// Select Drive:
ide_write(i, ATA_REG_HDDEVSEL, 0xA0 | (j << 4)); // Select Drive.
sleep(1); // Wait 1ms for drive select to work.
// Select Drive:
ide_write(i, ATA_REG_HDDEVSEL, 0xA0 | (j << 4)); // Select Drive.
sleep(1); // Wait 1ms for drive select to work.
// Send ATA Identify Command:
ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
sleep(1); // This function should be implemented in your OS. which waits
// for 1 ms. it is based on System Timer Device Driver.
// Send ATA Identify Command:
ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
sleep(1); // This function should be implemented in your OS. which waits
// for 1 ms. it is based on System Timer Device Driver.
// Polling:
if (ide_read(i, ATA_REG_STATUS) == 0)
continue; // If Status = 0, No Device.
// Polling:
if (ide_read(i, ATA_REG_STATUS) == 0)
continue; // If Status = 0, No Device.
while (1) {
status = ide_read(i, ATA_REG_STATUS);
if ((status & ATA_SR_ERR)) {
err = 1;
break;
} // If Err, Device is not ATA.
if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRQ))
break; // Everything is right.
}
while (1) {
status = ide_read(i, ATA_REG_STATUS);
if ((status & ATA_SR_ERR)) {
err = 1;
break;
} // If Err, Device is not ATA.
if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRQ))
break; // Everything is right.
}
// Read Identification Space of the Device:
ide_read_buffer(i, ATA_REG_DATA, (unsigned int)ide_buf, 128);
// Read Identification Space of the Device:
ide_read_buffer(i, ATA_REG_DATA, (unsigned int)ide_buf, 128);
// Read Device Parameters:
ide_devices[count].Reserved = 1;
ide_devices[count].Type = type;
ide_devices[count].Channel = i;
ide_devices[count].Drive = j;
ide_devices[count].Signature = *((unsigned short *)(ide_buf + ATA_IDENT_DEVICETYPE));
ide_devices[count].Capabilities = *((unsigned short *)(ide_buf + ATA_IDENT_CAPABILITIES));
ide_devices[count].CommandSets = *((unsigned int *)(ide_buf + ATA_IDENT_COMMANDSETS));
// Read Device Parameters:
ide_devices[count].Reserved = 1;
ide_devices[count].Type = type;
ide_devices[count].Channel = i;
ide_devices[count].Drive = j;
ide_devices[count].Signature =
*((unsigned short *)(ide_buf + ATA_IDENT_DEVICETYPE));
ide_devices[count].Capabilities =
*((unsigned short *)(ide_buf + ATA_IDENT_CAPABILITIES));
ide_devices[count].CommandSets =
*((unsigned int *)(ide_buf + ATA_IDENT_COMMANDSETS));
// Get Size:
if (ide_devices[count].CommandSets & (1 << 26))
// Device uses 48-Bit Addressing:
ide_devices[count].Size = *((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA_EXT));
else
// Device uses CHS or 28-bit Addressing:
ide_devices[count].Size = *((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA));
// Get Size:
if (ide_devices[count].CommandSets & (1 << 26))
// Device uses 48-Bit Addressing:
ide_devices[count].Size =
*((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA_EXT));
else
// Device uses CHS or 28-bit Addressing:
ide_devices[count].Size =
*((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA));
// String indicates model of device (like Western Digital HDD and SONY
// DVD-RW...):
for (k = 0; k < 40; k += 2) {
ide_devices[count].Model[k] = ide_buf[ATA_IDENT_MODEL + k + 1];
ide_devices[count].Model[k + 1] = ide_buf[ATA_IDENT_MODEL + k];
}
ide_devices[count].Model[40] = 0; // Terminate String.
count++;
// String indicates model of device (like Western Digital HDD and SONY
// DVD-RW...):
for (k = 0; k < 40; k += 2) {
ide_devices[count].Model[k] = ide_buf[ATA_IDENT_MODEL + k + 1];
ide_devices[count].Model[k + 1] = ide_buf[ATA_IDENT_MODEL + k];
}
ide_devices[count].Model[40] = 0; // Terminate String.
count++;
}
// Print Summary:
for (int i = 0; i < 4; i++) {
if (ide_devices[i].Reserved == 1) {
terminal_writestring("IDE FOUND DEVICE-> ");
terminal_writestring(
(const char *[]){"ATA", "ATAPI"}[ide_devices[i].Type]);
terminal_writestring(" Drive ");
terminal_writestring(itoa(ide_devices[i].Size / 1024 / 2));
terminal_writestring("MB - ");
terminal_writeline(ide_devices[i].Model);
// Print Summary:
for (int i = 0; i < 4; i++) {
if (ide_devices[i].Reserved == 1) {
printf("IDE FOUND DEVICE-> %s Drive %dMB - %s\n", (const char *[]){"ATA", "ATAPI"}[ide_devices[i].Type],
ide_devices[i].Size / 1024 / 2, ide_devices[i].Model);
}
}
}
}
// ATA/ATAPI Read/Write Modes:
@ -321,198 +302,215 @@ void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2,
void ide_irq() { ide_irq_invoked = 1; }
void ide_wait_irq() {
while (!ide_irq_invoked)
;
ide_irq_invoked = 0;
while (!ide_irq_invoked)
;
ide_irq_invoked = 0;
}
unsigned char ide_ata_access(unsigned char direction, unsigned char drive,
unsigned int lba, uint8_t *buf) {
unsigned char lba_mode /* 0: CHS, 1:LBA28, 2: LBA48 */,
dma /* 0: No DMA, 1: DMA */, cmd;
unsigned char lba_io[6];
unsigned int channel = ide_devices[drive].Channel; // Read the Channel.
unsigned int slavebit =
ide_devices[drive].Drive; // Read the Drive [Master/Slave]
unsigned int bus =
channels[channel].base; // Bus Base, like 0x1F0 which is also data port.
unsigned int words =
256; // Almost every ATA drive has a sector-size of 512-byte.
unsigned short cyl, i;
unsigned char head, sect, err;
unsigned char lba_mode /* 0: CHS, 1:LBA28, 2: LBA48 */,
dma /* 0: No DMA, 1: DMA */, cmd;
unsigned char lba_io[6];
unsigned int channel = ide_devices[drive].Channel; // Read the Channel.
unsigned int slavebit = ide_devices[drive].Drive; // Read the Drive [Master/Slave]
unsigned int bus = channels[channel].base; // Bus Base, like 0x1F0 which is also data port.
unsigned int words = 256; // Almost every ATA drive has a sector-size of 512-byte.
unsigned short cyl, i;
unsigned char head, sect, err;
ide_write(channel, ATA_REG_CONTROL,
channels[channel].nIEN = (ide_irq_invoked = 0x0) + 0x02);
ide_write(channel, ATA_REG_CONTROL,
channels[channel].nIEN = (ide_irq_invoked = 0x0) + 0x02);
// Read parameters
// Select one from LBA28, LBA48 or CHS;
if (lba >= 0x10000000) { // Sure Drive should support LBA in this case, or you
// are giving a wrong LBA.
// LBA48:
lba_mode = 2;
lba_io[0] = (lba & 0x000000FF) >> 0;
lba_io[1] = (lba & 0x0000FF00) >> 8;
lba_io[2] = (lba & 0x00FF0000) >> 16;
lba_io[3] = (lba & 0xFF000000) >> 24;
lba_io[4] = 0; // LBA28 is integer, so 32-bits are enough to access 2TB.
lba_io[5] = 0; // LBA28 is integer, so 32-bits are enough to access 2TB.
head = 0; // Lower 4-bits of HDDEVSEL are not used here.
} else if (ide_devices[drive].Capabilities & 0x200) { // Drive supports LBA?
// LBA28:
lba_mode = 1;
lba_io[0] = (lba & 0x00000FF) >> 0;
lba_io[1] = (lba & 0x000FF00) >> 8;
lba_io[2] = (lba & 0x0FF0000) >> 16;
lba_io[3] = 0; // These Registers are not used here.
lba_io[4] = 0; // These Registers are not used here.
lba_io[5] = 0; // These Registers are not used here.
head = (lba & 0xF000000) >> 24;
} else {
// CHS:
lba_mode = 0;
sect = (lba % 63) + 1;
cyl = (lba + 1 - sect) / (16 * 63);
lba_io[0] = sect;
lba_io[1] = (cyl >> 0) & 0xFF;
lba_io[2] = (cyl >> 8) & 0xFF;
lba_io[3] = 0;
lba_io[4] = 0;
lba_io[5] = 0;
head = (lba + 1 - sect) % (16 * 63) /
(63); // Head number is written to HDDEVSEL lower 4-bits.
}
dma = 0; // 0 = We don't support DMA
// Wait if the drive is busy...
while (ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY)
; // Wait if busy.
// Select Drive from the controller...
if (lba_mode == 0)
ide_write(channel, ATA_REG_HDDEVSEL,
0xA0 | (slavebit << 4) | head); // Drive & CHS.
else
ide_write(channel, ATA_REG_HDDEVSEL,
0xE0 | (slavebit << 4) | head); // Drive & LBA
// Write Parameters;
if (lba_mode == 2) {
ide_write(channel, ATA_REG_SECCOUNT1, 0);
ide_write(channel, ATA_REG_LBA3, lba_io[3]);
ide_write(channel, ATA_REG_LBA4, lba_io[4]);
ide_write(channel, ATA_REG_LBA5, lba_io[5]);
}
ide_write(channel, ATA_REG_SECCOUNT0,
1); // Number of sectors, always 1 in our case
ide_write(channel, ATA_REG_LBA0, lba_io[0]);
ide_write(channel, ATA_REG_LBA1, lba_io[1]);
ide_write(channel, ATA_REG_LBA2, lba_io[2]);
// Select the command and send it;
// Routine that is followed:
// If ( DMA & LBA48) DO_DMA_EXT;
// If ( DMA & LBA28) DO_DMA_LBA;
// If ( DMA & LBA28) DO_DMA_CHS;
// If (!DMA & LBA48) DO_PIO_EXT;
// If (!DMA & LBA28) DO_PIO_LBA;
// If (!DMA & !LBA#) DO_PIO_CHS;
if (lba_mode == 0 && dma == 0 && direction == 0)
cmd = ATA_CMD_READ_PIO;
if (lba_mode == 1 && dma == 0 && direction == 0)
cmd = ATA_CMD_READ_PIO;
if (lba_mode == 2 && dma == 0 && direction == 0)
cmd = ATA_CMD_READ_PIO_EXT;
if (lba_mode == 0 && dma == 1 && direction == 0)
cmd = ATA_CMD_READ_DMA;
if (lba_mode == 1 && dma == 1 && direction == 0)
cmd = ATA_CMD_READ_DMA;
if (lba_mode == 2 && dma == 1 && direction == 0)
cmd = ATA_CMD_READ_DMA_EXT;
if (lba_mode == 0 && dma == 0 && direction == 1)
cmd = ATA_CMD_WRITE_PIO;
if (lba_mode == 1 && dma == 0 && direction == 1)
cmd = ATA_CMD_WRITE_PIO;
if (lba_mode == 2 && dma == 0 && direction == 1)
cmd = ATA_CMD_WRITE_PIO_EXT;
if (lba_mode == 0 && dma == 1 && direction == 1)
cmd = ATA_CMD_WRITE_DMA;
if (lba_mode == 1 && dma == 1 && direction == 1)
cmd = ATA_CMD_WRITE_DMA;
if (lba_mode == 2 && dma == 1 && direction == 1)
cmd = ATA_CMD_WRITE_DMA_EXT;
ide_write(channel, ATA_REG_COMMAND, cmd); // Send the Command.
if (dma) {
if (direction == 0) {
// DMA read.
// Read parameters
// Select one from LBA28, LBA48 or CHS;
if (lba >= 0x10000000) { // Sure Drive should support LBA in this case, or you
// are giving a wrong LBA.
// LBA48:
lba_mode = 2;
lba_io[0] = (lba & 0x000000FF) >> 0;
lba_io[1] = (lba & 0x0000FF00) >> 8;
lba_io[2] = (lba & 0x00FF0000) >> 16;
lba_io[3] = (lba & 0xFF000000) >> 24;
lba_io[4] = 0; // LBA28 is integer, so 32-bits are enough to access 2TB.
lba_io[5] = 0; // LBA28 is integer, so 32-bits are enough to access 2TB.
head = 0; // Lower 4-bits of HDDEVSEL are not used here.
} else if (ide_devices[drive].Capabilities & 0x200) { // Drive supports LBA?
// LBA28:
lba_mode = 1;
lba_io[0] = (lba & 0x00000FF) >> 0;
lba_io[1] = (lba & 0x000FF00) >> 8;
lba_io[2] = (lba & 0x0FF0000) >> 16;
lba_io[3] = 0; // These Registers are not used here.
lba_io[4] = 0; // These Registers are not used here.
lba_io[5] = 0; // These Registers are not used here.
head = (lba & 0xF000000) >> 24;
} else {
// DMA write.
// CHS:
lba_mode = 0;
sect = (lba % 63) + 1;
cyl = (lba + 1 - sect) / (16 * 63);
lba_io[0] = sect;
lba_io[1] = (cyl >> 0) & 0xFF;
lba_io[2] = (cyl >> 8) & 0xFF;
lba_io[3] = 0;
lba_io[4] = 0;
lba_io[5] = 0;
head = (lba + 1 - sect) % (16 * 63) /
(63); // Head number is written to HDDEVSEL lower 4-bits.
}
} else {
if (direction == 0) {
// PIO Read.
if (err = ide_polling(channel, 1))
return err; // Polling, set error and exit if there is.
inportsm(bus, buf, words);
ide_write(channel, ATA_REG_COMMAND,
dma = 0; // 0 = We don't support DMA
// Wait if the drive is busy...
while (ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY)
; // Wait if busy.
// Select Drive from the controller...
if (lba_mode == 0)
ide_write(channel, ATA_REG_HDDEVSEL,
0xA0 | (slavebit << 4) | head); // Drive & CHS.
else
ide_write(channel, ATA_REG_HDDEVSEL,
0xE0 | (slavebit << 4) | head); // Drive & LBA
// Write Parameters;
if (lba_mode == 2) {
ide_write(channel, ATA_REG_SECCOUNT1, 0);
ide_write(channel, ATA_REG_LBA3, lba_io[3]);
ide_write(channel, ATA_REG_LBA4, lba_io[4]);
ide_write(channel, ATA_REG_LBA5, lba_io[5]);
}
ide_write(channel, ATA_REG_SECCOUNT0,
1); // Number of sectors, always 1 in our case
ide_write(channel, ATA_REG_LBA0, lba_io[0]);
ide_write(channel, ATA_REG_LBA1, lba_io[1]);
ide_write(channel, ATA_REG_LBA2, lba_io[2]);
// Select the command and send it;
// Routine that is followed:
// If ( DMA & LBA48) DO_DMA_EXT;
// If ( DMA & LBA28) DO_DMA_LBA;
// If ( DMA & LBA28) DO_DMA_CHS;
// If (!DMA & LBA48) DO_PIO_EXT;
// If (!DMA & LBA28) DO_PIO_LBA;
// If (!DMA & !LBA#) DO_PIO_CHS;
if (lba_mode == 0 && dma == 0 && direction == ATA_READ)
cmd = ATA_CMD_READ_PIO;
if (lba_mode == 1 && dma == 0 && direction == ATA_READ)
cmd = ATA_CMD_READ_PIO;
if (lba_mode == 2 && dma == 0 && direction == ATA_READ)
cmd = ATA_CMD_READ_PIO_EXT;
if (lba_mode == 0 && dma == 1 && direction == ATA_READ)
cmd = ATA_CMD_READ_DMA;
if (lba_mode == 1 && dma == 1 && direction == ATA_READ)
cmd = ATA_CMD_READ_DMA;
if (lba_mode == 2 && dma == 1 && direction == ATA_READ)
cmd = ATA_CMD_READ_DMA_EXT;
if (lba_mode == 0 && dma == 0 && direction == ATA_WRITE)
cmd = ATA_CMD_WRITE_PIO;
if (lba_mode == 1 && dma == 0 && direction == ATA_WRITE)
cmd = ATA_CMD_WRITE_PIO;
if (lba_mode == 2 && dma == 0 && direction == ATA_WRITE)
cmd = ATA_CMD_WRITE_PIO_EXT;
if (lba_mode == 0 && dma == 1 && direction == ATA_WRITE)
cmd = ATA_CMD_WRITE_DMA;
if (lba_mode == 1 && dma == 1 && direction == ATA_WRITE)
cmd = ATA_CMD_WRITE_DMA;
if (lba_mode == 2 && dma == 1 && direction == ATA_WRITE)
cmd = ATA_CMD_WRITE_DMA_EXT;
ide_write(channel, ATA_REG_COMMAND, cmd); // Send the Command.
if (dma) {
if (direction == ATA_READ) {
// DMA read.
} else {
// DMA write.
}
} else {
if (direction == ATA_READ) {
// PIO Read.
if (err = ide_polling(channel, 1))
return err; // Polling, set error and exit if there is.
inportsm(bus, buf, words);
ide_write(channel, ATA_REG_COMMAND,
(char[]){(char)ATA_CMD_CACHE_FLUSH, (char)ATA_CMD_CACHE_FLUSH,
(char)ATA_CMD_CACHE_FLUSH_EXT}[lba_mode]);
ide_polling(channel, 0); // Polling.
} else {
// PIO Write.
ide_polling(channel, 0); // Polling.
outportsm(bus, buf, words);
ide_write(channel, ATA_REG_COMMAND,
(char)ATA_CMD_CACHE_FLUSH_EXT}[lba_mode]);
ide_polling(channel, 0); // Polling.
} else {
// PIO Write.
ide_polling(channel, 0); // Polling.
outportsm(bus, buf, words);
ide_write(channel, ATA_REG_COMMAND,
(char[]){ATA_CMD_CACHE_FLUSH, ATA_CMD_CACHE_FLUSH,
ATA_CMD_CACHE_FLUSH_EXT}[lba_mode]);
ide_polling(channel, 0);
ATA_CMD_CACHE_FLUSH_EXT}[lba_mode]);
ide_polling(channel, 0);
}
}
}
return 0; // Easy, isn't it? no
return 0; // Easy, isn't it? no
}
uint8_t ide_read_sectors(unsigned char drive, unsigned int lba, uint8_t *buf) {
// Check if the drive is present:
if (drive > 3 || ide_devices[drive].Reserved == 0)
return 0x01; // Drive not present
// Check if the drive is present:
if (drive > 3 || ide_devices[drive].Reserved == 0)
return 0x01; // Drive not present
// Check if inputs are valid:
if (((lba + 1) > ide_devices[drive].Size) && (ide_devices[drive].Type == IDE_ATA))
return 0x02; // Seeking to invalid position.
// Check if inputs are valid:
if (((lba + 1) > ide_devices[drive].Size) &&
(ide_devices[drive].Type == IDE_ATA))
return 0x02; // Seeking to invalid position.
// Read in PIO Mode through Polling & IRQs:
unsigned char err;
if (ide_devices[drive].Type == IDE_ATA) {
err = ide_ata_access(ATA_READ, drive, lba, buf);
} else {
// err = ide_atapi_read(drive, lba + i, 1, es, edi + (i*2048));
return 0x03; // We don't support this yet.
}
return ide_print_error(drive, err);
// Read in PIO Mode through Polling & IRQs:
unsigned char err;
if (ide_devices[drive].Type == IDE_ATA) {
err = ide_ata_access(ATA_READ, drive, lba, buf);
} else {
// err = a_read(drive, lba + i, 1, es, edi + (i*2048));
return 0x03; // We don't support this yet.
}
return ide_print_error(drive, err);
}
uint8_t ide_write_sectors(unsigned char drive, unsigned int lba, uint8_t *buf) {
if (drive > 3 || ide_devices[drive].Reserved == 0)
return 0x01; // Drive not present
if (((lba + 1) > ide_devices[drive].Size) &&
(ide_devices[drive].Type == IDE_ATA))
return 0x02; // Seeking to invalid position.
if (drive > 3 || ide_devices[drive].Reserved == 0)
return 0x01; // Drive not present
if (((lba + 1) > ide_devices[drive].Size) &&
(ide_devices[drive].Type == IDE_ATA))
return 0x02; // Seeking to invalid position.
// Write in PIO Mode through Polling & IRQs:
unsigned char err;
if (ide_devices[drive].Type == IDE_ATA) {
err = ide_ata_access(ATA_WRITE, drive, lba, buf);
} else {
err = 4; // Write-Protected.
}
return ide_print_error(drive, err);
// Write in PIO Mode through Polling & IRQs:
unsigned char err;
if (ide_devices[drive].Type == IDE_ATA) {
err = ide_ata_access(ATA_WRITE, drive, lba, buf);
} else {
err = 4; // Write-Protected.
}
return ide_print_error(drive, err);
}
void ide_init() {
ide_initialize(0x1F0, 0x3F6, 0x170, 0x376, 0x000);
sleep(1);
sleep(1);
ide_initialize(0x1F0, 0x3F6, 0x170, 0x376, 0x000);
sleep(1);
sleep(1);
sleep(1);
printf("Testing IDE drive...\n");
uint8_t buf[512] = {0};
memcpy(buf, "Hello world", sizeof("Hello world"));
ide_write_sectors(0, 1, buf);
sleep(1);
sleep(1);
sleep(1);
uint8_t outbuf[512] = {0};
ide_read_sectors(0, 1, outbuf);
sleep(1);
sleep(1);
sleep(1);
for (uint8_t i = 0; i < 11; i++) {
printf("%d: %c | ", i, outbuf[i]);
}
printf("\n");
}

478
arch/i386/std/stdio.c Normal file
View file

@ -0,0 +1,478 @@
#include <std/stdio.h>
#include <std/string.h>
#include <std/ctype.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdarg.h>
// shamelessly stolen from https://wiki.osdev.org/User:A22347/Printf
char* __int_str(intmax_t i, char b[], int base, bool plusSignIfNeeded, bool spaceSignIfNeeded,
int paddingNo, bool justify, bool zeroPad) {
char digit[32] = {0};
memset(digit, 0, 32);
strcpy(digit, "0123456789");
if (base == 16) {
strcat(digit, "ABCDEF");
} else if (base == 17) {
strcat(digit, "abcdef");
base = 16;
}
char* p = b;
if (i < 0) {
*p++ = '-';
i *= -1;
} else if (plusSignIfNeeded) {
*p++ = '+';
} else if (!plusSignIfNeeded && spaceSignIfNeeded) {
*p++ = ' ';
}
intmax_t shifter = i;
do {
++p;
shifter = shifter / base;
} while (shifter);
*p = '\0';
do {
*--p = digit[i % base];
i = i / base;
} while (i);
int padding = paddingNo - (int)strlen(b);
if (padding < 0) padding = 0;
if (justify) {
while (padding--) {
if (zeroPad) {
b[strlen(b)] = '0';
} else {
b[strlen(b)] = ' ';
}
}
} else {
char a[256] = {0};
while (padding--) {
if (zeroPad) {
a[strlen(a)] = '0';
} else {
a[strlen(a)] = ' ';
}
}
strcat(a, b);
strcpy(b, a);
}
return b;
}
void displayCharacter(char c, int* a) {
putchar(c);
*a += 1;
}
void displayString(char* c, int* a) {
for (int i = 0; c[i]; ++i) {
displayCharacter(c[i], a);
}
}
int vprintf (const char* format, va_list list)
{
int chars = 0;
char intStrBuffer[256] = {0};
for (int i = 0; format[i]; ++i) {
char specifier = '\0';
char length = '\0';
int lengthSpec = 0;
int precSpec = 0;
bool leftJustify = false;
bool zeroPad = false;
bool spaceNoSign = false;
bool altForm = false;
bool plusSign = false;
bool emode = false;
int expo = 0;
if (format[i] == '%') {
++i;
bool extBreak = false;
while (1) {
switch (format[i]) {
case '-':
leftJustify = true;
++i;
break;
case '+':
plusSign = true;
++i;
break;
case '#':
altForm = true;
++i;
break;
case ' ':
spaceNoSign = true;
++i;
break;
case '0':
zeroPad = true;
++i;
break;
default:
extBreak = true;
break;
}
if (extBreak) break;
}
while (isdigit(format[i])) {
lengthSpec *= 10;
lengthSpec += format[i] - 48;
++i;
}
if (format[i] == '*') {
lengthSpec = va_arg(list, int);
++i;
}
if (format[i] == '.') {
++i;
while (isdigit(format[i])) {
precSpec *= 10;
precSpec += format[i] - 48;
++i;
}
if (format[i] == '*') {
precSpec = va_arg(list, int);
++i;
}
} else {
precSpec = 6;
}
if (format[i] == 'h' || format[i] == 'l' || format[i] == 'j' ||
format[i] == 'z' || format[i] == 't' || format[i] == 'L') {
length = format[i];
++i;
if (format[i] == 'h') {
length = 'H';
} else if (format[i] == 'l') {
length = 'q';
++i;
}
}
specifier = format[i];
memset(intStrBuffer, 0, 256);
int base = 10;
if (specifier == 'o') {
base = 8;
specifier = 'u';
if (altForm) {
displayString("0", &chars);
}
}
if (specifier == 'p') {
base = 16;
length = 'z';
specifier = 'u';
}
switch (specifier) {
case 'X':
base = 16;
case 'x':
base = base == 10 ? 17 : base;
if (altForm) {
displayString("0x", &chars);
}
case 'u':
{
switch (length) {
case 0:
{
unsigned int integer = va_arg(list, unsigned int);
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
displayString(intStrBuffer, &chars);
break;
}
case 'H':
{
unsigned char integer = (unsigned char) va_arg(list, unsigned int);
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
displayString(intStrBuffer, &chars);
break;
}
case 'h':
{
unsigned short int integer = va_arg(list, unsigned int);
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
displayString(intStrBuffer, &chars);
break;
}
case 'l':
{
unsigned long integer = va_arg(list, unsigned long);
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
displayString(intStrBuffer, &chars);
break;
}
case 'q':
{
unsigned long long integer = va_arg(list, unsigned long long);
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
displayString(intStrBuffer, &chars);
break;
}
case 'j':
{
uintmax_t integer = va_arg(list, uintmax_t);
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
displayString(intStrBuffer, &chars);
break;
}
case 'z':
{
size_t integer = va_arg(list, size_t);
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
displayString(intStrBuffer, &chars);
break;
}
case 't':
{
ptrdiff_t integer = va_arg(list, ptrdiff_t);
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
displayString(intStrBuffer, &chars);
break;
}
default:
break;
}
break;
}
case 'd':
case 'i':
{
switch (length) {
case 0:
{
int integer = va_arg(list, int);
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
displayString(intStrBuffer, &chars);
break;
}
case 'H':
{
signed char integer = (signed char) va_arg(list, int);
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
displayString(intStrBuffer, &chars);
break;
}
case 'h':
{
short int integer = va_arg(list, int);
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
displayString(intStrBuffer, &chars);
break;
}
case 'l':
{
long integer = va_arg(list, long);
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
displayString(intStrBuffer, &chars);
break;
}
case 'q':
{
long long integer = va_arg(list, long long);
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
displayString(intStrBuffer, &chars);
break;
}
case 'j':
{
intmax_t integer = va_arg(list, intmax_t);
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
displayString(intStrBuffer, &chars);
break;
}
case 'z':
{
size_t integer = va_arg(list, size_t);
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
displayString(intStrBuffer, &chars);
break;
}
case 't':
{
ptrdiff_t integer = va_arg(list, ptrdiff_t);
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
displayString(intStrBuffer, &chars);
break;
}
default:
break;
}
break;
}
case 'c':
{
if (length == 'l') {
//displayCharacter(va_arg(list, wint_t), &chars);
} else {
displayCharacter(va_arg(list, int), &chars);
}
break;
}
case 's':
{
displayString(va_arg(list, char*), &chars);
break;
}
case 'n':
{
switch (length) {
case 'H':
*(va_arg(list, signed char*)) = chars;
break;
case 'h':
*(va_arg(list, short int*)) = chars;
break;
case 0: {
int* a = va_arg(list, int*);
*a = chars;
break;
}
case 'l':
*(va_arg(list, long*)) = chars;
break;
case 'q':
*(va_arg(list, long long*)) = chars;
break;
case 'j':
*(va_arg(list, intmax_t*)) = chars;
break;
case 'z':
*(va_arg(list, size_t*)) = chars;
break;
case 't':
*(va_arg(list, ptrdiff_t*)) = chars;
break;
default:
break;
}
break;
}
case 'e':
case 'E':
emode = true;
/*
case 'f':
case 'F':
case 'g':
case 'G':
{
double floating = va_arg(list, double);
while (emode && floating >= 10) {
floating /= 10;
++expo;
}
int form = lengthSpec - precSpec - expo - (precSpec || altForm ? 1 : 0);
if (emode) {
form -= 4; // 'e+00'
}
if (form < 0) {
form = 0;
}
__int_str(floating, intStrBuffer, base, plusSign, spaceNoSign, form, \
leftJustify, zeroPad);
displayString(intStrBuffer, &chars);
floating -= (int) floating;
for (int i = 0; i < precSpec; ++i) {
floating *= 10;
}
intmax_t decPlaces = (intmax_t) (floating + 0.5);
if (precSpec) {
displayCharacter('.', &chars);
__int_str(decPlaces, intStrBuffer, 10, false, false, 0, false, false);
intStrBuffer[precSpec] = 0;
displayString(intStrBuffer, &chars);
} else if (altForm) {
displayCharacter('.', &chars);
}
break;
}
*/
case 'a':
case 'A':
//ACK! Hexadecimal floating points...
break;
default:
break;
}
if (specifier == 'e') {
displayString("e+", &chars);
} else if (specifier == 'E') {
displayString("E+", &chars);
}
if (specifier == 'e' || specifier == 'E') {
__int_str(expo, intStrBuffer, 10, false, false, 2, false, true);
displayString(intStrBuffer, &chars);
}
} else {
displayCharacter(format[i], &chars);
}
}
return chars;
}
__attribute__ ((format (printf, 1, 2))) int printf (const char* format, ...) {
va_list list;
va_start (list, format);
int i = vprintf (format, list);
va_end (list);
return i;
}

View file

@ -38,8 +38,7 @@ char* itoa(int res) {
return ret;
}
unsigned int atoi(const char *in)
{
unsigned int atoi(const char *in) {
unsigned int size = 0;
unsigned int j;
unsigned int count = 1;

View file

@ -1,5 +1,4 @@
#ifndef _AHCI_H
#define _AHCI_H 1
#pragma once
#ifdef __cplusplus
extern "C" {
@ -350,5 +349,3 @@ void ahci_init(void);
#ifdef __cplusplus
}
#endif
#endif /* _AHCI_H */

View file

@ -1,5 +1,4 @@
#ifndef _DEVICE_H
#define _DEVICE_H 1
#pragma once
#ifdef __cplusplus
extern "C" {
@ -18,5 +17,3 @@ void* write(int descriptor, void* data);
#ifdef __cplusplus
}
#endif
#endif /* _DEVICE_H */

View file

@ -1,7 +1,7 @@
#ifndef _IDE_H
#define _IDE_H 1
#pragma once
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
@ -103,9 +103,8 @@ extern "C" {
// ---- Functions -----
void ide_init();
uint8_t ide_write_sectors(unsigned char drive, unsigned int lba, uint8_t *buf);
#ifdef __cplusplus
}
#endif
#endif /* _IDE_H */

View file

@ -1,5 +1,4 @@
#ifndef _IDT_H
#define _IDT_H 1
#pragma once
#include <stdint.h>
#include <std/util.h>
@ -19,8 +18,7 @@ struct idt_entry {
unsigned short int offset_higherbits;
};
struct interrupt_frame
{
struct interrupt_frame {
uintptr_t ip;
uintptr_t cs;
uintptr_t flags;
@ -34,5 +32,3 @@ void idt_register_handler(uint8_t interrupt, unsigned long address);
#ifdef __cplusplus
}
#endif
#endif /* _IDT_H */

View file

@ -1,5 +1,4 @@
#ifndef _ISR_H
#define _ISR_H 1
#pragma once
#include <drivers/idt/idt.h>
@ -12,5 +11,3 @@ void isr_install(void);
#ifdef __cplusplus
}
#endif
#endif /* _ISR_H */

View file

@ -1,5 +1,4 @@
#ifndef _KEYBOARD_H
#define _KEYBOARD_H 1
#pragma once
#include <drivers/idt/isr.h>
#include <drivers/terminal/terminal.h>
@ -18,5 +17,3 @@ uint8_t keyboard_enabled(void);
#ifdef __cplusplus
}
#endif
#endif /* _KEYBOARD_H */

View file

@ -1,5 +1,4 @@
#ifndef _PIC_H
#define _PIC_H 1
#pragma once
#include <std/inline.h>
@ -27,5 +26,3 @@ void pic_irq_disable(uint8_t no);
#ifdef __cplusplus
}
#endif
#endif /* _PIC_H */

View file

@ -1,5 +1,4 @@
#ifndef _TAR_H
#define _TAR_H 1
#pragma once
#ifdef __cplusplus
extern "C" {
@ -23,5 +22,3 @@ struct tar_header* tar_seek(int fd, char filename[100]);
#ifdef __cplusplus
}
#endif
#endif /* _TAR_H */

View file

@ -1,5 +1,4 @@
#ifndef _TERMINAL_H
#define _TERMINAL_H 1
#pragma once
#include <stddef.h>
#include <stdint.h>
@ -70,5 +69,3 @@ static inline void terminal_writeline(const char* data) {
#ifdef __cplusplus
}
#endif
#endif /* _TERMINAL_H */

15
include/std/ctype.h Normal file
View file

@ -0,0 +1,15 @@
#pragma once
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
inline int isdigit(int c) {
return c >= '0' && c <= '9';
}
#ifdef __cplusplus
}
#endif

View file

@ -1,5 +1,4 @@
#ifndef INLINE_H_
#define INLINE_H_
#pragma once
#include <stdbool.h>
#include <stdint.h>
@ -20,6 +19,10 @@ static inline void outportl(uint16_t const port, uint32_t const val) {
asm volatile ( "outl %0, %1" : : "a"(val), "Nd"(port) );
}
static inline void outportsm(unsigned short port, unsigned char* data, unsigned long size) {
asm volatile ("rep outsw" : "+S" (data), "+c" (size) : "d" (port));
}
static inline uint8_t inportb(uint16_t const port) {
uint8_t ret;
asm volatile ( "inb %1, %0" : "=a"(ret) : "Nd"(port) );
@ -38,6 +41,10 @@ static inline uint32_t inportl(uint16_t const port) {
return ret;
}
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 io_wait() {
asm volatile("outb %%al, $0x80" : : "a"(0));
}
@ -50,20 +57,9 @@ static inline bool are_interrupts_enabled() {
return flags & (1 << 9);
}
inline static void inportsm(unsigned short port, unsigned char* data, unsigned long size)
{
asm volatile ("rep insw" : "+D" (data), "+c" (size) : "d" (port) : "memory");
}
inline static void outportsm(unsigned short port, unsigned char* data, unsigned long size) {
asm volatile ("rep outsw" : "+S" (data), "+c" (size) : "d" (port));
}
static void insl(unsigned reg, unsigned int *buffer, int quads)
{
static inline void insl(unsigned reg, unsigned int *buffer, int quads) {
int index;
for(index = 0; index < quads; index++)
{
for (index = 0; index < quads; index++) {
buffer[index] = inportl(reg);
}
}
@ -71,5 +67,3 @@ static void insl(unsigned reg, unsigned int *buffer, int quads)
#ifdef __cplusplus
}
#endif
#endif /* INLINE_H_ */

17
include/std/stdio.h Normal file
View file

@ -0,0 +1,17 @@
#pragma once
#include <drivers/terminal/terminal.h>
#ifdef __cplusplus
extern "C" {
#endif
inline void putchar(char c) {
terminal_putchar(c);
}
__attribute__ ((format (printf, 1, 2))) int printf (const char* format, ...);
#ifdef __cplusplus
}
#endif

View file

@ -1,5 +1,4 @@
#ifndef _STRING_H
#define _STRING_H 1
#pragma once
#include <stddef.h>
@ -18,5 +17,3 @@ char* strcat(char* dst, const char* src);
#ifdef __cplusplus
}
#endif
#endif /* _STRING_H */

View file

@ -1,5 +1,4 @@
#ifndef _UTIL_H
#define _UTIL_H 1
#pragma once
#include <stddef.h>
@ -20,5 +19,3 @@ unsigned int atoi(const char *in);
#ifdef __cplusplus
}
#endif
#endif /* _UTIL_H */