Page 6 of 20

Re: How to make a GDT?

Posted: Wed Oct 12, 2022 11:43 am
by Octocontrabass
zap8600 wrote:Can BOOTBOOT load x86 code?
If you mean 32-bit x86, no. BOOTBOOT can only load 64-bit code.
zap8600 wrote:If I understand correctly, BOOTBOOT will need to load the x86 part of the kernel, then the GDT and paging will be setup.
There is no "x86 part" of the kernel. Your kernel will be entirely x86-64 code.
zap8600 wrote:Or should I just make my own bootloader?
No.
zap8600 wrote:If I should, then I would like it to boot from UEFI.
There are several bootloaders out there that already support UEFI, including BOOTBOOT.

Re: How to make a GDT?

Posted: Wed Oct 12, 2022 12:05 pm
by zap8600
Octocontrabass wrote:
zap8600 wrote:Can BOOTBOOT load x86 code?
If you mean 32-bit x86, no. BOOTBOOT can only load 64-bit code.
So then how do I setup the GDT and paging from my kernel? Doesn't it have to be in Protected Mode to do so?

Re: How to make a GDT?

Posted: Wed Oct 12, 2022 12:13 pm
by Octocontrabass
zap8600 wrote:So then how do I setup the GDT and paging from my kernel?
Prepare your GDT and page tables, then tell the CPU to use them.
zap8600 wrote:Doesn't it have to be in Protected Mode to do so?
No.

Re: How to make a GDT?

Posted: Wed Oct 12, 2022 12:29 pm
by zap8600
Octocontrabass wrote:
zap8600 wrote:Doesn't it have to be in Protected Mode to do so?
No.
I think I understand now. I was just confused. Thanks for the help. I will probably be back later, though.

Re: How to make a GDT?

Posted: Thu Oct 13, 2022 10:50 am
by nullplan
linguofreak wrote:With respect to the IDT specifically, I'd argue that that's not so much of an outgrowth of Intel segmentation: the 8086 had segments, but a fixed IVT. The VAX was entirely a flat-address-space machine, but had a register that set the base address for a System Control Block, which contained interrupt and exception vectors. And I'd say it's generally good practice in designing a CPU architecture to expose things like that in registers so the OS can put them where it wants them, rather than baking addresses into the microcode.
I guess I should have written it the other way around. I meant that the IDT is an outgrowth of the 8086's interrupt handling mechanism. You know, where it has multiple interrupt cycles, and the hardware has to place the vector number onto the data bus at the right cycle. That stuff just doesn't exist anywhere else, most other CPU architectures give you one exception for "external interrupt" and then you have to ask your interrupt controller for details. I am however admittedly not very experienced with other CISC architectures, except maybe the 6502 (which also had a fixed exception table, and only a single entry for external interrupts).

I would disagree with your point about flexibility. It has its place, but can also cause a lot of configuration effort to get right. PowerPC has its exceptions at a fixed address, which basically necessitates all OSes on that architecture to load the kernel to address 0. However, when the kernel loads, all of address space is free (or will be free eventually), and so that is not a large burden.

Re: How to make a GDT?

Posted: Tue Oct 18, 2022 7:04 pm
by zap8600
I'm having some trouble setting up my kernel in x86_64. I'm using the Meaty Skeleton tutorial. Do I need a boot.S file? How should the link.ld file be setup? I have look at multiple articles and the BOOTBOOT example kernel.

Re: How to make a GDT?

Posted: Tue Oct 18, 2022 9:25 pm
by Octocontrabass
zap8600 wrote:Do I need a boot.S file?
You don't need it. You can still have it if you want it, though.
zap8600 wrote:How should the link.ld file be setup?
Use the linker script provided with the example kernel.

Re: How to make a GDT?

Posted: Tue Oct 18, 2022 9:34 pm
by nullplan
zap8600 wrote:I'm having some trouble setting up my kernel in x86_64. I'm using the Meaty Skeleton tutorial. Do I need a boot.S file? How should the link.ld file be setup? I have look at multiple articles and the BOOTBOOT example kernel.
BOOTBOOT is an ELF64 loader that apparently already sets up a stack. From my brief glance at the documentation just now, I would expect not. Indeed I think you are following the wrong tutorial. In short, you can just create a normal C application, except it starts at _start(), and compile it with -ffreestanding -nostdlib, and link it with a start address of -2GB.

I have a linker file that does the job for me:

Code: Select all

OUTPUT_FORMAT("elf64-x86-64")

PHDRS {
    headers PT_PHDR PHDRS;
    text PT_LOAD FILEHDR PHDRS;
    data PT_LOAD;
}

SECTIONS {
    . = 0xffffffff80000000 + SIZEOF_HEADERS;
    .text : {
        *(.text)
        *(.text.*)
    } :text
    .rodata : {
        *(.rodata)
        *(.rodata.*)
    }

    .eh_frame_hdr : {
        __eh_frame_hdr = .;
        *(.eh_frame_hdr)
    }
    .eh_frame : {
        *(.eh_frame)
        *(.eh_frame.*)
    }

    /* Normally, the overlap between text and data section is handled by having
     * two different pages for the last bits of text and the first bits of data.
     * That way, if the last bits of text are overwritten, it won't affect the
     * text that is actually used. Unfortunately, for the kernel this is not
     * possible. The whole file is loaded into memory en bloc, so the same page
     * would be mapped twice. Therefore, a write access to the writable page
     * would end up being visible in the non-writable side of things. Therefore,
     * we must actually page-align here.
     */
    . = ALIGN(2M);
    .data : {
        *(.data)
        *(.data.*)
    } :data
    .bss : {
        *(.bss)
        *(COMMON)
        *(.bss.*)
    }
}

Re: How to make a GDT?

Posted: Tue Oct 18, 2022 9:50 pm
by Octocontrabass
nullplan wrote:I have a linker file that does the job for me:
BOOTBOOT is much more limited than whichever bootloader you're using, so your linker script won't work with BOOTBOOT.

Re: How to make a GDT?

Posted: Wed Oct 19, 2022 7:03 am
by zap8600
nullplan wrote: BOOTBOOT is an ELF64 loader that apparently already sets up a stack. From my brief glance at the documentation just now, I would expect not. Indeed I think you are following the wrong tutorial. In short, you can just create a normal C application, except it starts at _start(), and compile it with -ffreestanding -nostdlib, and link it with a start address of -2GB.
I probably should have said that I'm using the tutorial as a base. The boot.S file also uses _start:.

Re: How to make a GDT?

Posted: Wed Oct 19, 2022 9:56 am
by nullplan
Octocontrabass wrote:BOOTBOOT is much more limited than whichever bootloader you're using, so your linker script won't work with BOOTBOOT.
How so? Does it not like the high load VMA? Is that why bzt had a bee in his bonnet about -mcmodel=kernel? Anyway, I use my own adapters. The main kernel is linked with that script, and the adapters adapt their boot environment appropriately to this main kernel. I have one for multiboot that is ca. 600 lines of C and another 300 lines of ASM. The UEFI one is still under development.

Oh my god. I just had a look at BOOTBOOT's ELF loader. Talk about a hack. Every page that I turn, I find more questionable things there. So sorry zap8600, I don't think that script will work for you. There is one in the example kernel, tho.
zap8600 wrote:I probably should have said that I'm using the tutorial as a base. The boot.S file also uses _start:.
Yes, I require you to think for yourself a bit. Obviously the Meaty Skeleton code will not work in a 64-bit environment as-is. You need to change it to fit the new environment. Now, one change is that with BOOTBOOT, your _start() symbol already has the stack setup, and you can just write it in C rather than ASM. So now you actually need to read that boot.S you pilfered to figure out what it is doing and whether you need to keep it or not.

Re: How to make a GDT?

Posted: Wed Oct 19, 2022 10:55 am
by zap8600
nullplan wrote: Oh my god. I just had a look at BOOTBOOT's ELF loader. Talk about a hack. Every page that I turn, I find more questionable things there. So sorry zap8600, I don't think that script will work for you. There is one in the example kernel, tho.
It is alright. I'll try to figure out how to write my own. It is very confusing, so I'll probably come back for help. How should I start?
nullplan wrote: Yes, I require you to think for yourself a bit. Obviously the Meaty Skeleton code will not work in a 64-bit environment as-is. You need to change it to fit the new environment. Now, one change is that with BOOTBOOT, your _start() symbol already has the stack setup, and you can just write it in C rather than ASM. So now you actually need to read that boot.S you pilfered to figure out what it is doing and whether you need to keep it or not.
I have been converting the Meaty Skeleton code to x86_64. And for the record, I'm not exactly trying to pilfer the boot.S file. I'm using the Meaty Skeleton code as a base and/or reference.

Re: How to make a GDT?

Posted: Wed Oct 19, 2022 11:50 am
by Octocontrabass
zap8600 wrote:How should I start?
Copy the example kernel's linker script. It should have everything you need for now.

Re: How to make a GDT?

Posted: Wed Oct 19, 2022 5:46 pm
by zap8600
I'm unsure what I'm doing wrong. Here is the error I get.

Code: Select all

mkdir -p /home/linuxlite/workspace/CCOS-new/sysroot/usr/include
cp -R --preserve=timestamps include/. /home/linuxlite/workspace/CCOS-new/sysroot/usr/include/.
mkdir -p /home/linuxlite/workspace/CCOS-new/sysroot/usr/include
cp -R --preserve=timestamps include/. /home/linuxlite/workspace/CCOS-new/sysroot/usr/include/.
mkdir -p /home/linuxlite/workspace/CCOS-new/sysroot/usr/include
cp -R --preserve=timestamps include/. /home/linuxlite/workspace/CCOS-new/sysroot/usr/include/.
mkdir -p /home/linuxlite/workspace/CCOS-new/sysroot/usr/lib
cp libk.a /home/linuxlite/workspace/CCOS-new/sysroot/usr/lib
mkdir -p /home/linuxlite/workspace/CCOS-new/sysroot/usr/include
cp -R --preserve=timestamps include/. /home/linuxlite/workspace/CCOS-new/sysroot/usr/include/.
x86_64-elf-gcc --sysroot=/home/linuxlite/workspace/CCOS-new/sysroot -isystem=/usr/include -T arch/x86_64/linker.ld -o myos.kernel -O2 -g -Wall -Wextra -ffreestanding    arch/x86_64/crti.o arch/x86_64/crtbegin.o arch/x86_64/tty.o  kernel/kernel.o font/unifont.o  -nostdlib -lk -lgcc  arch/x86_64/crtend.o arch/x86_64/crtn.o 
/home/linuxlite/opt/cross/lib/gcc/x86_64-elf/12.2.0/../../../../x86_64-elf/bin/ld: warning: myos.kernel has a LOAD segment with RWX permissions
`.eh_frame' referenced in section `.text' of arch/x86_64/crtbegin.o: defined in discarded section `.eh_frame' of arch/x86_64/crtbegin.o
`.eh_frame' referenced in section `.text' of arch/x86_64/crtbegin.o: defined in discarded section `.eh_frame' of arch/x86_64/crtbegin.o
arch/x86_64/crtbegin.o: in function `deregister_tm_clones':
crtstuff.c:(.text+0x1): relocation truncated to fit: R_X86_64_32 against symbol `__TMC_END__' defined in .dtors section in myos.kernel
crtstuff.c:(.text+0x18): relocation truncated to fit: R_X86_64_32 against `.tm_clone_table'
arch/x86_64/crtbegin.o: in function `register_tm_clones':
crtstuff.c:(.text+0x31): relocation truncated to fit: R_X86_64_32 against symbol `__TMC_END__' defined in .dtors section in myos.kernel
crtstuff.c:(.text+0x5a): relocation truncated to fit: R_X86_64_32 against `.tm_clone_table'
arch/x86_64/crtbegin.o: in function `__do_global_dtors_aux':
crtstuff.c:(.text+0x88): relocation truncated to fit: R_X86_64_32 against `.dtors'
crtstuff.c:(.text+0x8e): relocation truncated to fit: R_X86_64_32 against symbol `__DTOR_END__' defined in .dtors section in arch/x86_64/crtend.o
arch/x86_64/crtbegin.o: in function `frame_dummy':
crtstuff.c:(.text+0x10c): relocation truncated to fit: R_X86_64_32 against `.bss'
/home/linuxlite/opt/cross/lib/gcc/x86_64-elf/12.2.0/../../../../x86_64-elf/bin/ld: arch/x86_64/tty.o: in function `terminal_initialize':
/home/linuxlite/workspace/CCOS-new/kernel/arch/x86_64/tty.c:14: undefined reference to `_binary_console_sfn_start'
kernel/kernel.o: in function `_start':
/home/linuxlite/workspace/CCOS-new/kernel/kernel/kernel.c:7:(.text+0xc): relocation truncated to fit: R_X86_64_32 against `.rodata.str1.1'
arch/x86_64/crtend.o: in function `__do_global_ctors_aux':
crtstuff.c:(.text+0x13): relocation truncated to fit: R_X86_64_32 against `.ctors'
collect2: error: ld returned 1 exit status
make: *** [Makefile:57: myos.kernel] Error 1
Here is my Makefile file.

Code: Select all

DEFAULT_HOST!=../default-host.sh
HOST?=DEFAULT_HOST
HOSTARCH!=../target-triplet-to-arch.sh $(HOST)

CFLAGS?=-O2 -g
CPPFLAGS?=
LDFLAGS?=
LIBS?=

DESTDIR?=
PREFIX?=/usr/local
EXEC_PREFIX?=$(PREFIX)
BOOTDIR?=$(EXEC_PREFIX)/boot
INCLUDEDIR?=$(PREFIX)/include

CFLAGS:=$(CFLAGS) -Wall -Wextra -ffreestanding
CPPFLAGS:=$(CPPFLAGS) -D__is_kernel -Iinclude
LDFLAGS:=$(LDFLAGS)
LIBS:=$(LIBS) -nostdlib -lk -lgcc

ARCHDIR=arch/$(HOSTARCH)

include $(ARCHDIR)/make.config

CFLAGS:=$(CFLAGS) $(KERNEL_ARCH_CFLAGS)
CPPFLAGS:=$(CPPFLAGS) $(KERNEL_ARCH_CPPFLAGS)
LDFLAGS:=$(LDFLAGS) $(KERNEL_ARCH_LDFLAGS)
LIBS:=$(LIBS) $(KERNEL_ARCH_LIBS)

KERNEL_OBJS=\
$(KERNEL_ARCH_OBJS) \
kernel/kernel.o \
font/unifont.o

OBJS=\
$(ARCHDIR)/crti.o \
$(ARCHDIR)/crtbegin.o \
$(KERNEL_OBJS) \
$(ARCHDIR)/crtend.o \
$(ARCHDIR)/crtn.o \

LINK_LIST=\
$(LDFLAGS) \
$(ARCHDIR)/crti.o \
$(ARCHDIR)/crtbegin.o \
$(KERNEL_OBJS) \
$(LIBS) \
$(ARCHDIR)/crtend.o \
$(ARCHDIR)/crtn.o \

.PHONY: all clean install install-headers install-kernel
.SUFFIXES: .o .c .S

all: myos.kernel

myos.kernel: $(OBJS) $(ARCHDIR)/linker.ld
	$(CC) -T $(ARCHDIR)/linker.ld -o $@ $(CFLAGS) $(LINK_LIST)
	x86_64-elf-strip -s -K mmio -K fb -K bootboot -K environment -K initstack myos.kernel

font/unifont.o: 
	x86_64-elf-ld -r -b binary -o font/unifont.o font/unifont.sfn

$(ARCHDIR)/crtbegin.o $(ARCHDIR)/crtend.o:
	OBJ=`$(CC) $(CFLAGS) $(LDFLAGS) -print-file-name=$(@F)` && cp "$$OBJ" $@

.c.o:
	$(CC) -MD -c $< -o $@ -std=gnu11 $(CFLAGS) $(CPPFLAGS)

.S.o:
	$(CC) -MD -c $< -o $@ $(CFLAGS) $(CPPFLAGS)

clean:
	rm -f myos.kernel
	rm -f $(OBJS) *.o */*.o */*/*.o
	rm -f $(OBJS:.o=.d) *.d */*.d */*/*.d

install: install-headers install-kernel

install-headers:
	mkdir -p $(DESTDIR)$(INCLUDEDIR)
	cp -R --preserve=timestamps include/. $(DESTDIR)$(INCLUDEDIR)/.

install-kernel: myos.kernel
	mkdir -p $(DESTDIR)$(BOOTDIR)
	cp myos.kernel $(DESTDIR)$(BOOTDIR)

-include $(OBJS:.o=.d)
I'm trying to use the ssfn library as well. Here is my tty.c file.

Code: Select all

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>

#define SSFN_CONSOLEBITMAP_TRUECOLOR        /* use the special renderer for 32 bit truecolor packed pixels */
#include <kernel/ssfn.h>
#include <kernel/tty.h>

extern uint8_t fb;
extern volatile unsigned char _binary_console_sfn_start;

void terminal_initialize(void) {
	ssfn_src = &_binary_console_sfn_start;      /* the bitmap font to use */
	ssfn_dst.ptr = &fb;                  /* framebuffer address and bytes per line */
	ssfn_dst.p = 4096;
	ssfn_dst.fg = 0xFFFFFFFF;                   /* colors, white on black */
	ssfn_dst.bg = 0;
	ssfn_dst.x = 100;                           /* coordinates to draw to */
	ssfn_dst.y = 200;
}

void terminal_putentryat(char *s) {
	if(*s == '\n') {
    		ssfn_dst.y += ssfn_src->height;
    		ssfn_dst.x = 0;
	} else
    		ssfn_putc(*s);
}

void terminal_putchar(char c) {
	terminal_putentryat(c);
}

void terminal_write(const char* data, size_t size) {
	for (size_t i = 0; i < size; i++)
		terminal_putchar(data[i]);
}

void terminal_writestring(const char* data) {
	terminal_write(data, strlen(data));
}
Any help is appreciated.

Re: How to make a GDT?

Posted: Wed Oct 19, 2022 6:00 pm
by Octocontrabass
zap8600 wrote:

Code: Select all

relocation truncated to fit
You need to add "-mcmodel=kernel" to your CFLAGS. You should also add "-mno-red-zone" to avoid problems later.
zap8600 wrote:

Code: Select all

undefined reference to `_binary_console_sfn_start'
The symbol name depends on the file name. Your font is named "font/unifont.sfn" instead of "console.sfn", so you need to replace "_binary_console_sfn_start" with "_binary_font_unifont_sfn_start".