mirror of
https://github.com/originalmk/mkos32.git
synced 2025-01-18 16:29:19 +00:00
Non-flat segmentation set from C
Playing with non-flat segmentation, but it seems that it won't be feasible to use it with C programs - implementing paging and flat segmentation scheme will be neceassary.
This commit is contained in:
parent
4fc60d7440
commit
47990aac56
56
boot.s
56
boot.s
@ -29,17 +29,14 @@
|
||||
|
||||
.section .bss
|
||||
.align 16
|
||||
.global stack_top
|
||||
.global stack_bottom
|
||||
stack_bottom:
|
||||
/* Stos o wielkości 16 KB */
|
||||
.skip 16834
|
||||
.skip 16384
|
||||
stack_top:
|
||||
|
||||
.section .data
|
||||
/* 31, bo będą 4 deskryptory po 8 bajtów, a przekazujemy wielkość - 1*/
|
||||
// TODO
|
||||
gdtr: .word 23
|
||||
/* Na 4 MiB daję bazę dla GDT, czyli tam gdzie zaczynają się dane kernela */
|
||||
gdtb: .long 0x400000
|
||||
|
||||
/*
|
||||
Oznaczenie startu, tu zaczyna się kod kernela!
|
||||
@ -48,48 +45,23 @@ gdtb: .long 0x400000
|
||||
.global _start
|
||||
.type _start, @function
|
||||
_start:
|
||||
/* Tutaj podobno jest tryb chroniony już, jednak zastanawia czy faktycznie
|
||||
* bootloader ustawia za nas segmentacje pamięci?
|
||||
* EDIT: Ustawia, ale pod własne potrzeby, więc i tak trzeba zmienić
|
||||
* Ustawię zatem najprostszy model segmentacji */
|
||||
|
||||
// Domyślne ustawienia z GRUB-a są takie, że pomijają segmentację!
|
||||
// Dodam w ramach segmentu danych kernela, czyli u mnie 4-8 MiB
|
||||
|
||||
mov gdtb, %eax
|
||||
// 1. Pusty (null) deskryptor
|
||||
movl $0, (%eax)
|
||||
movl $0, 4(%eax)
|
||||
// 2. Deskryptor kodu jądra
|
||||
movl $0x000003FF, 8(%eax)
|
||||
movl $0x00c09800, 12(%eax)
|
||||
// 3. Deskryptor danych jądra
|
||||
movl $0x000003FF, 16(%eax)
|
||||
movl $0x00C09240, 20(%eax)
|
||||
// 4. Deskryptor kodu użytkownika
|
||||
// 6. Load GDT
|
||||
lgdt (gdtr)
|
||||
// 7. Refresh registers
|
||||
mov %cs, 8(%eax)
|
||||
mov %ds, 16(%eax)
|
||||
mov %es, 16(%eax)
|
||||
mov %fs, 16(%eax)
|
||||
mov %gs, 16(%eax)
|
||||
mov %ss, 16(%eax)
|
||||
|
||||
// Wpisywane jest i tak pod %ds:64
|
||||
movb $69, (64)
|
||||
|
||||
/* Ustawienie ESP na wierzchołek stosu */
|
||||
mov $stack_top, %esp
|
||||
|
||||
/* Tutaj jakieś ustawienia inicjalizacyjne trzeba zrobić normalnie */
|
||||
//mov $69, %esi
|
||||
//mov $_start, %edi
|
||||
|
||||
/* Wywołanie kernela */
|
||||
call kernel_main
|
||||
|
||||
mov $0x10, %ax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
mov %ax, %ss
|
||||
jmp $0x08,$cs_refresh
|
||||
cs_refresh:
|
||||
mov $0x4000, %esp
|
||||
push $5
|
||||
|
||||
/* Wieczne oczekiwanie po zakończeniu kodu kernela */
|
||||
cli
|
||||
1: hlt
|
||||
|
120
kernel.c
120
kernel.c
@ -164,24 +164,45 @@ void terminal_write(const char *data, size_t size)
|
||||
}
|
||||
}
|
||||
|
||||
void terminal_writenum(uint64_t number, int base)
|
||||
// Pad length is what number length should be, including padding
|
||||
void terminal_writenumpad(uint64_t number, int base, int pad_length)
|
||||
{
|
||||
char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
size_t size = 0;
|
||||
int size = 0;
|
||||
char numChars[32];
|
||||
|
||||
while (number != 0)
|
||||
if (number == 0)
|
||||
{
|
||||
uint64_t rest = number / base;
|
||||
uint64_t digit = number % base;
|
||||
numChars[31] = '0';
|
||||
size = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (number != 0)
|
||||
{
|
||||
uint64_t rest = number / base;
|
||||
uint64_t digit = number % base;
|
||||
|
||||
numChars[31 - size++] = digits[digit];
|
||||
number = rest;
|
||||
numChars[31 - size++] = digits[digit];
|
||||
number = rest;
|
||||
}
|
||||
}
|
||||
|
||||
// Write pad_length - size of zeros
|
||||
// If padding won't be needed (number is longer than pad_legnth)
|
||||
// then loop won't run at all
|
||||
while (pad_length > size) {
|
||||
numChars[31 - size++] = digits[0];
|
||||
}
|
||||
|
||||
terminal_write(numChars + (32 - size), size);
|
||||
}
|
||||
|
||||
void terminal_writenum(uint64_t number, int base)
|
||||
{
|
||||
terminal_writenumpad(number, base, 0);
|
||||
}
|
||||
|
||||
void terminal_writestring(const char *data)
|
||||
{
|
||||
terminal_write(data, strlen(data));
|
||||
@ -230,7 +251,7 @@ struct gdt_entry {
|
||||
#define KERNEL_SEGMENT 0
|
||||
#define USER_SEGMENT 1
|
||||
#define CODE_SEGMENT 0
|
||||
#define USER_SEGMENT 1
|
||||
#define DATA_SEGMENT 1
|
||||
|
||||
struct gdt_entry gdt_entry_create(size_t start_address, size_t pages_size,
|
||||
int kernel_or_user, int code_or_data)
|
||||
@ -276,11 +297,13 @@ struct gdt_entry gdt_entry_create(size_t start_address, size_t pages_size,
|
||||
// F = G DB L -
|
||||
uint64_t gdt_entry_encode(struct gdt_entry entry)
|
||||
{
|
||||
entry.base = entry.base << 12;
|
||||
|
||||
uint64_t gdt_encoded = 0;
|
||||
|
||||
// Insert base
|
||||
gdt_encoded |= ((uint64_t) (entry.base & 0xFF000000) << 32);
|
||||
gdt_encoded |= ((uint64_t) (entry.base & 0x00FFFFFF) << 16);
|
||||
gdt_encoded |= ((((uint64_t) entry.base) & 0xFF000000) << 32);
|
||||
gdt_encoded |= ((((uint64_t) entry.base) & 0x00FFFFFF) << 16);
|
||||
|
||||
// Insert limit
|
||||
gdt_encoded |= ((uint64_t) (entry.limit & 0xF0000) << 32);
|
||||
@ -306,14 +329,15 @@ uint64_t gdt_entry_encode(struct gdt_entry entry)
|
||||
access_byte |= entry.was_accessed;
|
||||
|
||||
// Insert access byte
|
||||
gdt_encoded |= (access_byte << 20);
|
||||
gdt_encoded |= (access_byte << 40);
|
||||
|
||||
return gdt_encoded;
|
||||
}
|
||||
|
||||
struct gdt_table {
|
||||
uint16_t entries_count;
|
||||
uint32_t *dest_pointer;
|
||||
struct __attribute__((__packed__)) gdt_table
|
||||
{
|
||||
uint16_t size_in_bytes;
|
||||
uint64_t *dest_pointer;
|
||||
struct gdt_entry entries[16];
|
||||
};
|
||||
|
||||
@ -323,26 +347,19 @@ void apply_table(struct gdt_table table)
|
||||
uint64_t null_entry_encoded = 0;
|
||||
*table.dest_pointer = null_entry_encoded;
|
||||
|
||||
for (int i = 0; i < table.entries_count; i++)
|
||||
int entries_count = (table.size_in_bytes + 1) / 8;
|
||||
for (int i = 0; i < entries_count; i++)
|
||||
{
|
||||
uint64_t entry_encoded = gdt_entry_encode(table.entries[i]);
|
||||
uint32_t *dest_address = table.dest_pointer + (i + 1) * 8;
|
||||
uint64_t *dest_address = table.dest_pointer + i + 1;
|
||||
*dest_address = entry_encoded;
|
||||
}
|
||||
|
||||
__asm__("lgdt (%0)" : : "r" (&table));
|
||||
}
|
||||
|
||||
void kernel_main(void)
|
||||
void print_texts()
|
||||
{
|
||||
/*
|
||||
* Initialize terminal interface
|
||||
*/
|
||||
terminal_initialize();
|
||||
|
||||
/*
|
||||
* Newline support is left as an exercise.
|
||||
*/
|
||||
terminal_writestring("TEGO NIE POWINNO BYC WIDAC\n");
|
||||
terminal_writestring
|
||||
("Witam i pozdrawiam, MK\nTest wielolinijkowosci\n");
|
||||
@ -374,11 +391,50 @@ void kernel_main(void)
|
||||
size_t human_readable = start_point / (1024 * 1024);
|
||||
terminal_writenum(human_readable, 10);
|
||||
terminal_writestring(" MiB\n");
|
||||
|
||||
terminal_writestring("Test wpisu GDT:\n");
|
||||
struct gdt_entry entry =
|
||||
gdt_entry_create(0, 0x400, KERNEL_SEGMENT, CODE_SEGMENT);
|
||||
uint64_t entry_encoded = gdt_entry_encode(entry);
|
||||
terminal_writenum(entry_encoded, 16);
|
||||
terminal_newline();
|
||||
}
|
||||
|
||||
void gdt_setup()
|
||||
{
|
||||
struct gdt_entry kernel_code_entry =
|
||||
gdt_entry_create(0, 0x400, KERNEL_SEGMENT, CODE_SEGMENT);
|
||||
struct gdt_entry kernel_data_entry =
|
||||
gdt_entry_create(0x400, 0x400, KERNEL_SEGMENT, DATA_SEGMENT);
|
||||
struct gdt_entry user_code_entry =
|
||||
gdt_entry_create(0x800, 0x400, USER_SEGMENT, CODE_SEGMENT);
|
||||
struct gdt_entry user_data_entry =
|
||||
gdt_entry_create(0xC00, 0x400, USER_SEGMENT, DATA_SEGMENT);
|
||||
|
||||
struct gdt_table gdt_table;
|
||||
gdt_table.size_in_bytes = 39;
|
||||
gdt_table.dest_pointer = (uint64_t*)0x400000;
|
||||
gdt_table.entries[0] = kernel_code_entry;
|
||||
gdt_table.entries[1] = kernel_data_entry;
|
||||
gdt_table.entries[2] = user_code_entry;
|
||||
gdt_table.entries[3] = user_data_entry;
|
||||
|
||||
apply_table(gdt_table);
|
||||
terminal_writestring("GDT table applied\n");
|
||||
|
||||
__asm__ volatile(
|
||||
"mov $stack_bottom, %%esi;"
|
||||
"mov $0x500000, %%edi;"
|
||||
"mov $16384, %%ecx;"
|
||||
"cld;"
|
||||
"rep movsb;"
|
||||
:
|
||||
:
|
||||
:
|
||||
"esi","edi","ecx"
|
||||
);
|
||||
|
||||
__asm__(
|
||||
"xchg %bx, %bx"
|
||||
);
|
||||
}
|
||||
|
||||
void kernel_main(void)
|
||||
{
|
||||
terminal_initialize();
|
||||
print_texts();
|
||||
gdt_setup();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user