(With Real Time Keyboard Interrupt Acknowledgement)
By
Anirban Sinha (University Roll:XXXXXXXX)
DEPARTMENT OF COMPUTER SCIENCE AND ENGINEERING INSTITUTE OF ENGINEERING AND MANAGEMENT
AN HONORS THESIS Submitted in partial fulfillment of the of the requirements of Degree of Bachelor of Technology (B.Tech) in Computer Science and Engineering the under the affiliation of Kalyani University
Under the guidance of
Prof. B.K.Dutta
Project Guide and HOD Department of Computer Science and Engineering Institute of Engineering and Management
INSTITUTE OF ENGINEERING AND MANAGEMENT Y-12, BLOCK EP, SECTOR V, SALT LAKE ELECTRONICS COMPLEX KOLKATA 700091, WEST BENGAL, INDIA
May 2002
Anirban Sinha, 2002
Acknowledgements
We are grateful to our beloved instructor, Prof Bimal Kumar Dutta who is also the head of the department, Computer Engineering, IEM for help, advice and suggestions in our endeavor. We are also grateful to all those people who have published their work in this subject on the Internet from where we got immense help and guidance. This work would not have been successful if they had not shared their immense and valuable suggestions and experiences with all others working in this field. Special thanks go to Christopher Giese (geezer@execpc.com) for his work on the protected mode tutorials and his guidance in the midst of our work.
Design of a 32-bit Multitasking Operating System
3
Abstract
This work deals with the development of the kernel and boot loader of an operating system so that the machine can boot into a basic user environment. The user can input some specific commands for the execution by the system. Provisions are made so that more than one process can run simultaneously on different virtual consoles so that multitasking can be achieved.
Design of a 32-bit Multitasking Operating System
4
System Requirements
SOFTWARE RESOURCES:
The software resources to build the kernel include DJGPP: GNU C compiler for windows, NASM: Netwide Assembler, CM32 Compiler, decompilers etc.
HARDWARE RESOURCES:
Hardware resources for running the system include a 32 bit 80386 or above Intel based Microprocessor, standard keyboard, display device, standard floppy drive controller (optional).
Design of a 32-bit Multitasking Operating System
5
Contents
CHAPTER 1 INTRODUCTION..........................................................................................................................6 CHAPTER 2 BOOTING PHASE.........................................................................................................................8 2.1 PLAIN BOOTING PHASE (STAGE 1 OF TWO STAGE BOOTING)..........................................................................8 2.2 ENVIRONMENT SETTING PHASE (STAGE 2 OF TWO STAGE BOOTING) .............................................................9 2.2.1 Writing ISR s:.................................................................................................................................9 2.2.2 Switching to Protected Mode.........................................................................................................10 2.2.3 Enabling the Extended Memory ...................................................................................................12 2.2.4 Reprogramming 8259 - The Idea..................................................................................................13 2.2.5 Loading the Kernel ........................................................................................................................15 CHAPTER 3 KERNEL DEVELOPMENT PHASE.........................................................................................16 3.1 KERNEL BOOTSTRAPPING CODE ...................................................................................................................16 3.2 THE MAIN KERNEL CODE............................................................................................................................21 3.3 FUNCTIONS OF THE PROGRAM MODULE VIDEO.C......................................................................................22 3.4 FUNCTIONS OF THE PROGRAM MODULE KBD.C..................................................................................23 CHAPTER 4 DEVICE DRIVER MODULES...................................................................................................27 4.1 DESCRIPTION OF THE FLOPPY DISK DRIVER.................................................................................................27 CHAPTER 5 THE SOURCE CODES...............................................................................................................29 5.1 MODULE MAIN.C THE MAIN KERNEL CODE..........................................................................................30 5.2 MODULE VIDEO.C VIDEO HANDLING MODULE .....................................................................................36 5.3 MODULE KBD.C KEYBOARD HANDLING MODULE .................................................................................45 5.4 LIBRARY ROUTINES.....................................................................................................................................60 5.4.1 Hardware Interface Functions .....................................................................................................60 5.4.2 String Manipulation Functions....................................................................................................61 5.4.3 Segment Jump Functions .............................................................................................................62 5.4.4 The Printf Function .................................................................................................................64 5.5 DRIVER ROUTINES.......................................................................................................................................72 5.5.1 Floppy Disk Driver ........................................................................................................................72 CHAPTER 6 FUTURE WORK.........................................................................................................................78 BIBLIOGRAPHY................................................................................................................................................79 Design of a 32-bit Multitasking Operating System
6 Chapter 1 Introduction
Developing operating system kernels is not a new task. There are several sample operating system kernels available on the Internet designed by many amateur developers. Many people have worked in this area before and many more will work in the future. However, since at the honors level, we are not supposed to implement a novel idea in a final year project, this work seemed appropriate enough. The reasons for this are many. Some of them are enumerated below. Firstly, no one in this institute had previously taken this venture of designing an operating system from scratch. The work seemed to be challenging enough since developing an operating system required a lot of depth in understanding the x86 architecture, the operating system modules and functions along with good skills in C and assembly programming at low level. We wanted to take this challenge as this would give us the perfect opportunity to acquire strong foundation in basic areas of computer science. Secondly, the knowledge acquired by working through this project would help us not only in testing the operating system concepts hands on but also help us in pursuing and exploring higher and more complicated areas of computer science research, basis of which lay in the areas we explore in this project. Thirdly, this project would also give us an idea about the design and development of embedded systems which is one of the primary areas of interest in the industry. Lastly, through this project, if successful, we would get the fun & satisfaction of creating something new and something of our very own. Thus undertaking this project was absolutely relevant in the areas of our study. The entire work took approximately ten months from submitting the proposal to delivery of this final report. Due to shortage of time available for final year projects (less than one year) & strict deadlines, we could not ultimately implement many important features which are essential for a fully blown operating system. However, regardless of this important drawback, we found it extremely satisfying and useful working through this project and being able to design a fully working operating system kernel. Design of a 32-bit Multitasking Operating System
7 The project has been divided into two parts, namely the Booting phase and development of the Kernel which are described in succeeding chapters of this thesis.
Design of a 32-bit Multitasking Operating System
8 Chapter 2 Booting Phase
This phase is further divided into two main functional sections:
1. Booting the computer and 2. Setting the environment to load the kernel into the extended memory.
2.1 Plain Booting Phase (Stage 1 of two stage booting)
In the plain booting phase we assure the following: A valid boot sector has the code 0xAA55 at an offset of 510 at the very first sector of the disk. Therefore just after POST operation BIOS simply checks the corresponding location of drive 0 for the code (depending upon the CMOS booting sequence settings specified). If a valid boot sector is found then it is loaded at location 0:07C0H in main memory. We wrote our own boot sector, assembled it into a flat binary file using NASM and loaded it into the first sector (sector 0, track 0) of the disk. We wrote our own C program to write the boot sector to the first sector of the disk. This was done using BIOS interrupt 0x13 and service number Ah=02. The C program that writes the boot sector plain binary file to sector 0 track 0 is given below:
/ / ***************START****************
#i ncl ude <bi os. h> #i ncl ude <st di o. h>
voi d mai n( ) { FI LE *i n; unsi gned char buf f er [ 520] ;
i f ( ( i n = f open( " boot sect " , " r b" ) ) ==NULL) { pr i nt f ( " Er r or l oadi ng f i l e\ n" ) ; exi t ( 0) ; }
f r ead( &buf f er , 512, 1, i n) ; Design of a 32-bit Multitasking Operating System
9
whi l e( bi osdi sk( 3, 0, 0, 0, 1, 1, buf f er ) ) ;
f cl ose( i n) ; }
/ / *************END****************************
During this phase itself, the boot sector code at first checks the processor. Since our kernel supports Intel 80386 and above processor, any lower version of the processor brings the system to a halt by the initial bootstrap code. If a valid processor is found, we land up in our second stage of our two-stage boot loader, one that performs the environment initialization process.
2.2 Environment Setting Phase (Stage 2 of two stage booting)
Things to be done before the kernel is loaded in memory are:
Write Operating Systems own Interrupt Service Routines. Switch to 32 bit protected mode. Enable A20 line of the keyboard controller chip so as to enable XMS memory. Reprogram the 8259 Interrupt controller to accommodate OS-defined interrupts. Load the kernel to the predefined location in XMS-memory from the Disk
2.2.1 Writing ISR s:
Interrupt handlers can be written exactly in the same way as all other codes are written. For example, somewhere in our assembly code we write:
i sr 30: pusha push gs push f s push es push ds Design of a 32-bit Multitasking Operating System
10
( act ual code f or t he handl er )
pop ds pop es pop f s pop gs popa i r et
Here we first save the contents of all the registers that we are going to use in our ISR and then we put the actual code for the service routine.
Now in the Interrupt Descriptor Table entry we point one of the descriptors to this ISR in the following way: ~
i dt : dw i sr 30
dw SYS_CODE_SEL db 0 db 0x8E dw 0
The descriptors are also written in the same way as we write any other assembly code, but all descriptors MUST be written in the contiguous fashion.
Some static data structures must be initialized at this time.(viz. GDT, IDT etc). They are done by loading the GDTR and IDTR with appropriate values and pointing them to the section of the code that holds these tables.
2.2.2 Switching to Protected Mode
Before switching to protected mode, a minimum set of system data structures and code modules must be loaded into memory. We have shown how that is being done. Once these tables are created, software initialization code can switch into protected mode.
Executing a MOV CR0 instruction that sets the PE flag in the CR0 register enables the protected mode. (In the same instruction, the PG flag in register CR0 can be set to enable paging.)
Execution in protected mode begins with a CPL of 0.
Design of a 32-bit Multitasking Operating System
11 The 32-bit Intel Architecture processors have slightly different requirements for switching to protected mode. To insure upwards and downwards code compatibility with all 32-bit Intel Architecture processors, it is recommended that the following steps be performed:
1. Disable interrupts. A CLI instruction disables maskable hardware interrupts. NMI interrupts can be disabled with external circuitry. (Software must guarantee that no exceptions or interrupts are generated during the mode switching operation). 2. Execute the LGDT instruction to load the GDTR register with the base address of the GDT. 3. Execute a MOV CR0 instruction that sets the PE flag (and optionally the PG flag) in control register CR0. 4. Immediately following the MOV CR0 instruction, execute a far J MP or far CALL instruction. (This operation is typically a far jump or call to the next instruction in the instruction stream). The J MP or CALL instruction immediately after the MOV CR0 instruction changes the flow of execution and serializes the processor. If paging is enabled, the code for the MOV CR0 instruction and the J MP or CALL instruction must come from a page that is identity mapped (that is, the linear address before the jump is the same as the physical address after paging and protected mode is enabled). The target instruction for the J MP or CALL instruction does not need to be identity mapped. 5. If a local descriptor table is going to be used, execute the LLDT instruction to load the segment selector for the LDT in the LDTR register. 6. Execute the LTR instruction to load the task register with a segment selector to the initial protected-mode task or to a writable area of memory that can be used to store TSS information on a task switch. 7. After entering protected mode, the segment registers continue to hold the contents they had in real-address mode. The J MP or CALL instruction in step 4 resets the CS register.
Perform one of the following operations to update the contents of the remaining segment registers: - Design of a 32-bit Multitasking Operating System
12
o Reload segment registers DS, SS, ES, FS, and GS. If the ES, FS, and/or GS registers are not going to be used, load them with a null selector. o Perform a J MP or CALL instruction to a new task, which automatically resets the values of the segment registers and branches to a new code segment. 8. Execute the LIDT instruction to load the IDTR register with the address and limit of the protected-mode IDT. 9. Execute the STI instruction to enable maskable hardware interrupts and perform the necessary hardware operation to enable NMI interrupts.
2.2.3 Enabling the Extended Memory
When the AT was introduced, it was able to access up to sixteen megabytes of memory, but in order to remain compatible with the IBM-XT, memory wraparound had to be duplicated in the AT so things would work the same The 20th address line on the bus (A20) was turned off so this "wrap-around" effect worked and software from the old XT days continued to work The A20 line is controlled by the keyboard controller unit. This is usually a derivative of the 8042 chips.
After enabling the A20 line of 8042, we can access memory beyond the 1 Megabyte boundary. This memory over and above the 1 MB limit is known as the Extended memory or the XMS memory.
We have to enable the A20 line to prevent memory wraparound and to use more than 1 MB of memory in protected mode. To enable the A20 line, some hardware IO is used using the Keyboard Controller chip (8042 chip) and enable it. We have to enable the A20 line to prevent memory wraparound and to use more than 1 MB of memory in protected mode. The basic algorithm is given below:-
1. Disable Interrupts 2. Wait until the keyboard buffer is empty 3. Send command to disable the keyboard 4. Wait until the keyboard buffer is empty 5. Send command to read output port 6. Wait until the keyboard buffer is empty 7. Save byte from input port Design of a 32-bit Multitasking Operating System
13 8. Wait until the keyboard buffer is empty 9. Send command Write output port 10. Wait until the keyboard buffer is empty 11. Send saved byte OR by 2 (GATE A20 to ON) 12. Wait until the keyboard buffer is empty 13. Enable the keyboard 14. Enable interrupts
The 8259A is a device specifically designed for use in real time, interrupt driven microcomputer systems. It manages eight levels or requests and has built-in features for expandability to other 8259A's (up to 64 levels). It is programmed by the system's software as an I/O peripheral.
The 8259A accepts two types of command words generated by the CPU:
Design of a 32-bit Multitasking Operating System
14 1. Initialization Command Words (ICWs): Before normal operation can begin, each 8259A in the system must be brought to a starting pointby a sequence of 2 to 4 bytes timed by WR pulses.
2. Operation Command Words (OCWs): These are the command words which command the 8259A to operate in various interrupt modes. These modes are:
The OCWs can be written into the 8259A anytime after initialization.
8259 can be reprogrammed to accommodate additional interrupts that are written when an operating system is initialized. These are the interrupts supported only by the present OS.
Each 8259 supports 8 interrupt request levels that generates call to 8 locations in memory that are spaced equally apart , spaced either 4 memory locations or 8 memory locations away from each other. The starting address, call address interval, mode of operation (single or cascaded) and level/edge triggered operating mode will have to be specified using the Initialization Code Word-1 and Initialization Code Word-2.
If there are two 8259s used in cascading modes, the master/slave configuration is specified using the Initialization Code Word-3. If required, Initialization Code Word-4 may be used to fine tune 8259 further.
Next, we will have to enable IRQs at these interrupts using the Operational Code Word-1.
Lets say we want to enable interrupts 0x20 to 0x2F (INT 0x20-INT 0x2F) and let us suppose we will use two 8259s in cascaded mode, master will handle interrupts 0x20 to 0x27 and the slave handles interrupts 0x28 to 0x2F. Here is the example sample code:
mov al , 0x11 out 0x20, al out 0xA0, al
mov al , 0x20 out 0x21, al add al , 8 out 0xA1, al mov al , 4 out 0x21, al mov al , 2 Design of a 32-bit Multitasking Operating System
15 out 0xA1, al mov al , 1 out 0x21, al out 0xA1, al mov al , 0xFE out 0x21, al mov al , 0xFF out 0xA1, al
2.2.5 Loading the Kernel
The main task after the proper environment for the kernel has been set up is to load the kernel from disk into the main memory and begin execution of the kernel.
This is accomplished by using the BIOS interrupt 13H. This interrupt first resets the Disk controller chip and then reads a specified number of bytes from the specified sector, head, track of either the hard disk or the floppy disk after positioning the head over the specified location.
One thing is carefully considered. Before we begin, we must first know the exact size of the kernel .bin file and the exact physical position of the disk where it is written. Also we must fix the physical address in the main memory where the kernel will be loaded.
Another thing that is of utmost importance is that as we read the kernel binary file, we must recalculate the position of the read/write head every time a block of binary data is read. This calculation has to be done manually since the Interrupt gives the facility of only reading a fixed size of data from the disk location specified. Also we must increment the physical address of the memory location to which the block of binary data is being written, the increment being equal to the size of the block being read.
Lastly, some provisions must be made in case there is some failure in reading the data from the disk. A fixed number of attempts are made to read the data from the specified location and if it fails within this specified number of attempts, the disk is considered to be bad and appropriate message must be written to the output device. Design of a 32-bit Multitasking Operating System
16 Chapter 3 Kernel Development Phase
The development of the kernel takes place module wise. The main modules call the subordinate modules and they in turn call their dependent modules. Each of the modules once called becomes a terminate and stay resident program until the user issues reboot command where the memory is cleared and machine reboots. Initially, an assembly level bootstrap program performs some initial checking functions and then calls the main C program and freezes.
3.1 Kernel bootstrapping code The main bootstrapping of the kernel is done in assembly. From within this code, other modules and functions are invoked. The assembly code is given below.
GLOBAL ent r y ent r y: ; check i f dat a segment l i nked, l ocat ed, and l oaded pr oper l y mov eax, [ ds_magi c] cmp eax, DS_MAGI C j e ds_ok
; di spl ay a bl i nki ng whi t e- on- bl ue ' D' and f r eeze Design of a 32-bit Multitasking Operating System
17 mov wor d [ 0B8000h] , 9F44h j mp shor t $ ds_ok: I MP mai n call main ; call C code jmp $ ; freeze ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; name: get vect ; act i on: r eads i nt er r upt vect or ; i n: [ EBP + 12] = vect or number ; out : vect or st or ed at addr ess gi ven by [ EBP + 8] ; modi f i es: EAX, EDX ; mi ni mumCPU: ' 386+ ; not es: C pr ot ot ype: ; t ypedef st r uct ; { unsi gned access_byt e, ei p; } vect or _t ; ; get vect ( vect or _t *v, unsi gned vect _num) ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
EXP get vect push ebp mov ebp, esp push esi push ebx mov esi , [ ebp + 8]
; get access byt e f r omI DT[ i ] xor ebx, ebx mov bl , [ ebp + 12] shl ebx, 3 mov al , [ i dt + ebx + 5] mov [ esi + 0] , eax
; get handl er addr ess f r omst ub mov eax, i sr 1 sub eax, i sr 0 ; assume st ub si ze < 256 byt es Design of a 32-bit Multitasking Operating System
18 mul byt e [ ebp + 12] mov ebx, eax add ebx, i sr 0 mov eax, [ ebx + ( i sr 0. 1 - i sr 0 + 1) ] mov [ esi + 4] , eax pop ebx pop esi pop ebp r et ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; name: set vect ; act i on: wr i t es i nt er r upt vect or ; i n: [ EBP + 12] = vect or number , ; vect or st or ed at addr ess gi ven by [ EBP + 8] ; out : ( not hi ng) ; modi f i es: EAX, EDX ; mi ni mumCPU: ' 386+ ; not es: C pr ot ot ype: ; t ypedef st r uct ; { unsi gned access_byt e, ei p; } vect or _t ; ; get vect ( vect or _t *v, unsi gned vect _num) ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
EXP set vect push ebp mov ebp, esp push esi push ebx mov esi , [ ebp + 8]
; st or e access byt e i n I DT[ i ] mov eax, [ esi + 0] xor ebx, ebx mov bl , [ ebp + 12] shl ebx, 3 mov [ i dt + ebx + 5] , al Design of a 32-bit Multitasking Operating System
19
; st or e handl er addr ess i n st ub mov eax, i sr 1 sub eax, i sr 0 ; assume st ub si ze < 256 byt es mul byt e [ ebp + 12] mov ebx, eax add ebx, i sr 0 mov eax, [ esi + 4] mov [ ebx + ( i sr 0. 1 - i sr 0 + 1) ] , eax pop ebx pop esi pop ebp r et ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; i nt er r upt / except i on st ubs ; *** CAUTI ON: t hese must be consecut i ve, and must al l be t he same si ze. ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
I NTR 0 ; zer o di vi de ( f aul t ) I NTR 1 ; debug/ si ngl e st ep I NTR 2 ; non- maskabl e i nt er r upt ( t r ap) I NTR 3 ; I NT3 ( t r ap) I NTR 4 ; I NTO ( t r ap) I NTR 5 ; BOUND ( f aul t ) I NTR 6 ; i nval i d opcode ( f aul t ) I NTR 7 ; copr ocessor not avai l abl e ( f aul t ) I NTR_EC 8 ; doubl e f aul t ( abor t w/ er r or code) I NTR 9 ; copr oc segment over r un( abor t ; 386/ 486SX onl y) I NTR_EC 0Ah ; bad TSS ( f aul t w/ er r or code) I NTR_EC 0Bh ; segment not pr esent ( f aul t w/ er r or code) I NTR_EC 0Ch ; st ack f aul t ( f aul t w/ er r or code) I NTR_EC 0Dh ; GPF ( f aul t w/ er r or code) I NTR_EC 0Eh ; page f aul t I NTR 0Fh ; r eser ved I NTR 10h ; FP except i on/ copr ocessor er r or ( t r ap) I NTR 11h ; al i gnment check ( t r ap; 486+ onl y) Design of a 32-bit Multitasking Operating System
20 I NTR 12h ; machi ne check ( Pent i um+ onl y) I NTR 13h I NTR 14h I NTR 15h I NTR 16h I NTR 17h I NTR 18h I NTR 19h I NTR 1Ah I NTR 1Bh I NTR 1Ch I NTR 1Dh I NTR 1Eh I NTR 1Fh
; i sr 20 t hr ough i sr 2F ar e har dwar e i nt er r upt s. The 8259 pr ogr ammabl e ; i nt er r upt cont r ol l er ( PI C) must be r epr ogr ammed t o make t hese wor k. I NTR 20h ; I RQ 0/ t i mer i nt er r upt I NTR 21h ; I RQ 1/ keyboar d i nt er r upt I NTR 22h I NTR 23h I NTR 24h I NTR 25h I NTR 26h ; I RQ 6/ f l oppy i nt er r upt I NTR 27h I NTR 28h ; I RQ 8/ r eal - t i me cl ock i nt er r upt I NTR 29h I NTR 2Ah I NTR 2Bh I NTR 2Ch I NTR 2Dh ; I RQ 13/ mat h copr ocessor i nt er r upt I NTR 2Eh ; I RQ 14/ pr i mar y ATA ( " I DE" ) dr i ve i nt er r upt I NTR 2Fh ; I RQ 15/ secondar y ATA dr i ve i nt er r upt
; syscal l sof t war e i nt er r upt I NTR 30h Design of a 32-bit Multitasking Operating System
21 ; t he ot her 207 vect or s ar e undef i ned %assi gn i 31h %r ep ( 0FFh - 30h) I NTR i %assi gn i ( i + 1) %endr ep
The data structure regs used here is:
typedef struct { /* pushed by pusha */ unsigned edi, esi, ebp, esp, ebx, edx, ecx, eax; /* pushed separately */ unsigned ds, es, fs, gs; unsigned which_int, err_code; /* pushed by exception. Exception may also push err_code. user_esp and user_ss are pushed only if a privilege change occurs. */ unsigned eip, cs, eflags, user_esp, user_ss; } regs_t;
3.2 The Main Kernel Code The main kernel code is a C program written in ANSI C given below.
i nt mai n( voi d) { vect or _t v; i ni t _vi deo( ) ; / / Initializes video kpr i nt f ( " \ n\ nDevel oper s of AVOS: \ n" ) ; / / ot her messeges . . . . i ni t _keyboar d( ) ; / / initializes keyboard
i ni t _8259s( ) ; / / initializes 8259 interrupt handler
Design of a 32-bit Multitasking Operating System
22 kpr i nt f ( " I nst al l i ng keyboar d i nt er r upt handl er . . . \ n" ) ; / * we don' t save t he ol d vect or */ v. ei p = ( unsi gned) keyboar d_i r q; v. access_byt e = 0x8E; / * pr esent , r i ng 0, ' 386 i nt er r upt gat e */ set vect ( &v, 0x21) ; kpr i nt f ( " Enabl i ng har dwar e i nt er r upt s. . . \ n" ) ; enabl e( ) ; / / Enable all interrupts
kpr i nt f ( " Enabl i ng Fl opy Di sk Cont r ol l er \ n" ) ; f d_i ni t ( ) ; / / Enabling Floppy Controller
kpr i nt f ( " *** Pr ess HLP t o see command t abl e ***\ n" ) ; kpr i nt f ( " *** Pr ess Ct r l +Al t +Del t o r eboot ***\ n\ n\ n" ) ; kpr i nt f ( " $>" ) ; / / the prompt whi l e( 1) / * freeze but remain resident in memory */ ; r et ur n 0; }
As can be seen from the above code, the main program module calls other functions from other program modules as and when required. Each of these functions in the module either initializes any one single device of the machine or performs certain device specific functions. For example, the program module video.c contains not only the function init_video() which initializes the video device, but also contains other video related specific functions. Some of these modules are described in subsequent sections. 3.3 Functions of the program module video.c
void select_vc(unsigned which_vc) // selects video consoles static void move_csr(void) // moves the caret on the screen static void set_attrib(console_t *con, unsigned att) // sets attributes of the characters on the screen static void scroll(console_t *con) // scrolls one screen at a time Design of a 32-bit Multitasking Operating System
23 void init_video(void) // initializes the video void blink(void) // how about blinking characters? static void putch_help(console_t *con, unsigned c) and void putch(unsigned c) // our very own printf function The entire framebuffer is divided into a maximum of 12 virtual consoles, each operating independently. For each of the 12 VCs, independent data structure is maintained as shown below:- typedef struct /* circular queue */ { unsigned char *data; unsigned size, in_base, in_ptr/*, out_base*/, out_ptr; } queue_t;
Here, console_t is the data structure that maintains all variables corresponding to a single virtual console. The function void select_vc(unsigned which_vc) selects a virtual console from among the 12 virtual consoles simply by updating the current cursor address and modifying the current base address of video display. Thus, more than one command can be issued at the various command consoles at approximately the same time which execute paralleley, creating a multitasking effect. 3.4 Functions of the program module kbd.c static void reboot(void) // reboots machine static void write_kbd(unsigned adr, unsigned data) // writes to keyboard input buffer Design of a 32-bit Multitasking Operating System
24 static unsigned convert(unsigned key) void keyboard_irq(void) // the keyboard irq int search_comnd(char *comnd) // searches for valid command word void init_keyboard(void) // initializes keyboard
Each of these functions are called as and when required and some of these like keyboard_irq remains hooked to the keyboard irq of 8259 interrupt controller and is called every time a key is pressed. The following piece of code does this:-
where access_byte is the access rights of the modified interrupt vector and eip is the instruction pointer pointing to the address of the first instruction of the interrupt service routine. In this case, eip points to keyboard_irq, the symbolic address of the starting instruction of the isr that handles all the keyboard related functions.
Setvect is an assembly coded function given below
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; name: set vect ; act i on: wr i t es i nt er r upt vect or ; i n: [ EBP + 12] = vect or number , vect or st or ed at addr ess [ EBP + 8] ; out : ( not hi ng) Design of a 32-bit Multitasking Operating System
25 ; modi f i es: EAX, EDX ; mi ni mumCPU: ' 386+ ; not es: C pr ot ot ype: ; t ypedef st r uct ; { unsi gned access_byt e, ei p; } vect or _t ; ; get vect ( vect or _t *v, unsi gned vect _num) ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; EXP set vect push ebp mov ebp, esp push esi push ebx mov esi , [ ebp + 8] ; store access byte in IDT[i]; the main task of this subroutine mov eax,[esi + 0] xor ebx,ebx mov bl,[ebp + 12] shl ebx,3 mov [idt + ebx + 5],al ; st or e handl er addr ess i n st ub mov eax, i sr 1 sub eax, i sr 0 ; assume st ub si ze < 256 byt es mul byt e [ ebp + 12] mov ebx, eax add ebx, i sr 0 mov eax, [ esi + 4] mov [ ebx + ( i sr 0. 1 - i sr 0 + 1) ] , eax pop ebx pop esi pop ebp r et
The function makes the entry in the Interrupt Descriptor table for the keyboard interrupt (0x21) point to the keyboard_irq subroutine address. So each time the keyboard interrupt is raised, we land up in the keyboard_irq subroutine, which then handles the interrupt.
Design of a 32-bit Multitasking Operating System
26 Here comes the real time nature of our O.S. The user presses the key in real time and instantaneously, the OS begins to service the interrupt to the user. There is no delay (saving the interrupt for later service) in our code. However, in a truly real time environment, the OS handles larger numbers of interrupts than is done by our operating system. Design of a 32-bit Multitasking Operating System
27 Chapter 4 Device Driver Modules
Some device drives are needed to access some specific hardware. We have written (with the help of Intel Manuals) only one such device driver, that of the Floppy Disk. The Floppy disk driver is written for all Intel based motherboards, having 82077A Floppy Disk Controller chip.
4.1 Description of the Floppy Disk Driver
The file fd.ccontains all the codes for the floppy driver. The driver consists of the following functions:
void fd_init() // initializes floppy disk controller, the main function void fd_reset() // resets controler void fd_out(byte val) // writes a byte to controller FIFO register uchar fd_in() // reads a byte from controller FIFO register void fd_start(int drive) // Activate drive void fd_stop(int drive) // Deactivates Drive void fd_seek() // positions head to a particular cylinder, sector, track The main function here is the fd_init function. It performs the following functions in sequence: Resets the floppy controller. Checks the version of the floppy controller and prints appropriate message on the screen. In case the floppy controller is of non-standard type, prints unknown controller. Design of a 32-bit Multitasking Operating System
28 Probes the bios CMOS settings directly to read the exact type of the floppy, 1.2 MB, 1.44 MB, 2.88MB, etc. installed. If the floppy controller is present, but the floppy is disabled from the bios CMOS settings, a probe at this stage reveals this fact. Finally, it demonstrates that the driver is actually properly functioning by activating and then deactivating the drive once. This process can be done each time the user tries to access the floppy through the functions in the driver.
The commands used by the driver are the standard command bytes recognized by the 82077A Floppy Disk Controller chip. The base address used for the controller is 3F0 Hex, which is the standard address used by the controller chip for all PC-AT based machines. The number of floppy drives available to the system is assumed to be two, however if more than two floppy drives present, they can be easily accommodated in this driver by minor modifications.
We used the 82077AA chmos single-chip floppy disk controller manual extensively in the coding process. Design of a 32-bit Multitasking Operating System
29 Chapter 5 The Source Codes
We used DJ GPP, the GNU C compiler for DOS for building our entire source codes for this project. Before the assembly file and the C files can be patched together and compiled into a single kernel file, appropriate make files must be written so that the dependencies are well established. Makefiles are actually like dos batch files; they enumerate the list of commands the gnu make.exe should execute in sequence in order to build the project. The difference is that makefiles are much more powerful, efficient and can be used to write compact abbreviated codes for compilation.
We give below the entire contents of the make file of our project.
. SUFFI XES: . asm # def i nes MAKEFI LE=makef i l e MAKEDEP=$( MAKEFI LE) I NCDI R = . . / avos/ i nc # chose COFF, PE/ WI N32, or ELF i n t he next t wo l i nes LDSCRI PT=. . / avos/ cof f kr nl . l d NASM =nasmw - f cof f - dUNDERBARS=1 - i $( I NCDI R) / GCC =gcc - g - Wal l - W- O2 - nost di nc - f no- bui l t i n - I $( I NCDI R) LD =l d - g - T $( LDSCRI PT) - nost dl i b LI BC = . . / avos/ l i b/ l i bc. a OBJ S =kst ar t . o mai n. o vi deo. o debug. o kbd. o f d. o # t ar get s al l : kr nl . x # i mpl i ci t r ul es . asm. o: $( NASM) - o$@$<
. c. o: $( GCC) - c - o$@$< # dependenci es kst ar t . o: kst ar t . asm $( MAKEDEP) mai n. o: mai n. c $( MAKEDEP) Design of a 32-bit Multitasking Operating System
30 vi deo. o: vi deo. c $( MAKEDEP) debug. o: debug. c $( MAKEDEP) kbd. o: kbd. c $( MAKEDEP) f d. o: f d. c $( MAKEDEP)
# expl i ci t r ul es
$( LI BC) : . . / avos/ l i b/ $( MAKEFI LE) make - C . . / avos/ l i b - f $( MAKEFI LE)
kr nl . x: $( OBJ S) $( LDSCRI PT) $( LI BC) $( MAKEDEP) $( LD) - o$@$( OBJ S) $( LI BC) obj dump - - sour ce $@>kr nl . l st nm- - l i ne- number s $@| sor t >kr nl . sym st r i p $@
Below is the listing of the C source codes of our kernel. They all follow Ansi C syntax.
5.1 Module Main.c The Main Kernel Code
/ *===================================================================== MAI N KERNEL CODE EXPORTS: voi d kpr i nt f ( const char *f mt , . . . ) ; i nt mai n( voi d) ; =====================================================================*/ #i ncl ude <st dar g. h> / * va_l i st , va_st ar t ( ) , va_end( ) */ #i ncl ude <st r i ng. h> / * NULL */ #i ncl ude <x86. h> / * di sabl e( ) */ #i ncl ude <_pr i nt f . h> / * do_pr i nt f ( ) */ #i ncl ude " _kr nl . h" / * r egs_t */
/ * I MPORTS f r omKSTART. ASM */ voi d get vect ( vect or _t *v, unsi gned vect _num) ; voi d set vect ( vect or _t *v, unsi gned vect _num) ; / * f r omVI DEO. C */ Design of a 32-bit Multitasking Operating System
31 voi d bl i nk( voi d) ; voi d put ch( unsi gned c) ; voi d i ni t _vi deo( voi d) ;
/ * f r omKBD. C */ voi d keyboar d_i r q( voi d) ; voi d i ni t _keyboar d( voi d) ;
/ * f r omFD. C */ voi d f d_i ni t ( voi d) ;
/ ********************************************************************** **********************************************************************/ st at i c i nt kpr i nt f _hel p( unsi gned c, voi d **pt r ) { put ch( c) ; r et ur n 0; } / ********************************************************************** **********************************************************************/ voi d kpr i nt f ( const char *f mt , . . . ) { va_l i st ar gs;
va_st ar t ( ar gs, f mt ) ; ( voi d) do_pr i nt f ( f mt , ar gs, kpr i nt f _hel p, NULL) ; va_end( ar gs) ; } / ********************************************************************** **********************************************************************/ voi d pani c( const char *f mt , . . . ) { va_l i st ar gs; di sabl e( ) ; / * i nt er r upt s of f */ va_st ar t ( ar gs, f mt ) ; ( voi d) do_pr i nt f ( f mt , ar gs, kpr i nt f _hel p, NULL) ; Design of a 32-bit Multitasking Operating System
32 whi l e( 1) / * f r eeze */ ; } / ********************************************************************** **********************************************************************/ voi d f aul t ( r egs_t *r egs) { st at i c const char * const msg[ ] = { " di vi de er r or " , " debug except i on" , " NMI " , " I NT3" , " I NTO" , " BOUND except i on" , " i nval i d opcode" , " no copr ocessor " , " doubl e f aul t " , " copr ocessor segment over r un" , " bad TSS" , " segment not pr esent " , " st ack f aul t " , " GPF" , " page f aul t " , " ??" , " copr ocessor er r or " , " al i gnment check" , " ??" , " ??" , " ??" , " ??" , " ??" , " ??" , " ??" , " ??" , " ??" , " ??" , " ??" , " ??" , " ??" , " ??" , " I RQ0" , " I RQ1" , " I RQ2" , " I RQ3" , " I RQ4" , " I RQ5" , " I RQ6" , " I RQ7" , " I RQ8" , " I RQ9" , " I RQ10" , " I RQ11" , " I RQ12" , " I RQ13" , " I RQ14" , " I RQ15" , " syscal l " }; swi t ch( r egs- >whi ch_i nt ) { / * t hi s handl er i nst al l ed at compi l e- t i me Keyboar d handl er i s i nst al l ed at r un- t i me ( see bel ow) */ case 0x20: / * t i mer I RQ 0 */ bl i nk( ) ; / * r eset har dwar e i nt er r upt at 8259 chi p */ out por t b( 0x20, 0x20) ; br eak; def aul t : kpr i nt f ( " Except i on #%u" , r egs- >whi ch_i nt ) ; i f ( r egs- >whi ch_i nt <= si zeof ( msg) / si zeof ( msg[ 0] ) ) Design of a 32-bit Multitasking Operating System
33 kpr i nt f ( " ( %s) " , msg[ r egs- >whi ch_i nt ] ) ; pani c( " \ nSYSTEM HALTED\ nuse r eset but t on t o end" ) ; } } / ********************************************************************** ***********************************************************************/ st at i c voi d i ni t _8259s( voi d) { st at i c const unsi gned i r q0_i nt = 0x20, i r q8_i nt = 0x28;
/ * I ni t i al i zat i on Cont r ol Wor d #1 ( I CW1) */ out por t b( 0x20, 0x11) ; out por t b( 0xA0, 0x11) ; / * I CW2: r out e I RQs 0- 7 t o I NTs 20h- 27h */ out por t b( 0x21, i r q0_i nt ) ; / * r out e I RQs 8- 15 t o I NTs 28h- 2Fh */ out por t b( 0xA1, i r q8_i nt ) ; / * I CW3 */ out por t b( 0x21, 0x04) ; out por t b( 0xA1, 0x02) ; / * I CW4 */ out por t b( 0x21, 0x01) ; out por t b( 0xA1, 0x01) ; / * enabl e I RQ0 ( t i mer ) and I RQ1 ( keyboar d) */ out por t b( 0x21, ~0x03) ; out por t b( 0xA1, ~0x00) ; } / ********************************************************************** f or Mi nGW32 **********************************************************************/ #i f def __WI N32__ i nt __mai n( voi d) { r et ur n 0; } #endi f / ********************************************************************** **********************************************************************/ Design of a 32-bit Multitasking Operating System
34 i nt mai n( voi d) { vect or _t v;
i ni t _vi deo( ) ; / / Enabling video chipset
kpr i nt f ( " \ n\ nDevel oper s of AVOS: \ n" ) ; kpr i nt f ( " Ani r ban Si nha, B. t ech Fi nal Year , CSE, I EM, Kol kat a\ n" ) ; kpr i nt f ( " Sat yaj i t Chakr abar t i , B. t ech Fi nal Year , CSE, I EM, Kol kat a\ n" ) ; kpr i nt f ( " Soumya Baner j ee, B. t ech Fi nal Year , CSE, I EM, Kol kat a\ n" ) ; kpr i nt f ( " Sat yabr at a Sar kar , B. t ech Fi nal Year , CSE, I EM, Kol kat a\ n************************************************************ *********\ n" ) ; kpr i nt f ( " I dea Concei ved by: Sat yaj i t Chakr abar t i \ n\ nConsol e Command I nt er pr et er devel oped by: Ani r ban Si nha\ n***************************************************\ n\ n" ) ;
i ni t _keyboar d( ) ; / / Enabling keyboard controller
i ni t _8259s( ) ; / / Enabling 8259 interrupt controller kpr i nt f ( " I nst al l i ng keyboar d i nt er r upt handl er . . . \ n" ) ; / * we don' t save t he ol d vect or */ v. ei p = ( unsi gned) keyboar d_i r q; v. access_byt e = 0x8E; / * pr esent , r i ng 0, ' 386 i nt er r upt gat e */ set vect ( &v, 0x21) ;
kpr i nt f ( " Enabl i ng har dwar e i nt er r upt s. . . \ n" ) ; enabl e( ) ;
kpr i nt f ( " Enabl i ng Fl opy Di sk Cont r ol l er \ n" ) ; f d_i ni t ( ) ; / / Enabling Floppy Controller
kpr i nt f ( " ***************************************************\ n" ) ; kpr i nt f ( " *** Pr ess F1, F2, et c. t o change vi r t ual consol es ( t ot al 12 VC' s) ***\ n" ) ; Design of a 32-bit Multitasking Operating System
35 kpr i nt f ( " *** Pr ess HLP t o see command t abl e ***\ n" ) ; kpr i nt f ( " *** Pr ess Ct r l +Al t +Del t o r eboot ***\ n\ n\ n" ) ; kpr i nt f ( " $>" ) ; / / t he pr ompt whi l e( 1) / * f r eeze */ ; / * t hi s i s not r eached */ r et ur n 0; }
Note:
Some of the functions that are supposed to be done by the boot loader have been incorporated into the main kernel code; this makes bootloader independent of the type of kernel used and helps to configure the system according to the needs of the present kernel regardless of the bootloader used. For example: the configuring of 8259s has been done in the kernel code. This reconfiguration may also have been done in the bootloader program but that would make the bootloader dependent on the kernel since the type of interrupts used depends on the design of the kernel. As far as possible, we have made the boot loader independent of our kernel. Design of a 32-bit Multitasking Operating System
36 5.2 Module Video.c Video Handling Module
/ *===================================================================== TEXT VI DEO ROUTI NES EXPORTS: voi d bl i nk( voi d) ; voi d sel ect _vc( unsi gned whi ch_con) ; voi d put ch( unsi gned char c) ; voi d i ni t _vi deo( voi d) ; =====================================================================*/ #i ncl ude <st r i ng. h> / * memcpy( ) , memset w( ) */ #i ncl ude <ct ype. h> / * i sdi gi t ( ) */ #i ncl ude <x86. h> / * out por t b( ) , i npor t b( ) */ #i ncl ude " _kr nl . h" / * MAX_VC, consol e_t */ #i ncl ude <coni o. h> / * KEY_nn */
/ * I MPORTS f r omMAI N. C */ voi d kpr i nt f ( const char *f mt , . . . ) ;
#def i ne VGA_MI SC_READ 0x3CC consol e_t _vc[ MAX_VC] ; st at i c unsi gned shor t _num_vcs; st at i c consol e_t *_cur r _vc; st at i c unsi gned shor t *_vga_f b_adr ; st at i c unsi gned _cr t c_i o_adr , _vc_wi dt h, _vc_hei ght ; / ********************************************************************** **********************************************************************/ voi d bl i nk( voi d) { ( *( unsi gned char *) _vga_f b_adr ) ++; } / ********************************************************************** **********************************************************************/ st at i c voi d scr ol l ( consol e_t *con) { Design of a 32-bit Multitasking Operating System
37 unsi gned shor t *f b_adr ; unsi gned bl ank, t emp; bl ank = 0x20 | ( ( unsi gned) con- >at t r i b << 8) ; f b_adr = con- >f b_adr ; / * scr ol l up */ i f ( con- >csr _y >= _vc_hei ght ) { t emp = con- >csr _y - _vc_hei ght + 1; memcpy( f b_adr , f b_adr + t emp * _vc_wi dt h, ( _vc_hei ght - t emp) * _vc_wi dt h * 2) ; / * bl ank t he bot t oml i ne of t he scr een */ memset w( f b_adr + ( _vc_hei ght - t emp) * _vc_wi dt h, bl ank, _vc_wi dt h) ; con- >csr _y = _vc_hei ght - 1; } } / ********************************************************************** **********************************************************************/
st at i c voi d set _at t r i b( consol e_t *con, unsi gned at t ) { st at i c const unsi gned ansi _t o_vga[ ] = { 0, 4, 2, 6, 1, 5, 3, 7 }; unsi gned new_at t ;
new_at t = con- >at t r i b; i f ( at t == 0) new_at t &= ~0x08; / * bol d of f */ el se i f ( at t == 1) new_at t | = 0x08; / * bol d on */ el se i f ( at t >= 30 && at t <= 37) { at t = ansi _t o_vga[ at t - 30] ; new_at t = ( new_at t & ~0x07) | at t ; / * f g col or */ Design of a 32-bit Multitasking Operating System
38 } el se i f ( at t >= 40 && at t <= 47) { at t = ansi _t o_vga[ at t - 40] << 4; new_at t = ( new_at t & ~0x70) | at t ; / * bg col or */ } con- >at t r i b = new_at t ; } / ********************************************************************** **********************************************************************/
st at i c voi d move_csr ( voi d) { unsi gned shor t t emp;
t emp = ( _cur r _vc- >csr _y * _vc_wi dt h + _cur r _vc- >csr _x) + ( _cur r _vc- >f b_adr - _vga_f b_adr ) ; out por t b( _cr t c_i o_adr + 0, 14) ; out por t b( _cr t c_i o_adr + 1, t emp >> 8) ; out por t b( _cr t c_i o_adr + 0, 15) ; out por t b( _cr t c_i o_adr + 1, t emp) ; } / ********************************************************************** **********************************************************************/ voi d sel ect _vc( unsi gned whi ch_vc) { unsi gned i ;
i f ( whi ch_vc >= _num_vcs) r et ur n; _cur r _vc = _vc + whi ch_vc; i = _cur r _vc- >f b_adr - _vga_f b_adr ; out por t b( _cr t c_i o_adr + 0, 12) ; out por t b( _cr t c_i o_adr + 1, i >> 8) ; out por t b( _cr t c_i o_adr + 0, 13) ; out por t b( _cr t c_i o_adr + 1, i ) ; Design of a 32-bit Multitasking Operating System
39 / * oops, f or got t hi s: */ move_csr ( ) ; } / ********************************************************************** **********************************************************************/ st at i c voi d put ch_hel p( consol e_t *con, unsi gned c) { unsi gned shor t *f b_adr ; unsi gned at t ;
at t = ( unsi gned) con- >at t r i b << 8; f b_adr = con- >f b_adr ; / * st at e machi ne t o handl e t he escape sequences ESC */ i f ( con- >esc == 1) { i f ( c == ' [ ' ) { con- >esc++; con- >esc1 = 0; r et ur n; } / * el se f al l - t hr ough: zer o esc and pr i nt c */ } / * ESC[ */ el se i f ( con- >esc == 2) { i f ( i sdi gi t ( c) ) { con- >esc1 = con- >esc1 * 10 + c - ' 0' ; r et ur n; } el se i f ( c == ' ; ' ) { con- >esc++; con- >esc2 = 0; r et ur n; Design of a 32-bit Multitasking Operating System
40 } / * ESC[ 2J - - cl ear scr een */ el se i f ( c == ' J ' ) { i f ( con- >esc1 == 2) { memset w( f b_adr , ' ' | at t , _vc_hei ght * _vc_wi dt h) ; con- >csr _x = con- >csr _y = 0; } } / * ESC[ num1m- - set at t r i but e num1 */ el se i f ( c == ' m' ) set _at t r i b( con, con- >esc1) ; con- >esc = 0; / * anyt hi ng el se wi t h one numer i c ar g */ r et ur n; } / * ESC[ num1; */ el se i f ( con- >esc == 3) { i f ( i sdi gi t ( c) ) { con- >esc2 = con- >esc2 * 10 + c - ' 0' ; r et ur n; } el se i f ( c == ' ; ' ) { con- >esc++; / * ESC[ num1; num2; */ con- >esc3 = 0; r et ur n; } / * ESC[ num1; num2H - - move cur sor t o num1, num2 */ el se i f ( c == ' H' ) { i f ( con- >esc2 < _vc_wi dt h) con- >csr _x = con- >esc2; Design of a 32-bit Multitasking Operating System
41 i f ( con- >esc1 < _vc_hei ght ) con- >csr _y = con- >esc1; } / * ESC[ num1; num2m- - set at t r i but es num1, num2 */ el se i f ( c == ' m' ) { set _at t r i b( con, con- >esc1) ; set _at t r i b( con, con- >esc2) ; } con- >esc = 0; r et ur n; } / * ESC[ num1; num2; num3 */ el se i f ( con- >esc == 4) { i f ( i sdi gi t ( c) ) { con- >esc3 = con- >esc3 * 10 + c - ' 0' ; r et ur n; } / * ESC[ num1; num2; num3m- - set at t r i but es num1, num2, num3 */ el se i f ( c == ' m' ) { set _at t r i b( con, con- >esc1) ; set _at t r i b( con, con- >esc2) ; set _at t r i b( con, con- >esc3) ; } con- >esc = 0; r et ur n; } con- >esc = 0;
/ * escape char act er */ i f ( c == 0x1B) { con- >esc = 1; Design of a 32-bit Multitasking Operating System
42 r et ur n; } / * backspace */ i f ( ( c == 0x08) | | ( c== KEY_LFT) ) { i f ( con- >csr _x ! = 2) { con- >csr _x- - ; unsi gned shor t *wher e; unsi gned bl k; bl k=0x20; wher e = f b_adr + ( con- >csr _y * _vc_wi dt h + con- >csr _x) ; *wher e = ( bl k | at t ) ; }
} / * t ab */ el se i f ( c == 0x09) con- >csr _x = ( con- >csr _x + 8) & ~( 8 - 1) ; / * car r i age r et ur n */ el se i f ( c == ' \ r ' ) / * 0x0D */ con- >csr _x = 0; / * l i ne f eed */ / / el se i f ( c == ' \ n' ) / * 0x0A */ / / con- >csr _y++; / * CR/ LF */ el se i f ( c == ' \ n' ) / * ### - 0x0A agai n */ { con- >csr _x = 0; con- >csr _y++; } / * pr i nt abl e ASCI I */ el se i f ( c >= ' ' ) { unsi gned shor t *wher e;
Design of a 32-bit Multitasking Operating System
43 wher e = f b_adr + ( con- >csr _y * _vc_wi dt h + con- >csr _x) ; *wher e = ( c | at t ) ; con- >csr _x++; } i f ( con- >csr _x >= _vc_wi dt h) { con- >csr _x = 0; con- >csr _y++; } scr ol l ( con) ; / * move cur sor onl y i f t he VC we' r e wr i t i ng i s t he cur r ent VC */ i f ( _cur r _vc == con) move_csr ( ) ; }
/ ********************************************************************** **********************************************************************/ voi d put ch( unsi gned c) { / * al l ker nel messages t o VC #0 */ / / put ch_hel p( _cur r _vc, c) ; / * al l ker nel messages t o cur r ent VC */ put ch_hel p( _cur r _vc, c) ; } / ********************************************************************** **********************************************************************/ voi d i ni t _vi deo( voi d) { unsi gned i ;
/ * check f or monochr ome or col or VGA emul at i on */ i f ( ( i npor t b( VGA_MI SC_READ) & 0x01) ! = 0) { _vga_f b_adr = ( unsi gned shor t *) 0xB8000L; _cr t c_i o_adr = 0x3D4; } Design of a 32-bit Multitasking Operating System
44 el se { _vga_f b_adr = ( unsi gned shor t *) 0xB0000L; _cr t c_i o_adr = 0x3B4; }
/ * r ead cur r ent scr een si ze f r omBI OS dat a segment ( addr esses 400- 4FF) */ _vc_wi dt h = *( unsi gned shor t *) 0x44A; _vc_hei ght = *( unsi gned char *) 0x484 + 1;
/ * f i gur e out how many VCs we can have wi t h 32K of di spl ay memor y. Use I NTEGER di vi si on t o r ound down. */ _num_vcs = 32768L / ( _vc_wi dt h * _vc_hei ght * 2) ; i f ( _num_vcs > MAX_VC) _num_vcs = MAX_VC;
/ * i ni t VCs, wi t h a di f f er ent f or egr ound col or f or each */ f or ( i = 0; i < _num_vcs; i ++) { _cur r _vc = _vc + i ; _cur r _vc- >at t r i b = i + 7; _cur r _vc- >f b_adr = _vga_f b_adr + _vc_wi dt h * _vc_hei ght * i ; / * ESC[ 2J cl ear s t he scr een */ kpr i nt f ( " \ x1B[ 2J Advanced OS ver : 1. 0. 0 \ n You ar e at Vi r t ual Consol e #%u ( of 1- %u) \ n" , i +1, _num_vcs) ; kpr i nt f ( " I ni t i t i al i zi ng vi deo: %s emul at i on, %u x %u, f r amebuf f er at " " 0x%l X\ n" , ( _cr t c_i o_adr == 0x3D4) ? " col or " : " mono" , _vc_wi dt h, _vc_hei ght , _vga_f b_adr ) ; i f ( i ! =0) kpr i nt f ( " $>" ) ; / / t he pr ompt } sel ect _vc( 0) ;
Design of a 32-bit Multitasking Operating System
45 }
5.3 Module kbd.c Keyboard Handling Module
/ *===================================================================== KEYBOARD ROUTI NES
EXPORTS: voi d keyboar d_i r q( voi d) ; voi d i ni t _keyboar d( voi d) ; =====================================================================*/
#i ncl ude <coni o. h> / * KEY_nnn */ #i ncl ude <x86. h> / * out por t b( ) , i npor t b( ) */ #i ncl ude " _kr nl . h" / * MAX_VC */
/ * I MPORTS f r omVI DEO. C */ ext er n consol e_t _vc[ ] ; voi d sel ect _vc( unsi gned whi ch_vc) ; voi d put ch( unsi gned c) ; i nt sear ch_comnd( char *) ; / / sear ches i nput t ed command st r i ng f or val i d command wor d / * f r omMAI N. C */ voi d kpr i nt f ( const char *f mt , . . . ) ;
/ * " r aw" set 1 scancodes f r omPC keyboar d. Keyboar d i nf o her e: */ #def i ne RAW1_LEFT_CTRL 0x1D #def i ne RAW1_RI GHT_CTRL 0x1D / * same as l ef t */ #def i ne RAW1_LEFT_SHI FT 0x2A #def i ne RAW1_RI GHT_SHI FT 0x36 #def i ne RAW1_LEFT_ALT 0x38 #def i ne RAW1_RI GHT_ALT 0x38 / * same as l ef t */ #def i ne RAW1_CAPS_LOCK 0x3A #def i ne RAW1_F1 0x3B Design of a 32-bit Multitasking Operating System
46 #def i ne RAW1_F2 0x3C #def i ne RAW1_F3 0x3D #def i ne RAW1_F4 0x3E #def i ne RAW1_F5 0x3F #def i ne RAW1_F6 0x40 #def i ne RAW1_F7 0x41 #def i ne RAW1_F8 0x42 #def i ne RAW1_F9 0x43 #def i ne RAW1_F10 0x44 #def i ne RAW1_NUM_LOCK 0x45 #def i ne RAW1_SCROLL_LOCK 0x46 #def i ne RAW1_F11 0x57 #def i ne RAW1_F12 0x58
#def i ne KBD_BUF_SI ZE 64 / ********************************************************************** **********************************************************************/ voi d del ay( ) { l ong cnt 1; l ong cnt 2;
r et ur n; } Design of a 32-bit Multitasking Operating System
47
/ ********************************************************************** **********************************************************************/ st at i c voi d r eboot ( voi d) / / reboots machine { unsi gned t emp;
di sabl e( ) ; / * f l ush t he keyboar d cont r ol l er */ do { t emp = i npor t b( 0x64) ; i f ( ( t emp & 0x01) ! = 0) { ( voi d) i npor t b( 0x60) ; cont i nue; } } whi l e( ( t emp & 0x02) ! = 0) ; / * pul se t he CPU r eset l i ne */ out por t b( 0x64, 0xFE) ; / * . . . and i f t hat di dn' t wor k, j ust hal t */ whi l e( 1) / * not hi ng */ ; } / ********************************************************************** **********************************************************************/ st at i c voi d wr i t e_kbd( unsi gned adr , unsi gned dat a) { unsi gned l ong t i meout ; unsi gned st at ;
f or ( t i meout = 500000L; t i meout ! = 0; t i meout - - ) { st at = i npor t b( 0x64) ; / * l oop unt i l 8042 i nput buf f er empt y */ i f ( ( st at & 0x02) == 0) Design of a 32-bit Multitasking Operating System
48 br eak; } i f ( t i meout ! = 0) out por t b( adr , dat a) ; }
/ ********************************************************************** **********************************************************************/ st at i c unsi gned conver t ( unsi gned key) { st at i c const unsi gned char set 1_map[ ] = { / * 00 */ 0, 0x1B, ' 1' , ' 2' , ' 3' , ' 4' , ' 5' , ' 6' , / * 08 */ ' 7' , ' 8' , ' 9' , ' 0' , ' - ' , ' =' , ' \ b' , ' \ t ' , / * 10 */ ' q' , ' w' , ' e' , ' r ' , ' t ' , ' y' , ' u' , ' i ' , / * 1Dh i s l ef t Ct r l */ / * 18 */ ' o' , ' p' , ' [ ' , ' ] ' , ' \ n' , 0, ' a' , ' s' , / * 20 */ ' d' , ' f ' , ' g' , ' h' , ' j ' , ' k' , ' l ' , ' ; ' , / * 2Ah i s l ef t Shi f t */ / * 28 */ ' \ ' ' , ' `' , 0, ' \ \ ' , ' z' , ' x' , ' c' , ' v' , / * 36h i s r i ght Shi f t */ / * 30 */ ' b' , ' n' , ' m' , ' , ' , ' . ' , ' / ' , 0, 0, / * 38h i s l ef t Al t , 3Ah i s Caps Lock */ / * 38 */ 0, ' ' , 0, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, / * 45h i s NumLock, 46h i s Scr ol l Lock */ / * 40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, 0, 0, KEY_HOME, / * 48 */ KEY_UP, KEY_PGUP, ' - ' , KEY_LFT, ' 5' , KEY_RT, ' +' , KEY_END, / * 50 */ KEY_DN, KEY_PGDN, KEY_I NS, KEY_DEL, 0, 0, 0, KEY_F11, / * 58 */ KEY_F12 }; st at i c unsi gned shor t kbd_st at us, saw_br eak_code; / **/ unsi gned shor t t emp; Design of a 32-bit Multitasking Operating System
49
/ * check f or br eak key ( i . e. a key i s r el eased) */ i f ( key >= 0x80) { saw_br eak_code = 1; key &= 0x7F; } / * t he onl y br eak codes we' r e i nt er est ed i n ar e Shi f t , Ct r l , Al t */ i f ( saw_br eak_code) { i f ( key == RAW1_LEFT_ALT | | key == RAW1_RI GHT_ALT) kbd_st at us &= ~KBD_META_ALT; el se i f ( key == RAW1_LEFT_CTRL | | key == RAW1_RI GHT_CTRL) kbd_st at us &= ~KBD_META_CTRL; el se i f ( key == RAW1_LEFT_SHI FT | | key == RAW1_RI GHT_SHI FT) kbd_st at us &= ~KBD_META_SHI FT; saw_br eak_code = 0; r et ur n 0; } / * i t ' s a make key: check t he " met a" keys, as above */ i f ( key == RAW1_LEFT_ALT | | key == RAW1_RI GHT_ALT) { kbd_st at us | = KBD_META_ALT; r et ur n 0; } i f ( key == RAW1_LEFT_CTRL | | key == RAW1_RI GHT_CTRL) { kbd_st at us | = KBD_META_CTRL; r et ur n 0; } i f ( key == RAW1_LEFT_SHI FT | | key == RAW1_RI GHT_SHI FT) { kbd_st at us | = KBD_META_SHI FT; r et ur n 0; } / * Scr ol l Lock, NumLock, and Caps Lock set t he LEDs. These keys Design of a 32-bit Multitasking Operating System
50 have on- of f ( t oggl e or XOR) act i on, i nst ead of moment ar y act i on */ i f ( key == RAW1_SCROLL_LOCK) { kbd_st at us ^= KBD_META_SCRL; got o LEDS; } i f ( key == RAW1_NUM_LOCK) { kbd_st at us ^= KBD_META_NUM; got o LEDS; } i f ( key == RAW1_CAPS_LOCK) { kbd_st at us ^= KBD_META_CAPS; LEDS: wr i t e_kbd( 0x60, 0xED) ; / * " set LEDs" command */ t emp = 0; i f ( kbd_st at us & KBD_META_SCRL) t emp | = 1; i f ( kbd_st at us & KBD_META_NUM) t emp | = 2; i f ( kbd_st at us & KBD_META_CAPS) t emp | = 4; wr i t e_kbd( 0x60, t emp) ; / * bot t om3 bi t s set LEDs */ r et ur n 0; } / * i gnor e i nval i d scan codes */ i f ( key >= si zeof ( set 1_map) / si zeof ( set 1_map[ 0] ) ) r et ur n 0; / * conver t r aw scancode i n key t o unshi f t ed ASCI I i n t emp */ t emp = set 1_map[ key] ; / * def ect i ve keyboar d? non- US keyboar d? mor e t han 104 keys? */ i f ( t emp == 0) r et ur n t emp; / * handl e t he t hr ee- f i nger sal ut e */ i f ( ( kbd_st at us & KBD_META_CTRL) && ( kbd_st at us & KBD_META_ALT) && ( t emp == KEY_DEL) ) Design of a 32-bit Multitasking Operating System
51 { kpr i nt f ( " \ x1B[ 2J " " \ n\ n\ n\ n\ n\ n\ n\ n\ n\ n\ n\ n" ) ; kpr i nt f ( " *** Good bye *** \ n" ) ; kpr i nt f ( " *** Wai t whi l e Reboot i ng! ***" ) ;
del ay( ) ;
r eboot ( ) ; }
r et ur n t emp; } / ********************************************************************** **********************************************************************/ voi d keyboar d_i r q( voi d) / / interpretes keyboard key inputs { unsi gned key, i ; st at i c unsi gned vc; st at i c char cmd_buf f [ 5] ; st at i c unsi gned buf f _pt r ; st at i c unsi gned bad_comnd; i nt comnd; bad_comnd=0;
/ * get scancode f r ompor t 0x60 */ key = i npor t b( 0x60) ;
/ * i f i t ' s F1, F2 et c. swi t ch t o t he appr opr i at e vi r t ual consol e */ swi t ch( key) { case RAW1_F1: i = 0; got o SWI TCH_VC; Design of a 32-bit Multitasking Operating System
52 case RAW1_F2: i = 1; got o SWI TCH_VC; case RAW1_F3: i = 2; got o SWI TCH_VC; case RAW1_F4: i = 3; got o SWI TCH_VC; case RAW1_F5: i = 4; got o SWI TCH_VC; case RAW1_F6: i = 5; got o SWI TCH_VC; case RAW1_F7: i = 6; got o SWI TCH_VC; case RAW1_F8: i = 7; got o SWI TCH_VC; case RAW1_F9: i = 8; got o SWI TCH_VC; case RAW1_F10: i = 9; got o SWI TCH_VC; case RAW1_F11: i = 10; got o SWI TCH_VC; case RAW1_F12: i = 11; SWI TCH_VC: sel ect _vc( i ) ; vc=i ; br eak; Design of a 32-bit Multitasking Operating System
53 def aul t : i = conver t ( key) ; i f ( ( i ==KEY_HOME) | | ( i ==0x09) | | ( i ==KEY_I NS) | | ( i ==KEY_LWI N) | | ( i ==KEY_RWI N) | | ( i ==KEY_MENU) | | ( i ==KEY_PRNT) | | ( i ==KEY_PAUSE) | | ( i ==KEY_DEL) | | ( i ==KEY_UP) | | ( i ==KEY_PGUP) | | ( i ==KEY_RT) | | ( i ==KEY_END) | | ( i ==KEY_DN) | | ( i ==KEY_PGDN) ) { br eak; }
i f ( ( ( i ==0x08) | | ( i ==KEY_LFT) ) && ( buf f _pt r ! =0) ) / / f or back space { i f ( buf f _pt r <=4) cmd_buf f [ buf f _pt r - 1] =' \ 0' ; buf f _pt r - - ; put ch( i ) ; br eak; }
i f ( ( i ! = 0) && ( i ! = ' \ n' ) && ( i ! = 0x08) ) { i f ( buf f _pt r <=4) { cmd_buf f [ buf f _pt r ] =i ;
} el se i f ( buf f _pt r > 4) bad_comnd=1;
buf f _pt r ++; put ch( i ) ; br eak; } i f ( i ==' \ n' && ( buf f _pt r >0) ) { Design of a 32-bit Multitasking Operating System
54 i f ( bad_comnd) { kpr i nt f ( " \ nI nval i d Command\ n" ) ; bad_comnd=0; }
comnd=sear ch_comnd( cmd_buf f ) ;
swi t ch( comnd) {
case 1: kpr i nt f ( " \ x1B[ 2J Advanced OS ver : 1. 0. 0 \ nYou ar e at Vi r t ual Consol e: %u\ n" , vc+1) ;
br eak; case 2: kpr i nt f ( " \ nAdvanced OS ver si on 1. 0. 0\ n" ) ; br eak; case 3:
kpr i nt f ( " \ x1B[ 2J " " \ n\ n\ n\ n\ n\ n\ n\ n\ n\ n\ n\ n" ) ; kpr i nt f ( " *** Good bye *** \ n" ) ; kpr i nt f ( " *** Wai t whi l e Reboot i ng! ***" ) ;
del ay( ) ; r eboot ( ) ; br eak; case 4: kpr i nt f ( " \ n\ nAVOS Hel p: \ n- - - - - - - - - - \ n\ n" ) ; Design of a 32-bit Multitasking Operating System
55 kpr i nt f ( " F1 Consol e #1\ n" ) ; kpr i nt f ( " F2 Consol e #2\ n" ) ; kpr i nt f ( " F3 Consol e #3\ n" ) ; kpr i nt f ( " F4 Consol e #4\ n" ) ; kpr i nt f ( " F5 Consol e #5\ n" ) ; kpr i nt f ( " F6 Consol e #6\ n" ) ; kpr i nt f ( " F7 Consol e #7\ n" ) ; kpr i nt f ( " F8 Consol e #8\ n" ) ; kpr i nt f ( " F9 Consol e #9\ n" ) ; kpr i nt f ( " F10 Consol e #10\ n" ) ; kpr i nt f ( " F11 Consol e #11\ n" ) ; kpr i nt f ( " F12 Consol e #12\ n\ n" ) ; kpr i nt f ( " cl s Cl ear s Cur r ent Consol e Scr een\ n" ) ; kpr i nt f ( " ver Pr i nt s AVOS Ver si on\ n" ) ; kpr i nt f ( " r eb Reboot s Comput er \ n\ n" ) ; br eak; case 5: case - 1: kpr i nt f ( " \ nI nval i d Command\ n" ) ; }
put ch( i ) ; kpr i nt f ( " $>" ) ; / / pr ompt buf f _pt r =0; cmd_buf f [ 0] =' \ 0' ; cmd_buf f [ 1] =' \ 0' ; cmd_buf f [ 2] =' \ 0' ; cmd_buf f [ 3] =' \ 0' ; cmd_buf f [ 4] =' \ 0' ; br eak; } el se i f ( ( i ==' \ n' ) && ( buf f _pt r ==0) ) / / si ngl e ent er key { put ch( i ) ; kpr i nt f ( " $>" ) ; Design of a 32-bit Multitasking Operating System
56 br eak; }
} / * r eset har dwar e i nt er r upt at 8259 chi p */ out por t b( 0x20, 0x20) ; }
/ ********************************************************************** **********************************************************************/ i nt sear ch_comnd( char *comnd) / / searches inputted command string for .. / / .. valid command word { i f ( *( comnd+3) ! =' \ 0' ) / / max l engt h of commands i s 3 char act er s r et ur n - 1; swi t ch( *( comnd+0) ) { case ' c' : case ' C' : swi t ch( *( comnd+1) ) { case ' l ' : case ' L' : swi t ch ( *( comnd+2) ) { case ' s' : case ' S' :
r et ur n 1;
br eak; def aul t : r et ur n - 1; } br eak; def aul t : r et ur n - 1; Design of a 32-bit Multitasking Operating System
57 } br eak;
case ' v' : case ' V' : swi t ch( *( comnd+1) ) { case ' e' : case ' E' : swi t ch ( *( comnd+2) ) { case ' r ' : case ' R' :
r et ur n 2;
br eak; def aul t : r et ur n - 1; } br eak; def aul t : r et ur n - 1; } br eak;
case ' r ' : case ' R' : swi t ch( *( comnd+1) ) { case ' e' : case ' E' : swi t ch ( *( comnd+2) ) { case ' b' : case ' B' : Design of a 32-bit Multitasking Operating System
58
r et ur n 3;
br eak; def aul t : r et ur n - 1; } br eak; def aul t : r et ur n - 1; } br eak; case ' h' : case ' H' : swi t ch( *( comnd+1) ) { case ' l ' : case ' L' : swi t ch ( *( comnd+2) ) { case ' p' : case ' P' : r et ur n 4;
br eak; def aul t : r et ur n - 1; } br eak; def aul t : r et ur n - 1; } br eak; case ' d' : case ' D' : swi t ch( *( comnd+1) ) { case ' t ' : Design of a 32-bit Multitasking Operating System
59 case ' T' : r et ur n 5; br eak; def aul t : r et ur n - 1; }
br eak;
def aul t : r et ur n - 1; } }
/ ********************************************************************** **********************************************************************/ voi d i ni t _keyboar d( voi d) { st at i c unsi gned char buf f er s[ KBD_BUF_SI ZE * MAX_VC] ; i nt i ; f or ( i = 0; i < MAX_VC; i ++) { _vc[ i ] . keyst r okes. dat a = buf f er s + KBD_BUF_SI ZE * i ; _vc[ i ] . keyst r okes. si ze = KBD_BUF_SI ZE; } kpr i nt f ( " I ni t i al i zi ng keyboar d: %u buf f er s, %u byt es each\ n" , MAX_VC, KBD_BUF_SI ZE) ; } Design of a 32-bit Multitasking Operating System
60 5.4 Library Routines
5.4.1 Hardware Interface Functions
1. Disable Interrupts
/ ************************************************************* *************************************************************/ unsi gned di sabl e( voi d) { unsi gned r et _val ;
__asm__ __vol at i l e__( " pushf l \ n" " popl %0\ n" " cl i " : " =a" ( r et _val ) : ) ; r et ur n r et _val ; }
2. Enable Interrupts
/ ************************************************************* *************************************************************/ voi d enabl e( voi d) { __asm__ __vol at i l e__( " st i " : : ) ; }
Design of a 32-bit Multitasking Operating System
61 3. Input from Port
/ ************************************************************* *************************************************************/ unsi gned i npor t b( unsi gned shor t por t ) { unsi gned char r et _val ;
__asm__ __vol at i l e__( " i nb %1, %0" : " =a" ( r et _val ) : " d" ( por t ) ) ; r et ur n r et _val ; }
4. Output to Port
/ ************************************************************* *************************************************************/ voi d out por t b( unsi gned por t , unsi gned val ) { __asm__ __vol at i l e__( " out b %b0, %w1" : : " a" ( val ) , " d" ( por t ) ) ; }
5.4.2 String Manipulation Functions
1. Copy contents of memory from one location to other / ********************************************************** **********************************************************/ voi d *memcpy( voi d *dst _pt r , const voi d *sr c_pt r , si ze_t count ) { voi d *r et _val = dst _pt r ; const char *sr c = ( const char *) sr c_pt r ; Design of a 32-bit Multitasking Operating System
62 char *dst = ( char *) dst _pt r ;
/ * copy up */ f or ( ; count ! = 0; count - - ) *dst ++ = *sr c++; r et ur n r et _val ; }
2. Find Length of String
/ ********************************************************** **********************************************************/ si ze_t st r l en( const char *st r ) { si ze_t r et _val ;
f or ( r et _val = 0; *st r ! = ' \ 0' ; st r ++) r et _val ++; r et ur n r et _val ; }
3. Fill count sized block of memory with a specific value val
/ ********************************************************** *********************************************************** voi d *memset w( voi d *dst , i nt val , si ze_t count ) { unsi gned shor t *t emp = ( unsi gned shor t *) dst ; f or ( ; count ! = 0; count - - ) *t emp++ = val ; r et ur n dst ; }
5.4.3 Segment Jump Functions
Design of a 32-bit Multitasking Operating System
63 1. Intra Segment J ump
i nt set j mp( j mp_buf buf ) { __asm__ __vol at i l e__( " movl %%edi , ( %0) \ n" " movl %%esi , 4( %0) \ n" " movl %%ebp, 8( %0) \ n" " movl %%ebx, 16( %0) \ n" " movl %%edx, 20( %0) \ n" " movl %%ecx, 24( %0) \ n" / * ESP val ue af t er we RET f r omt hi s f unct i on */ " l eal 8( %%ebp) , %%eax\ n" " movl %%eax, 32( %0) \ n" / * EI P val ue af t er we RET f r omt hi s f unct i on */ " movl 4( %%ebp) , %%eax\ n" " movl %%eax, 36( %0) \ n" : : " b" ( buf ) ) ; r et ur n 0; }
2. Inter Segment J ump (Long J ump)
voi d l ongj mp( j mp_buf buf , i nt r et _val ) { unsi gned *esp2; / * make sur e r et ur n val ue i s not 0 */ i f ( r et _val == 0) r et _val ++; / * st or e i t i n buf - >eax */ buf - >eax = r et _val ; / * get ESP f or new st ack */ esp2 = ( unsi gned *) buf - >esp2; / * push r et ur n EI P on new st ack */ esp2- - ; *esp2 = buf - >ei p; / * updat e st or ed ESP */ Design of a 32-bit Multitasking Operating System
64 buf - >esp2 = ( unsi gned) esp2; / * make buf t he st ack */ __asm__ __vol at i l e__( " movl %0, %%esp\ n" / * pop GP r egi st er s */ " popa\ n" / * pop ESP f or new st ack */ " pop %%esp\ n" / * r et ur n */ " r et \ n" : : " m" ( buf ) ) ; }
5.4.4 The Printf Function
/ ***************************************************************** name: do_pr i nt f act i on: mi ni mal subf unct i on f or ?pr i nt f , cal l s f unct i on ' f n' wi t h ar g ' pt r ' f or each char act er t o be out put r et ur ns: t ot al number of char act er s out put not es: does not handl e l ong l ong ( 64- bi t ) val ues, f ar poi nt er s, f l oat s, pr eci si on par t of f i el d wi dt h, l eadi ng si gn, or l eadi ng bl anks. *****************************************************************/ / * f l ags used i n pr ocessi ng f or mat st r i ng */ #def i ne PR_LJ 0x01 / * l ef t j ust i f y */ #def i ne PR_CA 0x02 / * use A- F i nst ead of a- f f or hex */ #def i ne PR_SG 0x04 / * si gned numer i c conver si on ( %d vs. %u) */ #def i ne PR_32 0x08 / * l ong ( 32- bi t ) numer i c conver si on */ #def i ne PR_16 0x10 / * shor t ( 16- bi t ) numer i c conver si on */ #def i ne PR_WS 0x20 / * PR_SG set and numwas < 0 */ #def i ne PR_LZ 0x40 / * pad l ef t wi t h ' 0' i nst ead of ' ' */ #def i ne PR_FP 0x80 / * poi nt er s ar e f ar */
/ * l ar gest number handl ed i s 2^32- 1, l owest r adi x handl ed i s 8. Design of a 32-bit Multitasking Operating System
65 2^32- 1 i n base 8 has 11 di gi t s ( add 5 f or t r ai l i ng NUL and f or sl op) */ #def i ne PR_BUFLEN 16
t ypedef i nt ( *f npt r _t ) ( unsi gned c, voi d **hel per ) ;
i nt do_pr i nt f ( const char *f mt , va_l i st ar gs, f npt r _t f n, voi d *pt r ) { unsi gned st at e, f l ags, r adi x, act ual _wd, count , gi ven_wd; unsi gned char *wher e, buf [ PR_BUFLEN] ; l ong num; st at e = f l ags = count = gi ven_wd = 0; / * begi n scanni ng f or mat speci f i er l i st */ f or ( ; *f mt ; f mt ++) { swi t ch( st at e) { / * STATE 0: AWAI TI NG %*/ case 0: i f ( *f mt ! = ' %' ) / * not %. . . */ { f n( *f mt , &pt r ) ; / * . . . j ust echo i t */ count ++; br eak; } / * f ound %, get next char and advance st at e t o check i f next char i s a f l ag */ st at e++; f mt ++; / * FALL THROUGH */ / * STATE 1: AWAI TI NG FLAGS ( %- 0) */ case 1: i f ( *f mt == ' %' ) / * %%*/ { f n( *f mt , &pt r ) ; count ++; Design of a 32-bit Multitasking Operating System
66 st at e = f l ags = gi ven_wd = 0; br eak; } i f ( *f mt == ' - ' ) { i f ( f l ags & PR_LJ ) / * %- - i s i l l egal */ st at e = f l ags = gi ven_wd = 0; el se f l ags | = PR_LJ ; br eak; } / * not a f l ag char : advance st at e t o check i f i t ' s f i el d wi dt h */ st at e++; / * check now f or ' %0. . . ' */ i f ( *f mt == ' 0' ) { f l ags | = PR_LZ; f mt ++; } / * FALL THROUGH */ / * STATE 2: AWAI TI NG ( NUMERI C) FI ELD WI DTH */ case 2: i f ( *f mt >= ' 0' && *f mt <= ' 9' ) { gi ven_wd = 10 * gi ven_wd + ( *f mt - ' 0' ) ; br eak; } / * not f i el d wi dt h: advance st at e t o check i f i t ' s a modi f i er */ st at e++; / * FALL THROUGH */ / * STATE 3: AWAI TI NG MODI FI ER CHARS ( FNl h) */ case 3: i f ( *f mt == ' F' ) { f l ags | = PR_FP; Design of a 32-bit Multitasking Operating System
67 br eak; } i f ( *f mt == ' N' ) br eak; i f ( *f mt == ' l ' ) { f l ags | = PR_32; br eak; } i f ( *f mt == ' h' ) { f l ags | = PR_16; br eak; } / * not modi f i er : advance st at e t o check i f i t ' s a conver si on char */ st at e++; / * FALL THROUGH */ / * STATE 4: AWAI TI NG CONVERSI ON CHARS ( Xxpndi uocs) */ case 4: wher e = buf + PR_BUFLEN - 1; *wher e = ' \ 0' ; swi t ch( *f mt ) { case ' X' : f l ags | = PR_CA; / * FALL THROUGH */ / * xxx - f ar poi nt er s ( %Fp, %Fn) not yet suppor t ed */ case ' x' : case ' p' : case ' n' : r adi x = 16; got o DO_NUM; case ' d' : case ' i ' : f l ags | = PR_SG; Design of a 32-bit Multitasking Operating System
68 / * FALL THROUGH */ case ' u' : r adi x = 10; got o DO_NUM; case ' o' : r adi x = 8; / * l oad t he val ue t o be pr i nt ed. l =l ong=32 bi t s: */ DO_NUM: i f ( f l ags & PR_32) num= va_ar g( ar gs, unsi gned l ong) ; / * h=shor t =16 bi t s ( si gned or unsi gned) */ el se i f ( f l ags & PR_16) { i f ( f l ags & PR_SG) num= va_ar g( ar gs, shor t ) ; el se num=va_ar g( ar gs, unsi gned shor t ) ; } / * no h nor l : si zeof ( i nt ) bi t s ( si gned or unsi gned) */ el se { i f ( f l ags & PR_SG) num= va_ar g( ar gs, i nt ) ; el se num= va_ar g( ar gs, unsi gned i nt ) ; } / * t ake car e of si gn */ i f ( f l ags & PR_SG) { i f ( num< 0) { f l ags | = PR_WS; num= - num; } } / * conver t bi nar y t o oct al / deci mal / hex ASCI I OK, I f ound my mi st ake. The mat h her e i s _al ways_ unsi gned */ Design of a 32-bit Multitasking Operating System
69 do { unsi gned l ong t emp; t emp = ( unsi gned l ong) num%r adi x; wher e- - ; i f ( t emp < 10) *wher e = t emp + ' 0' ; el se i f ( f l ags & PR_CA) *wher e = t emp - 10 + ' A' ; el se *wher e = t emp - 10 + ' a' ; num= ( unsi gned l ong) num/ r adi x; } whi l e( num! = 0) ; got o EMI T; case ' c' : / * di sal l ow pad- l ef t - wi t h- zer oes f or %c */ f l ags &= ~PR_LZ; wher e- - ; *wher e = ( unsi gned char ) va_ar g( ar gs, unsi gned char ) ; act ual _wd = 1; got o EMI T2; case ' s' : / * di sal l ow pad- l ef t - wi t h- zer oes f or %s */ f l ags &= ~PR_LZ; wher e = va_ar g( ar gs, unsi gned char *) ; EMI T: act ual _wd = st r l en( wher e) ; i f ( f l ags & PR_WS) act ual _wd++; / * i f we pad l ef t wi t h ZEROES, do t he si gn now */ i f ( ( f l ags & ( PR_WS | PR_LZ) ) ==( PR_WS | PR_LZ) ) { f n( ' - ' , &pt r ) ; count ++; } / * pad on l ef t wi t h spaces or zer oes ( f or r i ght j ust i f y) */ Design of a 32-bit Multitasking Operating System
70 EMI T2: i f ( ( f l ags & PR_LJ ) == 0) { whi l e( gi ven_wd > act ual _wd) { f n( f l ags & PR_LZ ? ' 0' : ' ' , &pt r ) ; count ++; gi ven_wd- - ; } } / * i f we pad l ef t wi t h SPACES, do t he si gn now */ i f ( ( f l ags & ( PR_WS | PR_LZ) ) == PR_WS) { f n( ' - ' , &pt r ) ; count ++; } / * emi t st r i ng/ char / conver t ed number */ whi l e( *wher e ! = ' \ 0' ) { f n( *wher e++, &pt r ) ; count ++; } / * pad on r i ght wi t h spaces ( f or l ef t j ust i f y) */ i f ( gi ven_wd < act ual _wd) gi ven_wd = 0; el se gi ven_wd - = act ual _wd; f or ( ; gi ven_wd; gi ven_wd- - ) { f n( ' ' , &pt r ) ; count ++; } br eak; def aul t : br eak; } def aul t : Design of a 32-bit Multitasking Operating System
71 st at e = f l ags = gi ven_wd = 0; br eak; } } r et ur n count ; } Design of a 32-bit Multitasking Operating System
72 5.5 Driver Routines 5.5.1 Floppy Disk Driver
/ * * f d. c - f l oppy di sk handl i ng */
/ *============================================================ EXPORTS: voi d f d_i ni t ( voi d) ============================================================*/
/ / I MPORTS f r omMAI N. C: voi d kpr i nt f ( const char *f mt , . . . ) ;
#i ncl ude <x86. h> / * f or out por t b( ) , i npor t b( ) */
t ypedef unsi gned char byt e; t ypedef unsi gned char uchar ; t ypedef unsi gned shor t ushor t ; t ypedef unsi gned l ong ul ong; t ypedef unsi gned i nt ui nt ;
t ypedef unsi gned i nt si ze_t ; #def i ne _SI ZE_T
#i f ndef NULL #def i ne NULL ( ( voi d*) 0 ) #endi f #endi f st at i c uchar ver si on; st at i c uchar cmos_t ype; st at i c uchar t ype;
st at i c uchar mot or _mask = 0; Design of a 32-bit Multitasking Operating System
73 st at i c ui nt cur _op = 0; st at i c ui nt cur _dr v; st at i c ui nt cur _head; st at i c ui nt cur _t r k;
#def i ne FD_SEEK 0x02
#def i ne NFD ( 2) / / Number of drives supported
#def i ne FD_BASEI O 0x3F0 / / Base Address of FDC
/ / Commands #def i ne F_MASTER 0x80 #def i ne F_DI R 0x40 #def i ne F_CMDBUSY 0x10 #def i ne FD_DATA 0x05 / / Data FIFO Register #def i ne FD_STATUS 0x04 / / Main Status Register
/ * * fdc commands */ #def i ne FDC_VERSI ON 0x10 #def i ne FDC_I NTS 0x08 / * SENSEI */ #def i ne FDC_RESET 0x04 / * SENSE */ #def i ne FDC_SEEK 0x0F
#def i ne FDC_VER_765A 0x80 #def i ne FDC_VER_765B 0x90
#def i ne FDTYPE_MASK 0x0F
#def i ne FDTYPE_NONE 0x00 #def i ne FDTYPE_360 0x01 #def i ne FDTYPE_1200 0x02 #def i ne FDTYPE_720 0x03 #def i ne FDTYPE_1440 0x04 Design of a 32-bit Multitasking Operating System
74 #def i ne FDTYPE_2880 0x05 #def i ne ENABLE_I NTS 0x0C #def i ne FD_MOTOR 0x02 #def i ne MOTOR_0 0x10 #def i ne MOTOR_1 0x20 #def i ne RTCSEL 0x70 #def i ne RTCDATA 0x71 #def i ne NVRAM_FD 0x10
uchar f d_i n( ) / / reads a byte from FIFO register { ui nt c; i nt r ;
c = 1000000;
do { r = ( i npor t b( FD_BASEI O+FD_STATUS) & ( F_MASTER | F_DI R | F_CMDBUSY) ) ; i f ( r == ( F_MASTER | F_DI R | F_CMDBUSY ) ) br eak; c- - ; } whi l e( c) ;
i f ( c == 0 ) r et ur n 0;
r et ur n i npor t b( FD_BASEI O+FD_DATA) ; }
voi d f d_out ( byt e val ) / / writes a byte from FIFO register { ui nt c; i nt r ; c = 1000000; do { Design of a 32-bit Multitasking Operating System
75 r = ( i npor t b( FD_BASEI O+FD_STATUS) & ( F_MASTER | F_DI R) ) ; i f ( r == F_MASTER) br eak; c- - ; } whi l e( c) ;
i f ( c == 0 ) { kpr i nt f ( " f d_out : t i meout \ n" ) ; r et ur n; } out por t b( FD_BASEI O+FD_DATA, val ) ; }
voi d f d_r eset ( ) / / Reset Drive { i nt c; di sabl e( ) ;
out por t b( FD_BASEI O+FD_MOTOR, 0) ; out por t b( FD_BASEI O+FD_MOTOR, ENABLE_I NTS) ;
enabl e( ) ;
f or ( c = 0; c < 10000; c++) ; }
voi d f d_st ar t ( i nt dr i ve) / / activate motor of floppy drive { mot or _mask | = dr i ve; i f ( dr i ve == 0x00 ) { mot or _mask | = MOTOR_0; } el se { mot or _mask | = MOTOR_1; } out por t b( FD_BASEI O+FD_MOTOR, mot or _mask) ; } Design of a 32-bit Multitasking Operating System
76 voi d f d_st op( i nt dr i ve) / / Stop motor { i f ( dr i ve == 0x00 ) { mot or _mask &= ~MOTOR_0; } el se { mot or _mask &= ~MOTOR_1; } out por t b( FD_BASEI O+FD_MOTOR, mot or _mask) ; } voi d f d_seek( ) / / seek to a physical location in the drive { cur _op = FD_SEEK; cur _head = 0; cur _t r k = 0; cur _dr v = 0;
f d_out ( FDC_SEEK) ; f d_out ( ( cur _head << 2) | cur _dr v) ; f d_out ( cur _t r k) ; } voi d f d_i ni t ( ) / / Initializes Floppy disk { i nt c; ui nt l ; kpr i nt f ( " \ nI ni t i al i zi ng FDC: \ n" ) ; f d_r eset ( ) ; f d_out ( FDC_VERSI ON) ; ver si on = f d_i n( ) ; kpr i nt f ( " Ver si on %d f ound: " , ver si on) ;
i f ( ver si on == FDC_VER_765A ) kpr i nt f ( " st ar dar d FDC f ound\ n" ) ; el se i f ( ver si on == FDC_VER_765B ) kpr i nt f ( " enhanced FDC f ound\ n" ) ; el se Design of a 32-bit Multitasking Operating System
77 i f ( ver si on == 0 ) kpr i nt f ( " t i meout \ n" ) ; el se kpr i nt f ( " unknown cont r ol l er \ n" ) ;
f or ( c = 0; c < NFD; ++c) { out por t b( RTCSEL, NVRAM_FD) ; cmos_t ype = i npor t b( RTCDATA) ;
swi t ch( t ype) { case FDTYPE_1200: kpr i nt f ( " \ t f d_i ni t - > %d : 1. 2MB f l oppy dr i ve f ound\ n" , c) ; br eak; case FDTYPE_1440: kpr i nt f ( " \ t f d_i ni t - > %d : 1. 44MB f l oppy dr i ve f ound\ n" , c) ; br eak; def aul t : kpr i nt f ( " \ t f d_i ni t - > %d : no dr i ve\ n" , c) ; br eak; } } mot or _mask | = ( FDC_I NTS | FDC_RESET) ; f d_st ar t ( 0) ; f or ( l = 0; l < 1000000; l ++) ; f d_st op( 0) ; } Design of a 32-bit Multitasking Operating System
78
Chapter 6 Future Work
The operating system developed is a very preliminary one with a simple command interpreter that interprets some basic commands. Lots of enhancements can be done based on the existing work to make it a fully grown operating system.
1. Firstly, we have not implemented any file system interface and basic file handling operations. So, the user cannot browse through the existing files on the disk. With appropriate modifications and with the help of the file system drivers, the kernel can be made to identify the file system and do basic file handling operations. 2. No CPU scheduling policy has been implemented; neither proper memory, IO & disk management modules are present. These are definitely areas which needs a lot of work. 3. Proper and well defined APIs must be provided so that user level applications for the system can be designed. 4. We can write device drivers for other devices such as mouse, CD ROM and even printer, which give greater functionality to the operating system and greater user friendliness. 5. Certain sound functions through the PC speaker can also be incorporated so as to alert the user at certain critical command executions and errors. 6. Greater number of system processes can be incorporated, like processes that inform the user of any anomaly in the system, processes that do the garbage collection, processes that handle some other devices like the printer etc and these processes can be synchronized using semaphores or message based protocols. Design of a 32-bit Multitasking Operating System
79 Bibliography
[1] Protected mode and operating systems: http://www.execpc.com/~geezer/os/ [2] OS Development For Dummies (OSD) http://www.execpc.com/~geezer/osd/index.htm [3] Write Your Own Operating System http://www.mega-tokyo.com/os/os-faq.html [4] Ralf Brown's Files http://www.cs.cmu.edu/afs/cs.cmu.edu/user/ralf/pub/WWW/files.html, http://www.ctyme.com/rbrown.htm [5] OSD PC bootstrap process http://www.execpc.com/~geezer/osd/boot/index.htm#grub [6] My 'FAQ' for amateur OS Designers http://www.overwhelmed.org/shawn/faq.html [7] OSD Text-mode console output for VGA http://www.execpc.com/~geezer/osd/cons/index.htm#vmm [8] Interrupt Vector Table http://www.geocities.com/electronic_ed/tae/appd/ivt.htm [9] Inline asm with GCC http://www.delorie.com/djgpp/doc/brennan/brennan_att_inline_djgpp.html [11] DJ GPP can be downloaded freely from the following website: http://www.delorie.com/djgpp/ [12] Operating Systems Resource Center http://www.nondot.org/sabre/os [13] OSRC Disk and Disc Drives http://www.nondot.org/sabre/os/articles/DiskandDiscDrives/ [14] MMURTL V1 by Richard A. Burgess http://www.sensorypublishing.com/mmurtl.html Design of a 32-bit Multitasking Operating System
80 [15] Intel Programmers Reference Manuals http://www.microsym.com/386intel.pdf or the three original Intel manuals in PDF:- http://kos.enix.org/pub/intelvol1.pdf.gz (Manual Vol: 1) http://kos.enix.org/pub/intelvol2.pdf.gz (Manual Vol: 2) http://kos.enix.org/pub/intelvol3.pdf.gz (Manual Vol: 3) [16] Intel Floppy Disk Controller, 8272A Manual http://www.nondot.org/sabre/os/files/Disk/82077AA_FloppyControllerDatasheet.pdf http://www.nondot.org/sabre/os/files/Disk/FLOPPY.TXT [17] Intel 8259 Programmable Interrupt Controller Manual http://satya.virtualave.net/8259.html or the original Intel Manual in PDF: ftp://download.intel.com/support/controllers/peripheral/231468.pdf