Bootloader issue fix. #1

Open
opened 2024-01-23 16:47:45 -08:00 by gbowne1 · 6 comments
Owner

Bootloader fix:

boot1.asm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Stage 1 bootloader for ClassicOS ;
; -------------------------------- ;
; Determines if it was loaded from ;
;  a floppy disk or an hard disk   ;
;  drive, and then loads stage 2   ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;
; Assembler directives ;
;;;;;;;;;;;;;;;;;;;;;;;;

; tells the assembler that the program will be loaded at 0x7C00
; this is done by the BIOS
org 0x7C00

; we are targeting (x86) 16-bit real mode
bits 16

;;;;;;;;;;;;;;;;;
; Jump to start ;
;;;;;;;;;;;;;;;;;
jmp start

;;;;;;;;
; Data ;
;;;;;;;;
; fdd geometry & options
fddsamt  db 8        ; how many sectors to load
fddretr  db 5        ; max retries for fdd operations
fddcretr db 0        ; current retries left

; misc strings
welcome1 db "Welcome to the ClassicOS Stage 1 bootloader.", 13, 10, 0
disktype db "Drive type: ", 0
diskfdd  db "FDD", 13, 10, 0
diskhdd  db "HDD", 13, 10, 0
loaded   db "Data loaded!", 13, 10, 0

; errors
fdderes  db "FDD reset failed.", 13, 10, 0
fddeload db "FDD read failed.", 13, 10, 0

; storage
disknum  db 0

;;;;;;;;;;;
; Program ;
;;;;;;;;;;;

start:
   xor ax, ax             ; set up segment registers to segment 0 since
   mov ds, ax             ; our addresses are already relative to 0x7C00
   mov es, ax

   mov [disknum], dl      ; save disk number to memory

   mov ah, 0x01           ; set cursor shape
   mov cx, 0x0100         ; hide cursor by setting ch = 1 and cl = 0x00
   int 0x10               ; video interrupt

   mov ah, 0x08           ; read page number into bh
   int 0x10

   mov si, welcome1       ; print welcome
   call printstr

   mov si, disktype       ; print first part of disk type
   call printstr

   mov dl, [disknum]      ; restore disk number - should not be
                          ; strictly necessary but you never know
   and dl, 0x80           ; sets zf if disk is floppy
   jz fddload

hddload:
   mov si, diskhdd        ; print disk type
   call printstr

   jmp halt               ; not implemented!

fddload:
   mov si, diskfdd        ; print disk type
   call printstr

fddload_onto_reset:
   mov ah, [fddretr]     ; load max retries in memory
   mov [fddcretr], ah
fddload_reset:
   mov si, fdderes        ; load error message pointer
   dec byte [fddcretr]    ; decrement the retries counter
   jz fddload_err         ; if it is 0, we stop trying

   mov ah, 0x00           ; otherwise, reset function (int 0x13)
   int 0x13
   jc fddload_reset       ; if jc (error), we try again

fddload_onto_load:
   mov ah, [fddretr]      ; reset retries counter
   mov [fddcretr], ah
   mov ax, 0x1000         ; need to stay within real mode limits
   mov es, ax
fddload_load:              ; loads 512*fddsamt bytes from sector 2 on.
   mov si, fddeload
   dec byte [fddcretr]
   jz fddload_err

   mov dh, 0              ; head 0
   mov ch, 0              ; cyl/track 0
   mov cl, 2              ; start sector
   mov bx, 0              ; memory location
   mov al, [fddsamt]      ; how many sectors to read
   mov ah, 0x02           ; read function (int 0x13)
   int 0x13
   jc fddload_load        ; if jc (error), we try again
   cmp al, [fddsamt]      ; also if al is not 1, we have a problem
   jnz fddload_load

fddload_done:
   mov si, loaded         ; we have successfully loaded the data
   call printstr
   jmp halt               ; this will be jmp 0x1000:0x0000

fddload_err:
   call printstr          ; print
   jmp halt               ; and die

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; printstr routine, prints the string pointed by si using int 0x10 ;
; sets the direction flag to 0                                     ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
printstr:
   cld                    ; clear df flag - lodsb increments si
printstr_loop:
   lodsb                  ; load next character into al, increment si
   or al, al              ; sets zf if al is 0x00
   jz printstr_end
   mov ah, 0x0E           ; teletype output (int 0x10)
   int 0x10               ; print character
   jmp printstr_loop
printstr_end:
   ret                    ; return to caller address


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; halt routine - infinite loop ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
halt:
   cli
   jmp halt

;;;;;;;;;;;
; Padding ;
;;;;;;;;;;;
; $ is the address of the current line, $$ is the base address for
; this program.
; the expression is expanded to 510 - ($ - 0x7C00), or
; 510 + 0x7C00 - $, which is, in other words, the number of bytes
; before the address 510 + 0x7C00 (= 0x7DFD), where the 0xAA55
; signature shall be put.
times 510 - ($ - $$) db 0x00

;;;;;;;;;;;;;;;;;;
; BIOS signature ;
;;;;;;;;;;;;;;;;;;
dw 0xAA55
Bootloader fix: boot1.asm ```asm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Stage 1 bootloader for ClassicOS ; ; -------------------------------- ; ; Determines if it was loaded from ; ; a floppy disk or an hard disk ; ; drive, and then loads stage 2 ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;; ; Assembler directives ; ;;;;;;;;;;;;;;;;;;;;;;;; ; tells the assembler that the program will be loaded at 0x7C00 ; this is done by the BIOS org 0x7C00 ; we are targeting (x86) 16-bit real mode bits 16 ;;;;;;;;;;;;;;;;; ; Jump to start ; ;;;;;;;;;;;;;;;;; jmp start ;;;;;;;; ; Data ; ;;;;;;;; ; fdd geometry & options fddsamt db 8 ; how many sectors to load fddretr db 5 ; max retries for fdd operations fddcretr db 0 ; current retries left ; misc strings welcome1 db "Welcome to the ClassicOS Stage 1 bootloader.", 13, 10, 0 disktype db "Drive type: ", 0 diskfdd db "FDD", 13, 10, 0 diskhdd db "HDD", 13, 10, 0 loaded db "Data loaded!", 13, 10, 0 ; errors fdderes db "FDD reset failed.", 13, 10, 0 fddeload db "FDD read failed.", 13, 10, 0 ; storage disknum db 0 ;;;;;;;;;;; ; Program ; ;;;;;;;;;;; start: xor ax, ax ; set up segment registers to segment 0 since mov ds, ax ; our addresses are already relative to 0x7C00 mov es, ax mov [disknum], dl ; save disk number to memory mov ah, 0x01 ; set cursor shape mov cx, 0x0100 ; hide cursor by setting ch = 1 and cl = 0x00 int 0x10 ; video interrupt mov ah, 0x08 ; read page number into bh int 0x10 mov si, welcome1 ; print welcome call printstr mov si, disktype ; print first part of disk type call printstr mov dl, [disknum] ; restore disk number - should not be ; strictly necessary but you never know and dl, 0x80 ; sets zf if disk is floppy jz fddload hddload: mov si, diskhdd ; print disk type call printstr jmp halt ; not implemented! fddload: mov si, diskfdd ; print disk type call printstr fddload_onto_reset: mov ah, [fddretr] ; load max retries in memory mov [fddcretr], ah fddload_reset: mov si, fdderes ; load error message pointer dec byte [fddcretr] ; decrement the retries counter jz fddload_err ; if it is 0, we stop trying mov ah, 0x00 ; otherwise, reset function (int 0x13) int 0x13 jc fddload_reset ; if jc (error), we try again fddload_onto_load: mov ah, [fddretr] ; reset retries counter mov [fddcretr], ah mov ax, 0x1000 ; need to stay within real mode limits mov es, ax fddload_load: ; loads 512*fddsamt bytes from sector 2 on. mov si, fddeload dec byte [fddcretr] jz fddload_err mov dh, 0 ; head 0 mov ch, 0 ; cyl/track 0 mov cl, 2 ; start sector mov bx, 0 ; memory location mov al, [fddsamt] ; how many sectors to read mov ah, 0x02 ; read function (int 0x13) int 0x13 jc fddload_load ; if jc (error), we try again cmp al, [fddsamt] ; also if al is not 1, we have a problem jnz fddload_load fddload_done: mov si, loaded ; we have successfully loaded the data call printstr jmp halt ; this will be jmp 0x1000:0x0000 fddload_err: call printstr ; print jmp halt ; and die ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; printstr routine, prints the string pointed by si using int 0x10 ; ; sets the direction flag to 0 ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; printstr: cld ; clear df flag - lodsb increments si printstr_loop: lodsb ; load next character into al, increment si or al, al ; sets zf if al is 0x00 jz printstr_end mov ah, 0x0E ; teletype output (int 0x10) int 0x10 ; print character jmp printstr_loop printstr_end: ret ; return to caller address ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; halt routine - infinite loop ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; halt: cli jmp halt ;;;;;;;;;;; ; Padding ; ;;;;;;;;;;; ; $ is the address of the current line, $$ is the base address for ; this program. ; the expression is expanded to 510 - ($ - 0x7C00), or ; 510 + 0x7C00 - $, which is, in other words, the number of bytes ; before the address 510 + 0x7C00 (= 0x7DFD), where the 0xAA55 ; signature shall be put. times 510 - ($ - $$) db 0x00 ;;;;;;;;;;;;;;;;;; ; BIOS signature ; ;;;;;;;;;;;;;;;;;; dw 0xAA55 ```
gbowne1 self-assigned this 2024-01-23 16:47:45 -08:00
Karutoh was assigned by gbowne1 2024-01-23 16:47:45 -08:00
Author
Owner

2nd stage boot2.asm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Stage 2 bootloader for ClassicOS ;
; -------------------------------- ;
; Loads the kernel, sets up tables, ;
; and transitions to protected mode ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;
; Assembler directives ;
;;;;;;;;;;;;;;;;;;;;;;;;

; tells the assembler that the program will be loaded at 0x8000
; this is done by the first stage bootloader
org 0x8000

; we are targeting (x86) 16-bit real mode
bits 16

;;;;;;;;;;;;;;;;;
; Jump to start ;
;;;;;;;;;;;;;;;;;
jmp start

;;;;;;;;
; Data ;
;;;;;;;;
; kernel file name
kername db "KERNEL.BIN", 0

;;;;;;;;;;;
; Program ;
;;;;;;;;;;;

start:
   xor ax, ax             ; set up segment registers to segment 0 since
   mov ds, ax             ; our addresses are already relative to 0x8000
   mov es, ax

   mov si, kername         ; print kernel file name
   call printstr

   ; Load the kernel into memory
   ; ...

   ; Set up GDT, IDT, IVT
   ; ...

   ; Switch to protected mode
   ; ...

   ; Set up stack and start executing kernel's code
   ; ...

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; printstr routine, prints the string pointed by si using int 0x10 ;
; sets the direction flag to 0                                     ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
printstr:
   cld                    ; clear df flag - lodsb increments si
printstr_loop:
   lodsb                 ; load next character into al, increment si
   or al, al              ; sets zf if al is 0x00
   jz printstr_end
   mov ah, 0x0E           ; teletype output (int 0x10)
   int 0x10               ; print character
   jmp printstr_loop
printstr_end:
   ret                    ; return to caller address

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; halt routine - infinite loop ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
halt:
   cli
   jmp halt

;;;;;;;;;;;
; Padding ;
;;;;;;;;;;;
; $ is the address of the current line, $$ is the base address for
; this program.
; the expression is expanded to 510 - ($ - 0x8000), or
; 510 + 0x8000 - $, which is, in other words, the number of bytes
; before the address 510 + 0x8000 (= 0x80FD), where the 0xAA55
; signature shall be put.
times 510 - ($ - $$) db 0x00

;;;;;;;;;;;;;;;;;;
; BIOS signature ;
;;;;;;;;;;;;;;;;;;
dw 0xAA55
2nd stage boot2.asm ```asm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Stage 2 bootloader for ClassicOS ; ; -------------------------------- ; ; Loads the kernel, sets up tables, ; ; and transitions to protected mode ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;; ; Assembler directives ; ;;;;;;;;;;;;;;;;;;;;;;;; ; tells the assembler that the program will be loaded at 0x8000 ; this is done by the first stage bootloader org 0x8000 ; we are targeting (x86) 16-bit real mode bits 16 ;;;;;;;;;;;;;;;;; ; Jump to start ; ;;;;;;;;;;;;;;;;; jmp start ;;;;;;;; ; Data ; ;;;;;;;; ; kernel file name kername db "KERNEL.BIN", 0 ;;;;;;;;;;; ; Program ; ;;;;;;;;;;; start: xor ax, ax ; set up segment registers to segment 0 since mov ds, ax ; our addresses are already relative to 0x8000 mov es, ax mov si, kername ; print kernel file name call printstr ; Load the kernel into memory ; ... ; Set up GDT, IDT, IVT ; ... ; Switch to protected mode ; ... ; Set up stack and start executing kernel's code ; ... ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; printstr routine, prints the string pointed by si using int 0x10 ; ; sets the direction flag to 0 ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; printstr: cld ; clear df flag - lodsb increments si printstr_loop: lodsb ; load next character into al, increment si or al, al ; sets zf if al is 0x00 jz printstr_end mov ah, 0x0E ; teletype output (int 0x10) int 0x10 ; print character jmp printstr_loop printstr_end: ret ; return to caller address ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; halt routine - infinite loop ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; halt: cli jmp halt ;;;;;;;;;;; ; Padding ; ;;;;;;;;;;; ; $ is the address of the current line, $$ is the base address for ; this program. ; the expression is expanded to 510 - ($ - 0x8000), or ; 510 + 0x8000 - $, which is, in other words, the number of bytes ; before the address 510 + 0x8000 (= 0x80FD), where the 0xAA55 ; signature shall be put. times 510 - ($ - $$) db 0x00 ;;;;;;;;;;;;;;;;;; ; BIOS signature ; ;;;;;;;;;;;;;;;;;; dw 0xAA55 ```
Author
Owner

Going to leave this in here in case its needed for reference.

Going to leave this in here in case its needed for reference.
Author
Owner

The old boot.asm

[BITS 16]
[ORG 0x7c00]

start:
    ; Processor initialization (only stack segment register needed)
    mov    ss, 0x1000 ; Set stack segment register
	mov    sp, 0x7C00  ; Set stack pointer (SP)
    mov    ds, ss      ; Set data segment register (DS)

; Identify boot device using BIOS calls
identify_drive:
    mov     ah, 0x0E    ; Get Interrupt Vector for INT 13h (Disk Services)
    int     0x80
    cmp     cl, 0x41    ; Check for floppy drive interrupt vector (example)
    je      is_floppy
    cmp     cl, 0x80    ; Check for hard disk interrupt vector (example)
    je      is_harddrive
    ; Handle invalid drive type (error handling)
    ; ...

is_floppy:
    ; Perform floppy disk access (assuming AH=0x02 for read sectors)
    mov     ah, 0x02    ; Read sectors
    mov     al, 1       ; Number of sectors to read (1)

    ; Set CH, CL, DH, DL for floppy based on your system configuration
    ; (Replace these values with appropriate settings for your floppy drive)
    mov     ch, 0       ; Cylinder (example, adjust based on your floppy)
    mov     cl, 1       ; Sector number (example, adjust based on boot sector location)
    mov     dh, 0       ; Head number (example, typically 0 for single-sided floppies)
    mov     dl, 0x00    ; Drive number (0x00 for floppy drive A)

    ; Set ES:BX to the memory address where you want to store the read data
    mov     es, 0x1000  ; Example segment (adjust as needed)
    mov     bx, 0x0      ; Memory offset within the segment (example)

    int     0x13
    jc      error_floppy

    ; Implement error handling (omitted here for brevity)
    ; Process the read data from the floppy sector (load second stage bootloader, etc.)

is_harddrive:

	; Sample code (not guaranteed to work universally)
	mov ah, 0x02 ; Set function for read sectors
	mov al, 0x01 ; Read one sector
	; Set CH, CL, DH for desired sector location (e.g., first sector)
	mov dl, 0x80 ; Drive number (assuming drive A is boot device)
	mov es, segment_address ; Set ES for buffer to store read data
	mov bx, buffer_offset ; Set BX for offset within the buffer

	int 13h ; Raise BIOS interrupt for disk read

	; Check Carry flag for error handling
	jc harddrive_not_found ; Jump if Carry flag is set (potential error)

	; Hard drive likely present (further processing can occur)

	; ... (rest of your bootloader code)

	harddrive_not_found:
	; Handle error condition (missing drive or other issue)

	; ... (error handling logic)

;memory_error:
    ; ... (error handling or continue with limited memory)

; Second stage loading (simplified example)
; Here's an improved version of the load_second_stage section with the placeholder jump replaced by actual loading logic:
; Code snippet

load_second_stage:
  ; Calculate address of second stage bootloader (assuming offset from boot sector)
  mov dx, 0x0000 ; Clear DX register for better calculation
  add dx, sector_count ; Add number of sectors to skip (adjust as needed)
  shl dx, 5 ; Multiply by sector size (512 bytes)
  add dx, 0x7C00 ; Add boot sector address offset

  ; Read second stage bootloader from calculated address
  mov ah, 0x02 ; Function for reading sectors
  mov al, 1     ; Number of sectors to read (1 for second stage)
  mov es, dx    ; Set ES segment register to calculated address
  mov bx, 0x0000 ; Set BX offset within the segment (example)

  int 13h      ; Raise BIOS interrupt for disk read

  ; Check Carry flag for error handling
  jc memory_error ; Jump if Carry flag is set (potential error)

  ; Second stage likely loaded successfully, jump to it
  jmp second_stage_address ; Direct jump to the defined address

error_floppy:
  ; Display a basic error message (optional)
  mov ah, 0x0E  ; BIOS video call for displaying text (educational purposes)
  mov bh, 0x00  ; Set background color (black)
  mov bl, 0x07  ; Set text color (white)
  mov dx, error_floppy_message ; Address of error message string
  int 0x10     ; BIOS video interrupt

  ; Halt the boot process (replace with a retry or more advanced error handling)
  hlt          ; Halt instruction

error_floppy_message db 'Floppy disk read error!', 0x0

memory_error:
    ; Check for available memory (replace with actual method)
	; ... (e.g., call BIOS service for memory size or use a constant value)
	cmp available_memory, memory_threshold ; Compare with minimum required memory
	jb limited_memory_boot ; Jump if below threshold

  	; ... (standard error handling for other scenarios)

limited_memory_boot:
  ; Perform minimal setup for limited memory boot
  ; ... (disable non-essential features, adjust kernel parameters)

  ; Load and jump to second stage bootloader (potentially with adjustments)
  ; ... (modify loading logic if necessary)

; Define variables used for calculation (adjust as needed)
sector_count db 1  ; Number of sectors to skip before second stage (change if needed)
second_stage_address equ 0x8000  ; Replace with actual address of your second stage bootloader
available_memory equ 0x100000 ; Replace with actual memory size detection (1MB in this example)
memory_threshold equ 0x0A0000 ; Example minimum memory required (adjust based on needs)

; Padding and magic number (standard practice)
times 510-($-$$) db 0
dw 0xaa55
The old boot.asm ```asm [BITS 16] [ORG 0x7c00] start: ; Processor initialization (only stack segment register needed) mov ss, 0x1000 ; Set stack segment register mov sp, 0x7C00 ; Set stack pointer (SP) mov ds, ss ; Set data segment register (DS) ; Identify boot device using BIOS calls identify_drive: mov ah, 0x0E ; Get Interrupt Vector for INT 13h (Disk Services) int 0x80 cmp cl, 0x41 ; Check for floppy drive interrupt vector (example) je is_floppy cmp cl, 0x80 ; Check for hard disk interrupt vector (example) je is_harddrive ; Handle invalid drive type (error handling) ; ... is_floppy: ; Perform floppy disk access (assuming AH=0x02 for read sectors) mov ah, 0x02 ; Read sectors mov al, 1 ; Number of sectors to read (1) ; Set CH, CL, DH, DL for floppy based on your system configuration ; (Replace these values with appropriate settings for your floppy drive) mov ch, 0 ; Cylinder (example, adjust based on your floppy) mov cl, 1 ; Sector number (example, adjust based on boot sector location) mov dh, 0 ; Head number (example, typically 0 for single-sided floppies) mov dl, 0x00 ; Drive number (0x00 for floppy drive A) ; Set ES:BX to the memory address where you want to store the read data mov es, 0x1000 ; Example segment (adjust as needed) mov bx, 0x0 ; Memory offset within the segment (example) int 0x13 jc error_floppy ; Implement error handling (omitted here for brevity) ; Process the read data from the floppy sector (load second stage bootloader, etc.) is_harddrive: ; Sample code (not guaranteed to work universally) mov ah, 0x02 ; Set function for read sectors mov al, 0x01 ; Read one sector ; Set CH, CL, DH for desired sector location (e.g., first sector) mov dl, 0x80 ; Drive number (assuming drive A is boot device) mov es, segment_address ; Set ES for buffer to store read data mov bx, buffer_offset ; Set BX for offset within the buffer int 13h ; Raise BIOS interrupt for disk read ; Check Carry flag for error handling jc harddrive_not_found ; Jump if Carry flag is set (potential error) ; Hard drive likely present (further processing can occur) ; ... (rest of your bootloader code) harddrive_not_found: ; Handle error condition (missing drive or other issue) ; ... (error handling logic) ;memory_error: ; ... (error handling or continue with limited memory) ; Second stage loading (simplified example) ; Here's an improved version of the load_second_stage section with the placeholder jump replaced by actual loading logic: ; Code snippet load_second_stage: ; Calculate address of second stage bootloader (assuming offset from boot sector) mov dx, 0x0000 ; Clear DX register for better calculation add dx, sector_count ; Add number of sectors to skip (adjust as needed) shl dx, 5 ; Multiply by sector size (512 bytes) add dx, 0x7C00 ; Add boot sector address offset ; Read second stage bootloader from calculated address mov ah, 0x02 ; Function for reading sectors mov al, 1 ; Number of sectors to read (1 for second stage) mov es, dx ; Set ES segment register to calculated address mov bx, 0x0000 ; Set BX offset within the segment (example) int 13h ; Raise BIOS interrupt for disk read ; Check Carry flag for error handling jc memory_error ; Jump if Carry flag is set (potential error) ; Second stage likely loaded successfully, jump to it jmp second_stage_address ; Direct jump to the defined address error_floppy: ; Display a basic error message (optional) mov ah, 0x0E ; BIOS video call for displaying text (educational purposes) mov bh, 0x00 ; Set background color (black) mov bl, 0x07 ; Set text color (white) mov dx, error_floppy_message ; Address of error message string int 0x10 ; BIOS video interrupt ; Halt the boot process (replace with a retry or more advanced error handling) hlt ; Halt instruction error_floppy_message db 'Floppy disk read error!', 0x0 memory_error: ; Check for available memory (replace with actual method) ; ... (e.g., call BIOS service for memory size or use a constant value) cmp available_memory, memory_threshold ; Compare with minimum required memory jb limited_memory_boot ; Jump if below threshold ; ... (standard error handling for other scenarios) limited_memory_boot: ; Perform minimal setup for limited memory boot ; ... (disable non-essential features, adjust kernel parameters) ; Load and jump to second stage bootloader (potentially with adjustments) ; ... (modify loading logic if necessary) ; Define variables used for calculation (adjust as needed) sector_count db 1 ; Number of sectors to skip before second stage (change if needed) second_stage_address equ 0x8000 ; Replace with actual address of your second stage bootloader available_memory equ 0x100000 ; Replace with actual memory size detection (1MB in this example) memory_threshold equ 0x0A0000 ; Example minimum memory required (adjust based on needs) ; Padding and magic number (standard practice) times 510-($-$$) db 0 dw 0xaa55 ```
Author
Owner

The old boot2.asm

[BITS  16]
[ORG  0x0000]

start:
    ; Initialize stack
    MOV AX, 0x0000 ; Set up a segment for the stack
    MOV SS, AX
    MOV SP, 0xFFFF ; Stack grows downwards from the top of the segment

    ; Copy boot sector data to a safe location
    call mCopyBootSector
    ; Load the kernel
    CALL load_kernel

switch_to_protected_mode:
	CLI             ; Disable interrupts
	lgdt [gdt_descriptor] ; Load the global descriptor table
	MOV EAX, CR0
	OR EAX, 0x1     ; Set the PE (Protection Enable) bit
	MOV CR0, EAX
	; Far jump to flush CPU queue after changing to protected mode
	JMP CODE_SEG:init_pm ; CODE_SEG is the segment selector for code segment in GDT
init_pm:
	; Update segment registers here
	; Set code segment register (CS) to point to code segment descriptor (selector 1)
	mov ax, 0x0001
	mov ds, ax ; Set data segment register (DS) to point to data segment descriptor (selector 2)
	mov es, ax ; Set other segment registers (ES, SS, etc.) as needed
	RET

enable_a20:
	cli             ; Disable interrupts to prevent interference
	call a20wait    ; Wait for the keyboard controller to be ready
	mov al, 0xAD    ; Command to disable keyboard
	out 0x64, al    ; Send command to keyboard controller command port
	call a20wait    ; Wait for the keyboard controller to be ready
	mov al, 0xD0    ; Command to read output port
	out 0x64, al    ; Send command to keyboard controller command port
	call a20wait    ; Wait for the keyboard controller to be ready
	in al, 0x60     ; Read current state of output port
	or al, 0x02     ; Set A20 bit
	out 0x64, al    ; Send command to keyboard controller command port
	call a20wait    ; Wait for the keyboard controller to be ready
	mov al, 0xD1    ; Command to write output port
	out 0x64, al    ; Send command to keyboard controller command port
	call a20wait    ; Wait for the keyboard controller to be ready
	mov al, 0xAE    ; Command to re-enable keyboard
	out 0x64, al    ; Send command to keyboard controller command port
	sti             ; Re-enable interrupts
	ret

; Wait for keyboard controller to be ready
a20wait:
	in al, 0x64         ; Read keyboard controller status port
	test al, 0x02       ; Check if input buffer is full
	jnz a20wait         ; Wait until it's not full
	ret

; Enter kernel space and jump to the kernel entry point
JMP  0x1000:0x0000

; Code to set up flat memory model for protected mode
; This involves setting up the segment registers with selectors
; that point to descriptors in the GDT that define a flat memory model

limit = 0x00CFFFFFh  ; Define limit as a separate variable within gdt_struct

; Placeholder instruction to satisfy NASM
dummy_instruction DB 0x90  ; NOP instruction as a placeholder

gdt_struct:

    base_addr equ 0x0000000

    ; Null descriptor (ignored)
    dd base_addr, 0  ; Both values are zero for a null descriptor

    ; Code segment descriptor (flat memory model)
    dd base_addr, limit
    db 0x9A
    db 0xCF

    ; Data segment descriptor (flat memory model)
    dd base_addr, limit
    db 0x92
    db 0xCF

; Macro to copy boot sector data to a safe location
mCopyBootSector:
    pusha                       ; Save all general-purpose registers
    mov si, 0x7C00              ; Source address: where BIOS loads the boot sector
    mov di, 0x6000              ; Destination address: safe memory area
    mov cx, 512                 ; Number of bytes to copy (size of boot sector)
    cld                         ; Clear direction flag to increment SI and DI
copy_loop:
    lodsb                       ; Load byte at address DS:SI into AL, increment SI
    stosb                       ; Store byte from AL to address ES:DI, increment DI
    loop copy_loop              ; Decrement CX; if CX != 0, repeat loop
    popa                        ; Restore all general-purpose registers
    ret

; Subroutine to load the kernel
load_kernel:
    ; Disable interrupts
    cli

    ; Setup disk parameters
    ; ... (set CH, CL, DH, DL for LBA, set DX for drive number)

    ; Calculate load address for kernel
    ; ... (set ES:BX to the target memory address)

    ; Read sectors from disk into memory
    mov ah,  0x02 ; Read sectors function
    mov al,  1    ; Number of sectors to read
    int  0x13     ; BIOS disk services

    ; Check for read error
    jc .disk_error ; Carry flag set means an error occurred

    ; Enable A20 line if necessary
    ; ... (implementation depends on your system)

    ; Jump to the kernel's entry point
    jmp  0x1000:0x0000 ; Assuming the kernel is loaded at  0x1000:0x0000

.disk_error:
    ; Handle disk read error
    ; ... (display error message or halt)

    hlt ; Halt the system

; Function or Subroutine to switch to protected mode
switch_to_protected_mode:
    CLI             ; Disable interrupts
    LGDT [gdt_descriptor] ; Load the global descriptor table
    MOV EAX, CR0
    OR EAX,  0x1     ; Set the PE (Protection Enable) bit
    MOV CR0, EAX
    ; Far jump to flush CPU queue after changing to protected mode
    JMP CODE_SEG:init_pm ; CODE_SEG is the segment selector for code segment in GDT
The old boot2.asm ```asm [BITS 16] [ORG 0x0000] start: ; Initialize stack MOV AX, 0x0000 ; Set up a segment for the stack MOV SS, AX MOV SP, 0xFFFF ; Stack grows downwards from the top of the segment ; Copy boot sector data to a safe location call mCopyBootSector ; Load the kernel CALL load_kernel switch_to_protected_mode: CLI ; Disable interrupts lgdt [gdt_descriptor] ; Load the global descriptor table MOV EAX, CR0 OR EAX, 0x1 ; Set the PE (Protection Enable) bit MOV CR0, EAX ; Far jump to flush CPU queue after changing to protected mode JMP CODE_SEG:init_pm ; CODE_SEG is the segment selector for code segment in GDT init_pm: ; Update segment registers here ; Set code segment register (CS) to point to code segment descriptor (selector 1) mov ax, 0x0001 mov ds, ax ; Set data segment register (DS) to point to data segment descriptor (selector 2) mov es, ax ; Set other segment registers (ES, SS, etc.) as needed RET enable_a20: cli ; Disable interrupts to prevent interference call a20wait ; Wait for the keyboard controller to be ready mov al, 0xAD ; Command to disable keyboard out 0x64, al ; Send command to keyboard controller command port call a20wait ; Wait for the keyboard controller to be ready mov al, 0xD0 ; Command to read output port out 0x64, al ; Send command to keyboard controller command port call a20wait ; Wait for the keyboard controller to be ready in al, 0x60 ; Read current state of output port or al, 0x02 ; Set A20 bit out 0x64, al ; Send command to keyboard controller command port call a20wait ; Wait for the keyboard controller to be ready mov al, 0xD1 ; Command to write output port out 0x64, al ; Send command to keyboard controller command port call a20wait ; Wait for the keyboard controller to be ready mov al, 0xAE ; Command to re-enable keyboard out 0x64, al ; Send command to keyboard controller command port sti ; Re-enable interrupts ret ; Wait for keyboard controller to be ready a20wait: in al, 0x64 ; Read keyboard controller status port test al, 0x02 ; Check if input buffer is full jnz a20wait ; Wait until it's not full ret ; Enter kernel space and jump to the kernel entry point JMP 0x1000:0x0000 ; Code to set up flat memory model for protected mode ; This involves setting up the segment registers with selectors ; that point to descriptors in the GDT that define a flat memory model limit = 0x00CFFFFFh ; Define limit as a separate variable within gdt_struct ; Placeholder instruction to satisfy NASM dummy_instruction DB 0x90 ; NOP instruction as a placeholder gdt_struct: base_addr equ 0x0000000 ; Null descriptor (ignored) dd base_addr, 0 ; Both values are zero for a null descriptor ; Code segment descriptor (flat memory model) dd base_addr, limit db 0x9A db 0xCF ; Data segment descriptor (flat memory model) dd base_addr, limit db 0x92 db 0xCF ; Macro to copy boot sector data to a safe location mCopyBootSector: pusha ; Save all general-purpose registers mov si, 0x7C00 ; Source address: where BIOS loads the boot sector mov di, 0x6000 ; Destination address: safe memory area mov cx, 512 ; Number of bytes to copy (size of boot sector) cld ; Clear direction flag to increment SI and DI copy_loop: lodsb ; Load byte at address DS:SI into AL, increment SI stosb ; Store byte from AL to address ES:DI, increment DI loop copy_loop ; Decrement CX; if CX != 0, repeat loop popa ; Restore all general-purpose registers ret ; Subroutine to load the kernel load_kernel: ; Disable interrupts cli ; Setup disk parameters ; ... (set CH, CL, DH, DL for LBA, set DX for drive number) ; Calculate load address for kernel ; ... (set ES:BX to the target memory address) ; Read sectors from disk into memory mov ah, 0x02 ; Read sectors function mov al, 1 ; Number of sectors to read int 0x13 ; BIOS disk services ; Check for read error jc .disk_error ; Carry flag set means an error occurred ; Enable A20 line if necessary ; ... (implementation depends on your system) ; Jump to the kernel's entry point jmp 0x1000:0x0000 ; Assuming the kernel is loaded at 0x1000:0x0000 .disk_error: ; Handle disk read error ; ... (display error message or halt) hlt ; Halt the system ; Function or Subroutine to switch to protected mode switch_to_protected_mode: CLI ; Disable interrupts LGDT [gdt_descriptor] ; Load the global descriptor table MOV EAX, CR0 OR EAX, 0x1 ; Set the PE (Protection Enable) bit MOV CR0, EAX ; Far jump to flush CPU queue after changing to protected mode JMP CODE_SEG:init_pm ; CODE_SEG is the segment selector for code segment in GDT ```
Collaborator

Modified the first stage boot loader to add HDD support and made an Op. to jmp 0x8000:0x0000. Still not getting KERNEL.BIN printed from second stage boot loader.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Stage 1 bootloader for ClassicOS ;
; -------------------------------- ;
; Determines if it was loaded from ;
;  a floppy disk or an hard disk   ;
;  drive, and then loads stage 2   ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;
; Assembler directives ;
;;;;;;;;;;;;;;;;;;;;;;;;

; tells the assembler that the program will be loaded at 0x7C00
; this is done by the BIOS
org 0x7C00

; we are targeting (x86) 16-bit real mode
bits 16

;;;;;;;;;;;;;;;;;
; Jump to start ;
;;;;;;;;;;;;;;;;;
jmp start

;;;;;;;;
; Data ;
;;;;;;;;
; fdd geometry & options
fddsamt  db 1        ; how many sectors to load
fddretr  db 5        ; max retries for fdd operations
fddcretr db 0        ; current retries left

; misc strings
welcome1 db "Welcome to the ClassicOS Stage 1 bootloader.", 13, 10, 0
disktype db "Drive type: ", 0
diskfdd  db "FDD", 13, 10, 0
diskhdd  db "HDD", 13, 10, 0
loaded   db "Data loaded!", 13, 10, 0

; errors
fdderes  db "FDD reset failed.", 13, 10, 0
fddeload db "FDD read failed.", 13, 10, 0

; storage
disknum  db 0

;;;;;;;;;;;
; Program ;
;;;;;;;;;;;

start:
   xor ax, ax             ; set up segment registers to segment 0 since
   mov ds, ax             ; our addresses are already relative to 0x7C00
   mov es, ax

   mov [disknum], dl      ; save disk number to memory

   mov ah, 0x01           ; set cursor shape
   mov cx, 0x0100         ; hide cursor by setting ch = 1 and cl = 0x00
   int 0x10               ; video interrupt

   mov ah, 0x08           ; read page number into bh
   int 0x10

   mov si, welcome1       ; print welcome
   call printstr

   mov si, disktype       ; print first part of disk type
   call printstr

   mov dl, [disknum]      ; restore disk number - should not be
                          ; strictly necessary but you never know
   and dl, 0x80           ; sets zf if disk is floppy
   jz fddload

hddload:
   mov si, diskhdd        ; print disk type
   call printstr
   jmp load_onto_reset

fddload:
   mov si, diskfdd        ; print disk type
   call printstr

load_onto_reset:
   mov ah, [fddretr]     ; load max retries in memory
   mov [fddcretr], ah
load_reset:
   mov si, fdderes        ; load error message pointer
   dec byte [fddcretr]    ; decrement the retries counter
   jz load_err         ; if it is 0, we stop trying

   mov ah, 0x00           ; otherwise, reset function (int 0x13)
   int 0x13
   jc load_reset       ; if jc (error), we try again

load_onto_load:
   mov ah, [fddretr]      ; reset retries counter
   mov [fddcretr], ah
   mov ax, 0x8000         ; need to stay within real mode limits
   mov es, ax
load_load:              ; loads 512*fddsamt bytes from sector 2 on.
   mov si, fddeload
   dec byte [fddcretr]
   jz load_err

   mov dh, 0              ; head 0
   mov ch, 0              ; cyl/track 0
   mov cl, 2              ; start sector
   mov bx, 0x8000              ; memory location
   mov al, [fddsamt]      ; how many sectors to read
   mov ah, 0x02           ; read function (int 0x13)
   int 0x13
   jc load_load        ; if jc (error), we try again
   cmp al, [fddsamt]      ; also if al is not 1, we have a problem
   jnz load_load

load_done:
   mov si, loaded         ; we have successfully loaded the data
   call printstr
   jmp 0x8000:0x0000               ; this will be jmp 0x1000:0x0000

load_err:
   call printstr          ; print
   jmp halt               ; and die

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; printstr routine, prints the string pointed by si using int 0x10 ;
; sets the direction flag to 0                                     ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
printstr:
   cld                    ; clear df flag - lodsb increments si
printstr_loop:
   lodsb                  ; load next character into al, increment si
   or al, al              ; sets zf if al is 0x00
   jz printstr_end
   mov ah, 0x0E           ; teletype output (int 0x10)
   int 0x10               ; print character
   jmp printstr_loop
printstr_end:
   ret                    ; return to caller address


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; halt routine - infinite loop ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
halt:
   cli
   jmp halt

;;;;;;;;;;;
; Padding ;
;;;;;;;;;;;
; $ is the address of the current line, $$ is the base address for
; this program.
; the expression is expanded to 510 - ($ - 0x7C00), or
; 510 + 0x7C00 - $, which is, in other words, the number of bytes
; before the address 510 + 0x7C00 (= 0x7DFD), where the 0xAA55
; signature shall be put.
times 510 - ($ - $$) db 0x00

;;;;;;;;;;;;;;;;;;
; BIOS signature ;
;;;;;;;;;;;;;;;;;;
dw 0xAA55
Modified the first stage boot loader to add HDD support and made an Op. to `jmp 0x8000:0x0000`. Still not getting `KERNEL.BIN` printed from second stage boot loader. ```asm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Stage 1 bootloader for ClassicOS ; ; -------------------------------- ; ; Determines if it was loaded from ; ; a floppy disk or an hard disk ; ; drive, and then loads stage 2 ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;; ; Assembler directives ; ;;;;;;;;;;;;;;;;;;;;;;;; ; tells the assembler that the program will be loaded at 0x7C00 ; this is done by the BIOS org 0x7C00 ; we are targeting (x86) 16-bit real mode bits 16 ;;;;;;;;;;;;;;;;; ; Jump to start ; ;;;;;;;;;;;;;;;;; jmp start ;;;;;;;; ; Data ; ;;;;;;;; ; fdd geometry & options fddsamt db 1 ; how many sectors to load fddretr db 5 ; max retries for fdd operations fddcretr db 0 ; current retries left ; misc strings welcome1 db "Welcome to the ClassicOS Stage 1 bootloader.", 13, 10, 0 disktype db "Drive type: ", 0 diskfdd db "FDD", 13, 10, 0 diskhdd db "HDD", 13, 10, 0 loaded db "Data loaded!", 13, 10, 0 ; errors fdderes db "FDD reset failed.", 13, 10, 0 fddeload db "FDD read failed.", 13, 10, 0 ; storage disknum db 0 ;;;;;;;;;;; ; Program ; ;;;;;;;;;;; start: xor ax, ax ; set up segment registers to segment 0 since mov ds, ax ; our addresses are already relative to 0x7C00 mov es, ax mov [disknum], dl ; save disk number to memory mov ah, 0x01 ; set cursor shape mov cx, 0x0100 ; hide cursor by setting ch = 1 and cl = 0x00 int 0x10 ; video interrupt mov ah, 0x08 ; read page number into bh int 0x10 mov si, welcome1 ; print welcome call printstr mov si, disktype ; print first part of disk type call printstr mov dl, [disknum] ; restore disk number - should not be ; strictly necessary but you never know and dl, 0x80 ; sets zf if disk is floppy jz fddload hddload: mov si, diskhdd ; print disk type call printstr jmp load_onto_reset fddload: mov si, diskfdd ; print disk type call printstr load_onto_reset: mov ah, [fddretr] ; load max retries in memory mov [fddcretr], ah load_reset: mov si, fdderes ; load error message pointer dec byte [fddcretr] ; decrement the retries counter jz load_err ; if it is 0, we stop trying mov ah, 0x00 ; otherwise, reset function (int 0x13) int 0x13 jc load_reset ; if jc (error), we try again load_onto_load: mov ah, [fddretr] ; reset retries counter mov [fddcretr], ah mov ax, 0x8000 ; need to stay within real mode limits mov es, ax load_load: ; loads 512*fddsamt bytes from sector 2 on. mov si, fddeload dec byte [fddcretr] jz load_err mov dh, 0 ; head 0 mov ch, 0 ; cyl/track 0 mov cl, 2 ; start sector mov bx, 0x8000 ; memory location mov al, [fddsamt] ; how many sectors to read mov ah, 0x02 ; read function (int 0x13) int 0x13 jc load_load ; if jc (error), we try again cmp al, [fddsamt] ; also if al is not 1, we have a problem jnz load_load load_done: mov si, loaded ; we have successfully loaded the data call printstr jmp 0x8000:0x0000 ; this will be jmp 0x1000:0x0000 load_err: call printstr ; print jmp halt ; and die ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; printstr routine, prints the string pointed by si using int 0x10 ; ; sets the direction flag to 0 ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; printstr: cld ; clear df flag - lodsb increments si printstr_loop: lodsb ; load next character into al, increment si or al, al ; sets zf if al is 0x00 jz printstr_end mov ah, 0x0E ; teletype output (int 0x10) int 0x10 ; print character jmp printstr_loop printstr_end: ret ; return to caller address ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; halt routine - infinite loop ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; halt: cli jmp halt ;;;;;;;;;;; ; Padding ; ;;;;;;;;;;; ; $ is the address of the current line, $$ is the base address for ; this program. ; the expression is expanded to 510 - ($ - 0x7C00), or ; 510 + 0x7C00 - $, which is, in other words, the number of bytes ; before the address 510 + 0x7C00 (= 0x7DFD), where the 0xAA55 ; signature shall be put. times 510 - ($ - $$) db 0x00 ;;;;;;;;;;;;;;;;;; ; BIOS signature ; ;;;;;;;;;;;;;;;;;; dw 0xAA55 ```
Author
Owner

@Karutoh Had to make a backup of the OS and archive it and start with a working bootloader from

http://3zanders.co.uk/2017/10/13/writing-a-bootloader/

see libera.chat IRC 6667 #gbowne1

@Karutoh Had to make a backup of the OS and archive it and start with a working bootloader from http://3zanders.co.uk/2017/10/13/writing-a-bootloader/ see libera.chat IRC 6667 #gbowne1
Sign in to join this conversation.
No Label
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: gbowne1/ClassicOS#1
No description provided.