flat assembler
Message board for the users of flat assembler.

Index > OS Construction > Need help with unreal mode code

Author
Thread Post new topic Reply to topic
NEOAethyr



Joined: 20 Aug 2007
Posts: 19
NEOAethyr 31 Jul 2008, 16:02
A little bit about the stuff I'm doing and want to do before I get on with the code.

I'm writing a bios, flpppy os, and com file all in one.
Allready done and working quite well, even in rom(on my dfi nf2).

Does svga mode(banked) (640x480x32/24 (nv or ati, sis compatible but not intel compatible yet).

Has some basic menu's, using #'ed keys as the input and ret/esc.
uses direct i/o when in rom or floppy, uses a irq when in com(dos/nt).

Gives you a map of:
cmos (extended 256byte ver)
ivt
bda
isa bridge (i/o chip, shows some temps and voltages)
Chipset (shows most timings and some hd controller info)
Svga info (only shows the bit depth for the moment)

It can also display bmp's from a file when in com mode using int21 (doesn't parse headers or flip them, I do that by hand).
It can do the same when in floppy mode using int13, and soon it'll doit in rom mode (but it's not perfect, which is why I need unreal mode help).

I've also written to the side a cmos dumping to file program, and flasher.
Vga rom dissasmbler.
Pci config parser.
Those I will intergrate with the main program later.


There's a few reasons why I need unreal mode support working.
Apic info dumping and modding.
Acpi info dumping.
Direct rom dumping.
Ability to use svga withough having to bank!!! (try double banking so you can copy a dword of data from the back buffer to the front ^^, it's slow...)

Svga banking, sometimes this can get quite complicated when you have to use a counter to know where you are.
And it happens that the 2 offsets that I'm counting are diff because I'm trying to copy to the back buffer a bmp background file, in 64k chunks...
In which case, the int13 function has a built in counter, and only reads in 512byte chunks as a min lol.
It was a real pain just to get it to align so I could see the pic lol, let alone tryign to get the 1st 64k off the front buffer to where it belongs(which I can do, but not without screwing it all up).

So..., I defently need to get away from the banking, it just to much work and sometimes it's to complicated.
Let alone it's slow as a dog, the actual banking function it's self is...
(speed wise, I did dump the actual bank function from rom to use it directly and to mod it, but it was calling this and that, was to complicated and a waste of time, so I trashed what I had started)


Ok to the point, here's my unreal code.
It will run in a bootsector fine, works too, and even runs code that uses irq's and such afterwards np, will even boot windows nt (2003, xp etc).
But if I run it right after the bootsector, it locks the computer.
If I run it in dos, it resets the computer.
If I run it in rom, it resets the computer.

At one time, when I was messing with it, I got it to reset the computer in windows nt...(probably not to hard though, there should be a port or 2 that does the same thing) :\

If I goto use any other example I can find, it's even worse or about the same.
The ONJY example I've ever found that has actually not reset my pc in dos mode, was the one in fasm's src it's self.
But I never got it working right and it was very quirky.

So does anyone know of any ways to fix this?
I wanna go BY THE BOOK btw, not half @ssed.

Oh and a few more thigns about this code it's self.
Ds is allways loaded with a 32bit segment esc, no matter if I choose to load it or not(in an emu anyways).
If I choose the real mode desc, I get 32bit mode ones anyways :\, I was able to choose real mode ver's at one time correctly but I doe'snt work anymore so I've long since stopped trying.

There is a few things that this code must and must not do.
ds, es, these 2 segments must be real mode types no matter what.
fs, gs, either one of those I need to be 32bit, I oly need one, so fs would do.
Again the code does work, but only in a bootsector.
I need it to be dos and rom compatible.
Lol, I need to beable to use fs well after I've called the mode function.
If I can't, I need to beable to call the function again so I can use 32bit fs without locking my pc up in some way.

Oh, and it cannot call any defines of any kind in this function.
Because I push and pop alot allready, I can't pop an self modding offset value into the middle of it, and can't find my relative offset from inside it either because I'de need to call a function, and I don't think that's a good idea.
The reason is that the code is not allways at org 0x0100, and I got all of my code that deal with stuff like defines as self modifying to account for that in my program.
Reason is the main use for my proggy is for bios work.

Using retf works for me in this function, but jmp far is not working, nor did it ever work for me Sad.
Using retf, the 1st one, kills the proggy.
The 2nd does not.

I do need working irq's after I've called this.

Edit:
Oh and loops don't clear the cache I found out, I can use those in a tight loop to stop dos from dieing out, but it's not worth anything.
I could use my self modifying offset code from in this function it's self, taking it from my Get_Entry_Point function if I REALLY needed to get to a define...
End of edit

Smile

Code:
align 8                                                ;Pseudo Descriptor Alignment
                times 6 db 0x90
GDT_PD:
              dw ((GDT_End - GDT) - 1)        ;GDT Table Limit In Bytes (8 Bytes * # Of Descriptors - 1 Byte)
             dd GDT                          ;GDT Base Address

align 8                                                ;GDT Alignment
GDT:
GDT_Descriptor_NULL:                          ;NULL Descriptor
                    dd 0x00000000
                       dd 0x00000000
GDT_Descriptor_Data_20:                            ;20 Bit Descriptor
                  db 0xFF, 0xFF           ;Segment Limit Bits 00-15
                   db 0x00, 0x00, 0x00     ;Segment Base Address Bits 00-23
                    db 10010010b            ;Segment Type, Descriptor Type, Descriptor Privilege Level, Segment Present
                 db 00001111b            ;Segment Limit Bits 16-19, Scratch, Reserved, Segment Size, Granularity
                     db 0x00                 ;Segment Base Address Bits 24-31
GDT_Descriptor_Data_32:                         ;32 Bit Descriptor
                  db 0xFF, 0xFF           ;Segment Limit Bits 00-15
                   db 0x00, 0x00, 0x00     ;Segment Base Address Bits 00-23
                    db 10010010b            ;Segment Type, Descriptor Type, Descriptor Privilege Level, Segment Present
                 db 11001111b            ;Segment Limit Bits 16-19, Scratch, Reserved, Segment Size, Granularity
                     db 0x00                 ;Segment Base Address Bits 24-31
GDT_End:

Unreal_Mode:
push ds
;push es
;push fs
;push gs
;push ss
cli                      ;Disable Interrupts
mov al, 0x80             ;Disable Non-Maskable Interrupts
out 0x70, al
in al, 0x92         ;Enable A20
or al, 0x02
out 0x92, al
xor ax, ax
mov ds, ax
lgdt [GDT_PD]
mov eax, cr0         ;Protected Mode
or al, 0x01
mov cr0, eax
;push cs
;push $+2
;retf                        ;Clear cs and cache
mov ax, 0x0010           ;Load Descriptor
;mov ds, ax         ;Automaticly happens anyways
;mov es, ax
mov fs, ax
;mov gs, ax
;mov ss, ax
mov eax, cr0         ;Unreal Mode
and al, 0xFE
mov cr0, eax
;push cs
;push $+2
;retf                  ;Clear cs and cache
;pop ss
;pop gs
;pop fs
;pop es
pop ds
mov al, 0x00               ;Enable Non-Maskable Interrupts
out 0x70, al
sti                  ;Enable Interrupts
ret
    
Post 31 Jul 2008, 16:02
View user's profile Send private message Reply with quote
DJ Mauretto



Joined: 14 Mar 2007
Posts: 464
Location: Rome,Italy
DJ Mauretto 31 Jul 2008, 18:10
Hello Smile
Code:
in al, 0x92             ;Enable A20
or al, 0x02
out 0x92, al     


Note that fast A20 it's not a default setting on pc ,usually you
must set it through the chipset , try to enable A20 through keyboard ports.
Reset PC = 99% of the times Wrong Address Wink

_________________
Nil Volentibus Arduum Razz
Post 31 Jul 2008, 18:10
View user's profile Send private message Reply with quote
NEOAethyr



Joined: 20 Aug 2007
Posts: 19
NEOAethyr 31 Jul 2008, 19:34
Code:
Enable_A20_Slow:
in al, 0x64           ;Keyboard Controller Status
or al, 0x03              ;Enable The A20, Ensure The CPU Is Not Reset
mov bl, al
out 0xEB, al              ;newiodelay
mov al, 0xD1             ;Keyboard Controller Command Write ?
out 0x64, al
out 0xEB, al            ;newiodelay
mov al, bl
out 0x60, al
ret

Enable_A20_Fast:
in al, 0x92
and al, 0xFE             ;Clear The CPU Reset Bit
or al, 0x02         ;Set The A20 Bit
out 0xEB, al                ;newiodelay
out 0x92, al
ret
    


Those look allright?
I'm assuming I should call these sometime after I actually call the unreal mode function and safely ret from it.

I don't normally use delays, but I figuered why not I guess.
That newiodelay is a macro used in award bios'es.
They used to do something else but I've can't remember what it was.
I am using an ami bios for testing at the moment though..., so I dn if I should be doing that...

I didn't add support for checking to see if the A20 was infact allready enabled or failed to change.
If I'm testing, or if I'm on some specific platform or something, I could get stuck in conditional jmp loop thing if it never changes.

I'll make myself some disable functions in a little bit.


Btw, I found that the hardlock with calling the unreal mode function after bootsector was just my error.
I was including the asm file in my bootsector, I was testing after the bootsector...(I had it working in the bootsector allready)
After moving the include to the main src file away from the bootsector it fixed that.
Now it reset the pc every time I run it lol, like it allways does...

I think I need to work with the stack segment and pointer too, but I have to take care with those.
I really need to restore them exactly to where they were before so if I'm running in rom, I can exit back to the bios where it can do the dmi pooling(not nessary...) and IPL loader(kinda nessary lol..., I still want it).


Update:
Here's the rest of the A20 stuff and a macro for the delay.

(Edit: had to do some fixups with this code, found some info and had to look up other info to make sure I was doign it right, I think it's good now, a20 wise)

(I'll have to make myself a Function called Enable A20, one that scans for the availibility of the fast A20 and stuff like that maybe, I dn yet)

Code:
macro New_IO_Delay
{
    out 0xEB, al    ;Award BIOS newiodelay
}

Enable_A20_Slow:
mov al, 0xD0            ;Read Controller Status
out 0x64, al
New_IO_Delay
in al, 0x60          ;Controller Status
or al, 0x03               ;Enable The A20, Ensure The CPU Is Not Reset
mov bl, al
New_IO_Delay
mov al, 0xD1              ;Write Controller Status
out 0x64, al
New_IO_Delay
mov al, bl
out 0x60, al
ret

Disable_A20_Slow:
mov al, 0xD0              ;Read Controller Status
out 0x64, al
New_IO_Delay
in al, 0x60          ;Controller Status
or al, 0x01               ;Ensure The CPU Is Not Reset
and al, 0xFD            ;Clear The A20 Bit
mov bl, al
New_IO_Delay
mov al, 0xD1                ;Write Controller Status
out 0x64, al
New_IO_Delay
mov al, bl
out 0x60, al
ret

Enable_A20_Fast:
in al, 0x92
and al, 0xFE                ;Clear The CPU Reset Bit
or al, 0x02         ;Set The A20 Bit
New_IO_Delay
out 0x92, al
ret

Disable_A20_Fast:
in al, 0x92
and al, 0xFC             ;Clear The CPU Reset Bit And A20 Bit
New_IO_Delay
out 0x92, al
ret
    
Post 31 Jul 2008, 19:34
View user's profile Send private message Reply with quote
DJ Mauretto



Joined: 14 Mar 2007
Posts: 464
Location: Rome,Italy
DJ Mauretto 01 Aug 2008, 09:03
Hi Very Happy
I don't have time to look at your source,
there are many example in this section about A20 ,
try to debug your code printing to the screen some numbers
every statment to search your bug , or insert wait to understand
where your code is buggy.

_________________
Nil Volentibus Arduum Razz
Post 01 Aug 2008, 09:03
View user's profile Send private message Reply with quote
NEOAethyr



Joined: 20 Aug 2007
Posts: 19
NEOAethyr 01 Aug 2008, 14:39
I put together a stand alone program to test the mode switch functionality.

It may look long, maybe messy, and lame.
I thaught there was no reason to post src that compiles into diff outputs types.

I'll step through it real quick.

I called it unreal.asm, so I'll be using that as an example.

Cmd prompt commands:
fasm unreal.asm unreal.ima

I'm running it with virtual pc because I can duplicate the same probs that I have both in rom and in real dos.

"Boot Sector Entry Point"
This is the org of the floppy and where the pragram 1st starts.
It then jumps to the bootsector init.

"BS_Init:" Boot Sector Init

The bootsector init 1st copies 64k-512b of drive0(floppy) to segment 0x1000, and offset 0x0100 (like a com file, to sim a com file from dos, it works for some programs too, I've tested a little before...).

That code maybe a hassle to read through if you're not looking to obtain it Smile.
The disk reading code I mean.
Just know that it indeed works well enough for a floppy.
And if I did the job right (not totally optimized probably though), then it should work completely with ECHS limits(Allmost 8gigs), just with a 64k transfer limit because it's baised on a bios irq.
I know for a fact it's workign quite well on the floppy because I've used it to transfer over 900k from the floppy into memory with 100% accuracy (a 24bit bmp).
It uses a 32bit lba offset scheme, however like I said before it's limited to ECHS limits if the bios in ? that supplies the irq has support for ECHS...
Otherwise it would be limited to 500m or something, like back in the old days with some 486's.
And it is somewhat reliable.
So you can ignore it, I just include it so I have a full example and demo of the probs at hand.


call BS_Unreal_Mode
mov eax, 0x000B8000 ; note 32 bit offset
mov word [fs:eax], 0x0F01 ; attrib/char of smiley

Here is has the option to test the unreal mode code from the bootsector.
This works.

;BS_Init_Loop:
;mov cx, 0xFFFF
;loop BS_Init_Loop

An inf to test for probs related to the bootsector, it "could" be reloacted to a diff spot in the bootsaector if needed...

push word 0x1000 ;Segment
push word 0x0100 ;Offset
retf ;pop cs:ip

It's commented I think Smile, it effectivally jumps to the code that was loaded from the disk a bit ago.
So now in this example, we'll be relocating cs to 0x1000, and ip to 0x0100.
That's the position of "Entry Point"

times (65536-($-$$)) db 0x00
org 0x0100
jmp Init

Some hack work, a new org, and the jump to init.
Making it act as if it were loaded from a command prompt.
I'm positioning the main code 64k from the start of the floppy image.
I just felt like doing it this way when I original wrote it, I'm still fine with it.

"Init:"
The main program init.

call Unreal_Mode <-- This fails

mov al, "1"
mov ah, 0x0E
dw 0x10CD
This never happens if unreal mode was called from the main program section.
It does work if it was called not though.

mov eax, 0x000B8004 ; note 32 bit offset
mov word [fs:eax], 0x0F01 ; attrib/char of smiley

mov al, "2"
mov ah, 0x0E
dw 0x10CD

mov eax, 0x000B8008 ; note 32 bit offset
mov word [fs:eax], 0x0F01 ; attrib/char of smiley

Init_Loop_2:
mov cx, 0xFFFF
loop Init_Loop_2

More test code, and an inf loop to see the final results.
All of that test code works if I called unreal from just the bootsector.
It never runs if I call unreal from the main program.
Does'nt matter if I call it from both the bootsector and the main program, it still won't get past the 2nd call of unreal mode from within the main program segment.

Under the main program functions, ther is a function called "Unreal_Mode:".
In there you'll see this:

Init_Loop: ;Dies after this...
mov cx, 0xFFFF
loop Init_Loop

Just as the comment says.

mov ax, 0x0010 ;Load Descriptor
;mov ds, ax ;Automaticly happens anyways
;mov es, ax
mov fs, ax
;mov gs, ax
;mov ss, ax

This kills my main program code if I call it from there.
But the very same code byte for byte under BS_Unreal_Mode in the boot sector works^^.

Now unreal called from the bootsector does work.
And it's still working after I've switched code segments(changed my program running location).

Both the int13 disk access and the simple bios print char irq access are not screwing with the code and resetting the limits, or causing me any probs.
But I can't say for sure I won't run across anything that would, I know I actually have too, just have'nt spent the time to figuer what it was (No example in this code)...

So if I played it safe from a bootsector, I could probably get by.
Watching and paying close attention after every new function I put into the program I could get by if...
Well, that's the thing, I can't be stuck with just a bootsector function.
If it causes dos probs, I don't really care as much.
But it messes up while in rom(real rom), causing me resets just like dos...
And this example I'm posting, it resets just the same if I call it as if I wasn't a bootsector.

I sometimes need working examples in order to figuer things out.
However in the case of switching to protected mode and back, I haven't found one that's done the trick well enough to beable to be called anywhere from within a real mode env.

I'm not to worried about access rights and limits, I want all access (as much as protected limits provide memory access wise), and full rights.
I'm sure I won't have to worry much if I reset the limits once before booting anything, if anything I could learn and how redo the limits.
But I don't think I'll have a prob, I can boot nt if I've allready setup unreal mode.
I probably can't setup memtest or stuff that checks for it, I dn, still.
Like i said, I could allways redo the limits before pop'ing the stack back into the code that called my program, bios(bootsector and rom), dos, etc.

Oh btw,. the footer algo is off because of the main entry ptr section org.
And also note that I don't have to do a thign with the A20 gate with virtual pc, so I can't say for sure anything about the current a20 functions.
I don't need them in the example, if virtual pc is used (microsoft emu, it's allright..., never tried bochs).

... Offtopic like.
Ther code that's in the macro New_IO_Delay.
I dn, like i meantioned in an above post, if it's safe or not for all bios types.
I only know award is safe.
Anyways, if one where to use that macro now that I think about it, and have enough functions that used it.
One could comment out the code in the macro or replace it with nop's depending on the situation (static offsets or compiled offsets).
It's kinda useful as a macro now that I think about it if you tend to work with the instruction alot...
Onestly I don't think you need i/o delays these days...
I've never had any probs removing delays and having it still work fine(well I have ran across some, but they were fixable by aligning output a little when I'm doing large transfers).

And yes I allways write my irq's out that way in plain word hex format...
It's that same for me as if I were to put 0x in front of a hex # instead of using h at the end of it.
It's just comment practice to me, even if it may seem odd :\, it's just something I do.

Here's the code I put together as an example:
Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Unreal
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Macros
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

macro New_IO_Delay
{
       out 0xEB, al    ;Award BIOS newiodelay
}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Boot Sector Entry Point
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

org 0x7C00            ;Floppy
jmp BS_Init

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Boot Sector Defines
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

align 8                                             ;Pseudo Descriptor Alignment
                times 6 db 0x90
BS_GDT_PD:
           dw ((BS_GDT_End - BS_GDT) - 1)  ;GDT Table Limit In Bytes (8 Bytes * # Of Descriptors - 1 Byte)
             dd BS_GDT                       ;GDT Base Address

align 8                                                ;GDT Alignment
BS_GDT:
BS_GDT_Descriptor_NULL:                            ;NULL Descriptor
                    dd 0x00000000
                       dd 0x00000000
BS_GDT_Descriptor_Data_20:                 ;20 Bit Descriptor
                  db 0xFF, 0xFF           ;Segment Limit Bits 00-15
                   db 0x00, 0x00, 0x00     ;Segment Base Address Bits 00-23
                    db 10010010b            ;Segment Type, Descriptor Type, Descriptor Privilege Level, Segment Present
                 db 00001111b            ;Segment Limit Bits 16-19, Scratch, Reserved, Segment Size, Granularity
                     db 0x00                 ;Segment Base Address Bits 24-31
BS_GDT_Descriptor_Data_32:                      ;32 Bit Descriptor
                  db 0xFF, 0xFF           ;Segment Limit Bits 00-15
                   db 0x00, 0x00, 0x00     ;Segment Base Address Bits 00-23
                    db 10010010b            ;Segment Type, Descriptor Type, Descriptor Privilege Level, Segment Present
                 db 11001111b            ;Segment Limit Bits 16-19, Scratch, Reserved, Segment Size, Granularity
                     db 0x00                 ;Segment Base Address Bits 24-31
BS_GDT_End:

BS_Disk_Offset               dd 0x00000000

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Boot Sector Functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

BS_Get_Entry_Point:    ;Out: AX = Entry Point Offset (ORG)
call $+0x0003                ;push ip
pop ax                      ;mov ax, ip
sub ax, $-0x0001
ret

BS_Ret_Function:
ret

BS_Delay:
dec ecx
cmp ecx, 0x00000000
je BS_Ret_Function
jmp BS_Delay

BS_Read_Disk:         ;IN: BS_Disk_Offset = LBA Offset(Min = 1), CL = Tranfer Size - Limited To 64k(0x80), DL = Drive, ES:BX = Buffer
push cx                      ;Transfer Size
call BS_Read_Disk_Sector
cmp cl, 0x01
je BS_Read_Disk_Error
pop cx                   ;Transfer Size
call BS_Get_Entry_Point
mov si, BS_Disk_Offset
add di, ax
inc dword [cs:di]      ;LBA Offset
add bx, 0x0200           ;Buffer Offset
dec cl
cmp cl, 0x00
je BS_Ret_Function
jmp BS_Read_Disk

BS_Read_Disk_Error:
jmp BS_Exit                ;Temp Code
ret

BS_Read_Disk_Sector:
call BS_Get_Entry_Point
mov si, BS_Disk_Offset
add si, ax
mov eax, [cs:si]
call BS_LBA2CHS         ;Convert LBA to CHS
mov ah, 0x02             ;Function: Read Sectors
mov al, 0x01             ;# Of Sectors To Read
push bx
dw 0x13CD
jc BS_Read_Disk_Sector_Error
mov cl, 0x00           ;No Error
pop bx                     ;Buffer Offset
ret

BS_Read_Disk_Sector_Error:
mov cl, 0x01             ;Error
pop bx                        ;Buffer Offset
ret

BS_LBA2CHS:            ;IN: EAX = 32bit LBA Offset (2tb limit, far beyond the 8gig limit of ECHS, but limited by ECHS...)
push bx                       ;Buffer Offset
push dx                       ;Drive
push eax
shr eax, 0x00000010
mov dx, ax
pop eax
mov bx, 0x0012            ;Sectors Per Track
div bx
mov cl, dl
inc cl                    ;Sector
push eax
shr eax, 0x00000010
mov dx, ax
pop eax
mov bx, 0x0002           ;Heads Per Cylinder
div bx
mov ch, al             ;Cylinder
and ah, 0xFC
shl ah, 0x06
or cl, ah
mov dh, dl            ;Head
pop bx
mov dl, bl           ;Drive
pop bx                        ;Buffer Offset
ret


BS_Unreal_Mode:

push ds
;push es
;push fs
;push gs
;push ss

cli                  ;Disable Interrupts
mov al, 0x80             ;Disable Non-Maskable Interrupts
out 0x70, al

xor ax, ax
mov ds, ax

lgdt [BS_GDT_PD]

mov eax, cr0            ;Protected Mode
or al, 0x01
mov cr0, eax

;push cs
;push $+2
;retf                    ;Clear cs and cache

mov ax, 0x0010               ;Load Descriptor
;mov ds, ax         ;Automaticly happens anyways
;mov es, ax
mov fs, ax
;mov gs, ax
;mov ss, ax

mov eax, cr0             ;Unreal Mode
and al, 0xFE
mov cr0, eax

;push cs
;push $+2
;retf                      ;Clear cs and cache

;pop ss
;pop gs
;pop fs
;pop es
pop ds

mov al, 0x00               ;Enable Non-Maskable Interrupts
out 0x70, al
sti                  ;Enable Interrupts

ret


BS_Enable_A20_Slow:
mov al, 0xD0                ;Read Controller Status
out 0x64, al
New_IO_Delay
in al, 0x60          ;Controller Status
or al, 0x03               ;Enable The A20, Ensure The CPU Is Not Reset
mov bl, al
New_IO_Delay
mov al, 0xD1              ;Write Controller Status
out 0x64, al
New_IO_Delay
mov al, bl
out 0x60, al
ret

BS_Disable_A20_Slow:
mov al, 0xD0           ;Read Controller Status
out 0x64, al
New_IO_Delay
in al, 0x60          ;Controller Status
or al, 0x01               ;Ensure The CPU Is Not Reset
and al, 0xFD            ;Clear The A20 Bit
mov bl, al
New_IO_Delay
mov al, 0xD1                ;Write Controller Status
out 0x64, al
New_IO_Delay
mov al, bl
out 0x60, al
ret

BS_Enable_A20_Fast:
in al, 0x92
and al, 0xFE             ;Clear The CPU Reset Bit
or al, 0x02         ;Set The A20 Bit
New_IO_Delay
out 0x92, al
ret

BS_Disable_A20_Fast:
in al, 0x92
and al, 0xFC          ;Clear The CPU Reset Bit And A20 Bit
New_IO_Delay
out 0x92, al
ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Boot Sector Init
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

BS_Init:

push word 0x1000      ;Buffer Segment
pop es
mov bx, 0x0100             ;Buffer Offset
mov dl, 0x00          ;Drive

call BS_Get_Entry_Point
mov di, BS_Disk_Offset
add di, ax
mov dword [cs:di], 0x00000080
mov cl, 0x7F
call BS_Read_Disk

;call BS_Unreal_Mode
;call BS_Enable_A20_Fast

mov eax, 0x000B8000              ; note 32 bit offset
mov word [fs:eax], 0x0F01   ; attrib/char of smiley

;BS_Init_Loop:
;mov cx, 0xFFFF
;loop BS_Init_Loop

push word 0x1000      ;Segment
push word 0x0100    ;Offset
retf                 ;pop cs:ip

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Boot Sector Exit
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

BS_Exit:

mov al, "E"
mov ah, 0x0E
dw 0x10CD
mov al, "r"
mov ah, 0x0E
dw 0x10CD
mov al, "r"
mov ah, 0x0E
dw 0x10CD
mov al, "o"
mov ah, 0x0E
dw 0x10CD
mov al, "r"
mov ah, 0x0E
dw 0x10CD

BS_Exit_Loop:
jmp BS_Exit_Loop

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Boot Sector Footer
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

times (510-($-$$)) db 0x00             ;Floppy Boot Sector
dw 0xAA55

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Entry Point
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

times (65536-($-$$)) db 0x00
org 0x0100
jmp Init

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Defines
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

align 8                                           ;Pseudo Descriptor Alignment
                times 6 db 0x90
GDT_PD:
              dw ((GDT_End - GDT) - 1)        ;GDT Table Limit In Bytes (8 Bytes * # Of Descriptors - 1 Byte)
             dd GDT                          ;GDT Base Address

align 8                                                ;GDT Alignment
GDT:
GDT_Descriptor_NULL:                          ;NULL Descriptor
                    dd 0x00000000
                       dd 0x00000000
GDT_Descriptor_Data_20:                            ;20 Bit Descriptor
                  db 0xFF, 0xFF           ;Segment Limit Bits 00-15
                   db 0x00, 0x00, 0x00     ;Segment Base Address Bits 00-23
                    db 10010010b            ;Segment Type, Descriptor Type, Descriptor Privilege Level, Segment Present
                 db 00001111b            ;Segment Limit Bits 16-19, Scratch, Reserved, Segment Size, Granularity
                     db 0x00                 ;Segment Base Address Bits 24-31
GDT_Descriptor_Data_32:                         ;32 Bit Descriptor
                  db 0xFF, 0xFF           ;Segment Limit Bits 00-15
                   db 0x00, 0x00, 0x00     ;Segment Base Address Bits 00-23
                    db 10010010b            ;Segment Type, Descriptor Type, Descriptor Privilege Level, Segment Present
                 db 11001111b            ;Segment Limit Bits 16-19, Scratch, Reserved, Segment Size, Granularity
                     db 0x00                 ;Segment Base Address Bits 24-31
GDT_End:

Disk_Offset             dd 0x00000000

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Get_Entry_Point:   ;Out: AX = Entry Point Offset (ORG)
call $+0x0003                ;push ip
pop ax                      ;mov ax, ip
sub ax, $-0x0001
ret

Ret_Function:
ret

Delay:
dec ecx
cmp ecx, 0x00000000
je BS_Ret_Function
jmp BS_Delay

Read_Disk:          ;IN: BS_Disk_Offset = LBA Offset(Min = 1), CL = Tranfer Size - Limited To 64k(0x80), DL = Drive, ES:BX = Buffer
push cx                      ;Transfer Size
call BS_Read_Disk_Sector
cmp cl, 0x01
je BS_Read_Disk_Error
pop cx                   ;Transfer Size
call BS_Get_Entry_Point
mov si, BS_Disk_Offset
add di, ax
inc dword [cs:di]      ;LBA Offset
add bx, 0x0200           ;Buffer Offset
dec cl
cmp cl, 0x00
je BS_Ret_Function
jmp BS_Read_Disk

Read_Disk_Error:
jmp BS_Exit           ;Temp Code
ret

Read_Disk_Sector:
call BS_Get_Entry_Point
mov si, BS_Disk_Offset
add si, ax
mov eax, [cs:si]
call BS_LBA2CHS            ;Convert LBA to CHS
mov ah, 0x02             ;Function: Read Sectors
mov al, 0x01             ;# Of Sectors To Read
push bx
dw 0x13CD
jc BS_Read_Disk_Sector_Error
mov cl, 0x00           ;No Error
pop bx                     ;Buffer Offset
ret

Read_Disk_Sector_Error:
mov cl, 0x01                ;Error
pop bx                        ;Buffer Offset
ret

LBA2CHS:               ;IN: EAX = 32bit LBA Offset (2tb limit, far beyond the 8gig limit of ECHS, but limited by ECHS...)
push bx                       ;Buffer Offset
push dx                       ;Drive
push eax
shr eax, 0x00000010
mov dx, ax
pop eax
mov bx, 0x0012            ;Sectors Per Track
div bx
mov cl, dl
inc cl                    ;Sector
push eax
shr eax, 0x00000010
mov dx, ax
pop eax
mov bx, 0x0002           ;Heads Per Cylinder
div bx
mov ch, al             ;Cylinder
and ah, 0xFC
shl ah, 0x06
or cl, ah
mov dh, dl            ;Head
pop bx
mov dl, bl           ;Drive
pop bx                        ;Buffer Offset
ret


Unreal_Mode:

push ds
;push es
;push fs
;push gs
;push ss

cli                     ;Disable Interrupts
mov al, 0x80             ;Disable Non-Maskable Interrupts
out 0x70, al

xor ax, ax
mov ds, ax

lgdt [GDT_PD]

mov eax, cr0               ;Protected Mode
or al, 0x01
mov cr0, eax

;push cs
;push $+2
;retf                    ;Clear cs and cache

Init_Loop:               ;Dies after this...
mov cx, 0xFFFF
loop Init_Loop

mov ax, 0x0010           ;Load Descriptor
;mov ds, ax         ;Automaticly happens anyways
;mov es, ax
mov fs, ax
;mov gs, ax
;mov ss, ax

mov eax, cr0             ;Unreal Mode
and al, 0xFE
mov cr0, eax

;push cs
;push $+2
;retf                      ;Clear cs and cache

;pop ss
;pop gs
;pop fs
;pop es
pop ds

mov al, 0x00               ;Enable Non-Maskable Interrupts
out 0x70, al
sti                  ;Enable Interrupts

ret


Enable_A20_Slow:
mov al, 0xD0           ;Read Controller Status
out 0x64, al
New_IO_Delay
in al, 0x60          ;Controller Status
or al, 0x03               ;Enable The A20, Ensure The CPU Is Not Reset
mov bl, al
New_IO_Delay
mov al, 0xD1              ;Write Controller Status
out 0x64, al
New_IO_Delay
mov al, bl
out 0x60, al
ret

Disable_A20_Slow:
mov al, 0xD0              ;Read Controller Status
out 0x64, al
New_IO_Delay
in al, 0x60          ;Controller Status
or al, 0x01               ;Ensure The CPU Is Not Reset
and al, 0xFD            ;Clear The A20 Bit
mov bl, al
New_IO_Delay
mov al, 0xD1                ;Write Controller Status
out 0x64, al
New_IO_Delay
mov al, bl
out 0x60, al
ret

Enable_A20_Fast:
in al, 0x92
and al, 0xFE                ;Clear The CPU Reset Bit
or al, 0x02         ;Set The A20 Bit
New_IO_Delay
out 0x92, al
ret

Disable_A20_Fast:
in al, 0x92
and al, 0xFC             ;Clear The CPU Reset Bit And A20 Bit
New_IO_Delay
out 0x92, al
ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Init
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Init:

call Unreal_Mode

mov al, "1"
mov ah, 0x0E
dw 0x10CD

mov eax, 0x000B8004                ; note 32 bit offset
mov word [fs:eax], 0x0F01   ; attrib/char of smiley

mov al, "2"
mov ah, 0x0E
dw 0x10CD

mov eax, 0x000B8008            ; note 32 bit offset
mov word [fs:eax], 0x0F01   ; attrib/char of smiley


Init_Loop_2:
mov cx, 0xFFFF
loop Init_Loop_2

jmp Exit

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Exit
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Exit:
ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Footer
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

times (1409024-($-$$)) db 0x00

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    
Post 01 Aug 2008, 14:39
View user's profile Send private message Reply with quote
NEOAethyr



Joined: 20 Aug 2007
Posts: 19
NEOAethyr 02 Aug 2008, 17:21
Double post, sorry.

Just an update...

I've been testing my main program code with this more.
In virtual pc, as a floppy.

I was checking it a little under unreal mode.
I figuered out linear frame buffer access, simple as adding a 0x4xxx the mode #.
I have'nt figuered out how to get the address automatically, I thaught it would of been ModeInfoBlock_PhysBasePtr.

mov ebx, 0xF7FFFF00 ;Sis LFB Offset
That's what I got, and I was able to fill the screen with this Smile.
Which is a start.

I can't go straight lfb, I want to beable to compile a com file, and use it in windows, unless I could use lfb in windows...

Anyways I'll have some fun redo'ing a ton of code for linear fb, and then making sure that banking can still run.
Smile
It's gotta be in a flashable state where I can really test it Smile (if I re-wrote the whole thing I'de run it as a network rom so I could toggle it on or off with the cmos/bios menu just to be safe, incase it didn't work).

But for sure, I can boot windows right out of my debug rom floppy.
It boots automatically if the program exe's and then ret's from it's boot loader / ipl.
A soft reset essentually.
And windows boots with unreal mode pre-setup no ?'s asked.
Not that windows will probably reset all of that, still, my point is that windows can't tell the diff between unreal and real.


I still can't run unreal mode after the boot sector, but I can still get access to the full amount of mem if I setup it up before it.

I do not know the entry point of the floppy's boot sector.
My program's, or demo's is entry ptr of whatever I choose, right now 0x00010000 I think.
My program's rom entry point is usually 0x000D4000 (depends on other rom modules too).

Again my floppy's boot sector ptr, ???
I could find out though.

@DJ Mauretto, I think it's related to some address too now.

Stack maybe, irq's, ...
What else?
My main program works fine, I know inside and out pretty much.
My demo should be fine too, floppy disk access wise (would need and update to access hardrives) and etc.

My irq's are running fine after I run it from the bootsector.
So is my stack.
So maybe something related to the offset of with the unreal mode function...
Like the lgdtr instruction?

I thaught about that a long time ago.
And I tried to pass along the entry point inside my unreal mode set function.
Where I could add my entrypoint value of the gdt table offset, and pass that along as a register with the [] brackets like I usually do.
The compiler gives me an error.
I figuered the instruction was a type of one that was relative to the offset of the instruction it's self and not the actual define or lable.
But maybe..., I just thaught of something, all instrunctions of that type are bound to a max of one byte of distance to the lable, 8bit offset, 255 max offset.
I don't know if that instruction is able to read lables from a longer distance or not.

I mean if it's an instruction that's effected by org, then I've got a prob right there...
Then maybe I could get it to work in rom, but I dn about dos...
Because I've tried before as a standerd com file and just the unreal mode+ test, with no special org detecting code.
I dn why I put the get entry point function into the example though but that's what I'm using to figuer out where I am while in program.

Example:
call Get_Entry_Point
mov bx, Some_Memoy_Value_In_CS
add bx, ax ;this right here fixes the offset of the memory value to the correct one
mov ebx, [cs:bx] ;this right here is the 32bit value of "Some_Memory_Value_In_CS"

That's how I've been getting around in shadow ram.
Instead of copying the contents to a diff location of ram starting a preset org.
I'm fine with using it at the moment because I can stay at that location and still be there after windows 2003 has run(starting in rom).
It has come in handy, even though it makes my program bloat.
I've learn to deal with it and from time to time, optimize and reduces the programs code size.

So when I pass along a value form memory, or even pass along an offset.
I must beable to change that value before it's passed to an irq, or etc.

I'm gonna try some stuff...
lgdt [cs:bx]
[bx], compiles, oh crap, I must of never tried with [bx]...
oops.
I'll try it a little later on today and see if that fixes the code Smile.
That's probably a prob lol...


Edit: 08/03/08

Throughout yesterday I messed around a little and found that I could run unreal mode after the bootsector.
But the results are strange.

My code is'nt on this system, I swapped over all of the networking to a 2nd machine last night too...

Anyways, I shortend the unrealmode function.
With the same gdt as the above previous examples, I load descriptor fs with 0x0010(table 2).

Then on the one after the boot sector, I MUST load it with 0x0000.
Ex:
xor ax, ax
mov fs, ax

It runs though.
And with the 0'ed one(one after bootsector), I can't blindly find 0xB8000 addy.
But both match offsets at the vesa lfb, of 0xF8000000 (was a wierd addy before...) (now it's exactly as windows says it is in the device manager).

Also, the mode info ptr for the lfb addy is partially working.
I know all of my vesa and defines for it work.
So getting the value from the info blocks are np.

It's really odd.
I use the mode info blocks ptr for lfb, and I'm allowed to copy to the 1st bank of the screen, but nothing else.
But why in the heck am I getting the banked addy....
I dn if it's the same as the real one or not.
I'll have to figuer it out.

What I'm concerned about is that fact that offset 0x000B8000 is'nt working the way it should after I switch cpu modes after I've exited the boot block.

In a little bit I'm gonna get back on my other machine and check it out.
I'm gonna see if a com file will restart dos, or if it will behave now, with a vesa lfb inf loop.
I'll try in real dos too, and then make sure my main code is ok enough for rom, and make a menu entry for a demo of it, again, unreal mode then a vesa fill screen using lfb inf loop.

That lgdt [cs:bx], and a diff desc selector on the 2nd switch is what I did to get it working.
I don't think it's 100% right though, but I'm gonna try to figuer it out.
I mean, if it's not reseting at all anymore, then I can use it to dump address info to the screen, then I can figuer some stuff out maybe...
Post 02 Aug 2008, 17:21
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.