prabirshrestha avatar prabirshrestha committed 4d01f98

boot.c

Comments (0)

Files changed (7)

 CC = $(TOOLPATH)/clang/bin/clang
 CXX = $(TOOLPATH)/clang/bin/clang
 
+#CC = $(TOOLPATH)/gcc/bin/$(TOOLPREFIX)gcc
+
 AS = $(TOOLPATH)/gcc/bin/$(TOOLPREFIX)as
 LD = $(TOOLPATH)/gcc/bin/$(TOOLPREFIX)ld
 AR = $(TOOLPATH)/gcc/bin/$(TOOLPREFIX)ar

src/boot/x86/Makefile

 -include ../../../Makefile.config
 
-all: boot.bin boot1_5.bin floppy.img
+all: boot0.bin boot1_5all.bin floppy.img
 
-floppy.img: boot.bin boot1_5.bin
+boot0.o:
+	$(AS) -o $@ boot0.s
+
+boot0.out: boot0.o
+	$(LD) -nostartfiles -nostdlib -o boot0.out boot0.o -Ttext 0x7c00
+
+boot0.asm: boot0.out
+	$(OBJDUMP) -S boot0.out > boot0.asm
+
+boot0.bin: boot0.out
+	$(OBJCOPY) -O binary -j .text boot0.out boot0.bin
+
+boot1_5all.out:  boot1_5.o boot.o
+	$(LD) -T link.ld -o boot1_5all.out boot1_5.o boot.o
+
+boot1_5all.asm: boot1_5all.out
+	$(OBJDUMP) -S boot1_5all.out > boot1_5all.asm
+
+boot1_5all.bin: boot1_5.o boot.o
+	$(LD) -T link.ld -O binary -o boot1_5all.bin boot1_5.o boot.o
+
+boot1_5.o:
+	$(AS) -o $@ boot1_5.s
+
+floppy.img: boot0.bin boot1_5all.bin
 	# create an empty image
 	dd if=/dev/zero of=floppy.img bs=512 count=1440
 	mkdosfs -F 12 floppy.img
 
 	# copy mbr
-	dd if=boot.bin of=floppy.img bs=512 seek=0 count=1 conv=notrunc
+	dd if=boot0.bin of=floppy.img bs=512 seek=0 count=1 conv=notrunc
 
 	# copy stage 1.5 (32768 bytes / 32 kiB)
-	dd if=boot1_5.bin of=floppy.img bs=512 seek=1 conv=notrunc
+	dd if=boot1_5all.bin of=floppy.img bs=512 seek=1 conv=notrunc
 
 	# # mount floppy
 	# sudo mount -o loop floppy.img /media/floppy/
 	# # unmount floppy
 	# sudo mount /media/floppy/
 
-boot.bin: boot.out
-	$(OBJCOPY) -O binary -j .text boot.out boot.bin
-
-boot.out: boot.o
-	$(LD) -nostartfiles -nostdlib -o boot.out boot.o -Ttext 0x7c00
-	# $(OBJDUMP) -S boot.out > boot.asm
-
-boot.o:
-	$(AS) -o $@ boot.s
-
-boot1_5.bin: boot1_5.out
-	$(OBJCOPY) -O binary -j .text boot1_5.out boot1_5.bin
-
-boot1_5.out: boot1_5.o
-	$(LD) -nostartfiles -nostdlib -o boot1_5.out boot1_5.o -Ttext 0x1000
-	# $(OBJDUMP) -S boot1_5.out > boot1_5.asm
-
-boot1_5.o:
-	$(AS) -o $@ boot1_5.s
-
 qemu: floppy.img
 	$(QEMU) -m 16 -fda floppy.img
 
 	@echo "***     to set breakpoint at address 0x7c00"
 	@echo "***         b *0x7c00"
 	@echo "***    to set breakpoint using names load file first then set breakpoint"
-	@echo "***         file boot.out"
+	@echo "***         file boot0.out"
 	@echo "***         b main"
 	@echo "***    to continue until next breakpoint"
 	@echo "***         continue"

src/boot/x86/boot.c

+
+
+int bmain() {
+	/* Print a letter to screen to see everything is working: */
+   unsigned char *videoram = (char *)0xB8000;
+   videoram[0] = 67; /* character 'C' */
+   videoram[1] = 0x07; /* light grey (7) on black (0). */
+
+   while(1);
+}

src/boot/x86/boot.s

-# references:
-#   http://www.freebsd.org/doc/en/books/arch-handbook/book.html
-#   http://www.websofia.com/2011/10/writing-your-own-boot-loader-for-a-toy-operating-system-1/
-#   http://pastebin.com/HHcqnAuT
-
-# During boot, certain PC registers are set to a particurlar value.
-# instruction pointer (ip) register is set to 32-bit value of 0xfffffff0
-#   ip register points to the code to be executed.
-# cr0 register set to 0
-#   it is a 32-bit control register
-#   one of cr0's bit indicates whether the processor is runing in real or protected mode.
-#   during boot time this bit is cleared so it always boots in real mode.
-# value of 0xfffffff0 is slightly less then 4gb.
-
-# BIOS and its chip on motherboard has a small amount of ROM which contains
-# various low-level routines that are specific to the hardware suplied with motherboard.
-# So, the processor will first jump to the address 0xfffffff0,
-# which really resides in the BIOS's memory.
-# Usually this address contains a jump instruction to the BIOS's POST routines.
-
-# POST stands for Power On Self Test.
-# This is a set of routines including the
-#   memory check,
-#   system bus check
-#   and other low-level stuff
-# so that the CPU can initialize the computer properly.
-# The important step on this stage is determining the boot device.
-# All modern BIOS's allow the boot device to be set manually, so you can boot from a floppy, CD-ROM, harddisk etc.
-
-# The very last thing in the POST is the INT 0x19 instruction
-# That instruction reads 512 bytes from the first sector of boot device into the memory at address 0x7c00
-# This is first sector is also called MBR or Master Boot Record
-
-.code16                     # 16 bit code generation
-                            # Since all intel based start up with 16-bit instructions,
-                            # we won't be able to write 32 bit code yet. 
-
-.intel_syntax noprefix      # instruct GNU assembler that we’ll be using Intel syntax
-                            # (e.g. mov ax, 1 instead of movw $1, %ax – some prefer the latter
-
-.text                       # code segment
-.org 0x0                    # the origin of our code will be 0×0,
-                            # i.e. all absolute addresses start at 0×0, which will be convenient.
-
-# Constants
-.set STAGE2_SEGMENT, 0x0000     # stage 2 load segment
-.set STAGE2_OFFSET, 0x1000 - 24 # stage 2 load offset
-.set STAGE2_BYTES, 0x8000       # 32768 bytes / 32 kiB.
-.set STAGE2_SECTORS, 54         # Stage 2 sectors (CHS HDDs)
-
-.global main                # making entry point visible to the linker
-
-main:
-    jmp stage1_start        # this is the main entry point of our code which corresponds to the first byte
-    nop                     # of actual output when assembled The code under "main" simply jumps over the
-                            # BPB and EBPB located at offset 0×3, resuming execution at the label stage1_start. 
-
-
-
-# code that prints a "Press any key to reboot" message, waits for a keystroke, and reboots the machine.
-.func Reboot
- Reboot:
-    lea    si, rebootmsg # Load address of reboot message into si
-    call   WriteString   # print the string
-    xor    ax, ax        # subfuction 0
-    int    0x16          # call bios to wait for key
-    .byte  0xEA          # machine language to jump to FFFF:0000 (reboot)
-    .word  0x0000
-    .word  0xFFFF
-.endfunc
-
-# Printing on screen
-# function that uses BIOS interrupt 0×10, sub-function 9 to print characters to the screen
-# The calling code must point DS:SI to the null-terminated string to be printed
-.func WriteString
- WriteString:
-    lodsb                   # load byte at ds:si into al (advancing si)
-    or     al, al           # test if character is 0 (end)
-    jz     WriteString_done # jump to end if 0.
-    mov    ah, 0xe          # Subfunction 0xe of int 10h (video teletype output)
-    mov    bx, 9            # Set bh (page nr) to 0, and bl (attribute) to white (9)
-    int    0x10             # call BIOS interrupt
-    jmp    WriteString      # Repeat for next character
-
- WriteString_done:
-    retw
-.endfunc
-
-# Write a string to stdout.
-# str = string to write
-.macro mWriteString str
-  lea    si,    \str
-  call   WriteString
-.endm
-
-# Reset disk system.
-# This is done through interrupt 0x13, subfunction 0.
-# If reset fails, carry is set and we jump to reboot.
-.macro mResetFddSystem
-  mov  dl, iBootDrive    # drive to reset
-  xor  ax, ax            # subfunction 0
-  int  0x13              # call interrupt 13h
-  # jc   bootFailure       # display error message if carry set (error)  
-.endm
-
-stage1_start:
-# Initialize various segments:
-# - The boot sector is loaded by BIOS at 0:7C00 (CS = 0)
-# - CS, DS and ES are set to zero.
-# - Stack point is set to 0x7C00 and will grow down from there.
-# - Interrupts may not act now, so they are disabled.
-    cli                     # block all maskable interrupts (does not block NMI - non-maskable interrupts)
-    mov  ax, cs             # CS is set to 0x0, because that is where boot sector is loaded (0:07c00)
-    mov  ds, ax             # DS = CS = 0x0 
-    mov  es, ax             # ES = CS = 0x0
-    mov  ss, ax             # SS = CS = 0x0
-    mov  sp, 0x7C00         # Stack grows down from offset 0x7C00 toward 0x0000.
-    mov  iBootDrive, dl     # save what drive we booted from (should be 0x0)
-                            # BIOS places the number of the boot drive in the DL register. We store it in our BPB for later use.
-    sti                     # enable interrupts
-#end init segements
-
-# Decide whether we are booting from hard disk (HDD) or floppy (FDD).
-is_hdd_or_fdd:
-    cmp byte ptr[iBootDrive], 0x0 # fdd(0x0), hdd(0x80)
-    je read_fdd
-    mWriteString hdd
-    jmp hang
-
-read_fdd:
-  # display A
-  mov ah,0x0E 
-  mov bh,0x00 
-  mov al,65
-  int 0x10
-
-  mResetFddSystem
-
-  # Set ES:BX to STAGE2_SEGMENT:STAGE2_OFFSET
-  mov     bx,     STAGE2_SEGMENT
-  mov     es,     bx
-  mov     bx,     STAGE2_OFFSET
-  
-  mov ax,0x1000 # When we read the sector, we are going to read address 0x1000
-  mov es,ax   #Set ES with 0x1000
-
-# Try to read the sectors.
-read_floppy_sectors:
-    mov     ah,     0x02            # Read sectors.
-    mov     al,     STAGE2_SECTORS  # Sectors 0 .. 63.
-    mov     ch,     0               # Cylinder 0.
-    mov     cl,     2               # Sector 2.
-    mov     dh,     0               # Head 0.
-    mov     dl,     [iBootDrive]        # Use the BIOS device.
-    int     0x13
-    jc read_floppy_sectors # If carry flag was set, try again (todo: retry)
-
-start_stage_1_5:
-  jmp STAGE2_OFFSET:STAGE2_SEGMENT # Jump to the start of second program
-
-# using combination of cli/hlt/jmp can create better efficient power saving
-# infinite loops then just using jmp
-hang:
-    cli                     # block all maskable interrupts (does not block NMI - non-maskable interrupts)
-    .hang:
-        hlt                 # halts until an interrup occurs
-        jmp .hang           # infinite loop
-
-bootFailure:
-  lea  si, diskerror
-  call WriteString
-  call Reboot
-
-# Data Section
-iBootDrive:     .byte   0   # holds drive that the boot sector came from
-fdd:  .asciz "fdd"
-hdd:  .asciz "hdd"
-diskerror:  .asciz "Disk error"
-rebootmsg:  .asciz "Press any key to reboot"
-r:  .asciz "r"
-
-.fill (510-(.-main)), 1, 0  # Pad with nulls up to 510 bytes (exclude boot magic)
-
-BootMagic:  .int 0xAA55     # magic word for BIOS
-                            # if the last word of bootsector contains 0xAA55,
-                            # then this disk is treated by BIOS as bootable

src/boot/x86/boot0.s

+# references:
+#   http://www.freebsd.org/doc/en/books/arch-handbook/book.html
+#   http://www.websofia.com/2011/10/writing-your-own-boot-loader-for-a-toy-operating-system-1/
+#   http://pastebin.com/HHcqnAuT
+
+# During boot, certain PC registers are set to a particurlar value.
+# instruction pointer (ip) register is set to 32-bit value of 0xfffffff0
+#   ip register points to the code to be executed.
+# cr0 register set to 0
+#   it is a 32-bit control register
+#   one of cr0's bit indicates whether the processor is runing in real or protected mode.
+#   during boot time this bit is cleared so it always boots in real mode.
+# value of 0xfffffff0 is slightly less then 4gb.
+
+# BIOS and its chip on motherboard has a small amount of ROM which contains
+# various low-level routines that are specific to the hardware suplied with motherboard.
+# So, the processor will first jump to the address 0xfffffff0,
+# which really resides in the BIOS's memory.
+# Usually this address contains a jump instruction to the BIOS's POST routines.
+
+# POST stands for Power On Self Test.
+# This is a set of routines including the
+#   memory check,
+#   system bus check
+#   and other low-level stuff
+# so that the CPU can initialize the computer properly.
+# The important step on this stage is determining the boot device.
+# All modern BIOS's allow the boot device to be set manually, so you can boot from a floppy, CD-ROM, harddisk etc.
+
+# The very last thing in the POST is the INT 0x19 instruction
+# That instruction reads 512 bytes from the first sector of boot device into the memory at address 0x7c00
+# This is first sector is also called MBR or Master Boot Record
+
+.code16                     # 16 bit code generation
+                            # Since all intel based start up with 16-bit instructions,
+                            # we won't be able to write 32 bit code yet. 
+
+.intel_syntax noprefix      # instruct GNU assembler that we’ll be using Intel syntax
+                            # (e.g. mov ax, 1 instead of movw $1, %ax – some prefer the latter
+
+.text                       # code segment
+.org 0x0                    # the origin of our code will be 0×0,
+                            # i.e. all absolute addresses start at 0×0, which will be convenient.
+
+# Constants
+.set STAGE2_SEGMENT, 0x0000     # stage 2 load segment
+.set STAGE2_OFFSET, 0x1000 - 24 # stage 2 load offset
+.set STAGE2_BYTES, 0x8000       # 32768 bytes / 32 kiB.
+.set STAGE2_SECTORS, 54         # Stage 2 sectors (CHS HDDs)
+
+.global main                # making entry point visible to the linker
+
+main:
+    jmp stage1_start        # this is the main entry point of our code which corresponds to the first byte
+    nop                     # of actual output when assembled The code under "main" simply jumps over the
+                            # BPB and EBPB located at offset 0×3, resuming execution at the label stage1_start. 
+
+
+
+# code that prints a "Press any key to reboot" message, waits for a keystroke, and reboots the machine.
+.func Reboot
+ Reboot:
+    lea    si, rebootmsg # Load address of reboot message into si
+    call   WriteString   # print the string
+    xor    ax, ax        # subfuction 0
+    int    0x16          # call bios to wait for key
+    .byte  0xEA          # machine language to jump to FFFF:0000 (reboot)
+    .word  0x0000
+    .word  0xFFFF
+.endfunc
+
+# Printing on screen
+# function that uses BIOS interrupt 0×10, sub-function 9 to print characters to the screen
+# The calling code must point DS:SI to the null-terminated string to be printed
+.func WriteString
+ WriteString:
+    lodsb                   # load byte at ds:si into al (advancing si)
+    or     al, al           # test if character is 0 (end)
+    jz     WriteString_done # jump to end if 0.
+    mov    ah, 0xe          # Subfunction 0xe of int 10h (video teletype output)
+    mov    bx, 9            # Set bh (page nr) to 0, and bl (attribute) to white (9)
+    int    0x10             # call BIOS interrupt
+    jmp    WriteString      # Repeat for next character
+
+ WriteString_done:
+    retw
+.endfunc
+
+# Write a string to stdout.
+# str = string to write
+.macro mWriteString str
+  lea    si,    \str
+  call   WriteString
+.endm
+
+# Reset disk system.
+# This is done through interrupt 0x13, subfunction 0.
+# If reset fails, carry is set and we jump to reboot.
+.macro mResetFddSystem
+  mov  dl, iBootDrive    # drive to reset
+  xor  ax, ax            # subfunction 0
+  int  0x13              # call interrupt 13h
+  # jc   bootFailure       # display error message if carry set (error)  
+.endm
+
+stage1_start:
+# Initialize various segments:
+# - The boot sector is loaded by BIOS at 0:7C00 (CS = 0)
+# - CS, DS and ES are set to zero.
+# - Stack point is set to 0x7C00 and will grow down from there.
+# - Interrupts may not act now, so they are disabled.
+    cli                     # block all maskable interrupts (does not block NMI - non-maskable interrupts)
+    mov  ax, cs             # CS is set to 0x0, because that is where boot sector is loaded (0:07c00)
+    mov  ds, ax             # DS = CS = 0x0 
+    mov  es, ax             # ES = CS = 0x0
+    mov  ss, ax             # SS = CS = 0x0
+    mov  sp, 0x7C00         # Stack grows down from offset 0x7C00 toward 0x0000.
+    mov  iBootDrive, dl     # save what drive we booted from (should be 0x0)
+                            # BIOS places the number of the boot drive in the DL register. We store it in our BPB for later use.
+    sti                     # enable interrupts
+#end init segements
+
+# Decide whether we are booting from hard disk (HDD) or floppy (FDD).
+is_hdd_or_fdd:
+    cmp byte ptr[iBootDrive], 0x0 # fdd(0x0), hdd(0x80)
+    je read_fdd
+    mWriteString hdd
+    jmp hang
+
+read_fdd:
+  # display A
+  mov ah,0x0E 
+  mov bh,0x00 
+  mov al,65
+  int 0x10
+
+  mResetFddSystem
+
+  # Set ES:BX to STAGE2_SEGMENT:STAGE2_OFFSET
+  mov     bx,     STAGE2_SEGMENT
+  mov     es,     bx
+  mov     bx,     STAGE2_OFFSET
+  
+  mov ax,0x1000 # When we read the sector, we are going to read address 0x1000
+  mov es,ax   #Set ES with 0x1000
+
+# Try to read the sectors.
+read_floppy_sectors:
+    mov     ah,     0x02            # Read sectors.
+    mov     al,     STAGE2_SECTORS  # Sectors 0 .. 63.
+    mov     ch,     0               # Cylinder 0.
+    mov     cl,     2               # Sector 2.
+    mov     dh,     0               # Head 0.
+    mov     dl,     [iBootDrive]    # Use the BIOS device.
+    int     0x13
+    jc read_floppy_sectors # If carry flag was set, try again (todo: retry)
+
+start_stage_1_5:
+  jmp STAGE2_OFFSET:STAGE2_SEGMENT # Jump to the start of second program
+
+# using combination of cli/hlt/jmp can create better efficient power saving
+# infinite loops then just using jmp
+hang:
+    cli                     # block all maskable interrupts (does not block NMI - non-maskable interrupts)
+    .hang:
+        hlt                 # halts until an interrup occurs
+        jmp .hang           # infinite loop
+
+bootFailure:
+  lea  si, diskerror
+  call WriteString
+  call Reboot
+
+# Data Section
+iBootDrive:     .byte   0   # holds drive that the boot sector came from
+fdd:  .asciz "fdd"
+hdd:  .asciz "hdd"
+diskerror:  .asciz "Disk error"
+rebootmsg:  .asciz "Press any key to reboot"
+r:  .asciz "r"
+
+.fill (510-(.-main)), 1, 0  # Pad with nulls up to 510 bytes (exclude boot magic)
+
+BootMagic:  .int 0xAA55     # magic word for BIOS
+                            # if the last word of bootsector contains 0xAA55,
+                            # then this disk is treated by BIOS as bootable

src/boot/x86/boot1_5.s

 .org 0x0                    # the origin of our code will be 0×0,
                             # i.e. all absolute addresses start at 0×0, which will be convenient.
 
-main:
+.global start, _start               # making entry point visible to the linker
+
+start:
+_start:
     jmp stage1_5
 
 stage1_5:
+# .fill (512-(.-stage1_5)), 1, 0  # Pad with nulls up to 510 bytes (exclude boot magic)
+
   # display B
   mov ah,0x0E 
   mov bh,0x00 
   mov al,66
   int 0x10
 
-hang:
-    jmp hang
+  call bmain

src/boot/x86/link.ld

+OUTPUT_FORMAT("binary")
+SECTIONS
+{
+    . = 0x00100000;
+
+    .text ALIGN (0x1000) :
+    {
+        *(.text)
+    }
+
+    .rodata ALIGN (0x1000) :
+    {
+        *(.rodata*)
+    }
+
+    .data ALIGN (0x1000) :
+    {
+        *(.data)
+    }
+
+    .bss :
+    {
+        sbss = .;
+        *(COMMON)
+        *(.bss)
+        ebss = .;
+    }
+}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.