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
|
.section .bss
|
||||||
.align 16
|
.align 16
|
||||||
|
.global stack_top
|
||||||
|
.global stack_bottom
|
||||||
stack_bottom:
|
stack_bottom:
|
||||||
/* Stos o wielkości 16 KB */
|
/* Stos o wielkości 16 KB */
|
||||||
.skip 16834
|
.skip 16384
|
||||||
stack_top:
|
stack_top:
|
||||||
|
|
||||||
.section .data
|
.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!
|
Oznaczenie startu, tu zaczyna się kod kernela!
|
||||||
@ -48,48 +45,23 @@ gdtb: .long 0x400000
|
|||||||
.global _start
|
.global _start
|
||||||
.type _start, @function
|
.type _start, @function
|
||||||
_start:
|
_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 */
|
/* Ustawienie ESP na wierzchołek stosu */
|
||||||
mov $stack_top, %esp
|
mov $stack_top, %esp
|
||||||
|
|
||||||
/* Tutaj jakieś ustawienia inicjalizacyjne trzeba zrobić normalnie */
|
|
||||||
//mov $69, %esi
|
|
||||||
//mov $_start, %edi
|
|
||||||
|
|
||||||
/* Wywołanie kernela */
|
/* Wywołanie kernela */
|
||||||
call kernel_main
|
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 */
|
/* Wieczne oczekiwanie po zakończeniu kodu kernela */
|
||||||
cli
|
cli
|
||||||
1: hlt
|
1: hlt
|
||||||
|
110
kernel.c
110
kernel.c
@ -164,12 +164,20 @@ 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";
|
char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
size_t size = 0;
|
int size = 0;
|
||||||
char numChars[32];
|
char numChars[32];
|
||||||
|
|
||||||
|
if (number == 0)
|
||||||
|
{
|
||||||
|
numChars[31] = '0';
|
||||||
|
size = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
while (number != 0)
|
while (number != 0)
|
||||||
{
|
{
|
||||||
uint64_t rest = number / base;
|
uint64_t rest = number / base;
|
||||||
@ -178,10 +186,23 @@ void terminal_writenum(uint64_t number, int base)
|
|||||||
numChars[31 - size++] = digits[digit];
|
numChars[31 - size++] = digits[digit];
|
||||||
number = rest;
|
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);
|
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)
|
void terminal_writestring(const char *data)
|
||||||
{
|
{
|
||||||
terminal_write(data, strlen(data));
|
terminal_write(data, strlen(data));
|
||||||
@ -230,7 +251,7 @@ struct gdt_entry {
|
|||||||
#define KERNEL_SEGMENT 0
|
#define KERNEL_SEGMENT 0
|
||||||
#define USER_SEGMENT 1
|
#define USER_SEGMENT 1
|
||||||
#define CODE_SEGMENT 0
|
#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,
|
struct gdt_entry gdt_entry_create(size_t start_address, size_t pages_size,
|
||||||
int kernel_or_user, int code_or_data)
|
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 -
|
// F = G DB L -
|
||||||
uint64_t gdt_entry_encode(struct gdt_entry entry)
|
uint64_t gdt_entry_encode(struct gdt_entry entry)
|
||||||
{
|
{
|
||||||
|
entry.base = entry.base << 12;
|
||||||
|
|
||||||
uint64_t gdt_encoded = 0;
|
uint64_t gdt_encoded = 0;
|
||||||
|
|
||||||
// Insert base
|
// Insert base
|
||||||
gdt_encoded |= ((uint64_t) (entry.base & 0xFF000000) << 32);
|
gdt_encoded |= ((((uint64_t) entry.base) & 0xFF000000) << 32);
|
||||||
gdt_encoded |= ((uint64_t) (entry.base & 0x00FFFFFF) << 16);
|
gdt_encoded |= ((((uint64_t) entry.base) & 0x00FFFFFF) << 16);
|
||||||
|
|
||||||
// Insert limit
|
// Insert limit
|
||||||
gdt_encoded |= ((uint64_t) (entry.limit & 0xF0000) << 32);
|
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;
|
access_byte |= entry.was_accessed;
|
||||||
|
|
||||||
// Insert access byte
|
// Insert access byte
|
||||||
gdt_encoded |= (access_byte << 20);
|
gdt_encoded |= (access_byte << 40);
|
||||||
|
|
||||||
return gdt_encoded;
|
return gdt_encoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct gdt_table {
|
struct __attribute__((__packed__)) gdt_table
|
||||||
uint16_t entries_count;
|
{
|
||||||
uint32_t *dest_pointer;
|
uint16_t size_in_bytes;
|
||||||
|
uint64_t *dest_pointer;
|
||||||
struct gdt_entry entries[16];
|
struct gdt_entry entries[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -323,26 +347,19 @@ void apply_table(struct gdt_table table)
|
|||||||
uint64_t null_entry_encoded = 0;
|
uint64_t null_entry_encoded = 0;
|
||||||
*table.dest_pointer = null_entry_encoded;
|
*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]);
|
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;
|
*dest_address = entry_encoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
__asm__("lgdt (%0)" : : "r" (&table));
|
__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("TEGO NIE POWINNO BYC WIDAC\n");
|
||||||
terminal_writestring
|
terminal_writestring
|
||||||
("Witam i pozdrawiam, MK\nTest wielolinijkowosci\n");
|
("Witam i pozdrawiam, MK\nTest wielolinijkowosci\n");
|
||||||
@ -374,11 +391,50 @@ void kernel_main(void)
|
|||||||
size_t human_readable = start_point / (1024 * 1024);
|
size_t human_readable = start_point / (1024 * 1024);
|
||||||
terminal_writenum(human_readable, 10);
|
terminal_writenum(human_readable, 10);
|
||||||
terminal_writestring(" MiB\n");
|
terminal_writestring(" MiB\n");
|
||||||
|
}
|
||||||
terminal_writestring("Test wpisu GDT:\n");
|
|
||||||
struct gdt_entry entry =
|
void gdt_setup()
|
||||||
gdt_entry_create(0, 0x400, KERNEL_SEGMENT, CODE_SEGMENT);
|
{
|
||||||
uint64_t entry_encoded = gdt_entry_encode(entry);
|
struct gdt_entry kernel_code_entry =
|
||||||
terminal_writenum(entry_encoded, 16);
|
gdt_entry_create(0, 0x400, KERNEL_SEGMENT, CODE_SEGMENT);
|
||||||
terminal_newline();
|
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