Page 11 of 20

Re: How to make a GDT?

Posted: Tue Oct 25, 2022 2:25 pm
by devc1
zap8600, I am honestly at a loss at this point. I would recommend ditching BOOTBOOT TBH. BOOTBOOT is very finicky from what I've seen. Try using Limine instead.
Why don't he create his own bootloader like everyone does ? He can skip the hard step which is the legacy bios bootloader, and create a simple UEFI bootloader.

Creating Legacy BIOS Support was a nightmare !! It's still a mess of assembly code, 5 assembly files [name:lines of code] (bootsect.asm:193, partbootsect.asm:36, bootmgr.asm:**1477**, bootldr64.asm:511, bptdefs.asm:23)


My Legacy BIOS bootloader's job :

Code: Select all

Consists of 2 stages, the bootsector and the partition bootsector along with the hole bootloader.
My FS Driver sets up some thing in the partition which makes it easier than creating a whole file system driver inside the bootloader.
- Enables A20
- Loads the memory map
- sets up VESA VBE
- Reads drive information
- Jumps to protected mode (32 bit)
- Reads the boot pointer table
- Reads the kernel & dependencies
- Relocates the kernel
- Checks long mode support
- Jump to long mode (64 bit)
- fills up some global variables inside the kernel (some sections like INITDATA, FIMPORT)

Re: How to make a GDT?

Posted: Tue Oct 25, 2022 2:27 pm
by zap8600
nexos wrote: What? Citation needed! Everyone agrees that making an OS on Linux is easier. Doing so on Windows is a nightmare!

The problem your having with compiling is rather simple. You need to use a cross compiler.

zap8600, I am honestly at a loss at this point. I would recommend ditching BOOTBOOT TBH. BOOTBOOT is very finicky from what I've seen. Try using Limine instead.
I was using BOOTBOOT because it would let me boot my OS on Raspberry Pi (when I port it to Raspberry Pi) easily, but I guess that I will have to use Limine. I figure something out for the Raspberry Pi later. Thanks. And yes, making an OS on Linux is easier.

Re: How to make a GDT?

Posted: Tue Oct 25, 2022 3:12 pm
by kzinti
I use UEFI, even on the Raspberry Pi.

https://github.com/pftf/RPi3
https://github.com/pftf/RPi4

Re: How to make a GDT?

Posted: Tue Oct 25, 2022 3:21 pm
by nexos
devc1 wrote:Why don't he create his own bootloader like everyone does ? He can skip the hard step which is the legacy bios bootloader, and create a simple UEFI bootloader.
UEFI? Simple? Citation needed again. I mean, it's better than BIOS, but most certainly not simple. Unless you having a particular use case, skip the hard part and use a tried-and-true bootloader.

Re: How to make a GDT?

Posted: Tue Oct 25, 2022 4:32 pm
by devc1
Huh, making a UEFI bootloader is very easy. For basic usage, You won't need more than 300 lines of code though, compared to a bios bootloader which can consume thousands of lines of code.

I meant simple for a basic usage, when you must read files to load a relocatable kernel, get the memory map and setup the frame buffer, of course some additional features aren't that simple.


My UEFI bootloader has 600 lines of code (half of it is just for some optimized memset/memcpy functions), the legacy bios bootloader has over 3000 lines of code to do the same job (it is written in assembly).

Re: How to make a GDT?

Posted: Tue Oct 25, 2022 9:26 pm
by nullplan
devc1 wrote:Why don't he create his own bootloader like everyone does ?
Because not everyone else does? Although my booting solution is to add yet another stage. I have a 32-bit kernel suitable for use with multiboot compliant boot loaders (whether that is GRUB or syslinux or something else doesn't really matter to me), and it sets up the page tables necessary and jumps to my 64-bit main kernel (multiboot does have module support). For UEFI, I plan on loading the main kernel from the boot FS, but there I have enough space to encode something like that.

All in all, I highly recommend the "use something established and add glue code to plaster over the differences" approach.

Re: How to make a GDT?

Posted: Tue Oct 25, 2022 9:27 pm
by zap8600
I got my OS to boot with Limine. So how do I make the ISRs?

Re: How to make a GDT?

Posted: Wed Oct 26, 2022 11:29 am
by zap8600
I've finally gotten a bit smarter and I think I (somewhat) know what I need to do. I need to know what my interrupt handler needs to do. I plan on using the Two-Stage Assembly Wrapping method of making an interrupt handler (because I'm way more confident in my C skills than in my assembly skills). What does my interrupt handler need to do? I'm also using GCC's interrupt handler code, so I'm wondering if I need to add anything to the interrupt_frame struct. I'm also having trouble getting I/O functions to work. I'm using the functions from here. Here is what I get when compiling.

Code: Select all

arch/x86_64/io.c: In function 'io_wait':
arch/x86_64/io.c:6:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    6 | {
      | ^
arch/x86_64/io.c:15:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
   15 | {
      | ^
arch/x86_64/io.c:24:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
   24 | {
      | ^
arch/x86_64/io.c:27: error: expected '{' at end of input
In file included from arch/x86_64/io.c:3:
include/kernel/io.h: At top level:
include/kernel/io.h:3:20: warning: 'outb' declared 'static' but never defined [-Wunused-function]
    3 | static inline void outb(uint16_t port, uint8_t val);
      |                    ^~~~
include/kernel/io.h:4:23: warning: 'inb' declared 'static' but never defined [-Wunused-function]
    4 | static inline uint8_t inb(uint16_t port);
      |                       ^~~
make: *** [Makefile:51: arch/x86_64/io.o] Error 1
Any help would be greatly appreciated.

Re: How to make a GDT?

Posted: Wed Oct 26, 2022 12:12 pm
by Octocontrabass
zap8600 wrote:I need to know what my interrupt handler needs to do.
Exceptions are also a type of interrupt, and you should set up handlers for them before you worry about hardware interrupts. Your exception handlers should halt the CPU and display debugging information (or output it over a serial port or something). Later, you might choose to resolve the condition that caused the exception and return, so don't assume your exception handler will never return when you write it.

Once you have exception handlers in place, you can write hardware interrupt handlers. What those need to do will depend on the hardware that raised the interrupt. Typically, it means acknowledging the device that raised the interrupt and acknowledging the interrupt controller, although there are devices and interrupt controllers that don't require any acknowledgement. It's also possible to mask the interrupt and schedule a deferred procedure to deal with the hardware; this allows you to do things like run drivers in ring 3.
zap8600 wrote:I plan on using the Two-Stage Assembly Wrapping method [...] I'm also using GCC's interrupt handler code,
You can't use both at the same time. You should use only the assembly wrapper without the function attribute.
zap8600 wrote:I'm wondering if I need to add anything to the interrupt_frame struct.
That depends on what you put on your stack. Also, the example assembly code you linked doesn't include passing a pointer to the stack frame, but there are examples out there that show how you could do it.
zap8600 wrote:I'm also having trouble getting I/O functions to work.
You didn't copy them correctly.

Re: How to make a GDT?

Posted: Wed Oct 26, 2022 12:26 pm
by zap8600
Octocontrabass wrote: Exceptions are also a type of interrupt, and you should set up handlers for them before you worry about hardware interrupts. Your exception handlers should halt the CPU and display debugging information (or output it over a serial port or something). Later, you might choose to resolve the condition that caused the exception and return, so don't assume your exception handler will never return when you write it.

Once you have exception handlers in place, you can write hardware interrupt handlers. What those need to do will depend on the hardware that raised the interrupt. Typically, it means acknowledging the device that raised the interrupt and acknowledging the interrupt controller, although there are devices and interrupt controllers that don't require any acknowledgement. It's also possible to mask the interrupt and schedule a deferred procedure to deal with the hardware; this allows you to do things like run drivers in ring 3.
I believe an ISR should be like the code below.

Code: Select all

isr0:
    cli
    push byte 0
    push byte 0
    jmp isr_common_stub
What would the isr_common_stub function need to do (in x86_64. I know what it does in x86.)?
Octocontrabass wrote: You didn't copy them correctly.
I fixed it.

Re: How to make a GDT?

Posted: Wed Oct 26, 2022 12:40 pm
by Octocontrabass
zap8600 wrote:I believe an ISR should be like the code below.
Close, but it shouldn't have CLI. Use an interrupt gate in your IDT if you want interrupts disabled at the start of your ISR. (Also, that code is NASM syntax, so you need to translate it to AT&T syntax.)
zap8600 wrote:What would the isr_common_stub function need to do (in x86_64. I know what it does in x86.)?
It needs to do pretty much the same things, just 64-bit instead of 32-bit. (You don't have to worry about SWAPGS until you're ready to set up GS as a per-CPU data pointer.)

Re: How to make a GDT?

Posted: Wed Oct 26, 2022 5:08 pm
by zap8600
As I expected, my code didn't work. The machine rebooted when booting the OS. If anyone needs to see my interrupt files, I have linked to the files on Github. There is int.S, ints.c, and ints.h.

Re: How to make a GDT?

Posted: Wed Oct 26, 2022 5:17 pm
by Octocontrabass
Don't you get compiler warnings from all the 32-bit fields you forgot to extend to 64-bit?

Re: How to make a GDT?

Posted: Wed Oct 26, 2022 5:47 pm
by zap8600
Octocontrabass wrote:Don't you get compiler warnings from all the 32-bit fields you forgot to extend to 64-bit?
I've made changes since then. Running my init_idt() function in the kernel works, but when it runs asm volatile ("int $0x3"), the machine reboots. I've changed kernel.c, ints.c, and ints.h. Here are the warnings I'm getting with my current code.

Code: Select all

arch/x86_64/ints.c: In function 'init_idt':
arch/x86_64/ints.c:20:5: warning: implicit declaration of function 'idt_set_gate' [-Wimplicit-function-declaration]
   20 |     idt_set_gate(0, _isr0);
      |     ^~~~~~~~~~~~
arch/x86_64/ints.c: At top level:
arch/x86_64/ints.c:59:6: warning: conflicting types for 'idt_set_gate'; have 'void(int,  struct regs * (*)(struct regs *))'
   59 | void idt_set_gate(int n, interrupt_handler_t handler)
      |      ^~~~~~~~~~~~
arch/x86_64/ints.c:20:5: note: previous implicit declaration of 'idt_set_gate' with type 'void(int,  struct regs * (*)(struct regs *))'
   20 |     idt_set_gate(0, _isr0);
      |     ^~~~~~~~~~~~

Re: How to make a GDT?

Posted: Wed Oct 26, 2022 8:10 pm
by Octocontrabass
zap8600 wrote:when it runs asm volatile ("int $0x3"), the machine reboots.
That's a triple fault. The QEMU interrupt log may be useful for finding the problem.
zap8600 wrote:

Code: Select all

warning: implicit declaration of function
If you see this warning, your code is broken. Fix this warning before you try to debug anything.