Who Uses GRUB?
-
- Member
- Posts: 2566
- Joined: Sun Jan 14, 2007 9:15 pm
- Libera.chat IRC: miselin
- Location: Sydney, Australia (I come from a land down under!)
- Contact:
Who Uses GRUB?
I just thought this would be interesting to find out how many use GRUB and how many use their own custom bootloader.
If you do write your own, post it's code for others to peruse.
If you do write your own, post it's code for others to peruse.
Re: Who Uses GRUB?
Now, who will be the first "courageous" person to offer the spoon-full of source codepcmattman wrote:I just thought this would be interesting to find out how many use GRUB and how many use their own custom bootloader.
If you do write your own, post it's code for others to peruse.
-
- Member
- Posts: 28
- Joined: Fri Feb 02, 2007 10:36 pm
I've gone for the 'use often' - I used to use my own boot loader as a learning excercise. Now I have done that, I've realised that GRUB is likely to be much more versatile than my own loader will ever be.
I am currently working on a second stage boot loader for my OS (does more with VESA, provides more information to the kernel, sets up paging, GDT and stack in the location I want etc...) which I hope to make fairly versatile - like with PDCLib where you just have to alter one header file to make it compatible with your own kernel. Oh - it also does COM debugging.
When I have a basic 'working unit' I'm happy with, I'll release the source and images as version 0.1 and see where it goes
Cheers,
Adam
I am currently working on a second stage boot loader for my OS (does more with VESA, provides more information to the kernel, sets up paging, GDT and stack in the location I want etc...) which I hope to make fairly versatile - like with PDCLib where you just have to alter one header file to make it compatible with your own kernel. Oh - it also does COM debugging.
When I have a basic 'working unit' I'm happy with, I'll release the source and images as version 0.1 and see where it goes
Cheers,
Adam
Hi,
I went for the "always write my own" option, although this isn't strictly correct...
My OS is designed for any number of different boot loaders, and for the last version of my OS I wrote a GRUB boot loader that ignores all the info GRUB supplied, switches back to real mode and restores the computer to the state my second stage expects. Eventually I'll probably port this to the new version of my OS.
IMHO this doesn't entirely count as "using" GRUB as most of the code is there to undo things GRUB did, and it's not intended as a "native" part of the OS - it's more like a compatability layer for situations where GRUB can't be easily removed (e.g. dual boot machines where someone elses OS uses GRUB).
Cheers
Brendan
I went for the "always write my own" option, although this isn't strictly correct...
My OS is designed for any number of different boot loaders, and for the last version of my OS I wrote a GRUB boot loader that ignores all the info GRUB supplied, switches back to real mode and restores the computer to the state my second stage expects. Eventually I'll probably port this to the new version of my OS.
IMHO this doesn't entirely count as "using" GRUB as most of the code is there to undo things GRUB did, and it's not intended as a "native" part of the OS - it's more like a compatability layer for situations where GRUB can't be easily removed (e.g. dual boot machines where someone elses OS uses GRUB).
Cheers
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
I think grub is a good program, and my kernel supports it. however, i have a custom bootloader which is much smaller which I use for floppy booting.
The reason for this is that i want to dual-boot with my own os, and grub would be the obvious way to do so.
So with the future in mind, I chose "often"
The reason for this is that i want to dual-boot with my own os, and grub would be the obvious way to do so.
So with the future in mind, I chose "often"
-
- Member
- Posts: 2566
- Joined: Sun Jan 14, 2007 9:15 pm
- Libera.chat IRC: miselin
- Location: Sydney, Australia (I come from a land down under!)
- Contact:
Re: Who Uses GRUB?
I get your point. This is my bootloader:SpooK wrote:Now, who will be the first "courageous" person to offer the spoon-full of source code
Code: Select all
; Mattise Boot Sector
; Assemble with NASM
bits 16
org 0x7C00
start: jmp short begin
nop
bsOEM db "Mattise1" ; OEM String
bsSectSize dw 512 ; Bytes per sector
bsClustSize db 1 ; Sectors per cluster
bsRessect dw 1 ; # of reserved sectors
bsFatCnt db 2 ; # of fat copies
bsRootSize dw 224 ; size of root directory
bsTotalSect dw 2880 ; total # of sectors if < 32 meg
bsMedia db 0xF0 ; Media Descriptor
bsFatSize dw 9 ; Size of each FAT
bsTrackSect dw 18 ; Sectors per track
bsHeadCnt dw 2 ; number of read-write heads
bsHidenSect dd 0 ; number of hidden sectors
bsHugeSect dd 0 ; if bsTotalSect is 0 this value is
; the number of sectors
bsBootDrv db 0 ; holds drive that the bs came from
bsReserv db 0 ; not used for anything
bsBootSign db 29h ; boot signature 29h
bsVolID dd 0 ; Disk volume ID also used for temp
; sector # / # sectors to load
bsVoLabel db "MATTISEOS " ; Volume Label
bsFSType db "FAT12 " ; File System type
begin: cli ; disable interrupts
mov [bsBootDrv],dl ; save drive number
mov ax,0x9000 ; put stack at 0x98000
mov ss,ax
mov sp,0x8000
mov cx,[bsTrackSect] ; update int 1E FDC param table
mov bx,0x0078
lds si,[ds:bx]
mov byte [si+4], cl
mov byte [si+9], 0x0F
sti ; enable interrupts
push ds
mov dl,[bsBootDrv] ; reset controller
xor ax,ax
int 0x13
pop ds
jc bootfail2 ; display error message
jmp _l1
bootfail2: jmp bootfail
_l1:
mov ax,0x0000
mov es,ax
mov ds,ax
mov si,MsgLoad ; display load message
call putstr
; find the root directory
xor ax,ax
mov al,[bsFatCnt]
mov bx,[bsFatSize]
mul bx
add ax,word [bsHidenSect]
adc ax,word [bsHidenSect+2]
add ax,word [bsRessect] ; ax holds root directory location
mov word [BootSig],ax
call checkroot
mov bx,word [bsVolID]
mov word [filesect],bx
xor ax,ax
add ax,word [start]
add ax,word [bsVolID] ; sector number
add ax,word [BootSig]
sub ax,2 ; correction for a mis-calc
mov cx,word [bsVolID+2] ; number of sectors
mov bx,0x8000
mov es,bx
nextsector: push ax ; save registers
push cx
push dx
push es
xor bx,bx ; set zero offset
call readsect ; read a sector
mov si,MsgDot ; display a dot
call putstr
pop es ; restore registers
pop dx
pop cx
pop ax
mov bx,es
add bx,20h ; increment address 512 bytes
mov es,bx
inc ax ; read next sector
loopnz nextsector
mov si,MsgComp ; display a dot
call putstr
mov ax,0x8000 ; set segment registers and jump
mov es,ax
mov ds,ax
push ax
mov ax,0
push ax
retf
checkroot:
push ax ; save registers
push bx
push cx
push dx
push si
push di
mov ax,0x8000 ; put root directory at 0x80000
mov es,ax
mov ax,32 ; AX = ((32*RootSize)/512) + 2
mul word [bsRootSize]
div word [bsSectSize]
mov cx,ax ; cx holds # of sectors in root
mov word [start],ax
mov ax,word [BootSig] ; get prev. saved loc. for root dir
r1: xor bx,bx
push cx ; save count
push ax ; save sector number
push es
push dx
call readsect
xor bx,bx
l_1: mov di,bx ; set address to check from
mov cx,11 ; check 11 bytes
mov si,FileName ; address of string to check with
repz cmpsb
je foundit
add bx,32 ; check next entry
cmp bx,[bsSectSize] ; end of sector?
je l_2
jmp l_1
l_2: pop dx ; restore registers
pop es
pop ax
pop cx
inc ax ; read next sector
loopnz r1
jmp bootfail
foundit: pop dx ; get these off the stack
pop es
pop ax
pop cx
mov di,0x1A ; get clustor #
add di,bx
push bx ; save bx for finding # of sectors
mov ax,[es:di]
xor bx,bx ; calculate sector #
mov bl,[bsClustSize]
mul bx ; ax holds sector #
mov word [bsVolID],ax
pop bx ; get location of directory entry
mov di,0x1C
add di,bx
mov ax,[es:di] ; put number of bytes in ax
xor dx,dx
mov bx,[bsClustSize] ; # of bytes / 512
div bx
inc ax
mov word [bsVolID+2],ax ; save number of sectors to load
pop di ; restore registers
pop si
pop dx
pop cx
pop bx
pop ax
ret ; return to caller
putstr: ; SI = address of string to display
lodsb
or al,al
jz short putstrd
mov ah,0x0E
mov bx,0x0007
int 0x10
jmp putstr
putstrd: retn ; return to caller
bootfail: ; display failure message
mov si,MsgBad ; display error message
call putstr
xor ax,ax ; wait for keypress
int 0x16
int 0x19 ; reboot
readsect: ; ES:BX = Location ; AX = Sector
mov si,[bsTrackSect]
div si ; divide logical sect by track size
inc dl ; sector # begins at 1
mov [bsReserv],dl ; sector to read
xor dx,dx ; logical track left in ax
div word [bsHeadCnt] ; leaves head in dl, cyl in ax
mov dh, [bsBootDrv] ;
xchg dl,dh ; head to dh, drive to dl
mov cx,ax ; cyl to cx
xchg cl,ch ; low 8 bits of cyl to ch, hi 2 bits
shl cl,6 ; shifted to bits 6 and 7
or cl, byte [bsReserv] ; or with sector number
mov al,1 ; number of sectors
mov ah,2 ; use read function of int 0x13
int 0x13 ; read sector
jc bootfail ; display error message
ret ; return to caller
FileName db "MATTISE COM"
MsgBad db "Couldn't boot!",13,10,0
MsgDot db ".",0
Newline db 13,10,0
MsgLoad db "Mattise Loading...",0
MsgComp db " Complete!",13,10,0
filesect dw 0
times 510-($-$$) db 0
BootSig db 0x55, 0xAA
Firstly, here is my multi-boot MBR so I can boot from more than a single partition, i actually use this on this machine, and it works great:
Ok, so now my boot loader has more than one part... the first part I replace depending on the file system/boot device,the second part doesn't change. First my Fat32 standard HD boot sector.
And, here is one for fat12/fat16 floppy disk or hard drive
And lastly is the include file that these both include (2ndStage.inc)
So, that's it, mbr is 512 bytes, boot loader is 1k no matter what boot medium (well, so far). It's still a work in progress, but works fine right now for what I'm doing. I need to do more work on the memory detection stuff, but other than that it is pretty much done.
Code: Select all
[bits 16]
[org 0]
jmp short Start
Choice
db '0' ;Default partition, set by fdisk type program!
Start:
;Setup our stack
xor eax, eax ;This is where we got loaded
mov ds, ax
mov es, ax
mov ax, 0x7c0 ;Right before boot sector!
mov sp, ax
;Lets copy ourself to another free location
mov si, 0x7c00 ;Were we are now
mov di, Location ;Move to our new location
mov ecx, 512/4 ;Total bytes to move
rep movsd
jmp 0:Reloaded+Location
Reloaded:
mov [BootDisk+Location], dl ;Store boot disk
mov si, BootMessage+Location
call PrintText
.AskAgain
xor edx, edx ;Partition zero
mov eax, Location+PartEntry+8 ;Start of partitions + LBA
mov [Location+PartEntry], dl
mov [Location+PartEntry+16], dl
mov [Location+PartEntry+32], dl
mov [Location+PartEntry+48], dl
.Again
mov ebx, [eax] ;LBA
cmp ebx, 0
je .NoPartition
call PrintNum
mov si, BootPart+Location
call PrintText
pusha
mov edx, ebx
call PrintNum
mov si, PartSep+Location
call PrintText
mov edx, [eax+4] ;Size in sectors
shr edx, 11 ;Divide by 2048 (*1024*1024/512, mb)
call PrintNum
mov si, PartEnd+Location
call PrintText
popa
.NoPartition
add eax, 16 ;Next...
inc dx
cmp dx, 4
jne .Again
mov bx, 182 ;10 seconds
; mov bx, 91 ;5 seconds
; mov bx, 9 ;1/2 second, just enough to see boot menu ;)
; mov bx, 46 ;2.5 seconds, just enough to see boot menu ;)
add bx, [0x46c] ;Bios clock!
.KeyWait
mov ah, 1
int 0x16
jnz .GetKey
cmp bx, [0x46c]
jge .KeyWait ;Still waiting...
mov al, [Choice+Location] ;Default partition
jmp .Default ;Default
.GetKey
xor ax, ax
int 0x16
call PrintChar
.Default
;Lets boot the partition now!
xor ecx, ecx
mov cl, al ;Get our choice
mov eax, Location+PartEntry
sub cl, '0' ;Now go from character to drive!
shl ecx, 4 ;Multiply by 16
add eax, ecx ;Move to the correct table
add eax, 8 ;Go to LBA of partition
mov ebx, [eax]
cmp ebx, 0
je .AskAgain
;Update our _lba to start of partition
mov [_lba+Location], ebx ;Put LBA of boot sector into _lba
;Write our MBR back out before reading the new one :)
sub eax, 8
mov dl, [BootDisk+Location]
mov [eax], dl ;Store our boot disk back into this
mov dh, 0 ;Head
mov cx, 1 ;Sector 1/Cylinder 0
mov ax, 0x0301 ;Write, 1 sector
mov bx, Location
int 0x13
;Reset drive
; mov ah, 0
; int 0x13
.ReadBootSector
;Lets use LBA
mov dl, [BootDisk+Location]
mov ah, 0x42 ;LBA read
mov si, _boot_lba+Location ;information block!
int 0x13
jc .ReadBootSector
mov dl, [BootDisk+Location] ;Let the bootsector know our boot drive
jmp 0:0x7c00 ;Jump to the boot sector where it thinks the bios loaded it ;)
;Inputs
; edx = value
PrintNum:
pusha
mov eax, edx
mov ebx, 10
xor ecx, ecx
.ValueToStack
xor edx, edx ;Zero out dx
div ebx
add dx, '0'
push dx
inc ecx ;Add to counter
cmp eax, 0
jne .ValueToStack
.PrintDecNext
pop ax
call PrintChar
loop .PrintDecNext
popa
ret
;Print char in al
PrintChar:
push ax
push bx
mov ah, 0x0e
mov bx, 0x07
int 0x10
pop bx
pop ax
ret
;si = message
PrintText:
push ax
.PrintNext
lodsb ;Load es:si into al
test al, al
jz .Done
call PrintChar
jmp .PrintNext ;Repeat
.Done
pop ax
ret
_boot_lba
db 0x10
db 0
_length
dw 1 ;1 sector
_location
dw 0x7c00
_segment
dw 0
_lba
dd 0 ;Sector to read, 4 bytes!
dd 0 ;Upper part of lba (8 bytes total!)
BootMessage
db 'PhatOS Multi Booter',13,10,0
BootPart
db '.) LBA ',0
PartSep
db ' Size : ',0
PartEnd
db 'mb',13,10,0
BootDisk ;Disk we booted from
db 0
Location equ 0x8000 ;Some random place out of the way
tick equ 0x46c ;Location of bios tick count!
PartEntry equ 446 ;Start of partition entries
times 446-($-$$) db 0 ;Up to boot sector info
times 510-($-$$) db 0 ;Up to boot signature
dw 0xaa55
Code: Select all
[bits 16]
[org 0x7c00]
jmp short Start ;0-2
nop
;Lets make our BPB
OEMName db 'PhatOS '
BytesPerSector dw 512 ;512 bytes is normal ;)
SectorsPerClustor db 1 ;Sector == cluster
ReservedSectors dw 1 ;Reserve the boot sector
FatCount db 1 ;1 copy of the fat (some things require this)
RootEntries dw 224 ;# of root entries
TotalSectors16 dw 0 ;# of sectors on the disk
MediaType db 0xF8 ;Ignored for most things
FatSize16 dw 0 ;Size of a single fat in sectors
SectorsPerTrack dw 0 ;Sectors Per Track
Heads dw 0 ;Head count
HiddenSectors dd 0 ;# of hidden sectors
TotalSectors32 dd 0 ;# of sectors, 32-bit!
;Fat32 section
FatSize32 dd 0 ;Size of a single Fat in sectors
ExtFlags dw 0 ;Used for mirroring, leave this alone
FSVersion dw 0 ;Our version is 0.0 :)
RootCluster dd 2 ;Cluster # of root, normally 2
FSInfo dw 0 ;Sector # of FS Info Block
BkBootSector dw 0 ;Backup boot sector... unused for us ;)
Reserved1 times 12 db 0 ;Reserved
DriveNum db 0 ;We don't care for this
Reserved2 db 0 ;Reserved
BootSig db 0x29 ;0x29 - next 3 things exist
VolumeID dd 0 ;Volume's ID, we don't care for it ;)
VolumeLabel db 'PhatOS ' ;11 bytes
FileSystem db 'FAT32 ' ;File system
Start:
cld
mov [BootDisk], dl ;Store boot disk
;Set up our stack at 0x07c0:0x0000 (goes downwards!)
xor ax, ax
mov ss, ax
mov es, ax
mov ax, 0x07c0
mov sp, ax
;Read our MBR to see what partition we booted from
mov eax, 0 ;MBR
mov bx, 0x1000 ;Random free address
mov cx, 1 ;One sector
call ReadSector
xor ecx, ecx
mov eax, 0x1000+446
;Lets determine boot partition + LBA
.CheckNext
cmp byte [eax], 0 ;Would be 0x80
jne .FoundBootPartition
inc cx
cmp cx, 4
je .DidntFindMBR
add eax, 16
jmp .CheckNext
.FoundBootPartition
mov [BootPartition], cl ;Store boot partition here...
mov ebx, [eax+8] ;Store into ebx
mov [PartitionLBA], ebx ;Store this here...
.DidntFindMBR
;Lets determine our Data Start now... based on params above :)
xor edx, edx
mov ebx, edx
mov eax, [FatSize32]
mov dl, [FatCount]
mov bx, [ReservedSectors]
or ax, [FatSize16]
mul dx
add eax, ebx
inc eax
mov [DataStart], eax ;This is our start sector of our kernel :)
;Lets load our second stage :)
mov eax, 1 ;Start of 2nd stage
mov bx, 0x7c00+512 ;Right after boot sector!
mov cx, 3 ;3 sectors
call ReadSector
jmp SecondStage ;Go to our second stage loader
BootDisk ;Disk we booted from
db 0
BootPartition ;Partition on disk we booted from (0xFF = no partitions!)
db 0xFF
PartitionLBA ;LBA of the boot partition
dd 0
SystemMemory ;Memory in bytes,4gb max
dd 0
;Read a sector from the boot disk/partition
;eax - sector to read
;bx - dest
;cx - length
ReadSector:
db 0x66
pusha
mov dl, [BootDisk] ;Use boot disk
add eax, [PartitionLBA] ;Start of partition
mov [_lba], eax ;Store linear block address
mov [_location], bx ;Store location
mov [_length], cx ;Length in sectors
mov ah, 0x42 ;Read function
mov si, _boot_lba ;Location of LBA block
int 0x13
db 0x66
popa
ret
_boot_lba
db 0x10 ;Size of lba block structure :)
db 0
_length
dw 0 ;Filled in from above!
_location
dw 0 ;4k page bounary
_segment
dw 0
_lba
dd 0 ;Sector to read, 8 bytes total!
dd 0
DataStart dd 0
times 502-($-$$) db 0 ;Last, enough for 4 entries :)
LoadEntries: ;Stores size of each file in sectors
times 510-($-$$) db 0
dw 0xaa55
%include '2ndStage.inc'
Code: Select all
[bits 16]
[org 0x7c00]
jmp short Start ;0-2
nop
;Lets make our BPB
OEMName db 'PhatOS '
BytesPerSector dw 512 ;512 bytes is normal ;)
SectorsPerClustor db 1 ;Sector == cluster
ReservedSectors dw 1 ;Reserve the boot sector
FatCount db 1 ;1 copy of the fat (some things require this)
RootEntries dw 224 ;# of root entries
TotalSectors16 dw 0 ;# of sectors on the disk
MediaType db 0xF8 ;Ignored for most things
FatSize16 dw 0 ;Size of a single fat in sectors
SectorsPerTrack dw 0 ;Sectors Per Track
Heads dw 0 ;Head count
HiddenSectors dd 0 ;# of hidden sectors
TotalSectors32 dd 0 ;# of sectors, 32-bit!
;Start of our Fat12/16 info
DriveNum db 0 ;Drive number (0x0x - floppy, 0x8x - hd
Reserved db 0 ;Reserved, set to 0
BootSig db 0x29 ;Set to 0x29 if next 3 values are present
VolumeID dd 0 ;Volume's ID, we don't care for it ;)
VolumeLabel db 'PhatOS ' ;11 bytes
FileSystem db 'FAT ' ;File system
Start:
cld
mov [BootDisk], dl ;Store boot disk
;Set up our stack at 0x07c0:0x0000 (goes downwards!)
xor ax, ax
mov ss, ax
mov es, ax
mov ax, 0x07c0
mov sp, ax
;Determine which read function to use...
test dl, 0x80 ;Hard Disk Bit?
jnz .KernelHD ;Lets use LBA if bit set
mov dword [ReadSectorFunc], ReadSectorFD
jmp DidntFindMBR
.KernelHD
mov dword [ReadSectorFunc], ReadSectorHD ;Use HD function
;Read our MBR to see what partition we booted from
mov eax, 0 ;MBR
mov bx, 0x1000 ;Random free address
mov cx, 1 ;One sector
call ReadSector
xor ecx, ecx
mov eax, 0x1000+446
;Lets determine boot partition + LBA
.CheckNext
cmp byte [eax], 0 ;Would be 0x80
jne .FoundBootPartition
inc cx
cmp cx, 4
je DidntFindMBR
add eax, 16
jmp .CheckNext
.FoundBootPartition
mov [BootPartition], cl ;Store boot partition here...
mov ebx, [eax+8] ;Store into ebx
mov [PartitionLBA], ebx ;Store this here...
DidntFindMBR:
;Lets determine our Data Start now... based on params above :)
xor edx, edx
mov ebx, edx
mov eax, edx
mov ecx, edx
mov cx, [RootEntries]
shr cx, 4 ;Divide by 16 to get # of sectors
mov dl, [FatCount]
mov bx, [ReservedSectors]
mov ax, [FatSize16]
mul dx
add eax, ebx
add eax, ecx
mov [DataStart], eax ;This is our start sector of our kernel :)
;Lets load our second stage :)
mov eax, 1 ;Start of 2nd stage
mov bx, 0x7c00+512 ;Right after boot sector!
mov cx, 1 ;1 sector
call ReadSector
jmp SecondStage ;Go to our second stage loader
BootDisk ;Disk we booted from
db 0
BootPartition ;Partition on disk we booted from (0xFF = no partitions!)
db 0xFF
PartitionLBA ;LBA of boot partition
dd 0
SystemMemory ;Memory in bytes,4gb max
dd 0
ReadSectorFunc
dd 0 ;Which read function to use
ResetDrive:
pusha
.Retry
mov ax, 0
mov dl, [BootDisk] ;Drive [BootDisk]
int 0x13
jc .Retry ;Didn't reset, lets try again
popa
ret
;Convert LBA -> CHS
;Inputs:
; eax - sector
; cx - length
; bx - destination
;Outputs: Standard CHS format
GetCHS:
xor edx, edx ;Zero out edx
div word [SectorsPerTrack]
mov cl, dl ;Sector # ?
inc cl
xor edx, edx
div word [Heads]
mov dh, dl ;Mov dl into dh (dh=head)
mov ch, al ;Mov cylinder into ch
;//??
shl ah, 6
or cl, ah
ret
;eax - sector to read
;bx - dest
ReadSingleSectorFD:
db 0x66
pusha
call GetCHS ;Grab our CHS
.Retry
call ResetDrive ;Get drive ready..
mov dl, [BootDisk] ;Grab our boot disk
mov ax, 0x0201 ;Read function, one sector
int 0x13
jc .Retry
db 0x66
popa
ret
;Floppy disk code
;eax - sector to read
;bx - dest
;cx - length
ReadSectorFD:
db 0x66
pusha
.ReadNext
call ReadSingleSectorFD
dec cx
jz .Done
add bx, 512 ;Next location..
inc eax ;Next LBA
jmp .ReadNext ;Keep reading
.Done
db 0x66
popa
ret
;Hard disk code
;eax - sector to read
;bx - dest
;cx - length
ReadSectorHD:
db 0x66
pusha
mov dl, [BootDisk] ;Use boot disk
add eax, [PartitionLBA] ;Start of partition
mov [_lba], eax ;Store linear block address
mov [_location], bx ;Store location
mov [_length], cx ;Length in sectors
mov ah, 0x42 ;Read function
mov si, _boot_lba ;Location of LBA block
int 0x13
db 0x66
popa
ret
ReadSector:
jmp [ReadSectorFunc] ;Jump to the correct function
_boot_lba
db 0x10
db 0
_length
dw 0 ;Filled in from above!
_location
dw 0x8000 ;4k page bounary
_segment
dw 0
_lba
dd 0 ;Sector to read, 8 bytes total!
dd 0
DataStart dd 0
times 502-($-$$) db 0 ;Last, enough for 4 entries :)
LoadEntries:
times 510-($-$$) db 0
dw 0xaa55
%include '2ndStage.inc'
Code: Select all
;Second Stage, completely I/O independant besides a few calls to first stage
[bits 16]
;Our 16-bit functions
A20Loop:
mov cx, 0x2000 ;8k tries!
A20Looper:
in al, 0x64
test al, 2
loopne A20Looper
ret
;Lets setup our new text mode before going to far... (80x50)
SetTextMode:
mov ax, 0x1112
xor bx, bx
int 0x10
mov word [0x60], 0x07 ;cursor to blank!
ret
EnableA20:
;Enable the A20 line
call A20Loop
jnz .EnableA20Done
mov al, 0xd1
out 0x64, al
call A20Loop
jnz .EnableA20Done
mov al, 0xdf
out 0x60, al
call A20Loop
.EnableA20Done
ret
;Print char in al
PrintChar:
push ax
push bx
mov ah, 0x0e
mov bx, 0x07
int 0x10
pop bx
pop ax
ret
PrintHex:
db 0x66
pusha
mov ecx, 8 ;8 values!
push word 13
push word 10
.ValueToStack
mov eax, edx
and eax, 15
shr edx, 4
cmp ax, 10
jl .Number
add al, 'A'-10-'0'
.Number
add al, '0'
push ax
loop .ValueToStack
push word 'x'
push word '0'
mov ecx, 12 ;8 values + CrLf + 0x
.PrintHexNext
pop ax
call PrintChar
loop .PrintHexNext
;This runs once ecx hits 0
db 0x66
popa
ret
;Create a memory mapping of the system!
FindMemory:
mov ax, 0xe801 ;Read system ram :)
xor ecx, ecx
xor edx, edx
int 0x15
shl ecx, 10 ;Multiply by 1024 to get MB's
;Returns 64kb blocks above 16mb into bx
shl edx, 16 ;Multiply by 16 to get MB's
add ecx, edx
cmp ecx, 0 ;Check if we have 0 bytes!
jne .MemGood
;Fallback?
mov ecx, 3*1024*1024 ;Assume 3mb + 1mb below = 4mb!
.MemGood
add ecx, 1024*1024 ;Tack on one extra meg since it only shows 15mb under 16mb!
mov [SystemMemory], ecx
ret
SecondStage:
call EnableA20 ;Enable our A20 line
mov ecx, 4
mov ebx, 0x9000
mov edx, LoadEntries
mov eax, [DataStart] ;Start sector of our kernel
.EntryLoop
push cx
mov cx, [edx] ;Sector count
cmp cx, 0
je .NothingThere
call ReadSector
.NothingThere
push edx
mov edx, eax ;LBA
call PrintHex
mov edx, ecx ;Sector Count
call PrintHex
pop edx
add eax, ecx ;Increment LBA...
shl cx, 9 ;Multiply by 512 to get byte count!
add bx, cx ;Move to next memory address
add edx, 2 ;Next entry
pop cx
loop .EntryLoop
;All 4 sections loaded...
;1 - Kernel
;2 - Memory Manager
;3 - Disk Driver
;4 - File System Driver
call SetTextMode ;Set our new text mode
call FindMemory ;Find the amount of memory we have in the system
;Lets get into 32-bit mode now
;Next thing is get into 32-bit mode
lgdt [gdt_desc]
cli ;Clear interrupts before we switch to 32-bit mode
mov eax, cr0
inc eax
mov cr0, eax
jmp 0x8:Go32 ;Jump to 32-bit code
[bits 32]
Go32:
mov eax, 0x10
mov ds, eax
mov es, eax
mov gs, eax
mov fs, eax
mov ss, eax
mov esp, 0x7000 ;Put stack right before some stuff :)
;Now lets enable paging...
;We're currently at 0x9000, we want to first map the bottom 1mb of memory...
;Mark each of these as completely available, but not loaded yet...
mov edi, Kern_PDE ;Kernel base :)
call SetAllAvailable
mov edi, Kern_PTE ;Kernel space :)
call SetAllAvailable
xor eax, eax ;Virtual Address
mov ebx, eax ;Physical Address
mov ecx, 256 ;Map only first 1mb
mov edx, Tmp_PTE ;Used to map lower 1mb
call MemoryMap ;Map this area :)
mov eax, 0xF0000000 ;Virtual address
mov ebx, 0x7000 ;Kernel address - 4k for functions + 4k for IDT
mov ecx, 64 ;First 256kb memory mapped
mov edx, Kern_PTE ;PTE to map kernel space
call MemoryMap
;Now lets map ourself
mov dword [Kern_PDE+0xDFC], Kern_PDE+3 ;Set it to itself!
mov eax, Kern_PDE
mov cr3, eax
mov eax, cr0
or eax, 0x80000000 ;Enable paging
mov cr0, eax
mov dl, [BootDisk]
mov dh, [BootPartition]
mov eax, [SystemMemory]
jmp 0xF0002000 ;Jump to kernel code at 0xF0000000
;edi = PDE/PTE to set!
SetAllAvailable:
mov eax, 0x200 ;Available, but not loaded
mov ecx, 1024 ;1024*4 = 4k
rep stosd
ret
;Memory map a 4mb region (not present)
;eax - virtual location, must be 4mb aligned
;ebx - physical memory to map, must be 4kb aligned
;ecx - number currently present
;edx - location of PTE
MemoryMap:
pusha
shr eax, 20 ;Divide by 1mb (divide by 4mb and mult index by 4)
add eax, Kern_PDE ;Add base address of PDE
mov [eax], edx ;Set the PDE entry to point to PTE
or byte [eax], 3 ;Set up for supervisor r/w
or ebx, 3 ;Set it up for supervisor : read/write present
.Loop
mov [edx], ebx ;Store the address here
add ebx, 4096 ;Next physical address
add edx, 4 ;Next entry
loop .Loop
popa
ret
Kern_PDE equ 0xC000 ;Location of first PDE
Kern_PTE equ 0xD000 ;First 4mb of kernel
Tmp_PTE equ 0xE000 ;PTE to map bottom 4mb
KernelPages dd 0 ;# of pages used for kernel/base drivers
gdt: ; Address for the GDT
gdt_null: ; Null Segment
dw 0
dw 0
db 0
db 0
db 0
db 0
gdt_code: ; Code segment, read/execute, nonconforming
dw 0xFFFF
dw 0
db 0
db 10011010b
db 11001111b
db 0
gdt_data: ; Data segment, read/write, expand down
dw 0xFFFF
dw 0
db 0
db 10010010b
db 11001111b
db 0
gdt_end: ; Used to calculate the size of the GDT
gdt_desc: ; The GDT descriptor
dw gdt_end - gdt - 1 ; Limit (size)
dd gdt ; Address of the GDT
times 1024-($-$$) db 0
- beyondsociety
- Member
- Posts: 39
- Joined: Tue Oct 17, 2006 10:35 pm
- Location: Eagle, ID (USA)
- Contact:
When I first started my operating system I went for writing my own custom bootloader as a learning process. In later versions, I decided to use grub as the bootloader simply because I had problems with my bootloader not working right with the kernel and wanted to move onto other things. For my current re-write of my os Im not sure if I will use grub or not, it depends on what design and architectures I decide to support. So I voted for using grub once or twice in my os.
For Xenon, I'm just using grub. For plan10 (a remake of plan9 on the SPARC64), I'm rolling my own due to a lack of a choice. Fortunately, I have 7.5K to play with, and the openprom actually is useful, which makes it easier.
My project: Xenon
i prefer to write my own boot system
i wont post my current code, since im in the midst of a complete rewrite, but basically, my boot-sector parses the FAT file system to find the 2nd stage, and my 2nd stage uses the routines from the bootsector (my 2nd stage never needs to know what filesystem is in use, or what disk is being booted)
currently i only boot FAT12/16/32, but this system should allow easy booting on a number of different filesystems without modifying the 2nd stage
i wont post my current code, since im in the midst of a complete rewrite, but basically, my boot-sector parses the FAT file system to find the 2nd stage, and my 2nd stage uses the routines from the bootsector (my 2nd stage never needs to know what filesystem is in use, or what disk is being booted)
currently i only boot FAT12/16/32, but this system should allow easy booting on a number of different filesystems without modifying the 2nd stage