Enable lto and move naked assembly functions to own files

This commit is contained in:
mintsuki 2020-09-04 01:37:24 +02:00
parent 5379787967
commit ba7ed52f6a
9 changed files with 315 additions and 342 deletions

Binary file not shown.

View File

@ -1,7 +1,7 @@
CC = ../toolchain/bin/i386-elf-gcc
LD = ../toolchain/bin/i386-elf-gcc
CFLAGS = -Os -pipe -Wall -Wextra
CFLAGS = -flto -Os -pipe -Wall -Wextra
INTERNAL_CFLAGS = \
-std=gnu99 \
@ -15,7 +15,7 @@ INTERNAL_CFLAGS = \
-I. \
-Wno-address-of-packed-member
LDFLAGS = -O2
LDFLAGS = -flto -Os
INTERNAL_LDFLAGS = \
-nostdlib \
@ -27,7 +27,8 @@ INTERNAL_LDFLAGS = \
.PHONY: all clean
C_FILES := $(shell find ./ -type f -name '*.c' | sort)
OBJ := $(C_FILES:.c=.o)
ASM_FILES := $(shell find ./ -type f -name '*.asm' | grep -v bootsect | sort)
OBJ := $(C_FILES:.c=.o) $(ASM_FILES:.asm=.o)
all: limine.bin
@ -38,5 +39,8 @@ limine.bin: $(OBJ)
%.o: %.c
$(CC) $(CFLAGS) $(INTERNAL_CFLAGS) -c $< -o $@
%.o: %.asm
nasm $< -f elf32 -o $@
clean:
rm -f $(OBJ)

View File

@ -68,127 +68,6 @@ void *balloc_aligned(size_t count, size_t alignment) {
return ret;
}
__attribute__((used)) static uint32_t int_08_ticks_counter;
__attribute__((naked)) static void int_08_isr(void) {
ASM_BASIC(
".code16\n\t"
"inc dword ptr cs:[int_08_ticks_counter]\n\t"
"int 0x40\n\t" // call callback
"iret\n\t"
".code32\n\t"
);
}
uint32_t *ivt = 0; // this variable is not static else gcc will optimise the
// 0 ptr to a ud2
__attribute__((used)) static void hook_int_08(void) {
ivt[0x40] = ivt[0x08]; // int 0x40 is callback interrupt
ivt[0x08] = (uint16_t)(size_t)int_08_isr;
}
__attribute__((used)) static void dehook_int_08(void) {
ivt[0x08] = ivt[0x40];
}
// This is a dirty hack but we need to execute this full function in real mode
__attribute__((naked))
int pit_sleep_and_quit_on_keypress(uint32_t ticks) {
ASM_BASIC(
"call hook_int_08\n\t"
// pit_ticks in edx
"mov edx, dword ptr ss:[esp+4]\n\t"
"lea ecx, int_08_ticks_counter\n\t"
"mov dword ptr ds:[ecx], 0\n\t"
// Save non-scratch GPRs
"push ebx\n\t"
"push esi\n\t"
"push edi\n\t"
"push ebp\n\t"
// Jump to real mode
FARJMP32("0x08", "1f")
"1: .code16\n\t"
"mov ax, 0x10\n\t"
"mov ds, ax\n\t"
"mov es, ax\n\t"
"mov fs, ax\n\t"
"mov gs, ax\n\t"
"mov ss, ax\n\t"
"mov eax, cr0\n\t"
"and al, 0xfe\n\t"
"mov cr0, eax\n\t"
FARJMP16("0", "1f")
"1:\n\t"
"mov ax, 0\n\t"
"mov ds, ax\n\t"
"mov es, ax\n\t"
"mov fs, ax\n\t"
"mov gs, ax\n\t"
"mov ss, ax\n\t"
"sti\n\t"
"10:\n\t"
"cmp dword ptr ds:[ecx], edx\n\t"
"je 30f\n\t" // out on timeout
"push ecx\n\t"
"push edx\n\t"
"mov ah, 0x01\n\t"
"xor al, al\n\t"
"int 0x16\n\t"
"pop edx\n\t"
"pop ecx\n\t"
"jz 10b\n\t" // loop
// on keypress
"xor ax, ax\n\t"
"int 0x16\n\t"
"mov eax, 1\n\t"
"jmp 20f\n\t" // out
"30:\n\t" // out on timeout
"xor eax, eax\n\t"
"20:\n\t"
"cli\n\t"
// Jump back to pmode
"mov ebx, cr0\n\t"
"or bl, 1\n\t"
"mov cr0, ebx\n\t"
FARJMP16("0x18", "1f")
"1: .code32\n\t"
"mov bx, 0x20\n\t"
"mov ds, bx\n\t"
"mov es, bx\n\t"
"mov fs, bx\n\t"
"mov gs, bx\n\t"
"mov ss, bx\n\t"
// Restore non-scratch GPRs
"pop ebp\n\t"
"pop edi\n\t"
"pop esi\n\t"
"pop ebx\n\t"
// Exit
"push eax\n\t"
"call dehook_int_08\n\t"
"pop eax\n\t"
"ret\n\t"
);
}
uint64_t strtoui(const char *s) {
uint64_t n = 0;
while (*s)

75
src/lib/builtins.asm Normal file
View File

@ -0,0 +1,75 @@
section .text
global memcpy
memcpy:
push esi
push edi
mov eax, dword [esp+12]
mov edi, eax
mov esi, dword [esp+16]
mov ecx, dword [esp+20]
rep movsb
pop edi
pop esi
ret
global memset
memset:
push edi
mov edx, dword [esp+8]
mov edi, edx
mov eax, dword [esp+12]
mov ecx, dword [esp+16]
rep stosb
mov eax, edx
pop edi
ret
global memmove
memmove:
push esi
push edi
mov eax, dword [esp+12]
mov edi, eax
mov esi, dword [esp+16]
mov ecx, dword [esp+20]
cmp edi, esi
ja .copy_backwards
rep movsb
jmp .done
.copy_backwards:
lea edi, [edi+ecx-1]
lea esi, [esi+ecx-1]
std
rep movsb
cld
.done:
pop edi
pop esi
ret
global memcmp
memcmp:
push esi
push edi
mov edi, dword [esp+12]
mov esi, dword [esp+16]
mov ecx, dword [esp+20]
repe cmpsb
jecxz .equal
mov al, byte [edi-1]
sub al, byte [esi-1]
movsx eax, al
jmp .done
.equal:
mov eax, ecx
.done:
pop edi
pop esi
ret

View File

@ -17,90 +17,6 @@ int tolower(int c) {
return c;
}
__attribute__((naked))
void *memcpy(void *dest, const void *src, size_t n) {
ASM_BASIC(
"push esi\n\t"
"push edi\n\t"
"mov eax, dword ptr [esp+12]\n\t"
"mov edi, eax\n\t"
"mov esi, dword ptr [esp+16]\n\t"
"mov ecx, dword ptr [esp+20]\n\t"
"rep movsb\n\t"
"pop edi\n\t"
"pop esi\n\t"
"ret\n\t"
);
}
__attribute__((naked))
void *memset(void *s, int c, size_t n) {
ASM_BASIC(
"push edi\n\t"
"mov edx, dword ptr [esp+8]\n\t"
"mov edi, edx\n\t"
"mov eax, dword ptr [esp+12]\n\t"
"mov ecx, dword ptr [esp+16]\n\t"
"rep stosb\n\t"
"mov eax, edx\n\t"
"pop edi\n\t"
"ret\n\t"
);
}
__attribute__((naked))
void *memmove(void *dest, const void *src, size_t n) {
ASM_BASIC(
"push esi\n\t"
"push edi\n\t"
"mov eax, dword ptr [esp+12]\n\t"
"mov edi, eax\n\t"
"mov esi, dword ptr [esp+16]\n\t"
"mov ecx, dword ptr [esp+20]\n\t"
"cmp edi, esi\n\t"
"ja 1f\n\t"
"rep movsb\n\t"
"jmp 2f\n\t"
"1:\n\t"
"lea edi, [edi+ecx-1]\n\t"
"lea esi, [esi+ecx-1]\n\t"
"std\n\t"
"rep movsb\n\t"
"cld\n\t"
"2:\n\t"
"pop edi\n\t"
"pop esi\n\t"
"ret\n\t"
);
}
__attribute__((naked))
int memcmp(const void *s1, const void *s2, size_t n) {
ASM_BASIC(
"push esi\n\t"
"push edi\n\t"
"mov edi, dword ptr [esp+12]\n\t"
"mov esi, dword ptr [esp+16]\n\t"
"mov ecx, dword ptr [esp+20]\n\t"
"repe cmpsb\n\t"
"jecxz 1f\n\t"
"mov al, byte ptr [edi-1]\n\t"
"sub al, byte ptr [esi-1]\n\t"
"movsx eax, al\n\t"
"jmp 2f\n\t"
"1:\n\t"
"mov eax, ecx\n\t"
"2:\n\t"
"pop edi\n\t"
"pop esi\n\t"
"ret\n\t"
);
}
char *strcpy(char *dest, const char *src) {
size_t i;

View File

@ -93,22 +93,22 @@ struct mbr_entry {
} __attribute__((packed));
static int mbr_get_part(struct part *ret, int drive, int partition) {
// Variables.
// Check if actually valid mbr
uint16_t hint;
read(drive, &hint, 444, sizeof(uint16_t));
if (hint && hint != 0x5a5a)
return INVALID_TABLE;
struct mbr_entry entry;
const size_t entry_address = 0x1be + sizeof(struct mbr_entry) * partition;
size_t entry_offset = 0x1be + sizeof(struct mbr_entry) * partition;
// Read the entry of the MBR.
int r;
if ((r = read(drive, &entry, entry_address, sizeof(struct mbr_entry)))) {
int r = read(drive, &entry, entry_offset, sizeof(struct mbr_entry));
if (r)
return r;
}
// Check if the partition exists, fail if it doesnt.
if (entry.type == 0) {
if (entry.type == 0)
return NO_PARTITION;
}
// Assign the final fields and return.
ret->first_sect = entry.first_sect;
ret->sect_count = entry.sect_count;
return 0;

118
src/lib/real.asm Normal file
View File

@ -0,0 +1,118 @@
section .text
global rm_int
rm_int:
; Self-modifying code: int $int_no
mov al, byte [esp+4]
mov byte [.int_no], al
; Save out_regs
mov eax, dword [esp+8]
mov dword [.out_regs], eax
; Save in_regs
mov eax, dword [esp+12]
mov dword [.in_regs], eax
; Save GDT in case BIOS overwrites it
sgdt [.gdt]
; Save non-scratch GPRs
push ebx
push esi
push edi
push ebp
; Jump to real mode
jmp 0x08:.bits16
.bits16:
bits 16
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov eax, cr0
and al, 0xfe
mov cr0, eax
jmp 0x00:.cszero
.cszero:
xor ax, ax
mov ss, ax
; Load in_regs
mov dword [ss:.esp], esp
mov esp, dword [ss:.in_regs]
pop gs
pop fs
pop es
pop ds
popfd
pop ebp
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
mov esp, dword [ss:.esp]
sti
; Indirect interrupt call
db 0xcd
.int_no:
db 0
cli
; Load out_regs
mov dword [ss:.esp], esp
mov esp, dword [ss:.out_regs]
lea esp, [esp + 10*4]
push eax
push ebx
push ecx
push edx
push esi
push edi
push ebp
pushfd
push ds
push es
push fs
push gs
mov esp, dword [ss:.esp]
; Restore GDT
lgdt [ss:.gdt]
; Jump back to pmode
mov eax, cr0
or al, 1
mov cr0, eax
jmp 0x18:.bits32
.bits32:
bits 32
mov ax, 0x20
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
; Restore non-scratch GPRs
pop ebp
pop edi
pop esi
pop ebx
; Exit
ret
align 16
.esp: dd 0
.out_regs: dd 0
.in_regs: dd 0
.gdt: dq 0

View File

@ -1,124 +0,0 @@
#include <stdint.h>
#include <lib/real.h>
#include <lib/asm.h>
__attribute__((naked))
void rm_int(uint8_t int_no, struct rm_regs *out_regs, struct rm_regs *in_regs) {
ASM_BASIC(
// Self-modifying code: int $int_no
"mov al, byte ptr ss:[esp+4]\n\t"
"mov byte ptr ds:[3f], al\n\t"
// Save out_regs
"mov eax, dword ptr ss:[esp+8]\n\t"
"mov dword ptr ds:[6f], eax\n\t"
// Save in_regs
"mov eax, dword ptr ss:[esp+12]\n\t"
"mov dword ptr ds:[7f], eax\n\t"
// Save GDT in case BIOS overwrites it
"sgdt [8f]\n\t"
// Save non-scratch GPRs
"push ebx\n\t"
"push esi\n\t"
"push edi\n\t"
"push ebp\n\t"
// Jump to real mode
FARJMP32("0x08", "1f")
"1: .code16\n\t"
"mov ax, 0x10\n\t"
"mov ds, ax\n\t"
"mov es, ax\n\t"
"mov fs, ax\n\t"
"mov gs, ax\n\t"
"mov ss, ax\n\t"
"mov eax, cr0\n\t"
"and al, 0xfe\n\t"
"mov cr0, eax\n\t"
FARJMP16("0", "1f")
"1:\n\t"
"xor ax, ax\n\t"
"mov ss, ax\n\t"
// Load in_regs
"mov dword ptr ss:[5f], esp\n\t"
"mov esp, dword ptr ss:[7f]\n\t"
"pop gs\n\t"
"pop fs\n\t"
"pop es\n\t"
"pop ds\n\t"
"popfd\n\t"
"pop ebp\n\t"
"pop edi\n\t"
"pop esi\n\t"
"pop edx\n\t"
"pop ecx\n\t"
"pop ebx\n\t"
"pop eax\n\t"
"mov esp, dword ptr ss:[5f]\n\t"
"sti\n\t"
// Indirect interrupt call
".byte 0xcd\n\t"
"3: .byte 0\n\t"
"cli\n\t"
// Load out_regs
"mov dword ptr ss:[5f], esp\n\t"
"mov esp, dword ptr ss:[6f]\n\t"
"lea esp, [esp + 10*4]\n\t"
"push eax\n\t"
"push ebx\n\t"
"push ecx\n\t"
"push edx\n\t"
"push esi\n\t"
"push edi\n\t"
"push ebp\n\t"
"pushfd\n\t"
"push ds\n\t"
"push es\n\t"
"push fs\n\t"
"push gs\n\t"
"mov esp, dword ptr ss:[5f]\n\t"
// Restore GDT
"lgdt ss:[8f]\n\t"
// Jump back to pmode
"mov eax, cr0\n\t"
"or al, 1\n\t"
"mov cr0, eax\n\t"
FARJMP16("0x18", "1f")
"1: .code32\n\t"
"mov ax, 0x20\n\t"
"mov ds, ax\n\t"
"mov es, ax\n\t"
"mov fs, ax\n\t"
"mov gs, ax\n\t"
"mov ss, ax\n\t"
// Restore non-scratch GPRs
"pop ebp\n\t"
"pop edi\n\t"
"pop esi\n\t"
"pop ebx\n\t"
// Exit
"ret\n\t"
// ESP
"5: .long 0\n\t"
// out_regs
"6: .long 0\n\t"
// in_regs
"7: .long 0\n\t"
// gdt
"8: .long 0\n\t"
" .long 0\n\t"
);
}

105
src/lib/sleep.asm Normal file
View File

@ -0,0 +1,105 @@
section .text
int_08_ticks_counter: dd 0
int_08_isr:
bits 16
inc dword [cs:int_08_ticks_counter]
int 0x80 ; call callback
iret
bits 32
global pit_sleep_and_quit_on_keypress
pit_sleep_and_quit_on_keypress:
; Hook int 0x08
mov edx, dword [0x08*4]
mov dword [0x80*4], edx
mov edx, int_08_isr
mov dword [0x08*4], int_08_isr
; pit_ticks in edx
mov edx, dword [esp+4]
mov dword [int_08_ticks_counter], 0
; Save non-scratch GPRs
push ebx
push esi
push edi
push ebp
; Jump to real mode
jmp 0x08:.bits16
.bits16:
bits 16
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov eax, cr0
and al, 0xfe
mov cr0, eax
jmp 0x00:.cszero
.cszero:
xor ax, ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
sti
.loop:
cmp dword [int_08_ticks_counter], edx
je .timeout
push ecx
push edx
mov ah, 0x01
xor al, al
int 0x16
pop edx
pop ecx
jz .loop
; on keypress
xor ax, ax
int 0x16
mov eax, 1
jmp .done
.timeout:
xor eax, eax
.done:
cli
; Jump back to pmode
mov ebx, cr0
or bl, 1
mov cr0, ebx
jmp 0x18:.bits32
.bits32:
bits 32
mov bx, 0x20
mov ds, bx
mov es, bx
mov fs, bx
mov gs, bx
mov ss, bx
; Restore non-scratch GPRs
pop ebp
pop edi
pop esi
pop ebx
; Dehook int 0x08
mov edx, dword [0x80*4]
mov dword [0x08*4], edx
ret