flat assembler
Message board for the users of flat assembler.

Index > OS Construction > How does bootloader call kernel stub?

Goto page Previous  1, 2
Author
Thread Post new topic Reply to topic
bzt



Joined: 09 Nov 2018
Posts: 77
bzt 08 Nov 2022, 23:34
FlierMate wrote:
I need the "extrn" label so that it can link to the entry point of my Pascal program.
That's a very bad idea. This means you have to recompile and reinstall the boot loader if your kernel changes. Instead I recommend to parse the kernel file and find the entry point address dynamically.

FlierMate wrote:
Since FASM generates binary image directly, I end up using NASM temporarily for this project, and it has been done, a "hello world" OS kernel written in Pascal!
You should switch back to FASM, it's much better than NASM.

You can also use my boot loader, BOOTBOOT, which is written with FASM and can load Pascal kernels out-of-the-box (not just on BIOS systems, but on UEFI as well, and works as a GRUB module too. There's also an example "Hello World" kernel in Pascal that you can use as a skeleton, tested with the FreePascal Compiler). This loader has several advantages, like setting up long mode, paging, graphical screen for you, able to load your kernel from a FAT partition, initializes multicore and runs your kernel on all cores in parallel etc., but this might be a bit overkill for you.

If you want to write your own boot sector, then I'd strongly recommend to take a look at imgrecv, which is also written in FASM, but much much simpler (one sector, 512 bytes only). I wrote it for a special use case, that's why it loads the kernel from the RS/232 port instead of disk (line 126 to 158, replace that with a disk read BIOS call), but otherwise it might be very useful to you.

This imgrecv boot sector loads the kernel at address LOAD_ADDR (which is defined as 1M), then it sets up protected mode, paging tables, enables A20, disables PIC, etc. and checks the loaded kernel's header. If it's a raw image, then the code simply jumps to the first byte of the kernel, at 1M. But if it's an ELF executable, then it checks if it's 64-bit, and if so, it sets up long mode too. In both cases (ELF32 and ELF64) it parses the ELF header to get the entry point (line 165, so there's no need for "extrn", as the code gets the address from the ELF header dynamically) and jumps to that. The advantage here is, you can compile your kernel in pure protmode or longmode, there's no need for 16-bit trampoline code, as the loader dynamically sets up the environment for your kernel.

If your Pascal compiler outputs PE (Windows' default), then the method is the same, it's just you can find the entry address at a different offset. Example PE header parser in FASM.

The point is, do not use "extrn" and link your loader with your kernel, instead write your loader in a way that parses the kernel's header (either ELF or PE) in run-time. This way you can replace the kernel without touching the loader.

Hope this helps,
bzt
Post 08 Nov 2022, 23:34
View user's profile Send private message Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4334
Location: Now
edfed 18 Mar 2023, 18:25
mbr.inc

Code:
format binary as 'img'
;version 15/03/2023 04:02
;version 04/06/2019 13.54
;version 01/05/2014 01:29
;version 27/11/2007 01:48
;bootcode:

;;; BEGIN OF MBR

;BOOTRELOC:   ;uncomment to test reloc

masterbootrecord:
use16
        org 7c00h
        mov ax,cs
        mov ss,ax
        mov ds,ax
        mov [bootdrive],dl

;copy bootloader from 0000h:7c00h to 0020h:7c00h
;linear 07c00h to 07e00h
;this is used to load boot sectors from other partitions or drives.
if defined BOOTRELOC

        mov ax,20h
        mov es,ax
        mov bx,200h
        mov di,7c00h
  @@:
        dec bx
        jl @f
        mov al,[di+bx]
        mov [es:di+bx],al
        jmp @b
  @@:

;and jump to the recopy.

        jmp 20h:@f
otherdrive db 80h   ;set this to any drive 
  @@:

;at this point, we can load another boot sector
;from another drive with code like this:
if defined otherdrive
        mov ah,0eh
        mov al,'B' ;print B each time it's reloaded
        int 10h
        mov dl,[otherdrive]
        mov ax,21h   ;load 1 sector
        mov cx,1
        xor dh,dh
        mov bx,7c0h
        mov es,bx
        xor bx,bx
        int 13h
        jmp 0:7c00h
end if  ;otherdrive


end if  ;BOOTRELOC

;load the system from sector 2 to lowmem
        mov cx,secondstage.packets
@@:
        push cx
        mov ah,42h
        mov dl,[bootdrive]
        mov si,dap
        int 13h
        add [dap.fptr+2],(40h*512)/16
        add dword[dap.lba],40h
        pop cx
        loop @b

        xor ax,ax
        mov ss,ax
        mov ds,ax
        jmp 0:secondstage.org

dap:
        db 10h,0
.cnt    dw 40h ;32k
.fptr   dd secondstage.seg:0
.lba    dd 1,0

        rb 509-($-$$)
bootdrive:
        db 0
        dw 0aa55h

;;; END OF MBR

include 'secondstage.inc'

if ~definite secondstage
secondstage:
.seg=800h
.org=.seg*16  ;starts at 32k
.packets=1


        org .org
        mov ax,ds
        mov es,ax
        mov ax,3
        int 10h

        mov si,.str
        call prints

        jmp $

.str:   db 'nothing to boot',0

prints:
        mov ah,0eh
@@:
        lodsb
        or al,al
        je @f
        int 10h
        jmp @b
@@:
        ret


end if  ;secondstage
    


secondstage.inc
Code:
secondstage:
.seg = 800h
.org = .seg*16  ;starts at 32k
.packets = 19   ;640 - 32k

        org .org
        call SMAP.query
        jmp kernel
include 'smap.inc'
kernel:
        mov si,.str
        call prints

        jmp entrypoint

.str:   db 'something booted, and you can read the SMAP',0

prints:
        mov ah,0eh
@@:
        lodsb
        or al,al
        je @f
        int 10h
        jmp @b
@@:
        ret

entrypoint:
        jmp $
    


in fact, it's better to don't use protected mode during boot process.

better to load a lot of stuff using bios and then, start the os


oups, and forgot to put the smap.inc file


Description:
Download
Filename: smap.inc
Filesize: 2.75 KB
Downloaded: 222 Time(s)

Description: both files ready to try and use at your own risksdscfdsfdd
Download
Filename: sys.zip
Filesize: 1.4 KB
Downloaded: 215 Time(s)

Post 18 Mar 2023, 18:25
View user's profile Send private message Visit poster's website Reply with quote
bzt



Joined: 09 Nov 2018
Posts: 77
bzt 22 Mar 2023, 14:58
edfed wrote:
in fact, it's better to don't use protected mode during boot process.
But then you can only access 640k tops, no more. Very likely a kernel compiled from a higher level language like Pascal is going to be bigger than that (especially if he wants to add a boot logo and console font too).

edfed wrote:
better to load a lot of stuff using bios and then, start the os
Yeah, but if the OS isn't DOS, then "starting the os" means the kernel's entry point expects protected mode or long mode in the first place, so mode switching has to implemented in the boot loader anyway.

(Alternatively one could add a trampoline code to the kernel, but that's very problematic linking-wise, not all toolchain supports that. It also ties you to the obsolete BIOS interface (you can forget about upgrading to UEFI later). And isn't always possible, as I've mentioned if the kernel doesn't fit into 7C00h - A0000h, then it's never going to work.)

Cheers,
bzt
Post 22 Mar 2023, 14:58
View user's profile Send private message Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 949
Location: Russia
macomics 22 Mar 2023, 17:40
Quote:
And isn't always possible, as I've mentioned if the kernel doesn't fit into 7C00h - A0000h, then it's never going to work.
Only you have a little more memory. You can use addresses 0x00600 .. { int 12h ~ ax * 1024 - 1 }
0x00000 .. 0x003FF - IDT
0x00400 .. 0x0052F - BIOS data
0x00530 .. 0x005FF - sector align
0x00600 .. { int 12h ~ ax * 1024 - 1 } - empty
{ int 12h ~ ax * 1024 } .. 0x9FFFF - Extended BIOS data (SMAP or its compilation program)
0xA0000 .. 0xAFFFF - video memory
0xB0000 .. 0xB7FFF - old text video memory
0xB8000 .. 0xBFFFF - text video memory
0xC0000 .. 0x.xxx - Video BIOS
0x.xxx+1 .. 0xEFFFF - Extended memory
0xF0000 .. 0xFFFFF - Main BIOS
0x100000 .. 0x1FFEF - HMA
0x100000 .. X - Expanded memory
Post 22 Mar 2023, 17:40
View user's profile Send private message Reply with quote
bzt



Joined: 09 Nov 2018
Posts: 77
bzt 23 Mar 2023, 05:51
macomics wrote:
Only you have a little more memory. You can use addresses 0x00600 .. { int 12h ~ ax * 1024 - 1 }
Not much, about 30k more. Accounted for in the 640k I wrote (640k is the theoretical maximum, in practice you're going to have less free memory than that: minus IVT, minus BDA, minus EBDA, minus your loader's code and data).
(If you wonder where that 640k comes from: real mode addressing uses segment addresses at every 16 bytes (shifted by 4 bits), and offsets with 16 bits. That's 20 bits in total, which is 2^20 = 1M, minus the VRAM and ROM area = 640k tops).

A viable workaround is to load a few sectors using BIOS into conventional memory (below A0000h), then temporarily switch to protmode, rep movs the loaded data into its final place (probably above 1M), and then switch back to real mode and go on as if no mode change happened.

Or the opposite: use protmode loader in the first place, temporarily switch to real mode to call BIOS and then switch back to protmode and copy the data. This is what I do, and it works well (note: the code I linked is a bit more complicated as it supports CD-ROMs and RAID disks too).

Cheers,
bzt
Post 23 Mar 2023, 05:51
View user's profile Send private message Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4334
Location: Now
edfed 23 Mar 2023, 14:09
the boot process is not the os initialization.

boot will just load stuff in lowmem using bios.
as bios is the only reliable thing on every pc.

uefi is not always there (old pc, pc104,...) , but nothing forbid you to make uefi bootloading.

when bootloader load all the necessary files, then, it passes the execution to the kernel entry.
and the kernel entry will be responsible to initialize all the stuff made by and for the OS.


bzt:
don't you think switching back to unrealmode can be better cause you can load files with bios, and copy them anywhere without returning to pm? i think it's better but maybe i'm wrong. maybe v86 is a good way too, as it can be called from pm and act like a sandbox.
Post 23 Mar 2023, 14:09
View user's profile Send private message Visit poster's website Reply with quote
bzt



Joined: 09 Nov 2018
Posts: 77
bzt 24 Mar 2023, 15:29
edfed wrote:
as bios is the only reliable thing on every pc.
uefi is not always there
Sadly the same goes for BIOS, Intel obsoleted the CSM compatibility layer a few years ago. https://arstechnica.com/gadgets/2017/11/intel-to-kill-off-the-last-vestiges-of-the-ancient-pc-bios-by-2020/

(I'm on Linus side on this debate, BIOS is so dummy, so limited, so simple and so early that nobody wants to use it for anything else than booting an OS and then get the hell out of there. UEFI on the other hand is a huge bloatware, full of security holes, easily expoilted and suffers from viruses, malware and rootkits. "Thankfully" it also provides a way to lift the malware into any kernel's address space in supervisor mode via the run-time services... Obsoleting BIOS won't make hardware really simpler as Intel claims, it just frees about 32k of ROM space, that's all, real mode circuits still needed in the CPU for backward compatibility.)

edfed wrote:
don't you think switching back to unrealmode can be better cause you can load files with bios, and copy them anywhere without returning to pm? i think it's better but maybe i'm wrong.
It definitely would be a better way. The problem with unreal is that it's a non-documented feature of the CPU, and therefore wasn't accounted for in the BIOS Boot Specification. Hence there's no guarantee that a certain BIOS implementation won't crash if you call its disk routines with unreal segments in the segment registers. It is also possible that it might just work, the problem is, you don't know, and you can't be sure what's going to happen. If you aim at VMs only, and you can test all possible VM BIOSes if they work with unreal then it's fine, but if you also want to support real hardware then you should avoid unreal (just to be on the safe side).

edfed wrote:
maybe v86 is a good way too, as it can be called from pm and act like a sandbox.
That's a viable way to go, yes. But I've found switching back to real mode is much easier (as the code is in a boot loader, it still has all the necessary things for real mode, IVT, BDA still untouched, no paging yet etc., so it is easier to just clear CR0 bit and load the segments than setting up v86 mode properly.)

Cheers,
bzt
Post 24 Mar 2023, 15:29
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page Previous  1, 2

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.