OS Development. Bootloader question

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
Milnadar
Posts: 3
Joined: Thu Aug 14, 2014 6:25 am

OS Development. Bootloader question

Post by Milnadar »

Hello everyone. I started to study OS development and got stuck with bootloader.
In an old online course i've found there was a task
Trace through the first few instructions of the boot loader again and identify the first instruction that would "break" or otherwise do the wrong thing if you were to get the boot loader's link address wrong. Then change the link address in Makefile to something wrong, run make clean, recompile the lab with make, and trace into the boot loader again to see what happens. Don't forget to change the link address back and make clean again afterward!
So here is the bootloader code:

Code: Select all

start:
  cli                         # BIOS enabled interrupts; disable

  # Zero data segment registers DS, ES, and SS.
  xorw    %ax,%ax             # Set %ax to zero
  movw    %ax,%ds             # -> Data Segment
  movw    %ax,%es             # -> Extra Segment
  movw    %ax,%ss             # -> Stack Segment

  # Physical address line A20 is tied to zero so that the first PCs 
  # with 2 MB would run software that assumed 1 MB.  Undo that.
seta20.1:
  inb     $0x64,%al               # Wait for not busy
  testb   $0x2,%al
  jnz     seta20.1

  movb    $0xd1,%al               # 0xd1 -> port 0x64
  outb    %al,$0x64

seta20.2:
  inb     $0x64,%al               # Wait for not busy
  testb   $0x2,%al
  jnz     seta20.2

  movb    $0xdf,%al               # 0xdf -> port 0x60
  outb    %al,$0x60

  # Switch from real to protected mode.  Use a bootstrap GDT that makes
  # virtual addresses map directly to physical addresses so that the
  # effective memory map doesn't change during the transition.
  lgdt    gdtdesc
  movl    %cr0, %eax
  orl     $CR0_PE, %eax
  movl    %eax, %cr0

//PAGEBREAK!
  # Complete transition to 32-bit protected mode by using long jmp
  # to reload %cs and %eip.  The segment descriptors are set up with no
  # translation, so that the mapping is still the identity mapping.
  ljmp    $(SEG_KCODE<<3), $start32
.code32  # Tell assembler to generate 32-bit code now.
start32:
  # Set up the protected-mode data segment registers
  movw    $(SEG_KDATA<<3), %ax    # Our data segment selector
  movw    %ax, %ds                # -> DS: Data Segment
I changed link adress for bootloader to 0x7d00.
Also i did trace though this code, and it fails at the last line
ljmp $(SEG_KCODE<<3), $start32

My question is:
BIOS loads bootloader at phisical adress 0x7c00
All code before line "ljmp $(SEG_KCODE<<3), $start32" is switching from real mode to protected mode.
So why then ljump fails?

Thank you
alexfru
Member
Member
Posts: 1112
Joined: Tue Mar 04, 2014 5:27 am

Re: OS Development. Bootloader question

Post by alexfru »

What is the offset that the assembler chooses/generates for the first instruction of your bootloader code? Is it implicitly set to 0 or is there some kind of an org (origin) directive that you're not showing us?

What are the segment base addresses in your GDT?

What is the address in your GDTR?

What is in the GDT?

When you answer these questions, you'll have more than 50% of the problem solved.
Milnadar
Posts: 3
Joined: Thu Aug 14, 2014 6:25 am

Re: OS Development. Bootloader question

Post by Milnadar »

alexfru wrote:What is the offset that the assembler chooses/generates for the first instruction of your bootloader code? Is it implicitly set to 0 or is there some kind of an org (origin) directive that you're not showing us?
It depends on a link adress i assign to a bootloader in a make file. So if for example as it says in a tas after i change adress to 0x7d00
disassembly will lok like this:

Code: Select all

Disassembly of section .text:

00007d00 <start>:
# with %cs=0 %ip=7c00.

.code16                       # Assemble for 16-bit mode
.globl start
start:
  cli                         # BIOS enabled interrupts; disable
    7d00:	fa                   	cli    

  # Zero data segment registers DS, ES, and SS.
  xorw    %ax,%ax             # Set %ax to zero
    7d01:	31 c0                	xor    %eax,%eax
  movw    %ax,%ds             # -> Data Segment
    7d03:	8e d8                	mov    %eax,%ds
  movw    %ax,%es             # -> Extra Segment
    7d05:	8e c0                	mov    %eax,%es
  movw    %ax,%ss             # -> Stack Segment
    7d07:	8e d0                	mov    %eax,%ss
Anf i don't know how to see what are values of GDT and GDTR
User avatar
hometue
Member
Member
Posts: 100
Joined: Thu Dec 19, 2013 1:40 am
Location: Asia, Singapore

Re: OS Development. Bootloader question

Post by hometue »

Use bochs(compile with the debugging feature). It will help you a lot and can display your GDT and GDTR (and much more).
CookieOS. Want a cookie? Its only black and white for now though, probably as bad as my baking skills.
CelestialMechanic
Member
Member
Posts: 52
Joined: Mon Oct 11, 2010 11:37 pm
Location: Milwaukee, Wisconsin

Re: OS Development. Bootloader question

Post by CelestialMechanic »

Also, what is the value in SP? I do not see the stack pointer being loaded. It should be loaded right after the load of SS, as in:

Code: Select all

movw %ax, %ss
movw something, %sp
If you are lucky, no harm will be done, but since we live in a universe where Murphy's laws are rigorously enforced your stack could be writing over your GDT, IDT or even the BIOS's IVT.
Microsoft is over if you want it.
Icee
Member
Member
Posts: 100
Joined: Wed Jan 08, 2014 8:41 am
Location: Moscow, Russia

Re: OS Development. Bootloader question

Post by Icee »

@CelestialMechanic
There is nothing in this code fragment that uses the stack, so your point is invalid.

In case the OP had not given up on this problem yet, I suggest having a closer look at the LGDT and LJMP instructions. How are they different from all other instructions in this fragment?
Milnadar
Posts: 3
Joined: Thu Aug 14, 2014 6:25 am

Re: OS Development. Bootloader question

Post by Milnadar »

I've been reading about memory and also read similar questions asked by people.
So i think i started to understand a bit why it fails.

Bios loads bootloader into memory to adress 0x7c00, and also sets CS:IP to 0:0x7c00
After GDT is loaded, ljmp just resets CS:IP to 0x8:(and here IP will be whatewer what was in a makefile. In a normal case 0x7c00, or if you changed a value as i did to 0x7d00)
So adress of a next instruction will be transformed to a real aress, 0x7d00, when code is loaded to adress 0x7c00.
So at the begining, when bootloader is loaded, there is no difference what is a virtual adress, because BIOS sets CS:IP for us, and code will run untill LJMP instruction

Is that coreect?
CelestialMechanic
Member
Member
Posts: 52
Joined: Mon Oct 11, 2010 11:37 pm
Location: Milwaukee, Wisconsin

Re: OS Development. Bootloader question

Post by CelestialMechanic »

Icee wrote:@CelestialMechanic
There is nothing in this code fragment that uses the stack, so your point is invalid.
You have a point in that the code makes no intentional use of the stack (push, call, int, etc.) Yet the SS register has been set. Exceptions are not masked, the NMI is not maskable (by definition), there really needs to be a properly configured stack. The OP would have one if only he had loaded the SP register immediately after loading SS, for which Intel has provided an uninterruptible slot since the 8086. Murphy's laws have a way of being enforced.

I see this omission a lot these days. I suspect it's a case of cutting and pasting and then deleting the lines that are not understood.
Microsoft is over if you want it.
Icee
Member
Member
Posts: 100
Joined: Wed Jan 08, 2014 8:41 am
Location: Moscow, Russia

Re: OS Development. Bootloader question

Post by Icee »

@CelestialMechanic
Strictly speaking, you are right, and I stand corrected. One could argue, though, that NMI is pretty much a one-way ticket and even if there is an installed handler and it returns control correctly, the execution is pretty much screwed anyway. The same Murphy law dictates that the NMI in question might very well have occurred because of memory corruption in the GDT, IDT or even the BIOS's IVT.

Also, the NMI is maskable, though this is by no means a good practice.
CelestialMechanic
Member
Member
Posts: 52
Joined: Mon Oct 11, 2010 11:37 pm
Location: Milwaukee, Wisconsin

Re: OS Development. Bootloader question

Post by CelestialMechanic »

Icee wrote:...

Also, the NMI is maskable, though this is by no means a good practice.
Quite right, I forgot about that. Thank you for the reminder. :D
Microsoft is over if you want it.
Post Reply