Re: Second stage pmode - 2005/03/22 05:47Just two things that came to my mind reading your post:
* Where do you load the 2nd stage ? I wrote the code to be loaded to (physical) 0x10000 and if you want to load it anywhere else, you'll need to change the ORG-directive accordingly.
* Did you change the location of the GDT or IDT aswell ? If you moved them above 64k, you'll need to change es because of the 16bit limitation in real-mode.
If that doesn't help some some more infos might be neccessary: - The address your FIRST stage jumps to [cs:ip] - Where do you want the GDT/IDT to be located ? - What's the value of IDT_PHYS_ADDR/GDT_PHYS_ADDR ? - The value of es
regards, gaf
| | The administrator has disabled public write access.
OSDEV Community
Advertisement
DRF
User Platinum Osdever
Posts: 123
Karma: 1
Re: Second stage pmode - 2005/03/22 23:01Wow this thread is big. Well I've not had a chance to play with the bootloader code more since the last post but I can tell you what the details are when I tried then.
The code was included (aka appended) to an existing bootloader (after my take on it failed to do what I wanted just to check it wasn't just my code).
So it was essentially appended to a second stage loaded at CS:1000h IP:0000 The locations the GDT was copied to was left the same. Literally to test it wasn't just my code I didn't change anything (other than to comment out the 'ORG' as it was defined earlier in the second-stage). There were no kind of jump conflicts or data conflicts (as that should of been picked up by nasm). Also ES and DS when I checked had the values correct (DS same as CS aka flat mode to copy from and ES zero'ed as a destination of the copy procedure).
Hence the code was loaded like:
[ORG 0x0000] ; CS = 1000h IP = 0000 *Second stage code aka FAT loading etc (still run in my test but the jump to the kernel commented out so this is only loading the stuff hence not really worth mentioning). *A20 line code (Which works fine) *Jump to the Entry label in the code above ------------ Functions/Data/The above Include --------- *Some procedures. (called by other funtions) *%include of above code snippit *Some data relevant to other stuff in the loader.
I'm happy with the location used above actually so found no need to change that.
Below is bochs readout of all the values just before the far jump to set CS that crashes the loader.
This to me looks about right. An attempt to set any of the registers (DS or jmp for CS) causes the loader to crash and restart. There is no associated error brought up by bochs that helps and I can't (due to this restart) get the data in the registers after the attempt to set DS/CS etc.
I will have a go at loading this code as the second stage rather than appending to an existing second stage of mine in a bit. (But time limitations and all means I'm not sure if this will be tomorrow today or end of the week)
Daniel
| | The administrator has disabled public write access.
DRF
User Platinum Osdever
Posts: 123
Karma: 1
Re: Second stage pmode - 2005/03/22 23:21Ok update to the above. I've tested the above code loaded as the second stage (using the same first stage with no modifcations) and it works fine.
Below are the register details at the same point as before but in this case when I remove the halt to let it contine it works.
Now this seems a little odd if it works in one case but not the other. I'm wondering if the fact (being that it's the only change I made) of changing the origin value made a difference. Or if some registers or flags should of been zero'ed properly before running the above the code.
The origin location is identical to that I currently use. Except I use the real mode ORG value [ORG 0x0000] where in your code snippit you use the linear version [ORG 0x10000].
Ok. Update (whilst writing I just tested this) seems that using the real mode ORG value causes the crash. So looks like an easy fix (yey) not that would ever of suggested it was to do with your code gaf
Daniel
| | The administrator has disabled public write access.
gaf
User Platinum Osdever
Posts: 153
Karma: 10
Re: Second stage pmode - 2005/03/23 08:48Good to hear that it works now. I think it's a pretty hard to spot mistake, so you should be lucky that you've found it
regards, gaf
| | The administrator has disabled public write access.
DRF
User Platinum Osdever
Posts: 123
Karma: 1
Re: Second stage pmode - 2005/03/23 10:38I certainly appreciate it. Means I can now go back to implmenting the same principles in my loader knowing where my mistake is. So hopefully the next step is to play around with unreal mode in the bootloader to load the kernel at/over 1mb. (Other than the current location of roughly 30000h linear) Among other tweaks.
I guess that the lgdt instruction must require that the physical/linear address is used as the origin rather than then the real mode style of origin where only the IP value is used above a certain limit. (What ever it is finding out the problem makes me certainly very happy, taken a while)
Thanks again,
Daniel
| | The administrator has disabled public write access.
gaf
User Platinum Osdever
Posts: 153
Karma: 10
Re: Second stage pmode - 2005/03/26 08:35Hmm... It should be 'happy' and not 'lucky', right ? My english teacher would probably kill me for making such stupid mistakes
I guess that the lgdt instruction must require that the physical/linear address is used as the origin rather than then the real mode style of origin where only the IP value is used above a certain limit. (What ever it is finding out the problem makes me certainly very happy, taken a while)
As far as I know the operand of the lgdt/lidt instruction is still addressed using real-mode segmentation. Only the address stored in pGDT must be physical, which shouldn't be a problem because the GDT's position is fixed anyway. I think the real problem is that you, by using an origin of 0x0000, implicitly assume that cs is 0x1000. This might be true in real-mode, but once you've enabled pmode cs becomes zero.
jmp dword 0x08mode_entry
For the jump to pmode the real-mode value in cs doesn't matter. It's already a pmode jump and, since cs is zero, it will simply go to 'pmode_entry'. I therefore think that the pmode jump didn't really fail but simply never reached its target. This should have caused an 'invalid opcode' exception which turned into an triple fault because there aren't any exception handlers installed. Please note that I'm not 100% sure about this. If you want to, you can try it out yourself by changing the origin back to 0x0000 and making sure that cs is also 0x1000(0) in pmode.
regards, gaf
| | The administrator has disabled public write access.
DRF
User Platinum Osdever
Posts: 123
Karma: 1
Re: Second stage pmode - 2005/03/27 07:34The reason why I was using the real mode style ORG is that the CS value can be anything. (Doesn't assume a value) so it means I can change where something is being loaded by changing the CS value and not having to worry about changing the ORG value in the file that is being loaded.
This comes in handy when loading MS-DOS style real flat applications as you don't have to stick to the same memory layout as DOS (which I'm not sure where it loads stuff anyway) but still remain compatible with applications compiled for it. (Saves recompiling all the applications if you decide to change it so apps load higher or lower in memory) So in my case I think the Second stage used ORG 0x0000 and the kernel and applications used 1000 Second stage was jmp 0x1000ecStage (ORG 0x0000) Kernel was jmp 0x1000:Kernel (ORG 0x1000) Applications were jmp 0x3000:Apps (ORG 0x1000)
Only thing I can think of is that the assembler assumes a physical org of 0x00000 so when a pmode jump is made the assembler has assumed an all zero physical address as the only ORG value it was given was real mode. Really this could be something fixed by making a compiler warning. (If [BITS 32] line in file and ORG value is only 4 digits print warning) But probably not enough demand to ask the nasm dev'ers to add this feature lol.
Other than that it could be related to lgdt etc but I think it's more likely that it's nasm making an assumption when it assembles and compiles the code. As halfway though the program the 'ORG' value is no longer large enough.
Daniel
| | The administrator has disabled public write access.
gaf
User Platinum Osdever
Posts: 153
Karma: 10
Re: Second stage pmode - 2005/03/27 13:07I think that your DOS-trick should still work if you're using an origin of 0x10000. As long as you're in real-mode it'll be the same as 0x1000:0x0000 (=> 0x0000) and you can change the apps location using cs. Once you've entered pmode, ip becomes eip and the origin is 0x0000:0x10000 again.
Only thing I can think of is that the assembler assumes a physical org of 0x00000 so when a pmode jump is made the assembler has assumed an all zero physical address as the only ORG value it was given was real mode.
Yes, ORG only has an impact on (e)ip and not on cs..
jmp dword 0x08mode_entry -> descriptor 0x08 has a base of 0x00000000 -> pmode_entry consists of [ORG]+[offset label]
jmp dword 0x00000000:[ORG]+[offset label]
[offset label] is always the same and depends on how many instructions/data there is before the label appears in your asm file. Since the descriptor's base is zero, origin and label have to add up to the physical address of your pmode entrypoint. If you're now using an origin of zero, the jump will simply go to [offset label], which is probably still somewhere in the real-mode interrupt vector table.
regards, gaf
| | The administrator has disabled public write access.
bubach
User Senior Osdever
Posts: 33
Karma: 0
Re: Second stage pmode - 2005/03/29 03:03This is funny, haven't read the whole thread yet, but just recently I got the same problem. Now I am hoping that this might help me. My problem is decsribed on: http://board.flatassembler.net/topic.php?t=3286
| | The administrator has disabled public write access.
gaf
User Platinum Osdever
Posts: 153
Karma: 10
Re: Second stage pmode - 2005/03/29 10:33Hi bubach, since the jump to pmode is still in the 16bit section of your code, fasm will automatically genarate a 16bit jump. This means that do_pmode can't be greater than 64k and an offset of 0x10000 is therefore already too big. You should be able to solve the problem by using a 32bit overwrite for the pmode jump. I've never used fasm, so I can't tell you how exactly it's done - just look it up in the documentation.
[nasm] jmp dword 0x08:do_pmode
regards, gaf
| | The administrator has disabled public write access.