Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Real mode BIOS routine and Protected Mode

I am doing some OS experiment. Until now, all my code utilized the real mode BIOS interrupt to manipulate hard disk and floppy. But once my code enabled the Protect Mode of the CPU, all the real mode BIOS interrupt service routine won't be available. How could I R/W the hard disk and floppy? Do I need to do some hardware drivers now? How could I start? Is this one of the reasons that an OS is so difficult to develop?

I know that hardwares are all controlled by reading from and writing to certain control or data registers. For example, I know that the Command Block Registers of hard disk range from 0x1F0 to 0x1F7. But I am wondering whether the register addresses of so many different hardwares are the same on the PC platform? Or do I have to detect that before using them? How to detect them??

Since I am not sure about how to R/W floppy or hard disk in Protect Mode, I have to use the BIOS interrupt to load all my necessary kernel file from floppy into memory for now. But what could I do if my kernel file exceeds the real mode 1M space limit?

For any responses I present my deep appreciation.

Update

I vaguely recall that there's a way to switch Protected Mode first and then switched back to real mode. And then we could use the BIOS routine in Protected Mode. Maybe I remember wrong. Did someone remember it right?

like image 445
smwikipedia Avatar asked Sep 02 '10 03:09

smwikipedia


People also ask

What is real mode and protected mode?

Typically, much operating system code and almost all application programs run in protected mode to ensure that essential data is not unintentionally overwritten. Real mode is program operation in which an instruction can address any space within the 1 megabyte of RAM.

Can you switch between real and protected mode?

The only data structure you need to switch from Real Mode to Protected Mode is GDT correctly set and loaded. Everything else (preparing IDT, loading TSS, reloading new GDT, etc.) is not strictly necessary to switch into Protected Mode.

How protected mode is better than real mode?

The advantages of protected mode (compared to real mode) are: Full access to all of the system's memory. There is no 1 MB limit in protected mode. Ability to multitask, meaning having the operating system manage the execution of multiple programs simultaneously.

Does BIOS run in real mode?

As of 2018, current x86 CPUs (including x86-64 CPUs) are able to boot real mode operating systems and can run software written for almost any previous x86 chip without emulation or virtualization. The PC BIOS which IBM introduced operates in real mode, as do the DOS operating systems (MS-DOS, DR-DOS, etc.).


6 Answers

While it's possible to switch between protected mode and real mode, it's almost certainly not what you'd want to do. This is how things were done on the 286 (quite clumsily, since it didn't intentionally support switching from protect mode back to real mode t all). Starting with the 386, however, they added a V86 mode which can run as a task in protected mode.

If you want to use the BIOS from protected mode, this is almost certainly the way to do things. You can basically create a V86 task, switch to it to use the BIOS, then switch back to another task to execute protected mode code.

If you want to play with this, you might want to take a look at DJGPP, which is a DOS extender (basically, a program like I just described to handle the switching into/out of a V86 task as needed to handle disk I/O and such) along with a port of a rather old version of gcc so you can write code that runs on it.

The commercial market for DOS extenders is now essentially dead, so at least one formerly commercial DOS extender (HX) is now available as open source. If you're going to play with that, you'd probably want to use it with the OpenWatcom compiler.

Edit: As far as how you read a file of more than 1 MB (for example), it's simple but clumsy: read the data in chunks, and when you've finished a read you either re-map the memory, or copy the contents, to get what you read to where you really want it, then read another chunk.

As far as talking to the hardware goes: a lot depends on whether you just want something that works to some degree, or if you want to take full advantage of the hardware that's present. Just using the basic IDE ports will let you talk to almost any hard drive that isn't really ancient -- but getting the most out of the hardware is quite a bit more work. IDE/ATAPI drives have used about a half dozen different DMA modes, each of which has to be set up slightly differently. Quite a few of those are old enough you probably don't care about them, so you might want to directly support only a couple of the newest, and for anything else fall back to basic (non-DMA) transfers.

like image 109
Jerry Coffin Avatar answered Oct 02 '22 05:10

Jerry Coffin


It seems that your question is not how to talk to hardware (the problem device drivers would solve) because the BIOS interfaces are sufficient for you.

Rather, you need to know how to communicate between protected mode ring 0 (which has unlimited access to BIOS calls and all other privileged instructions) and protected mode ring 3 where application code usually lives. This is a system call. Pretty much all architectures run interrupt handlers in privileged mode so a software interrupt is one way of implementing system calls, x86 also provides a syscall instruction which is optimized for this purpose.

Of course, you could just run everything in ring 0 with a flat memory model where you can access all memory directly.

Ring 0/ring 3 is the x86 terminology, but all systems with an MPU support some concept of a privileged mode which allows access to memory by physical address (and for split memory-I/O architectures, access to all of I/O space).

like image 39
Ben Voigt Avatar answered Oct 02 '22 04:10

Ben Voigt


If you use legacy IDE, all of the hardware will communicate in the same fashion - you don't have to worry about writing custom drivers (though should you get far enough, you will find that even though they all say they follow the same spec, they all have their fun quirks)

http://www.t13.org/ and http://www.t10.org are where you'll find the relevant specs - if you're feeling brave, you could also write a SATA driver - you'll find the AHCI spec on Intel's website (http://www.intel.com/technology/serialata/ahci.htm)

like image 36
Ana Betts Avatar answered Oct 02 '22 05:10

Ana Betts


If you'd like code to read the harddrive (or USB key) from 32-bit mode, you can find some from my OS project PwnOS. It doesn't support DMA or anything, but the basics work. Specifically, trunk/Core/IO/ATA Driver.asm contains the code for reading an ATA device, e.g. harddrive (without magic numbers! :D)

I decided not to write the code for writing a device, since I didn't want to risk it, but it's very similar. The specs can be found at the first google hit for "cottontail os dev" (you'll want the ATA/ATAPI-6 document), but they're a bit hard to follow.

If you have any more questions about it, feel free to ask. I've got code to get set up into 64-bit mode as well, as well as an assembly language editor that I specifically designed for OS development (search for Inventor IDE), in that it has built-in assembling and linking of 16-bit, 32-bit, and 64-bit code at defined addresses and file offsets. That way, you can focus on the part you're interested in, instead of the fluff.

like image 35
Neil Dickson Avatar answered Oct 02 '22 06:10

Neil Dickson


There's a set of tutorials on Protected Mode here. Tut15 and tut16 effectively run DOS and BIOS in v86 mode, all interrupts work.

like image 41
Alexey Frunze Avatar answered Oct 02 '22 06:10

Alexey Frunze


V86: yes the way to go, but if setting up an OS:

try this(designed for long mode but should work.I havent tested this YET, I see no reason it wont work yet.Issue is not nasm, its ld.)

LD H8s 16-bit ELF/aout references.This is standard to load from GRUB.

I kow the 32-bit CS is off, I need to double check its location. Otherwise it looks ok.

This is hard to find code.

-- ;modify for 32bit??

;this code is placed somewhere after 10000h
;-----we're in LONG MODE-----
  mov          dword [.stckptr], esp   ;first of all save stack
  sgdt         [.gdtv32]               ;save your gdt pointer
  lgdt         [.gdtv16]               ;load a new one
  sidt         [.idt32]                ;save your idt pointer
  lidt         [.idt16]                ;load real mode idt
  ;far jump in long mode is not possible, do a trick
  push         DESC_REAL
  push         @f-10000h               ;this is CS*10h, modify if needed!
  retfd
.stckptr:
  dd           0
  align        16
.gdtv32:
  dw           0
  dd           0
  align        16
.gdtv16:
  dw           .gdtend-.gdt-1
  dd           .gdt,0
  align        16
.gdt:
  dd           0,0                      ;null descriptor
DESC_DATA=8                                 ;descriptor in YOUR GDT (modify)
DESC_LONG=$-.gdt
  dd           00000000h,00209800h      ;32 bit  mode cs -MOD ME
DESC_REAL=$-.gdt
  dd           0000FFFFh,00009801h      ;16 bit real mode cs (modify base if needed!)
.gdtend:
  align        16
.idt32:
  dw           0
  dd           0
  align        16
.idt16:
  dw           3FFh
  dd           0
  USE16

;-----we're in COMPATIBLITY MODE-----
  ;disable paging and protmode at once
@@:   mov          eax, cr0
  and          eax, 7FFFFFFEh   
  mov          cr0, eax

  ;set up real mode segment registers and stack
  mov          esp, realmode_stack_top          ;modify it to your needs!
  xor          ax, ax
  mov          ds, ax
  mov          es, ax
  mov          fs, ax
  mov          gs, ax
  mov          ss, ax
  ;convert long mode rip to real mode cs:ip
  ;jmp CS:(pmode address)-CS*10h

  jmp          1000h:@f-10000h                  ;modify if needed!
;-----we're in REAL MODE-----
@@:   ;***********call some BIOS interrupt here**********
  mov          ax, 3
  int          10h


  ;switch back to long mode
  mov          eax, cr0
  or           eax, 80000001h
  mov          cr0, eax                         ;enable protmode and paging

  ;jmp         DESC_LONG:@f
  db           66h
  db           0EAh
  dd           @f
  dw           DESC_LONG
  USE32
;-----we're in protected MODE-----
@@:   lgdt         [cs:.gdtv32]                    ;restore gdt
  mov          ax, DESC_DATA                   ;read YOUR DATA descriptor to selectors
  mov          ds, ax
  mov          es, ax
  mov          fs, ax
  mov          gs, ax
  mov          ss, ax
  lidt         [.idt32]                        ;restore idt
  mov          rsp, qword [.stckptr]           ;restore stack
  ;must be a non rip-relative jump
  mov          eax, @f
  jmp          eax
@@:

  ;AS WE WERE!
like image 22
Richard Jasmin Avatar answered Oct 02 '22 05:10

Richard Jasmin