trouble bootloading
-
- Posts: 6
- Joined: Wed Feb 01, 2012 8:16 pm
trouble bootloading
I created my own bootloader via a tutorial and it is supposed to print hello world. It works perfect in qemu, yet does not work when actualy trying to boot. Instead it skips it to my windows installation when selecting to boot directly from the drive. Any ideas as to what the problem could be?
Re: trouble bootloading
Are you sure that it's trying to boot from the right media? In that case can we see the code? Did you make sure to include the boot signature at the end of your bootsector? If not, that might be why. Your BIOS might have better error checking to see that it's indeed bootable.
-
- Posts: 6
- Joined: Wed Feb 01, 2012 8:16 pm
Re: trouble bootloading
Yes I did check to make sure that the right drive was selected in the boot menu(tried both just in case)
Here is the code that I used:
It was compiled using nasm with
I then wrote it to the drive using RMPREPUSB.
Also I have verified that it wrote by using the Drive->File function of RMPREPUSB and it showed the exact same binary as was compiled.
Any help for what I am doing wrong would be greatly apprecieated.
I am new to OS Development and figured that the best place to start would be the beginning.
Here is the code that I used:
Code: Select all
[BITS 16] ; 16 bit code generation
[ORG 0x7C00] ; Origin location
; Main program
main: ; Label for the start of the main program
mov ax,0x0000 ; Setup the Data Segment register
; Location of data is DS:Offset
mov ds,ax ; This can not be loaded directly it has to be in two steps.
; 'mov ds, 0x0000' will NOT work due to limitations on the CPU
mov si, HelloWorld ; Load the string into position for the procedure.
call PutStr ; Call/start the procedure
jmp $ ; Never ending loop
; Procedures
PutStr: ; Procedure label/start
; Set up the registers for the interrupt call
mov ah,0x0E ; The function to display a chacter (teletype)
mov bh,0x00 ; Page number
mov bl,0x07 ; Normal text attribute
.nextchar ; Internal label (needed to loop round for the next character)
lodsb ; I think of this as LOaD String Block
; (Not sure if thats the real meaning though)
; Loads [SI] into AL and increases SI by one
; Check for end of string '0'
or al,al ; Sets the zero flag if al = 0
; (OR outputs 0's where there is a zero bit in the register)
jz .return ; If the zero flag has been set go to the end of the procedure.
; Zero flag gets set when an instruction returns 0 as the answer.
int 0x10 ; Run the BIOS video interrupt
jmp .nextchar ; Loop back round tothe top
.return ; Label at the end to jump to when complete
ret ; Return to main program
; Data
HelloWorld db 'Hello World',13,10,0
; End Matter
times 510-($-$$) db 0 ; Fill the rest with zeros
dw 0xAA55 ; Boot loader signature
It was compiled using nasm with
Code: Select all
nasm.exe boot.txt -f bin -o boot
Also I have verified that it wrote by using the Drive->File function of RMPREPUSB and it showed the exact same binary as was compiled.
Any help for what I am doing wrong would be greatly apprecieated.
I am new to OS Development and figured that the best place to start would be the beginning.
-
- Member
- Posts: 52
- Joined: Mon Oct 11, 2010 11:37 pm
- Location: Milwaukee, Wisconsin
Re: trouble bootloading
I don't think the ax and bx registers are preserved by INT 10H.
I had a look at one of my boot sectors and here's my bprint function. Notice that I reload BX and AH each time through the loop.
I hope this helps.
I had a look at one of my boot sectors and here's my bprint function. Notice that I reload BX and AH each time through the loop.
Code: Select all
bprint proc near
mov bx, 0007H
lodsb
or al, al
je bpout
mov ah, 0eH
int 10H
jmp bprint
bpout:
ret
bprint endp
Microsoft is over if you want it.
-
- Posts: 6
- Joined: Wed Feb 01, 2012 8:16 pm
Re: trouble bootloading
If it simply did not preserve the values then it would at least print out one character correct? After trying it on a different computer it just hangs with a blinking line in the top left, not printing out anything.
Also I am running on a quad core, could that have something to do with it?
Also I am running on a quad core, could that have something to do with it?
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: trouble bootloading
Which is a tool originally written to make windows bootable from USB (didn't that just happen?)blazinghell wrote:I then wrote it to the drive using RMPREPUSB.
Get a decent tool that can write your bootsector to the physical first sector instead of using someone else's bootloader. A windows version of dd that supports usb drives would be the right way to go.
Re: trouble bootloading
You forget to set up a stack. Typical beginner's mistake.
You use lodsb instruction without clearing direction flag. Could be set on real machine.
Every byte counts, so do not use "mov ax, 0", use "xor ax, ax" instead.
Use correct tool (like dd or rawrite) as Combuster suggested.
You use lodsb instruction without clearing direction flag. Could be set on real machine.
Every byte counts, so do not use "mov ax, 0", use "xor ax, ax" instead.
Use correct tool (like dd or rawrite) as Combuster suggested.
Re: trouble bootloading
Hi
RMPrepUSB should work no problem (I wrote it) and is safer than dd in that it will only select a USB drive by default. The latest Beta version also has a disk editor which allows you to see and edit the sector contents (or use Disk Info button in RMPrepUSB).
If you want to write some boot code, then take a look at the TESTMBR folder which is in RMPrepUSB installation folder (press F3). It includes the source code assembler file TESTMBR.ASM which you may find informative.
In your code you are loading DS with 0 but you have the ORG set to 7c00. It might be safer to load DS with CS (via AX). Not all BIOSes load code at 7c00, many use 7c0:0 and some others use a different address. I use offset addresses for this reason. Look at the value used for the offset in the instruction mov si,'hello world' - is it correct or is it 7cxx?
For a BIOS to run the boot code, the last two bytes should be 1FE=55 1FF=AA.
P.S. lodsb is load string byte, guess what lodsw is??? ;=)
RMPrepUSB should work no problem (I wrote it) and is safer than dd in that it will only select a USB drive by default. The latest Beta version also has a disk editor which allows you to see and edit the sector contents (or use Disk Info button in RMPrepUSB).
If you want to write some boot code, then take a look at the TESTMBR folder which is in RMPrepUSB installation folder (press F3). It includes the source code assembler file TESTMBR.ASM which you may find informative.
In your code you are loading DS with 0 but you have the ORG set to 7c00. It might be safer to load DS with CS (via AX). Not all BIOSes load code at 7c00, many use 7c0:0 and some others use a different address. I use offset addresses for this reason. Look at the value used for the offset in the instruction mov si,'hello world' - is it correct or is it 7cxx?
For a BIOS to run the boot code, the last two bytes should be 1FE=55 1FF=AA.
P.S. lodsb is load string byte, guess what lodsw is??? ;=)
-
- Posts: 6
- Joined: Wed Feb 01, 2012 8:16 pm
Re: trouble bootloading
I am guessing that lodsw is loading a string word? BTW props for the awesome app, it works wonderfully on vista, something that most others fail to do. Also it works when using external hard drives connected via USB XD.
Also thanks for your input, although I am rather limited on time right now I will be sure to try out your suggestions later today.
@combuster no it did not boot windows from the usb... it booted it from my primary hdd, completely skipping over the bootloader probably because I screwed it up...
Also does anyone know why this runs in an emulator but not on the real machine? At this point I just want to see something happen.
Also thanks for your input, although I am rather limited on time right now I will be sure to try out your suggestions later today.
@combuster no it did not boot windows from the usb... it booted it from my primary hdd, completely skipping over the bootloader probably because I screwed it up...
Also does anyone know why this runs in an emulator but not on the real machine? At this point I just want to see something happen.
Re: trouble bootloading
Just out of curiosity,what kind of media are you running it as in QEMU? if you have a floppy drive, i might suggest testing it on there
Not sane
Just remember, FIND Is Not DOS
Just remember, FIND Is Not DOS
-
- Posts: 6
- Joined: Wed Feb 01, 2012 8:16 pm
Re: trouble bootloading
I am booting it as a hard disk in qemu through the rmprepUSB test buton
After trying the real mode assembly tutorial, the one where the OS is put into the boot sector I can verify that rmprepusb is working just fine. As such the problem is not the tools but the code itself. I guess it is time to hit the assebly books and get to work. Thanks again for all your help everyone, and let me know if you find out what is broken, as I am still largely a newb in assembly. . . Goo c/c++
After trying the real mode assembly tutorial, the one where the OS is put into the boot sector I can verify that rmprepusb is working just fine. As such the problem is not the tools but the code itself. I guess it is time to hit the assebly books and get to work. Thanks again for all your help everyone, and let me know if you find out what is broken, as I am still largely a newb in assembly. . . Goo c/c++
- DavidCooper
- Member
- Posts: 1150
- Joined: Wed Oct 27, 2010 4:53 pm
- Location: Scotland
Re: trouble bootloading
You say it gets bypassed on one machine which just ignores it and boots Windows, while another machine tries to boot it and just blinks a cursor at you. That suggests that one of the machines has loaded and started to run your boot sector, but you go straight into some code using the BIOS to print to the screen which opens up loads of opportunities for bugs which I can't be bothered hunting down. Why don't you just start by putting b800 into es (via ax), then put 0 in di, then put 65 in al (decimal value for the letter A) and 12 (colour value for red) in ah and send them to the top left corner of the screen with stosw, and then go into a long or infinite loop (best to go for an infinite one as a simple long loop will be so quick on a modern machine that the red A could still be overwritten with nothing before you get a chance to see it). If you do that you'll find out for certain if any of your code is running.blazinghell wrote:As such the problem is not the tools but the code itself. I guess it is time to hit the assebly books and get to work.
The reason one machine is working and the other not may be something to do with where you've stored your boot sector on the USB drive. Is it at the start of a partition, or have you overwritten the MBR with it? If the latter, it will pretend to be a floppy disk, whereas the former will pretend to be a hard disk. From what I've read, some machines can boot using either arrangement, while others can only handle one of them (though you may be able to change a setting in the BIOS to switch it). More than that I do not know and I cannot be sure that even that is correct, but it would fit with what you're finding.
Edit: I've had a quick look through it for bugs and can't see anything obvious. I don't have a proper copy of the BIOS calls for printing chars - no one serious uses them these days.
Assuming those are right, there's no guarantee that they're preserved after each BIOS call - you should push them all and pop them afterwards to be on the safe side. I wouldn't be surprised if a modern BIOS has a major bug in this function either as there can't be many programs that would ever put it to the test.blazinghell wrote: PutStr: ; Procedure label/start
; Set up the registers for the interrupt call
mov ah,0x0E ; The function to display a chacter (teletype)
mov bh,0x00 ; Page number
mov bl,0x07 ; Normal text attribute
I suspect the b stands for byte, and the w in lodsw stands for word.lodsb ; I think of this as LOaD String Block
; (Not sure if thats the real meaning though)
Help the people of Laos by liking - https://www.facebook.com/TheSBInitiative/?ref=py_c
MSB-OS: http://www.magicschoolbook.com/computing/os-project - direct machine code programming
MSB-OS: http://www.magicschoolbook.com/computing/os-project - direct machine code programming
-
- Posts: 6
- Joined: Wed Feb 01, 2012 8:16 pm
Re: trouble bootloading
David you are a genius!!!
i was overwriting the mbr, so I switched to writing it to the primary partition and it booted up like a dream. Though this is the assembly os that does not use a bootloader, I have pretty much abandoned the above code and will modify the assembly os to suit my needs.
Thank you so much for your help everyone.
i was overwriting the mbr, so I switched to writing it to the primary partition and it booted up like a dream. Though this is the assembly os that does not use a bootloader, I have pretty much abandoned the above code and will modify the assembly os to suit my needs.
Thank you so much for your help everyone.
-
- Posts: 14
- Joined: Tue Feb 07, 2012 10:10 am
Re: trouble bootloading
I am trying to build a simple boot loader. I have this code working on bochs on two separate computers, and it boots via usb on a Dell inspiron 1750 (intel pentium inside), however on my box with ASUS M3N-HT deluxe, with AMD Penom x64 Quad, It does not boot via USB, just a flashy cursor in the corner. I am wondering if I am having similar issues as above, or if my bootloader is going completely in the wrong direction.
The following code works on all applications except my AMD via usb.
wondering if it has something to do with intel vs. AMD syntax??? I was under the impression they should be identical... Any help is greatly appreciated.
The following code works on all applications except my AMD via usb.
wondering if it has something to do with intel vs. AMD syntax??? I was under the impression they should be identical... Any help is greatly appreciated.
Code: Select all
;==============================================================================
; test assembled with: cd %COSPATH%/fasm/ && ./fasm %PATH%/CruiseOS/kernel_sa.asm %PATH%/CruiseOS/kernel.bin
; ".bin" is for flashing to bochs hdd image
; release assembled with: cd %COSPATH%/fasm/ && ./fasm %PATH%/CruiseOS/kernel.asm %PATH%/CruiseOS/kernel.img
; ".img" is for flashing onto usb
; Kernel is flashed to usb using ImageWriter for Ubuntu
; Kernel is flashed to a 4gb bochs hdd using a cpp program I created, let me know if you need a copy of the
; program source.
;
;File Name: kernel_sa.asm
;Revision: New
;Date Created: January 15th, 2012
;Date Last Modified: February 7th 2012
;Version: 0.0.0b.0
;Supported OS: CruiseOS
;Author: Timothy Giddens
;
;Assembled with: FASM
; ver: 1.69.35
;Overview:
; This is the kernel modual of CruiseOS with minimum procedures directly included, so
; that this is stand alone. This file is intended for use when asking for help.
format binary ;FASM outputs the file in machine code directly as writen below
;This is to facilitate flashing directly to USB
use16 ;Use x86 16-bit opcodes
label BOOT_SEC_START at 0x07C0 ;BIOS loads boot sec into segment:offset 0x07C0:0000
mov ax, BOOT_SEC_START ;Initialize segments for boot loader
mov ds, ax
mov es, ax
LBA_CHECK: ;This checks the BIOS for LBA compatability
mov ah, 0x41 ;BIOS LBA Check operation
mov bx, 0x55AA
mov dl, 0x80 ;HDD 1 (susspect this is why not booting on AMD box)
int 0x13
; jc error ;Sets carry on error. Some sort of exeption handler will go here eventually
DAP: ;(Disk Address Packet)This data structure is used for LBA reads
db 0x10 ;Always 0x10 (16) (structure size)
db 0x00 ;Always 0x00
dw 0x0003 ;Number of LBA's to read (512 bytes per LBA) (max 16 sectors per read) (max 8192 bytes per read)
dd 0x0000:0x0500 ;Segment:offset of memory to read bytes to.
dq 0x0000000000000001 ;LBA # to start read.
LBA_READ: ;This reads data from hdd
mov si, DAP ;Point to data structure
mov ah, 0x42 ;BIOS LBA read operation
mov dl, 0x80 ;
int 0x13
jmp 0x00:0x0500 ;Jump to kernel segment
db 510-($-$$) dup 0 ; boot sector must be 510 bytes plus 2 bytes at BOOT_SEC_END
BOOT_SEC_END:
db 0x55
db 0xAA
org 0x0500 ;Set everything to address from zero in kernel segment
KERNEL_START16: ;Start of 16-bit mode
;***********************Macros************************
macro ClrScr
{
call clr_scr
}
macro WriteString STRING* ;STRING structure, or reg pointing to
;string
{
pushad
mov si, STRING
call write_string
popad
}
macro GetInput BUFFER* ;BUFFER structure
{
mov di, BUFFER
mov dh, [#BUFFER#.size]
call get_input
}
macro strcmp string1*,string2*
{
pushad
mov si, string1
mov di, string2
call pStrcmp
popad
}
struc STRING [string]
;structure creates a null terminated string and a size.
{
common
. db string
db 0
.size = $ - .
}
struc BUFFER size
;creates a buffer of size.
{
common
. db size dup 0
.size = $ - .
}
lf equ 0x0A
cr equ 0x0D
nl equ lf,cr
;*********************END MACROS***************************
mov ax, 0x0000 ; set up segments
mov ds, ax
mov es, ax
jmp start
start:
ClrScr
WriteString welcome
jmp mainloop
mainloop:
WriteString prompt
GetInput input
mov si, input
cmp byte [si], 0 ;If the input line is blank ignore it
je mainloop ;
strcmp cmd_hi, input ; "hi" command
jc .helloworld
strcmp cmd_help, input ; "help" command
jc .help
strcmp cmd_test, input ; "test" command
jc .test
WriteString badcommand
jmp mainloop
.helloworld:
WriteString msg_helloworld
jmp mainloop
.help:
WriteString msg_help
jmp mainloop
;*****************TEST PROGRAM AREA******************
;This is where I am putting code as I test my system
.test:
jmp mainloop
;*****************END TEST AREA**********************
;*****************DATA*******************************
welcome STRING 'Welcome to CruiseOS V.0.0.0b.0!',nl
msg_helloworld STRING 'Hello User!',nl
badcommand STRING 'Bad command entered.',nl
prompt STRING '$>'
cmd_hi STRING 'hi'
cmd_help STRING 'help'
cmd_test STRING 'test'
msg_help STRING 'My OS: Commands: hi, help, test',nl
input BUFFER 64
KERNEL_END:
;*******************Procedures********************
;These were all pulled out of the include files
;So this can be assembled and tested as is,
;Thanks for your help!.
clr_scr:
pusha
mov cx, 0x0000 ;0x'row''column' (upper row)
mov dx, 0x184F ;0x'row''column' (lower row)
mov bh, 0x07 ;black bkgd, white cursor blink enabled
;will change this to a var later
mov ax, 0x0600 ;0x'scroll up''num rows' 0=all
int 0x10 ;BIOS interrupt
mov bh, 0x00 ;Page number
mov dx, 0x0000 ;0x'row''column'
mov ah, 0x02 ;Set cursor position
int 0x10 ;BIOS interrupt
popa
ret ;END clr_scr
write_string:
lodsb ;Load a byte based on SI
or al, al ;If result is zero then al is zero
jz .done ;and we have reached end of string
mov ah, 0x0E ;If al not zero print the character
int 0x10 ;
jmp write_string ;Try next character
.done: ;Done printing
ret
;End WriteString
get_input:
xor cl, cl ;wipe out cl used as a counter
.loop:
mov ah, 0 ;wait for user keypress
int 0x16 ;users key will be in AL
cmp al, 0x08
je .backspace ;Handle backspace event
cmp al, 0x0D
je .done ;Handle enter/return event
cmp al, 0x1B ;
je .escape ;handle escape event
sub dh, 1
cmp cl, dh ;Will only read in up to one less buffer size
je .loop ;If limit is reached only enter and backspace is read
mov ah, 0x0E
int 0x10 ;Print out "Echo" character
stosb ;put character in buffer
inc cl ;Increment character count
jmp .loop ;Return for more input
.backspace: ;Handle backspace event
cmp cl, 0 ;If this is the beginning of the prompt
je .loop ;ignore that backspace was pressed
dec di ;Move back one character in "buffer"
mov byte [di], 0 ;Write a null "delete character"
dec cl ;decrement character count
mov ah, 0x0E ;"Echo" backspace
mov al, 0x08 ;"cursor back one space"
int 10h ;
mov al, ' ' ;black char print
int 10h ;
mov al, 0x08 ;"cursor back one space"
int 0x10 ;
jmp .loop ;Get more input
.escape:
cmp cl, 0
jg .decpos
mov byte [di], 0x1B
jmp .done
.decpos:
cmp cl, 0 ;If this is the beginning of the prompt
je .loop ;ignore that backspace was pressed
dec di ;Move back one character in "buffer"
mov byte [di], 0 ;Write a null "delete character"
dec cl ;decrement character count
mov ah, 0x0E ;"Echo" backspace
mov al, 0x08 ;"cursor back one space"
int 10h ;
mov al, ' ' ;black char print
int 10h ;
mov al, 0x08 ;"cursor back one space"
int 10h
jmp .escape
.done:
mov al, 0 ;Add a null terminator to the string
stosb
mov ah, 0x0E ;Move cursor to new line
mov al, 0x0D ;Carriage Return
int 0x10
mov al, 0x0A ;Line Feed
int 0x10
ret
;End get_input
pStrcmp:
.loop:
mov al, [si] ;Grab a byte from SI
mov bl, [di] ;Grab a byte from DI
cmp al, bl ;Are the two equal?
jne .notequal ;If not then exit.
cmp al, 0 ;If both bytes are here they are equal, if they are null then the strings are finished
je .done ;yes, we're done.
inc di ;increment DI
inc si ;increment SI
jmp .loop ;
.notequal:
clc ;Clear the carry flag if strings are not equal
ret
.done:
stc ;Set the carry flag if strings are equal
ret
;End strcmp
macro mPadhddseg
;
; the intent of this macro is to pad the current address space to a 512
; byte boundry for direct flashing of the kernel so that it boots
; properly.
;
{
if $-$$ = 0
else
pad equ (((($-$$)/512)+1)*512)-($-$$)
if pad = 0
else
db pad dup 0
end if
end if
}
mPadhddseg
Re: trouble bootloading
Intel vs. AMD syntax? Wtf?Ariethenor wrote:I am trying to build a simple boot loader. I have this code working on bochs on two separate computers, and it boots via usb on a Dell inspiron 1750 (intel pentium inside), however on my box with ASUS M3N-HT deluxe, with AMD Penom x64 Quad, It does not boot via USB, just a flashy cursor in the corner. I am wondering if I am having similar issues as above, or if my bootloader is going completely in the wrong direction.
The following code works on all applications except my AMD via usb.
wondering if it has something to do with intel vs. AMD syntax??? I was under the impression they should be identical... Any help is greatly appreciated.
It's full of bugs. You do not set up a stack, clear direction flag, disable interrupts, etc. etc. etc.
Works with error check disabled? And executing lba packet? It's really hard to believe it works at all...Code: Select all
; jc error ;Sets carry on error. Some sort of exeption handler will go here eventually DAP: ;(Disk Address Packet)This data structure is used for LBA reads db 0x10 ;Always 0x10 (16) (structure size) db 0x00 ;Always 0x00 dw 0x0003 ;Number of LBA's to read (512 bytes per LBA) (max 16 sectors per read) (max 8192 bytes per read) dd 0x0000:0x0500 ;Segment:offset of memory to read bytes to. dq 0x0000000000000001 ;LBA # to start read.
Edit: oh, and you do not take into count partitions. GPT impossible by your design, MBR partitions missing. USB drives must have at least one partition.