new on board, and question on bootloading and bios

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

new on board, and question on bootloading and bios

Post by h0bby1 »

hi all :)

i started to make my os some 1 year ago, it's already at a fairly advanced stage, it can handle pci, usb (only hid for now), vesa/vga, image decompression and filtering, my own ABI that support dynamic linking, audio drivers and network througth ndis interface, file system basics, memory allocation and ttf font and it already has a nice set of feature for the moment

it use protected mode with segment, not the virtual paging mode, like this i can have physical address= virtual address at least for the kernel space, which can be rather handy to handle dma transfer, security is not a big issue for me for the moment, and i can always handle the old fahsioned multi tasking with segment/lgdt if i need securised process handling

now the first thing i'd ask is on the boot loader stage, i'm sure there are plenty of good article about on there, and i already have browsed this forum and the wiki for quite some time and didn't find a general outlook on this

the thing is i wonder mostly is how to handle properly the first stage of image loading, i'd rather not use a second stage boot loader, and for the moment the boot loader parse all drive and read the kernel from an iso file system present on one of the drive the bios can access , then load the kernel in memory

the problem is that the kernel then need to access the filesystem from the protected mode, and it's here i'm a bit wondering how to do this properly without if possible a second stage boot loader

for now the kernel use the bios int13 function from protected mode to load the iso image from the disk in memory, the whole iso is about 1Mo, and it's read at the beginning of the kernel loading process, so it's not big deal to load it entierly as a ram disk using bios int 13, the boot loader handle lba/chs mode with the good sector size, and there is no interupt or anything going on at this stage, technically the bootloader can boot from a floppy and autodetect the iso on another floppy or cdrom drive, but it's still too big to be loaded entierly from the real mode in the first stage boot loader, for now it just load the kernel from it and then jump to it

another option could be to do like in linux, to include all the necessary drivers files as binaries in the kernel to be loaded directly from the boot stage, and then initializing the devices needed to handle the disk drives, but currently the bus device drivers loading system use the file system to scan a folder to find all the drivers for a particular bus (usb, pci etc), and it's not designed to be able to use drivers included as binaries in the kernel, or maybe a reduced subset of drivers present on the iso could be loaded somewhere in the real mode memory before the switch to protected mode, but it would need some kind of organisation to be able to match the drivers loaded like this with a bus type, which is not really handled for the moment, as the bus drivers just scan the folder of the file system to find all drivers, and even so it's not that much a good solution if i need to load all the kernel directly from the first stage boot loader as size is an issue, even if for now the whole kernel is about 400k un compressed (including the libc, zlib and a lib for base system things ,it can load dynamically linked exectuable with my own ABI), and i guess the whole thing of the bus mannager, pci and usb bus drivers, and a reduced subset of device drivers like uhci/ohci/ata could fit in the real mode memory, but i'd rather avoid to have drivers included directly as binaries in the kernel

i'd rather avoid a second stage boot loader for many reason, because it make duplicate for all the code for device scan, because second stage boot loader are not that much reliable in case disk change of address or other, i don't really like the way grub and lilo works, and i don't want to have 3 kind of boot loader like iso linux, grub or other to handle different kind of booting mode which i can already do with only a first stage boot loader, the only problem is that it can only load limited amount of data from real mode, and that the kernel then need to either use bios funcs or i need to find a system to be able to load the iso where the drivers are from a disk from a kernel that has to be loaded in real mode memory

first i wonder if there is a major drawback about using bios function from protected mode, given it's mostly to load the iso image as a ramdisk at the first stage of the kernel intialisation, that there is no relevant interuption running at that moment, i know bios can be pretty buggy, and can be also hell to debug, but there are already some pretty good docs documenting all the bugs and possible quirk for different bioses, for just basic sector reading, provided the switch to 16 bit real mode and the pic is programmed correctly before each call it shouldn't be a problem ? i have a problem with this routine on some version of virtual box and bochs, it work fine on some version of virtual box and qemu and on real hardware, so i don't know if i'm doing something wrong there, or if there is really a major reason not to use the bios int 13h func at least in the first stage, to load the base image into protected mode memory

here is the base of the code to call a bios interupt from protected mode

even if it's slow as hell, i don't really care cause it's only to be used at the very first stage, and there is nothing else going on at the same time, and it's just to load a few megs from a cdrom or usbkey or whatever other media the iso containing the drivers are on, the corresponding code segment ( 0x30 ) is set with the 16 bit flags and start at 0x10000 which is the address at which the kernel is loaded, so i can easily translate address from 32 bits protected mode to 16 bit real mode and vice versa, normally it's supposed to work and it works fine, but it doesn't seem to work on boschs and some version of virtual box for some reason

Code: Select all

%define kern_base 0x10000
%define kern_org  0x10000
%define start_seg 0x00000

%define addr_to_real_mode  +start_seg
%define real_mode_to_addr  -kern_org

[BITS 16]
save_eax:dd 0

test_fn_16bits:

	
	push eax
	mov eax,cr0
	and	 ax ,~1
  	mov	cr0, eax		; PE set to 0 (CR0)

	mov 	ax ,	0x1000
	mov	ds ,	ax
	mov 	es ,	ax	
	pop eax
	
  	mov	[save_eax real_mode_to_addr],	eax	
	
 	xor     ax ,	ax
	mov	 ss ,	ax
 	mov	esp ,	0xFFFF
	
 	mov eax	,	[save_eax real_mode_to_addr]
	
 	jmp word 0x1000:(here_bios_call real_mode_to_addr)
 	here_bios_call:
	
 	pushf
	push	word 0x1000
	 push	word (addr_ret real_mode_to_addr)
 	jmp far [addr_real_mode_interupt real_mode_to_addr]
			
	addr_ret:

 	pushfd
 	pop	dword [cpu_eflags real_mode_to_addr]
	mov [ret_ax real_mode_to_addr],ax	
	
	 mov eax,cr0
 	or  ax ,1
	 mov cr0,eax		; PE mis a 1 (CR0)
		
 	mov ax	,	0x10		; segment de donne
	mov es	,	ax
 	mov ds	,	ax

	jmp	dword 0x08:(fn_here)
ret


[BITS 32]

call_real_mode_interupt_vector_c:
	
	;pushf
	;pop dword[flags_save]
  	
  	cli
  	
  	pusha
		call	 _init_pic_real_mode
		lidt	[orig_idt]
    popa
 
	jmp 0x08:testttt
    testttt:    
    
 	mov [safe_esp],esp
	mov esp,0xFFFF
	
	jmp dword 0x30:(test_fn_16bits real_mode_to_addr )
	fn_here:

	mov	ax	,	0x18
	mov	ss	,	ax
	mov esp	,	[safe_esp]		
			
	
	lidt [idtptr]
	jmp 0x08:testtttt
    testtttt:
      
    pusha
	call  _init_pic
    popa
	
	push	dword [cpu_eflags]
	popfd
	
	;test word[flags_save],(1<<9)
	;jz bios_call_no_sti
	;	sti
	;bios_call_no_sti:
ret

load_real_mode_interupt_vector_c:
	
	mov	ax							,0x40
	mov	ds							,ax
	mov eax							,[esp+4]		;interupt number
	shl eax							,2
	add eax							,[orig_idt+2]			; (start of vector list)

	mov	ebx							,dword [eax]
	;shl ebx						,4	
	;and ebx						,0x0FFFFFFF
	
	mov	ax							,0x10
	mov	ds							,ax	
	
	mov	[addr_real_mode_interupt]	,ebx
	mov  [addr_real_mode_int]		,ebx
	
	;mov esi		,text_load_i			
	;call _draw_cars
	
	;mov ecx,[addr_real_mode_interupt]
	;call _draw_dword_hex

	;mov edx		,' '
	;call _draw_car
	
	;mov ecx,[addr_real_mode_int]
	;call _draw_dword_hex
	
	;mov edx		,10
	;call _draw_car
	
	
ret





here is the code for the bootloader for now, it scan all drive first sectors to find an iso , not sure if it's 100% compliant or if there can be some bug in the way i handle some things, i just past it like that, normally it's supposed to work ok to scan an iso present on any drive the bios can handle and load the kernel from it, it's pretty tightly packed for the 512 bytes but it should do the job

it use addresses that are beyond the 512 bytes for unitinalized data, it should point to the memory area after the place where the bios loaded the bootloader , i hope it's not supposed to be an issue, it's not supposed to be loaded as part of the image, but just pointers to data in the area after the place where the bootloader has been loaded, because there is not a single byte free anymore, and everything is packed as much as i can, if someone know how to reduce the code size of this i take :) the more space = more room for test/check and debugging

Code: Select all


[BITS 16]
[ORG 0x0]
%define BIOS_START_ADDR 0x7C00
%define BIOS_START_SEG  (BIOS_START_ADDR>>4)


start_boot:
	mov ax ,BIOS_START_SEG	; 0x07C0
	mov ds ,ax
	mov es ,ax
	mov [BOOT_DEVICE],dl
	
	mov ax ,0x0000	; setup stack
	mov ss ,ax
	mov sp ,0x1000

	mov ax,03H
	int 10H

	;mov  al,'1'
	;call print_message_bios

	;reset disk
    xor ax    ,ax
    xor dx    ,dx
    int 13h
    
    
    loop_dsk:

		;-----------------------------------------
		;test for lba device
		;-----------------------------------------
		mov ah,41h
		mov dl,[BOOT_DEVICE]
		mov bx,0x55AA
		int 13h
		
		jc no_ext_lba
		;cmp bx,0xAA55
		;jne no_ext_lba
		test cx,1
		jz no_ext_lba
		
			;-----------------------------------------
			;get lba sector size
			;-----------------------------------------					
			mov ah,48h
			mov dl,[BOOT_DEVICE]
			mov si,data_available
			int 13h
			
			mov ax,[data_available+18h]
			mov word [sector_size]	,ax
			
			mov byte [has_lba]		,1
			
		jmp short geom_done
		no_ext_lba:
			;-----------------------------------------
			;chs device
			;-----------------------------------------
				
			mov word [sector_size]	,512
			mov byte [has_lba]		,0
			
			;-----------------------------------------
			;get chs disk geometry
			;-----------------------------------------			
			xor ax,ax
			mov es,ax
			xor di,di
			mov ah,0x08
			mov dl,[BOOT_DEVICE]
			int 13h
			jc	next_disk
			
			test cl,cl
			jz next_disk
			
			;-----------------------------------------
			;store result
			;-----------------------------------------		
						
			inc dh
			mov			[disk_nhds] ,dh
			
			mov [disk_ncyls]		,ch
			
			mov al,cl
			
			and al					,0x3F
			mov [disk_nsecs]		,al

			shr cl					,6
			mov [disk_ncyls+1]		,cl
			
			inc word [disk_ncyls]
				
			mov	al		,dh
			mul	byte [disk_nsecs]	
			mov [disk_hdsec],ax
	
		geom_done:
		
		;------------------------------------------------------------
		;check for iso file system at sector [iso_start]
		;------------------------------------------------------------		

		xor ax,ax
		mov word [iso_start],ax
		mov cx,2
			
		next_iso_test:
		
			call parse_iso
			test al,al
			jnz iso_found
			inc byte [iso_start]
		
		loopnz next_iso_test
			
		next_disk:
		
		inc byte[BOOT_DEVICE]
	jmp loop_dsk
	
	iso_found:
	
	;mov  al,'2'
    ;call print_message_bios
   
    mov word [jmp_addr+0]	,0x0
    mov word [jmp_addr+2]	,0x1000
    
    mov dl,[BOOT_DEVICE]
    jmp far [jmp_addr]
    
    




read_disk_sec:
	push es
	
	movzx  eax	, word [esp+4]
	
	add	   ax	, [iso_start]
	
	test  byte [has_lba],1
	jz  read_no_lba
		mov dl				,[BOOT_DEVICE]
		xor ecx,ecx
		
		push ds	
		push ecx
		push ecx
		push ecx
		push dword eax
		push word es
		push word bx
		push word 1
		push word 18h
		
		retry_lba:
		
			mov ax	,	ss
			mov	ds	,	ax
			mov si	,	sp
				
			mov ah	,	0x42			;read sector
			int 13h
		jc retry_lba
		
		add sp	,	24
		pop ds
	
	jmp short read_disk_done
	read_no_lba:

		;LBA = ( (cylinder * heads_per_cylinder + heads ) * sectors_per_track ) + sector - 1
		;cylinder = LBA / (heads_per_cylinder * sectors_per_track)
		;temp = LBA % (heads_per_cylinder * sectors_per_track)
		;head = temp / sectors_per_track
		;sector = temp % sectors_per_track + 1


		push	bp
		sub		sp,4
		mov		bp,sp
		
		xor		dx,dx

		div word [disk_hdsec]
		mov [bp]	,	ax			;cylinder

		mov ax		,	dx	
		div byte	[disk_nsecs]
		mov [bp+2]	,	al			;head
		
		inc ah
		mov [bp+3]	,	ah			;sector
		
		
		
		;- the parameters in CX change depending on the number of cylinders;
		;  the track/cylinder number is a 10 bit value taken from the 2 high
		;  order bits of CL and the 8 bits in CH (low order 8 bits of track):

		;  |F|E|D|C|B|A|9|8|7|6|5-0|  CX
		;   | | | | | | | | | |	`-----	sector number
		;   | | | | | | | | `---------  high order 2 bits of track/cylinder
		;   `------------------------  low order 8 bits of track/cyl number		
		
		retry_chs_read:	
			mov ah,2				;read sector
			mov ch,[bp]				;cyl number
			mov dh,[bp+2]			;head number
			mov cl,[bp+3]			;sector number
			mov dl,[BOOT_DEVICE]	;drive number
			mov al,1				;read 1 sector
			int 0x13	
		jc retry_chs_read
	
		add sp,4
		pop	bp
	
	
	read_disk_done:	
	
	pop es
ret 2

iso_to_hard_sec:
	cmp word [sector_size],512
	jne	read_sec_has_2048
		shl  ax,2
	read_sec_has_2048:
ret



parse_iso:
		
	push cx
	push es

	
	;-----------------------------------------------------------------
	;setup pointer to target memory
	;-----------------------------------------------------------------

	mov ax			, 0x1000
	mov es			, ax
	xor bx			, bx
	
	;-----------------------------------------------------------------
	;setup stack space
	;-----------------------------------------------------------------
	sub sp	,	16
	mov bp	,	sp
		

	;bp + 0 (word) => kern_file_start
	;bp + 2 (dword)=> kern_file_size
	;bp + 6 (word)=> cnt
			
	;-----------------------------------------------------------------
	;read file system entry
	;-----------------------------------------------------------------
			
	mov  ax,16
	call iso_to_hard_sec
		
	push  ax
	call  read_disk_sec
			
	xor al,al
	cmp word[es:1],0x4443
	jne end_loop_entries

	;128	=	volume size ofset
	;mov eax				, [es:128]
	;mov [volume_size]		, eax
	;mov [bp]				, eax

	;158	=	root entry ofset
	;mov ax					, [es:158]
	;shl eax					, 11
	;mov [ss:bp+4]			, eax
	;mov [root_entry_ext]	, eax
		
	;158+8	=	root entry size
	;mov eax					,[es:158+8]
	;mov [root_entry_sz]		,eax
	;mov [ss:bp+8]				,eax

	;-----------------------------------------------------------------
	;read root entry
	;-----------------------------------------------------------------
	xor bx			, bx

	mov  ax,[es:158]
	call iso_to_hard_sec
				
	push ax
	call  read_disk_sec
			
	;-----------------------------------------------------------------
	;parse root childs entry
	;-----------------------------------------------------------------
	xor di	,di
	loop_entries:
		
		xor     al,al
		cmp		byte [es:di], 0x00
		je		end_loop_entries
			
		test	byte[es:di+25],0x02
		jnz	not_file
		
			;-----------------------------------------------------------------
			;read file
			;-----------------------------------------------------------------
			
			mov ax					, word[es:di+2]
			call iso_to_hard_sec
			mov [bp]				, ax
		
			mov eax					, dword[es:di+10]
			shr eax					, 9
			inc ax
			mov [bp+2]				, ax
									
			mov	word [bp+6]			, 0
				
			loop_load_kern:
							
				mov     dx  ,  [bp+2]
				mov		ax	,  [bp+6]
				mov		bx  ,	ax
				
				cmp word [sector_size]	, 512
				jne	read_kern_has_2048_sec
					shr ax	,7			;128 sectors	= 1 segment (65536/512)
					and bx , 0x7F		;sector ofset
					shl bx , 9
					jmp short read_kern_sec_done
				read_kern_has_2048_sec:
					shr ax	,5			;32 sectors		= 1 segment (65536/2048)
					and bx , 0x1F		;sector ofset
					shl bx , 11	
					shr dx , 2
				read_kern_sec_done:
				
				shl ax	   , 12				;es = segment * 4096	 (segment * (65536/16) )
								
				add ax	   , 0x1000
				mov es	   , ax
				
				mov [bp+8] , dx

				push word [bp]
				call  read_disk_sec

				inc	word [bp]
				inc	word [bp+6]
				
				mov ax,word [bp+6]
								
			cmp ax,[bp+8]
			jl loop_load_kern
			
			mov al,1
			jmp	short end_loop_entries
		
		not_file:

		movzx	bx	,byte [es:di]
		add		di	,bx
	jmp short loop_entries
	
	end_loop_entries:
	
	add sp	,	16
	pop es
	pop cx
	
ret


;print_message_bios:
;   mov bl,7
;   mov ah,0eh
;   int 10h
;ret

the_end:
	

TIMES 510-($-$$) DB 0	
dw 0xAA55

BOOT_DEVICE :db 0

sector_size		:dw 0
iso_start		:dw 0
has_lba			:db 0
disk_nhds		:db 0
disk_nsecs		:db 0
disk_ncyls		:dw 0
disk_hdsec		:dw 0
jmp_addr		:dd 0

data_available	:

TIMES 1024-($-$$) DB 0	
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: new on board, and question on bootloading and bios

Post by egos »

Hi,
h0bby1 wrote:the thing is i wonder mostly is how to handle properly the first stage of image loading, i'd rather not use a second stage boot loader, and for the moment the boot loader parse all drive and read the kernel from an iso file system present on one of the drive the bios can access , then load the kernel in memory

the problem is that the kernel then need to access the filesystem from the protected mode, and it's here i'm a bit wondering how to do this properly without if possible a second stage boot loader

for now the kernel use the bios int13 function from protected mode to load the iso image from the disk in memory, the whole iso is about 1Mo, and it's read at the beginning of the kernel loading process, so it's not big deal to load it entierly as a ram disk using bios int 13, the boot loader handle lba/chs mode with the good sector size, and there is no interupt or anything going on at this stage, technically the bootloader can boot from a floppy and autodetect the iso on another floppy or cdrom drive, but it's still too big to be loaded entierly from the real mode in the first stage boot loader, for now it just load the kernel from it and then jump to it

another option could be to do like in linux, to include all the necessary drivers files as binaries in the kernel to be loaded directly from the boot stage, and then initializing the devices needed to handle the disk drives, but currently the bus device drivers loading system use the file system to scan a folder to find all the drivers for a particular bus (usb, pci etc), and it's not designed to be able to use drivers included as binaries in the kernel, or maybe a reduced subset of drivers present on the iso could be loaded somewhere in the real mode memory before the switch to protected mode, but it would need some kind of organisation to be able to match the drivers loaded like this with a bus type, which is not really handled for the moment, as the bus drivers just scan the folder of the file system to find all drivers, and even so it's not that much a good solution if i need to load all the kernel directly from the first stage boot loader as size is an issue, even if for now the whole kernel is about 400k un compressed (including the libc, zlib and a lib for base system things ,it can load dynamically linked exectuable with my own ABI), and i guess the whole thing of the bus mannager, pci and usb bus drivers, and a reduced subset of device drivers like uhci/ohci/ata could fit in the real mode memory, but i'd rather avoid to have drivers included directly as binaries in the kernel
Boot Spec. that I use natively requires to load two files into base memory and to run the first of them in RM. When kernel is booting (stage 2 is booting by the same way) the first file contains the kernel (including some basic drivers), and the second file contains boot device and FS driver (it's a usual PM driver except that it should hold all that is necessary to load all other data).
i'd rather avoid a second stage boot loader for many reason, because it make duplicate for all the code for device scan, because second stage boot loader are not that much reliable in case disk change of address or other, i don't really like the way grub and lilo works, and i don't want to have 3 kind of boot loader like iso linux, grub or other to handle different kind of booting mode which i can already do with only a first stage boot loader, the only problem is that it can only load limited amount of data from real mode, and that the kernel then need to either use bios funcs or i need to find a system to be able to load the iso where the drivers are from a disk from a kernel that has to be loaded in real mode memory
Usually I use stage 2 only for "Multiple versions on single volume" configuration. I don't need to load large amount of data in RM. My kernel still is too small. When system files will not fit in base memory I will split the kernel into two parts. The first part will be loading by the loader, the second part will be loading by the first part using the boot driver. I don't try to use storage devices/file systems that are not supported by my system natively. My kernel has Multiboot entry point. It can be loaded by syslinux as well using mboot module.
first i wonder if there is a major drawback about using bios function from protected mode, given it's mostly to load the iso image as a ramdisk at the first stage of the kernel intialisation, that there is no relevant interuption running at that moment, i know bios can be pretty buggy, and can be also hell to debug, but there are already some pretty good docs documenting all the bugs and possible quirk for different bioses, for just basic sector reading, provided the switch to 16 bit real mode and the pic is programmed correctly before each call it shouldn't be a problem ? i have a problem with this routine on some version of virtual box and bochs, it work fine on some version of virtual box and qemu and on real hardware, so i don't know if i'm doing something wrong there, or if there is really a major reason not to use the bios int 13h func at least in the first stage, to load the base image into protected mode memory
I think to use BIOS in this way is not a good practice. As I said above I don't try to use storage devices that are not supported by my system natively.
If you have seen bad English in my words, tell me what's wrong, please.
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: new on board, and question on bootloading and bios

Post by h0bby1 »

ultimatly i want to code at least ata drivers, and the scsi commands as apparently they are used for usb mass storage device, as i already have the drivers to handle usb controller, but the good thing about the bios is that it can handle all the controller of the mother board, so in a way it can be more reliable to handle sata drivers, i still remember in the days when one had to install windows on a sata drive, the user had to supply a driver disk with the sata driver during the installation process, if they would have used the bios, they could make it work without having the need for any drivers, and i want reliable disk loading function at least for the first steps to load base image in protected mode without space restriction, who can load from any drive that are present on the mother board, then after using the drivers for the drives that they can handle, and leaving the rest to bios

the thing is i really want to avoid any kind of installation process, other than just burning a bootable iso, or writing the boot sector and the iso image on a drive, and systems like grubs are not that much trivial to install, specially from windows, or macos, so if i want to distribute the os a minimum, i don't think requiring that the user has to install and configure grub or lilo or isolinux to be able to run it, it's no go, and misuse of grub could result in pretty bad thing like the computer could not boot anymore, or i would need to give a sort of installer to setup grub/lilo which would need to work from all os, and could result in the computer being unable to boot, having it compatible with grub and lilo could be a good think for multiple boot thougth, but the way i see it, it would not require lot of disk access outside of the read only ram disk, and could be run more or less as a live disk, even if disk could be used to store some setting or configuration, i'd rather avoid it a maximum exept for storing user data

and it would be better if drivers can be changed/updated without having to recompile anything, just by adding or removing files from the iso which can be done easily with many tools, and being able to change all drivers including pci bus management, ata or usb drivers without recompiling the kernel and just updating the drivers on the iso, but the catch is that without the bios it need those drivers who are on the disk to read the disk
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: new on board, and question on bootloading and bios

Post by egos »

h0bby1 wrote:the thing is i really want to avoid any kind of installation process, other than just burning a bootable iso, or writing the boot sector and the iso image on a drive...
I use similar approach. User may separately prepare system disk (this is optional), install boot loader, select and copy boot driver, copy all other files. But setup tool allows to make this simpler.

I can use modified GRUB as one of my second stage boot loaders. I just install stage 1, then I copy stage 2.
If you have seen bad English in my words, tell me what's wrong, please.
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: new on board, and question on bootloading and bios

Post by h0bby1 »

a second stage bootloader could have many advantage, if a second stage boot loader could run in real mode to handle the zlib or lza compression, i believe some version of lza can be found for 16 bits real mode, and then loading the kernal and a compressed filesystem in real mode memory with some base drivers to handle disk and file systems to be loaded by the kernel, or either it would need the second stage to run already in protected mode and being able to load and use the drivers , but then either it would need a sort of api for that the kernel can still access the structure the second stage has initialized, like pci bus tree and the drivers and device it has initialized, or otherwise it would require the whole pci scan and device reset and scan would be done entierly twice, once from the second stage loader, and then all over again when the kernel actually boot, or the kernel would need to have a way to access the structure of the second stage loader

other options would be that i make two iso, a first iso with only the minimum drivers and the kernel who would fit in the real mode memory, the first stage bootloader would load the whole iso and then jump at the address of the kernel file, and then the kernel could initialize the iso filesystem directly from memory, load the dirvers on it, and then the rest of the drivers and system file would be loaded with protected mode drivers from another filesystem, but then the kernel would not be loaded at a fixed address, or then loading the kernel and the small iso seperatly from the main iso who would contain the small iso as a file to be loaded in real mode memory with the bootloader

or either that the kernel file on the main iso would include this minimal iso as binary data, so there would be the main iso with the kernel binary who include this iso in it, but it would need to recompile the kernel or to alter the kernel binary to change files in this iso, and same the kernel with the iso would have to fit in real mode memory to be loaded by the bootloader, but it would have the disavantage to have the drivers scattered on two different filesystem,but it could be mannaged this way, and still limit on size for that a kernel loaded in real mode memory by first stage boot loader could have all it need to be able to read the rest of the os from another disk
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: new on board, and question on bootloading and bios

Post by egos »

h0bby1 wrote:a second stage bootloader could have many advantage, if a second stage boot loader could run in real mode to handle the zlib or lza compression, i believe some version of lza can be found for 16 bits real mode, and then loading the kernal and a compressed filesystem in real mode memory with some base drivers to handle disk and file systems to be loaded by the kernel
My native stage 2 is running in RM. It frees the space where it was loaded to load system files. Resident part of stage 2 kernel is moving to 100000h-10FFEFh. stage 2 driver is moving to 2000h, its non-resident part may exceed 7C00h. 7C00h-7FFFh is reserved additionally to be able to load stage 0/stage 1 images. 8000h is base address and entry point of the kernel/stage 2.
or either it would need the second stage to run already in protected mode and being able to load and use the drivers , but then either it would need a sort of api for that the kernel can still access the structure the second stage has initialized, like pci bus tree and the drivers and device it has initialized, or otherwise it would require the whole pci scan and device reset and scan would be done entierly twice, once from the second stage loader, and then all over again when the kernel actually boot, or the kernel would need to have a way to access the structure of the second stage loader
I plan to implement something like this for UEFI booting.
other options would be that i make two iso, a first iso with only the minimum drivers and the kernel who would fit in the real mode memory, the first stage bootloader would load the whole iso and then jump at the address of the kernel file, and then the kernel could initialize the iso filesystem directly from memory, load the dirvers on it, and then the rest of the drivers and system file would be loaded with protected mode drivers from another filesystem, but then the kernel would not be loaded at a fixed address, or then loading the kernel and the small iso seperatly from the main iso who would contain the small iso as a file to be loaded in real mode memory with the bootloader

or either that the kernel file on the main iso would include this minimal iso as binary data, so there would be the main iso with the kernel binary who include this iso in it, but it would need to recompile the kernel or to alter the kernel binary to change files in this iso, and same the kernel with the iso would have to fit in real mode memory to be loaded by the bootloader, but it would have the disavantage to have the drivers scattered on two different filesystem,but it could be mannaged this way, and still limit on size for that a kernel loaded in real mode memory by first stage boot loader could have all it need to be able to read the rest of the os from another disk
You can try to load two files (as I'm doing), the first with kernel, and the second with base image for RAM disk. Or you can merge two files in one to simplify their loading (I use PK file format and special 1st stage boot loaders for this purpose; it's easy to make PK file: copy /b /y %1.os+%1.fs %1.pk; in this case kernel should be able to detect the size of additional file without hint from boot loader, or kernel has to be patched with size value during merge). Or you can design a new image format (add restriction to existing format) to use only one image file with fixed kernel location within it. I can put small base image for RAM disk into boot driver. This is possible because boot driver can ask the kernel to use other than original boot device by calling RegBootDevice.
If you have seen bad English in my words, tell me what's wrong, please.
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: new on board, and question on bootloading and bios

Post by h0bby1 »

for the size of the other file, if it's stored on a filesystem on a disk it's possible to read the size of the file from the fs entry, if it's an image, iso contain the volume size in the volume header, so determining its size from the kernel should not be a problem if it knows where it start, and the first stage boot loader can already find file entry in the root directory of the iso filesystem and read it from floppy in chs mode or cd rom in lba with 2048 byte sectors, it should works as well from harddrive or usbkey, it's supposed to be able to find the iso in any media , and read it's root directory entry to load the kernel so it already has its size, and if any other file is to be loaded from the iso, it's size can be known at the first stage , and i can pass it to the kernel as a register before the jump to its address

i guess it's the best option, to load the kernel and a minimal ramdisk that can fit into the first 1Mo from the first stage boot loader in real mode, and then the kernel load it's disk drivers from there to load the remaining drivers, so would need to have two iso, the first 'main iso' with everything on it, and at the root folder there the kernel and the minimal ramdisk containing the drivers needed to have disk access, the kernel and this minimal ramdisk to be loaded by the first stage boot loader in real mode, like this it seems fine, the minimal ramdisk could even be a compressed image that the kernel could decompress, it just add a bit of complexity to make up the main iso with the ramdisk fs on it as a file, and to organize the build, but it's still mannageable
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: new on board, and question on bootloading and bios

Post by h0bby1 »

is there any simple way to map bios drive to actual drive ? i know grub seem to handle this so i might check it's source code to see how it does this, but i wonder the theory about it, the kernel still boot in real mode so there is way to still call bios interuption to get any relevant information the bios can give about the disk for that the kernel can then know where to look for the iso, if there is no simple and reliable way to do this, the kernel can still do the whole rescan of all disks to find where the iso is
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: new on board, and question on bootloading and bios

Post by egos »

GRUB uses BIOS drive number.

To get physical drive location from BIOS drive number use function int 13h/48h and other methods.
Detecting boot drive in protected mode
BIOS drive number & ATA primary/secondary master/slave
If you have seen bad English in my words, tell me what's wrong, please.
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: new on board, and question on bootloading and bios

Post by h0bby1 »

for now i implemented this system, the first stage bootloader look for the iso on all drive, then load the kernel and the ramdisk image from the root directory at fixed location, i hope the iso file order is really alphabetic order cause i don't have any byte left in the 512 byte to check the file name so i just set the fixed address at 0x1000 at the start of the loop and set it to 0x8000 after the first file, then the kernel look the iso at address 0x8000 and determine the size from volume header, the ramdisk image could even be compressed, iso is not very memory savy, the ramdisk image with bus manager, pci, usb and some drivers goes from 116kb to 27kb with compression, the kernel is 240k with the compressed image it shouldn't be an issue with the real mode memory limitation

ok i'll check this, i already looked into the get disk drive parameters interupt, but it only works for lba device no ? i guess the only drive that are not lba are floppy and are not really used anymore anyway, and in anycase, i guess you can easily deduce how to access it with ata controller from the device number, there are not that much possibilities to access floppy drive X, it's more tricky for other number above 0x80 or 0xe0 cause it can be pretty much anything or on any controller, i'll check your link to see how the match can be made :)
Post Reply