Initial checkin of toy OS project. master
authorScott Gasch <[email protected]>
Thu, 2 Jun 2016 02:37:09 +0000 (19:37 -0700)
committerScott Gasch <[email protected]>
Thu, 2 Jun 2016 02:37:09 +0000 (19:37 -0700)
39 files changed:
Makefile [new file with mode: 0644]
boot0/Makefile [new file with mode: 0755]
boot0/boot0.asm [new file with mode: 0644]
boot0/boot0.bin [new file with mode: 0644]
boot1/Makefile [new file with mode: 0755]
boot1/boot.com [new file with mode: 0644]
boot1/boot1.asm [new file with mode: 0644]
boot1/hardware.asm [new file with mode: 0644]
boot1/memory.asm [new file with mode: 0644]
boot1/video.asm [new file with mode: 0644]
floppy.img [new file with mode: 0644]
inc/defs.asm [new file with mode: 0644]
kernel/Makefile [new file with mode: 0644]
kernel/defines [new file with mode: 0644]
kernel/driver/keyboard.c [new file with mode: 0644]
kernel/driver/video.c [new file with mode: 0644]
kernel/hal/Makefile [new file with mode: 0644]
kernel/hal/counters.c [new file with mode: 0644]
kernel/hal/interrupts.c [new file with mode: 0644]
kernel/hal/interrupts.h [new file with mode: 0644]
kernel/hal/intsupport.asm [new file with mode: 0644]
kernel/hal/io.c [new file with mode: 0644]
kernel/hal/timer.c [new file with mode: 0644]
kernel/hal/timestamp.asm [new file with mode: 0644]
kernel/hal/video.h [new file with mode: 0644]
kernel/inc/constants.h [new file with mode: 0644]
kernel/inc/hal.h [new file with mode: 0644]
kernel/inc/kernel.h [new file with mode: 0644]
kernel/inc/macros.h [new file with mode: 0644]
kernel/inc/rtl.h [new file with mode: 0644]
kernel/inc/types.h [new file with mode: 0644]
kernel/init/Makefile [new file with mode: 0644]
kernel/init/entry.asm [new file with mode: 0644]
kernel/init/main.c [new file with mode: 0644]
kernel/kernel.bin [new file with mode: 0755]
kernel/kernel.map [new file with mode: 0644]
kernel/rtl/Makefile [new file with mode: 0644]
kernel/rtl/memory.c [new file with mode: 0644]
kernel/rtl/string.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..ca5c681
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,5 @@
+SUBDIR += boot0
+SUBDIR += boot1
+SUBDIR += kernel
+
+.include <bsd.port.subdir.mk>
diff --git a/boot0/Makefile b/boot0/Makefile
new file mode 100755 (executable)
index 0000000..162c810
--- /dev/null
@@ -0,0 +1,9 @@
+RM             =       /bin/rm
+TARGET                 =       boot0.bin
+SOURCES                =       boot0.asm
+
+all:           $(SOURCES)
+               nasm -f bin -o $(TARGET) $(SOURCES) ; \
+               mformat -f 1440 -B boot0.bin Q:
+clean:
+               $(RM) -f *.log *.core *~ *.gmon \#*\# $(TARGET)
diff --git a/boot0/boot0.asm b/boot0/boot0.asm
new file mode 100644 (file)
index 0000000..e31f126
--- /dev/null
@@ -0,0 +1,347 @@
+;
+; This boot sector was based on VnutZ's example available online
+; at http://www.geocities.com/mvea/bootstrap.htm.  It also made use
+; of info at http://support.microsoft.com/support/kb/articles/Q140/4/18.asp
+; and the source code for geekos.
+;
+; It searches the root directory of a floppy for two files: boot.com and
+; kernel.bin.  If either is missing the boot fails.  If they are found, they
+; are loaded into memory at BOOT1SEG:BOOT1OFF and KERNSEG:KERNOFF.  Then
+; control is passed to the next stage bootloader, boot.com.
+; 
+%include "../inc/defs.asm"
+        
+[BITS 16]
+[ORG 0]
+
+START:  
+        jmp AROUND_DATA
+        
+szOEM_ID              db "SCOTTOS", 0    ; 8 bytes, null not required
+wBytesPerSector       dw 0x0200          ; bytes per sector
+bSectorsPerCluster    db 0x01            ; sectors per cluster
+wReservedSectors      dw 0x0001          ; reserved sectors (boot sector)
+bTotalFATs            db 0x02            ; num copies of the FAT
+wMaxRootEntries       dw 0x00E0          ; max num entries in root directory
+wTotalSectorsSmall    dw 0x0B40          ; 
+bMediaDescriptor      db 0xF0            ; 
+wSectorsPerFAT        dw 0x0009          ; length of single FAT copy in sectors
+wSectorsPerTrack      dw 0x0012          ; sectors per track
+wNumHeads             dw 0x0002          ; num heads
+dwHiddenSectors       dd 0x00000000      ; num hidden sectors
+dwTotalSectorsLarge   dd 0x00000000      ; 
+bDriveNumber          db 0x00            ; 0x00=A: 0x01=B: 0x80=C: ...
+bFlags                db 0x00            ; 
+bSignature            db 0x29            ; 
+dwVolumeID            dd 0xFFFFFFFF      ; 
+szVolumeLabel         db "SCOTT BOOT", 0 ; 11 bytes, null not required
+szSystemID            db "FAT12   "      ; 
+
+AROUND_DATA:    
+;;; setup segment registers, this code is located at 7C00:0000
+        mov dx, BOOT0SEG        ; 7C00
+        mov ds, dx
+        mov es, dx
+        
+;;; create a temporary stack at the top of segment 7C00
+        mov ss, dx
+        mov sp, 0xFFFF          ; top of this segment
+
+LOAD_ROOT_DIRECTORY:
+;;; 
+;;; Compute the length (in number of disk sectors) of the floppy's
+;;; root directory information:
+;;;
+;;; wNumRootDirectorySectors = sizeof(directory_entry) *
+;;;                            wMaxRootEntries / wBytesPerSector
+;;;
+;;; Store this in cx and in the wNumRootDirectorySectors identifier.
+;;; 
+        mov ax, 0x0020          ; sizeof(directory_entry)
+        mul WORD [wMaxRootEntries]
+        div WORD [wBytesPerSector]
+        mov cx, ax              ; count of num sectors to read for dir
+
+;;; 
+;;; Compute the starting location of the root directory (sector number):
+;;;
+;;; wRootDirectoryStartSector = wReservedSectors +
+;;;                             (bTotalFATs * wSectorsPerFAT)
+;;; 
+        mov al, BYTE [bTotalFATs]
+        mul WORD [wSectorsPerFAT]
+        add ax, WORD [wReservedSectors]
+
+;;;
+;;; Compute the first sector after the root directory -- this is the
+;;; sector where real data starts on the floppy.
+;;;
+        mov WORD [wDriveDataStartSector], ax
+        add WORD [wDriveDataStartSector], cx
+
+;;; 
+;;; Read the floppy's root directory into memory at BOOT0SEG:0200 by
+;;; calling ReadSectors.  This function reads cx count (wNumRootDirSectors)
+;;; starting at sector ax (wRootDirStartSector) into memory at es:bx
+;;;
+        mov bx, 0x0200
+        call ReadSectors       
+
+SEARCH_ROOT_DIRECTORY:  
+;;;
+;;; Search the root directory for the stage two loader and the kernel.
+;;;
+        mov cx, WORD [wMaxRootEntries]
+        mov di, 0x0200          ; offset of first directory entry
+.LOOP:
+        push cx                 ; save current entry count
+        mov cx, 0x000B          ; 11 char name
+        mov si, szStage2Image   ; name we are seeking
+        push di                 ; save current entry ptr
+        rep cmpsb               ; test for match
+        pop di                  ; restore entry ptr
+        jne .TRY_KERN           ; match? if not see if it matches the kernel
+        mov dx, WORD [di+1Ah]   ; match. save the starting cluster
+        mov WORD [wStage2Cluster], dx
+.TRY_KERN:
+        mov cx, 0x000B          ; 11 char name
+        mov si, szKernelImage   ; name we are seeking
+        push di                 ; save current entry ptr
+        rep cmpsb               ; test for match
+        pop di                  ; restore entry ptr
+        jne .NEXT               ; match? if not next entry
+        mov dx, WORD [di+1Ah]   ; match. save the starting cluster
+        mov WORD [wKernelCluster], dx
+.NEXT:
+        pop cx                  ; cx = entry count again
+        add di, 0x0020          ; next directory entry (+32 bytes later)
+        loop .LOOP              ; cx -= 1, jmp .LOOP if cx != 0
+
+.DONE:
+;;;
+;;; Did we find both the kernel and the second stage boot loader?  If not
+;;; give them a "missing operating system" message.
+;;;
+        mov ax, [wStage2Cluster]
+        test ax, 0xFFFF
+        jz .NOOS
+        mov ax, [wKernelCluster]
+        test ax, 0xFFFF
+        jnz LOAD_FAT
+.NOOS:
+        mov si, szNoOperatingSystem
+        call Write
+FAIL:   mov ah, 0x00            ; wait for a keystroke and reboot
+        int 0x16
+        int 0x19
+
+LOAD_FAT:
+;;;
+;;; Prepare the load the FAT into memory.  Compute the size of the FAT (in
+;;; number of sectors) and store in cx for a call to ReadSectors.
+;;;
+        xor ax, ax
+        mov al, BYTE [bTotalFATs]
+        mul WORD [wSectorsPerFAT]
+        mov cx, ax
+
+;;; 
+;;; Compute location of FAT and store in ax
+;;; 
+        mov ax, WORD [wReservedSectors]
+
+;;; 
+;;; Read the FAT into memory at BOOT0SEG:0200.  This overwrites the root
+;;; directory information but we already have the cluster number for the
+;;; stage two boot loader and the kernel.
+;;; 
+        mov bx, 0x0200
+        call ReadSectors
+
+;;; 
+;;; Prepare to read the stage two boot loader into memory at 
+;;; BOOT1SEG:BOOT1OFF
+;;;
+        ;; point es:bx at where we want the stage two loader read into memory
+        mov ax, BOOT1SEG
+        mov es, ax              ; destination for image
+        mov bx, BOOT1OFF        ; destination for image
+        
+        ;; use the starting cluster we found by reading the directory
+        mov ax, WORD [wStage2Cluster]
+        mov WORD [wCluster], ax
+
+        ;; call LOAD_IMAGE to read in the file
+        call LOAD_IMAGE
+
+;;;
+;;; Prepare to read the kernel into memory at KERNSEG:KERNOFF
+;;; 
+        ;; point es:bx at where we want the kernel read into memory
+        mov ax, KERNSEG
+        mov es, ax
+        mov bx, KERNOFF
+
+        ;; use the starting cluster we found by reading the directory
+        mov ax, WORD [wKernelCluster]
+        mov WORD [wCluster], ax
+
+        ;; call LOAD_IMAGE to read in the file
+        call LOAD_IMAGE        
+
+DONE:
+;;;
+;;; We're done, transfer control to the second stage loader which we
+;;; put at BOOT1SEG:BOOT1OFF.
+;;; 
+        push WORD BOOT1SEG
+        push WORD BOOT1OFF
+        retf
+
+;; *************************************************************************
+;;  PROCEDURE ClusterLBA
+;;  convert FAT cluster into LBA addressing scheme
+;;  LBA = (cluster - 2) * sectors per cluster
+;; *************************************************************************
+ClusterLBA:
+        sub ax, 0x0002          ; cluster number is zero-based
+        xor cx, cx
+        mov cl, BYTE [bSectorsPerCluster];  convert byte to word
+        mul cx
+        add ax, WORD [wDriveDataStartSector];  base data sector
+        ret
+                
+;;; *************************************************************************
+;;; PROCEDURE LBACHS
+;;; 
+;;; convert ax LBA addressing scheme to CHS addressing scheme using these
+;;; formulas:
+;;; 
+;;; absolute sector = (logical sector / sectors per track) + 1
+;;; absolute head   = (logical sector / sectors per track) MOD number of heads
+;;; absolute track  = logical sector / (sectors per track * number of heads)
+;;; *************************************************************************
+LBACHS:
+        xor dx, dx
+        div WORD [wSectorsPerTrack]
+        inc dl                  ; adjust for sector 0
+        mov BYTE [bAbsoluteSector], dl
+        xor dx, dx              ; prepare dx:ax for operation
+        div WORD [wNumHeads]
+        mov BYTE [bAbsoluteHead], dl
+        mov BYTE [bAbsoluteTrack], al
+        ret
+        
+;;; *************************************************************************
+;;; PROCEDURE ReadSectors
+;;; 
+;;; reads disk sectors ax..ax+cx from the disk into memory at es:bx
+;;; 
+;;; *************************************************************************
+ReadSectors:
+.MAIN
+        mov di, 5               ; five retries for disk errors
+.SECTORLOOP
+        push ax
+        push bx
+        push cx
+        call LBACHS             ; convert LBA sector in ax into absolute CHT
+        mov ah, 0x02            ; BIOS read sector
+        mov al, 0x01            ; read one sector
+        mov ch, BYTE [bAbsoluteTrack]
+        mov cl, BYTE [bAbsoluteSector]
+        mov dh, BYTE [bAbsoluteHead]
+        mov dl, BYTE [bDriveNumber]
+        int 0x13
+        jnc .SUCCESS            ; CF=1 on read error
+
+        ;; read error, reset the disk and try again
+        xor ax, ax              ; BIOS reset disk
+        int 0x13
+        dec di                  ; error counter -= 1
+        pop cx                  ; restore registers
+        pop bx
+        pop ax
+        jnz .SECTORLOOP         ; if error counter != 0, try to read again
+
+        ;; give up
+        mov si, szReadError
+        call Write
+        jmp FAIL
+        
+        ;; sector read succeeded
+.SUCCESS
+        pop cx                  ; restore registers
+        pop bx
+        pop ax
+        inc ax                  ; next sector
+
+        ;;; bx += wBytesPerSector
+        add bx, WORD [wBytesPerSector]
+        loop .MAIN              ; cx -= 1, jmp .MAIN if cx != 0
+        ret
+        
+;;; *************************************************************************
+;;; PROCEDURE Write
+;;; 
+;;; display ASCIIZ string at ds:si via BIOS
+;;; *************************************************************************
+Write:
+        cld                     ; make sure direction flag is correct
+        lodsb                   ; load char to al, increment si
+        or al, al               ; see if it's null
+        jz .DONE                ; if so, we're finished
+        mov ah, 0x0E            ; service 0x0E: output one char
+        mov bh, 0x00            ; display page 0
+        mov bl, 0x07            ; char text attrib (white on black)
+        int 0x10                ; invoke bios
+        jmp Write               ; next char
+.DONE:
+        ret
+
+LOAD_IMAGE:
+        mov ax, WORD [wCluster] ; cluster to read
+        call ClusterLBA         ; convert cluster to LBA
+        xor cx, cx
+        mov cl, BYTE [bSectorsPerCluster]
+        call ReadSectors        ; this increments bx
+        
+        ;; compute next cluster
+        mov ax, WORD [wCluster] ; identify current cluster
+        mov cx, ax              ; copy current cluster
+        mov dx, ax              ; copy current cluster
+        shr dx, 0x0001          ; dx = wCluster / 2
+        add cx, dx              ; cx = wCluster + (wCluster / 2)
+        push bx
+        mov bx, 0x0200          ; location of FAT in memory
+        add bx, cx              ; index into FAT
+        mov dx, WORD [bx]       ; read two bytes from FAT
+        pop bx
+        test ax, 0x0001         ; is the cluster even or odd?
+        jnz .ODD
+.EVEN:
+        and dx, 0x0FFF          ; take low twelve bits
+        jmp .DONE
+.ODD:   
+        shr dx, 0x0004          ; take high twelve bits
+.DONE:
+        mov WORD [wCluster], dx ; store new cluster
+        cmp dx, 0x0FF0          ; test for end of file
+        jb LOAD_IMAGE           ; if not, go get the next one
+        ret
+        
+wDriveDataStartSector           dw      0x0000
+szStage2Image                   db      "BOOT    COM", 0
+wStage2Cluster                  dw      0x0000
+szKernelImage                   db      "KERNEL  BIN", 0
+wKernelCluster                  dw      0x0000
+szNoOperatingSystem             db      "Missing OS File", 13, 10, 0
+szReadError                     db      "Disk read error", 13, 10, 0
+wCluster                        dw      0x0000
+bAbsoluteSector                 db      0x00
+bAbsoluteHead                   db      0x00
+bAbsoluteTrack                  db      0x00
+szProgress                      db      ".", 0
+                
+        TIMES 510-($-$$) DB 0   ; 0 padding
+        DW 0xAA55               ; bootsector signature
diff --git a/boot0/boot0.bin b/boot0/boot0.bin
new file mode 100644 (file)
index 0000000..764f7a6
Binary files /dev/null and b/boot0/boot0.bin differ
diff --git a/boot1/Makefile b/boot1/Makefile
new file mode 100755 (executable)
index 0000000..5606866
--- /dev/null
@@ -0,0 +1,14 @@
+NASM=                  nasm
+NASMFLAGS=             -f bin -i../inc
+RM=                    /bin/rm
+TARGET=                        boot.com
+SOURCES=               boot1.asm
+SUPPORT=               video.asm hardware.asm
+
+all:   $(SOURCES) $(SUPPORT)
+               $(NASM) $(NASMFLAGS) $(SOURCES) -o $(TARGET) ; \
+               mcopy -o $(TARGET) Q:\
+
+clean:         
+               $(RM) -f *.log *.core *~ *.gmon \#*\# $(TARGET) ; \
+               mdel Q:\$(TARGET)
diff --git a/boot1/boot.com b/boot1/boot.com
new file mode 100644 (file)
index 0000000..663284c
Binary files /dev/null and b/boot1/boot.com differ
diff --git a/boot1/boot1.asm b/boot1/boot1.asm
new file mode 100644 (file)
index 0000000..59c0dd0
--- /dev/null
@@ -0,0 +1,113 @@
+[BITS 16]
+[ORG 0]
+
+START:
+        ;; initialize segments
+        mov    ax, BOOT1SEG
+        mov    ds, ax
+        mov es, ax
+        mov ss, ax
+
+        ;; make sure we are running on a 386+
+
+        ;; while we're still in real mode, detect system hardware via BIOS
+        call PROBE_VIDEO
+        call GET_EQUIPMENT_LIST
+        call GET_MEMORY_SIZE
+        call GET_TIME
+        
+        ;; switch the processor into protected mode, keep ints disabled
+        cli
+        lidt [IDT_Pointer]
+        lgdt [GDT_Pointer]
+        call ENABLE_A20
+        mov ax, 0x01
+        lmsw ax
+
+        ;; Jump to 32 bit code, this completes the transition to protected mode
+        db 0x66                        ; operand size override prefix
+        db 0xea                        ; jmp opcode
+        dd (BOOT1SEG<<4) + setup_32 ; want to jump here
+        dw (1<<3)              ; ...in the kernel code segment
+
+[BITS 32]
+setup_32:
+        ;; set up data segment registers
+        mov    ax, (2<<3)
+        mov    ds, ax
+        mov    es, ax
+        mov    fs, ax
+        mov    gs, ax
+        mov    ss, ax
+
+        ;; create an initial stack
+        mov esp, KERN_STACK + 4096
+        mov ebp, esp
+
+        ;; create a stack frame, pass ptr to hardware block as param
+        mov eax, (BOOT1SEG<<4)+BIOS_HARDWARE_BLOCK
+        push eax
+        push (BOOT1SEG<<4)+.HANG
+        jmp (1<<3):0x00010000     ; entry point of kernel
+
+.HANG:  
+        nop
+        jmp .HANG
+
+
+; Setup data
+; ----------------------------------------------------------------------
+
+BIOS_HARDWARE_BLOCK:
+bDisplayType            db      0x00
+bFontSize               db      0x00
+wEquipmentBitvector     dw      0x0000
+wMemorySize             dw      0x0000
+wSystemClock            dw      0x0000        
+        
+NUM_GDT_ENTRIES equ 3           ; number of entries in GDT
+GDT_ENTRY_SZ equ 8              ; size of a single GDT entry
+
+align 8, db 0
+GDT:
+       ; Descriptor 0 is not used
+       dw 0
+       dw 0
+       dw 0
+       dw 0
+
+       ; Descriptor 1: kernel code segment
+       dw 0xFFFF       ; bytes 0 and 1 of segment size
+       dw 0x0000       ; bytes 0 and 1 of segment base address
+       db 0x00         ; byte 2 of segment base address
+       db 0x9A         ; present, DPL=0, non-system, code, non-conforming,
+                       ;   readable, not accessed
+       db 0xCF         ; granularity=page, 32 bit code, upper nibble of size
+       db 0x00         ; byte 3 of segment base address
+
+       ; Descriptor 2: kernel data and stack segment
+       ; NOTE: what Intel calls an "expand-up" segment
+       ; actually means that the stack will grow DOWN,
+       ; towards lower memory.  So, we can use this descriptor
+       ; for both data and stack references.
+       dw 0xFFFF       ; bytes 0 and 1 of segment size
+       dw 0x0000       ; bytes 0 and 1 of segment base address
+       db 0x00         ; byte 2 of segment base address
+       db 0x92         ; present, DPL=0, non-system, data, expand-up,
+                       ;   writable, not accessed
+       db 0xCF         ; granularity=page, big, upper nibble of size
+       db 0x00         ; byte 3 of segment base address
+
+GDT_Pointer:
+       dw NUM_GDT_ENTRIES*GDT_ENTRY_SZ ; limit
+       dd (BOOT1SEG<<4) + GDT          ; base address
+
+IDT_Pointer:
+       dw 0
+       dd 00
+
+%include "defs.asm"
+%include "hardware.asm"
+%include "video.asm"
+        
+        
\ No newline at end of file
diff --git a/boot1/hardware.asm b/boot1/hardware.asm
new file mode 100644 (file)
index 0000000..b7ac3af
--- /dev/null
@@ -0,0 +1,42 @@
+[BITS 16]
+;;; Call BIOS to populate equipment bitv in the HARDWARE buffer.
+GET_EQUIPMENT_LIST:
+        xor ax, ax
+        int 0x11
+        mov [wEquipmentBitvector], ax
+        ret
+
+;;; Call BIOS to get the system memory size.
+GET_MEMORY_SIZE:
+        xor ax, ax
+        mov ah, 0x88
+        int 0x15
+        add ax, 1024
+        mov [wMemorySize], ax
+        ret
+        
+GET_TIME:
+        xor ax, ax
+        int 0x1a
+        push es
+        push si
+        mov es, cx
+        mov si, dx
+        mov cx, WORD [es:si]
+        mov [wSystemClock], cx
+        pop si
+        pop es
+        ret
+
+; Enable the A20 address line, so we can correctly address
+; memory above 1MB.
+ENABLE_A20:     
+        mov    al, 0xD1
+        out    0x64, al
+        nop
+        jmp .here
+.here:  mov    al, 0xDF
+        out    0x60, al
+        nop
+        jmp .there
+.there: ret
diff --git a/boot1/memory.asm b/boot1/memory.asm
new file mode 100644 (file)
index 0000000..d834825
--- /dev/null
@@ -0,0 +1,3 @@
+;;;
+SIZE_MEMORY:
+        
\ No newline at end of file
diff --git a/boot1/video.asm b/boot1/video.asm
new file mode 100644 (file)
index 0000000..61ff153
--- /dev/null
@@ -0,0 +1,81 @@
+;;; Display the ASCIIZ string at ds:si via BIOS VIDEO call (real mode only)
+Write:
+        lodsb                   ; load char to al, increment si
+        or al, al               ; see if it's null
+        jz .DONE                ; if so, we're finished
+        mov ah, 0x0E            ; service 0x0E: output one char
+        mov bh, 0x00            ; display page 0
+        mov bl, 0x07            ; char text attrib (white on black)
+        int 0x10                ; invoke bios
+        jmp Write      ; next char
+.DONE:
+        ret
+
+;;; Probe the video system of the machine via BIOS VIDEO calls, populate 
+;;; the HARDWARE_INFO buffer (real mode only).
+PROBE_VIDEO:
+        ;; identify the display type
+        call DISP_ID
+        mov [bDisplayType], al
+
+        ;; determine the font size
+        call FONT_SIZE
+        mov [bFontSize], al
+        ret
+
+;;; Determine the font size (width in pixels) of the current display.
+FONT_SIZE:
+        cmp al, 0x0a
+        jl .TRY_OLD
+        mov al, BYTE 16
+        ret
+.TRY_OLD:
+        cmp al, BYTE 1
+        jne .TRY_CGA
+        mov al, BYTE 14
+        ret
+.TRY_CGA:       
+        cmp al, BYTE 2
+        jne .TRY_VGA
+        mov al, BYTE 8
+        ret
+.TRY_VGA:
+        mov ah, 0x11
+        mov al, 0x30
+        mov bh, 0
+        int 0x10
+        mov al, cl
+        ret
+
+;;; Determine the video type via BIOS VIDEO call
+DISP_ID:
+        xor ax, ax
+        mov ah, 0x1a
+        int 0x10
+        cmp al, 0x1a
+        jne .TRY_EGA
+        mov al, bl
+        ret
+.TRY_EGA:
+        mov ah, 0x12
+        mov bx, 0x10
+        int 0x10
+        cmp bx, 0x10
+        je .OLD_BOARDS
+        cmp bh, 0
+        je .EGA_COLOR
+        mov al, 5
+        ret
+.EGA_COLOR:
+        mov al, 4
+        ret
+.OLD_BOARDS:
+        int 0x11
+        and al, 0x30
+        cmp al, 0x30
+        jne .CGA
+        mov al, 1
+        ret
+.CGA:
+        mov al, 2
+        ret
diff --git a/floppy.img b/floppy.img
new file mode 100644 (file)
index 0000000..fb06de4
Binary files /dev/null and b/floppy.img differ
diff --git a/inc/defs.asm b/inc/defs.asm
new file mode 100644 (file)
index 0000000..e022a89
--- /dev/null
@@ -0,0 +1,33 @@
+BOOT0SEG equ 0x07C0
+BOOT0OFF equ 0x0000
+
+BOOT1SEG equ 0x0100
+BOOT1OFF equ 0x0000
+
+KERNSEG equ 0x1000
+KERNOFF equ 0x0000
+
+VIDEOSEG equ 0xB800
+
+; 8259A PIC initialization codes.
+; Source: Linux bootsect.S, and Intel 8259A datasheet
+
+; The most important reason why we reprogram the PICs is to
+; route the hardware interrupts through vectors *above*
+; those reserved by Intel.  The BIOS (for historical reasons :-)
+; routes them such that they conflict with internal processor-generated
+; interrupts.
+
+ICW1 equ 0x11          ; ICW1 - ICW4 needed, cascade mode, interval=8,
+                       ;   edge triggered. (I think interval is irrelevant
+                       ;   for x86.)
+ICW2_MASTER equ 0x20   ; put IRQs 0-7 at 0x20 (above Intel reserved ints)
+ICW2_SLAVE equ 0x28    ; put IRQs 8-15 at 0x28
+ICW3_MASTER equ 0x04   ; IR2 connected to slave
+ICW3_SLAVE equ 0x02    ; slave has id 2
+ICW4 equ 0x01          ; 8086 mode, no auto-EOI, non-buffered mode,
+                       ;   not special fully nested mode
+
+KERN_THREAD_OBJ equ (1024*1024)
+KERN_STACK equ KERN_THREAD_OBJ + 4096       
+
diff --git a/kernel/Makefile b/kernel/Makefile
new file mode 100644 (file)
index 0000000..b5838d6
--- /dev/null
@@ -0,0 +1,30 @@
+DEBUGFLAGS=-DDEBUG
+
+SUBDIR += init
+SUBDIR += hal
+SUBDIR += rtl
+
+.include <bsd.port.subdir.mk>
+
+OBJCOPY=       objcopy
+OBJCOPY_FLAGS= -R .dynamic -R .note -R .comment
+OBJS=          init/entry.o init/main.o hal/video.o hal/io.o \
+               rtl/string.o rtl/memory.o hal/intsupport.o hal/interrupts.o \
+               hal/timer.o hal/keyboard.o hal/timestamp.o hal/counters.o
+RM=            /bin/rm
+
+all: kernel.bin
+
+kernel.bin: kernel.tmp
+       $(OBJCOPY) $(OBJCOPY_FLAGS) -S -O binary ./kernel.tmp kernel.bin ; \
+       mcopy -o ./kernel.bin Q: ; \
+       mcopy -o ./kernel.map Q: ; \
+       $(RM) -f kernel.tmp
+
+kernel.tmp: $(OBJS)
+       $(LD) -M -o kernel.tmp -Ttext 0x00010000 -e StartOfKernelImage $(OBJS) \
+       > kernel.map
+
+clean:
+       $(RM) -f $(TARGET) $(OBJS) *~ #*# .#* ; \
+       mdel Q:\$(TARGET)
diff --git a/kernel/defines b/kernel/defines
new file mode 100644 (file)
index 0000000..dcee875
--- /dev/null
@@ -0,0 +1,6 @@
+//
+// Symbols defined here are globally defined in all Makefiles below
+// here.
+//
+#define KERNEL
+#define DEBUG
\ No newline at end of file
diff --git a/kernel/driver/keyboard.c b/kernel/driver/keyboard.c
new file mode 100644 (file)
index 0000000..7410171
--- /dev/null
@@ -0,0 +1,37 @@
+//+----------------------------------------------------------------------------
+//
+// File:     keyboard.c
+//
+// Module:   
+//
+// Synopsis: 
+//
+// Created:  sgasch  21 Oct 2003
+//
+//+----------------------------------------------------------------------------
+
+#include "kernel.h"
+#include "hal.h"
+#include "rtl.h"
+#include "interrupts.h"
+
+void
+HalKeyboardInt(INTERRUPT_STATE *is)
+{
+    BYTE c;
+    BYTE k;
+
+    HalDisableInterrupts();
+
+    c = in(0x64);
+    HalIoDelay();
+    if (c & 1)
+    {
+        k = in(0x60);
+        HalIoDelay();
+        HalVideoPrint("Testing %x.\n\0", 1);
+    }
+
+    HalEnableInterrupts();
+}
+
diff --git a/kernel/driver/video.c b/kernel/driver/video.c
new file mode 100644 (file)
index 0000000..a63331b
--- /dev/null
@@ -0,0 +1,503 @@
+//+----------------------------------------------------------------------------
+//
+// File:     video.c
+//
+// Module:   Video driver
+//
+// Synopsis: low-level interface to video memory
+//
+// Created:  sgasch  5 Jul 2003
+//
+//+----------------------------------------------------------------------------
+
+#include <stdarg.h>
+
+#include "kernel.h"
+#include "hal.h"
+#include "rtl.h"
+#include "video.h"
+
+extern BIOS_HARDWARE_BLOCK g_BiosHardwareBlock;
+
+//
+// Local #defines
+//
+#define FG_BG_TO_ATTRIB_BYTE(fg,bg)            ((fg&0x0F)|((bg&0x0F)<<4))
+#define LINES                                  (0)
+#define COLS                                   (1)
+#define CRT_ADDR_REG                           (0x3D4)
+#define CRT_DATA_REG                           (0x3D5)
+#define CRT_CURSOR_LOC_HIGH_REG                (0x0E)
+#define CRT_CURSOR_LOC_LOW_REG                 (0x0F)
+#define ZERO_BASED_LINE_COL_TO_BYTE_OFFSET(L,C)\
+    (((g_bScreenResolution[COLS] << 1) * (L)) + ((C) << 1))
+#define ZERO_BASED_LINE_COL_TO_ULONG_OFFSET(L,C)\
+    (ZERO_BASED_LINE_COL_TO_BYTE_OFFSET((L),(C)) >> 2)
+
+//
+// Global identifiers
+//
+BYTE *g_pVideoMemory = NULL;
+BYTE g_bScreenResolution[2] = { 0, 0 };
+BYTE g_bSoftCursor[2] = { 0, 0 };
+BYTE g_bColorAttribute = FG_BG_TO_ATTRIB_BYTE(BLACK, WHITE);
+
+typedef struct _VIDEO_LOOKUP_ENTRY
+{
+    CHAR *szBoardName;
+    BYTE *pStartOfVideoMemory;
+    BYTE uScreenLines[3];
+}
+VIDEO_LOOKUP_ENTRY;
+
+static VIDEO_LOOKUP_ENTRY g_VideoLookupTable[] =
+{
+    { "No video adapter",
+      (BYTE *)0x000B0000,
+      { 25, 25, 25 } },
+    { "Monochrome display adapter",
+      (BYTE *)0x000B0000,
+      { 25, 25, 25 } },
+    { "CGA",
+      (BYTE *)0x000B8000,
+      { 25, 25, 25 } },
+    { "Code 3: Undefined",
+      (BYTE *)0x000B0000,
+      { 25, 25, 25 } },
+    { "EGA with color display",
+      (BYTE *)0x000B8000,
+      { 43, 25, 25 } },
+    { "EGA with mono display",
+      (BYTE *)0x000B0000,
+      { 43, 25, 25 } },
+    { "Code 6: Undefined",
+      (BYTE *)0x000B0000,
+      { 25, 25, 25 } },
+    { "VGA with mono display",
+      (BYTE *)0x000B0000,
+      { 50, 27, 25 } },
+    { "VGA with color display",
+      (BYTE *)0x000B8000,
+      { 50, 27, 25 } },
+    { "Code 9: Undefined",
+      (BYTE *)0x000B0000,
+      { 25, 25, 25 } },
+    { "MCGA with digital color",
+      (BYTE *)0x000B8000,
+      { 25, 25, 25 } },
+    { "MCGA with monochrome",
+      (BYTE *)0x000B0000,
+      { 25, 25, 25 } },
+    { "MCGA with analog color",
+      (BYTE *)0x000B8000,
+      { 25, 25, 25 } } 
+};
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:  VideopInitialize
+//
+// Synopsis:  
+//
+// Arguments: void
+//            
+// Returns:   STATUS
+//
+//+----------------------------------------------------------------------------
+STATUS 
+VideopInitialize(void)
+{
+    BYTE uType = g_BiosHardwareBlock.bDisplayType;
+    BYTE uIndex = 2;
+
+    //
+    // Based on the font size (width in pixels), set the index into the
+    // screen lines lookup table
+    //
+    switch(g_BiosHardwareBlock.bFontSize)
+    {
+        case 8:
+            uIndex = 0;
+            break;
+        case 14:
+            uIndex = 1;
+            break;
+        case 16:
+            uIndex = 2;
+            break;
+    }
+
+    //
+    // If the display type returned by BIOS is known to us, use the
+    // lookup table to populate some globals here.
+    //
+    if (uType <= ARRAY_LENGTH(g_VideoLookupTable))
+    {
+        g_pVideoMemory = g_VideoLookupTable[uType].pStartOfVideoMemory;
+        g_bScreenResolution[LINES] = 
+            g_VideoLookupTable[uType].uScreenLines[uIndex];
+    }
+    
+    //
+    // Otherwise make some guesses
+    //
+    else
+    {
+        g_pVideoMemory = (BYTE *)0x000B8000;
+        g_bScreenResolution[LINES] = 25;
+    }
+    g_bScreenResolution[COLS] = 80;
+
+    //
+    // Set color to WHITE on BLACK
+    //
+    VideoSetCurrentColorAttribute(WHITE, BLACK);
+
+    //
+    // Clear the screen and thus synchronize the hardware and soft cursor
+    // position.
+    //
+    VideoClearScreen();
+    return(STATUS_SUCCESS);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:  VideoDriverMain
+//
+// Synopsis:  
+//
+// Arguments: UINT uEvent
+//            
+// Returns:   STATUS
+//
+//+----------------------------------------------------------------------------
+STATUS 
+VideoDriverMain(UINT uEvent)
+{
+    switch(uEvent)
+    {
+        case DEVICE_DRIVER_INITIALIZATION:
+            return(VideopInitialize());
+
+        case DEVICE_DETATCH:
+            ASSERT(FALSE);
+            return(STATUS_NOT_SUPPORTED);
+
+        case DEVICE_DRIVER_SHUTDOWN:
+            g_fVideoEnabled = FALSE;
+            return(STATUS_SUCCESS);
+            
+        default:
+    }
+    return(TRUE);
+}
+
+STATUS
+VideoDriverRead(UINT uAddress,
+                void *pBuffer,
+                UINT uBufferLength);
+
+STATUS 
+VideoDriverWrite(UINT uAddress,
+                 void *pBuffer,
+                 UINT uBufferLength);
+
+STATUS
+VideoDriverIoctl(UINT uIoctlCode,
+                 void *pBuffer,
+                 UINT uBufferLength);
+
+
+//
+// Move the hardware cursor on the screen to sync up with the software
+// cursor position in g_bSoftwareCursor
+//
+void
+VideoSetHardwareCursor(void)
+{
+    WORD wOffset;                             // byte offset into video mem
+    BYTE bOrig;                               // original port contents holder
+
+    //
+    // Cursor is zero-based (e.g. line 24 is the last one)
+    //
+    ASSERT(g_bSoftCursor[LINES] < g_bScreenResolution[LINES]);
+    ASSERT(g_bSoftCursor[COLS] < g_bScreenResolution[COLS]);
+
+    wOffset = ZERO_BASED_LINE_COL_TO_BYTE_OFFSET(g_bSoftCursor[LINES],
+                                                 g_bSoftCursor[COLS]);
+    ASSERT(wOffset <= (g_bScreenResolution[LINES] * 
+                       g_bScreenResolution[COLS]) * 2 - 2);
+
+    //
+    // Save original contents of CRT address register.
+    //
+    bOrig = in(CRT_ADDR_REG);
+
+    //
+    // Set the high cursor location byte
+    //
+    out(CRT_ADDR_REG, CRT_CURSOR_LOC_HIGH_REG);
+    out(CRT_DATA_REG, (wOffset >> 8) & 0xFF);
+    IoDelay();
+
+    //
+    // Set the low cursor location byte
+    //
+    out(CRT_ADDR_REG, CRT_CURSOR_LOC_LOW_REG);
+    IoDelay();
+    out(CRT_DATA_REG, (wOffset & 0xFF));
+    IoDelay();
+
+    //
+    // Restore contents of the CRT address register
+    //
+    out(CRT_ADDR_REG, bOrig);
+    IoDelay();
+}
+
+void
+VideoSetCurrentColorAttribute(BYTE bFg, BYTE bBg)
+{
+    bFg &= 0x0F;                              // restrict these guys to colors
+    bBg &= 0x0F;                              // and the high intense bit
+
+    g_bColorAttribute = FG_BG_TO_ATTRIB_BYTE(bFg, bBg);
+}
+
+void
+VideoClearScreen(void)
+{
+    ULONG *p = (ULONG *)g_pVideoMemory;
+    ULONG uFill;
+    ULONG uCount;
+
+    //
+    // Start uCount at the number of ULONGs in visible video memory
+    //
+    uCount = ZERO_BASED_LINE_COL_TO_BYTE_OFFSET(g_bScreenResolution[LINES] - 1,
+                                                g_bScreenResolution[COLS] - 1);
+    uCount += 2;
+    uCount >>= 2;
+
+    //
+    // Construct a fill ULONG: blank attrib blank attrib
+    //
+    uFill = 0;
+    uFill |= (ULONG)g_bColorAttribute;
+    uFill |= ((ULONG)g_bColorAttribute) << 16;
+
+    //
+    // Blast uFills into video memory
+    //
+    while(uCount)
+    {
+        *p++ = uFill;
+        uCount--;
+    }
+    
+    //
+    // Set cursor position to 0,0
+    //
+    g_bSoftCursor[LINES] = g_bSoftCursor[COLS] = 0;
+    VideoSetHardwareCursor();
+}
+
+
+void 
+VideoScroll(void)
+{
+    ULONG *p = (ULONG *)g_pVideoMemory;
+    ULONG uUlongsPerLine = (g_bScreenResolution[COLS] >> 1); // 2X/4
+    ULONG i, j;
+    ULONG uFill;
+
+    ASSERT(sizeof(ULONG) == 4);
+    ASSERT(sizeof(BYTE) == 1);
+
+    for (i = 0;
+         i < (g_bScreenResolution[LINES] - 2);
+         i++)
+    {
+        //
+        // Start at i, 0.  Copy a ULONG up from i+1, 0.  Do the whole line i.
+        //
+        for (j = 0;
+             j < uUlongsPerLine;
+             j++)
+        {
+            *p = *(p + uUlongsPerLine);
+            p++;
+        }
+    }
+    
+    //
+    // Construct a fill ULONG: blank attrib blank attrib
+    //
+    uFill = 0;
+    uFill |= (ULONG)g_bColorAttribute;
+    uFill |= ((ULONG)g_bColorAttribute) << 16;
+
+    //
+    // Blank the last line
+    //
+    p = (ULONG *)(g_pVideoMemory + 
+        ZERO_BASED_LINE_COL_TO_BYTE_OFFSET(g_bScreenResolution[LINES] - 1, 0));
+    for (i = 0;
+         i < uUlongsPerLine;
+         i++)
+    {
+        *p = uFill;
+        p++;
+    }
+}
+
+void 
+VideoPutChar(BYTE c)
+{
+    BYTE *p = (g_pVideoMemory + 
+               ZERO_BASED_LINE_COL_TO_BYTE_OFFSET(g_bSoftCursor[LINES],
+                                                  g_bSoftCursor[COLS]));
+    switch(c)
+    {
+        case '\n':
+            g_bSoftCursor[LINES]++;
+            if (g_bSoftCursor[LINES] >= g_bScreenResolution[LINES])
+            {
+                VideoScroll();
+                g_bSoftCursor[LINES] = g_bScreenResolution[LINES] - 1;
+            }
+            g_bSoftCursor[COLS] = 0;
+            return;
+        default:
+            *p = c;
+            p++;
+            *p = g_bColorAttribute;
+            p++;
+            g_bSoftCursor[COLS]++;
+            if (g_bSoftCursor[COLS] >= g_bScreenResolution[COLS])
+            {
+                g_bSoftCursor[COLS] = 0;
+                g_bSoftCursor[LINES]++;
+                if (g_bSoftCursor[LINES] >= g_bScreenResolution[LINES])
+                {
+                    VideoScroll();
+                    g_bSoftCursor[LINES] = g_bScreenResolution[LINES] - 1;
+                }
+            }
+    }
+}
+
+void
+VideoPutNullTerminatedString(BYTE *s)
+{
+    ULONG uSafety = 0;
+
+    while (*s != 0)
+    {
+        VideoPutChar(*s);
+        s++;
+        uSafety++;
+
+        if (uSafety > 256) 
+        {
+            VideoPutNullTerminatedString("RUNAWAYSTRING!?!\n\0");
+            break;
+        }
+    }
+    VideoSetHardwareCursor();
+}
+
+void
+VideoSetCursorPosition(BYTE bLine, BYTE bCol)
+{
+    if (bLine >= g_bScreenResolution[LINES])
+    {
+        bLine = g_bScreenResolution[LINES] - 1;
+    }
+    if (bCol >= g_bScreenResolution[COLS])
+    {
+        bCol = g_bScreenResolution[COLS] - 1;
+    }
+
+    g_bSoftCursor[LINES] = bLine;
+    g_bSoftCursor[COLS] = bCol;
+    VideoSetHardwareCursor();
+}
+
+void
+VideoGetCursorPosition(BYTE *pbLine, BYTE *pbCol)
+{
+    *pbLine = g_bSoftCursor[LINES];
+    *pbCol = g_bSoftCursor[COLS];
+}
+
+void 
+VideoPrint(CHAR *szFormat, ...)
+{
+    CHAR *p = szFormat;
+    CHAR *q;
+    CHAR buf[32];
+    va_list args;
+    INT iVal;
+    UINT uVal;
+    CHAR *szVal;
+
+    va_start(args, szFormat);
+    while (*p != '\0')
+    {
+        switch (*p)
+        {
+            case '%':
+                p++;
+                switch (*p) 
+                {
+                    case '\0':
+                        goto done;
+                    case '%':
+                        VideoPutChar('%');
+                        break;
+                    case 'd':
+                        iVal = va_arg(args, int);
+                        q = RtlIntToAscii(iVal, buf, ARRAY_LENGTH(buf), 10);
+                        ASSERT(strlen(q) < 20);
+                        VideoPutNullTerminatedString(q);
+                        break;
+                    case 'u':
+                        uVal = va_arg(args, unsigned int);
+                        q = RtlIntToAscii(uVal, buf, ARRAY_LENGTH(buf), 10);
+                        ASSERT(strlen(q) < 20);
+                        VideoPutNullTerminatedString(q);
+                        break;
+                    case 'x':
+                        uVal = va_arg(args, unsigned int);
+                        q = RtlIntToAscii(uVal, buf, ARRAY_LENGTH(buf), 16);
+                        ASSERT(strlen(q) < 20);
+                        VideoPutNullTerminatedString(q);
+                        break;
+                    case 's':
+                        szVal = va_arg(args, char *);
+                        VideoPutNullTerminatedString(szVal);
+                        break;
+                    case 'c':
+                        iVal = va_arg(args, int);
+                        VideoPutChar(iVal & 0xFF);
+                        break;
+                    default:
+                        VideoPutChar(*p);
+                        break;
+                }
+                break;
+            default:
+                VideoPutChar(*p);
+                break;
+        }
+        p++;
+    }
+ done:
+    va_end(args);
+    VideoSetHardwareCursor();
+}
diff --git a/kernel/hal/Makefile b/kernel/hal/Makefile
new file mode 100644 (file)
index 0000000..3725f18
--- /dev/null
@@ -0,0 +1,20 @@
+CC=                            gcc
+CFLAGS=                -Wall -imacros ../defines -I../inc
+OBJS=                  video.o io.o interrupts.o intsupport.o keyboard.o timer.o \
+                               timestamp.o counters.o
+RM=                            /bin/rm
+NASM=                  nasm
+NASMFLAGS=             -f elf
+
+.SUFFIXES: .c .o .asm
+
+all: $(OBJS)
+
+.c.o:
+       $(CC) $(CFLAGS) -c $<
+
+.asm.o:
+       $(NASM) $(NASMFLAGS) -o $*.o $<
+
+clean:
+       $(RM) -f $(OBJS) *~ #*# .#*
diff --git a/kernel/hal/counters.c b/kernel/hal/counters.c
new file mode 100644 (file)
index 0000000..9bd9466
--- /dev/null
@@ -0,0 +1,17 @@
+//+----------------------------------------------------------------------------
+//
+// File:     counters.c
+//
+// Module:   
+//
+// Synopsis: 
+//
+// Copyright (C) 2003 Scott Gasch
+//
+// Created:  sgasch  24 Oct 2003
+//
+//+----------------------------------------------------------------------------
+
+#include "kernel.h"
+
+UINT64 g_ullTimeStampCounter = 0;
diff --git a/kernel/hal/interrupts.c b/kernel/hal/interrupts.c
new file mode 100644 (file)
index 0000000..94f2528
--- /dev/null
@@ -0,0 +1,230 @@
+//+----------------------------------------------------------------------------
+//
+// File:     interrupts.c
+//
+// Module:   
+//
+// Synopsis: 
+//
+// Created:  sgasch  6 Jul 2003
+//
+//+----------------------------------------------------------------------------
+
+#include "kernel.h"
+#include "hal.h"
+#include "rtl.h"
+#include "interrupts.h"
+
+IDT_ENTRY g_IDT[NUM_IDT_ENTRIES];
+INTERRUPT_HANDLER g_InterruptHandlerTable[NUM_IDT_ENTRIES];
+ULONG g_uInterruptsEnabled = 0;
+
+void
+HalEnableInterrupts(void)
+{
+    g_uInterruptsEnabled++;
+    ASSERT(g_uInterruptsEnabled == 1);
+
+    __asm__ __volatile__ (
+        "sti"
+        );
+}
+
+void
+HalDisableInterrupts(void)
+{
+    g_uInterruptsEnabled--;
+    ASSERT(g_uInterruptsEnabled == 0);
+
+    __asm__ __volatile__ (
+        "cli"
+        );
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:  DoNothing
+//
+// Synopsis:  The default interrupt handler, do nothing
+//
+// Arguments: INTERRUPT_STATE *p
+//            
+// Returns:   void
+//
+//+----------------------------------------------------------------------------
+void HalDoNothing(INTERRUPT_STATE *p)
+{
+    ;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:  InterruptSendIrqEoi
+//
+// Synopsis:  Send Interrupt ReQuest End Of Interrupt to the PIC.
+//
+// Arguments: INTERRUPT_STATE *is
+//            
+// Returns:   void
+//
+//+----------------------------------------------------------------------------
+void 
+HalInterruptSendIrqEoi(INTERRUPT_STATE *is)
+{
+    ULONG uIrq;
+    BYTE bCommand;
+    BYTE *p = (BYTE *)0x000B8000;
+
+    *p = '3';
+    *(p + 1) = ' ';
+    
+    if ((is->uIntNum >= FIRST_EXTERNAL_INT) &&
+        (is->uIntNum <= LAST_EXTERNAL_INT))
+    {
+        uIrq = (is->uIntNum - FIRST_EXTERNAL_INT);
+        ASSERT(uIrq >= 0);
+        ASSERT(uIrq <= 15);
+        bCommand = 0x60 | (uIrq & 0x7);
+        
+        if (uIrq < 8)
+        {
+            // EOI to master PIC
+            out(0x20, bCommand);
+            HalIoDelay();
+        }
+        else 
+        {
+            // EOI to slave PIC and cascade line EOI to master PIC
+            out(0xA0, bCommand);
+            out(0x20, 0x62);
+            HalIoDelay();
+        }
+    }
+
+    *p = '4';
+    *(p + 1) = ' ';
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function:  InterruptInitializeGate
+//
+// Synopsis:  Initializes an interrupt gate with given handler address
+//            and descriptor privilege level.
+//
+// Arguments: IDT_ENTRY *pEntry,
+//            void *pPreamble,
+//            ULONG uDpl
+//            
+// Returns:   void
+//
+//+----------------------------------------------------------------------------
+void 
+HalInterruptInitializeGate(IDT_ENTRY *pEntry, 
+                           void *pPreamble,
+                           ULONG uDpl)
+{
+    ULONG u = (ULONG)pPreamble;
+
+    pEntry->i.offsetLow = u & 0xffff;
+    pEntry->i.segmentSelector = (1<<3);
+    pEntry->i.reserved = 0;
+    pEntry->i.signature = 0x70; // == 01110000b
+    pEntry->i.dpl = uDpl;
+    pEntry->i.present = 1;
+    pEntry->i.offsetHigh = u >> 16;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:  InterruptInstallHandler
+//
+// Synopsis:  Installs an interrupt handler routine for a given IRQ number
+//
+// Arguments: ULONG uInterruptNumber,
+//            INTERRUPT_HANDLER pHandler
+//            
+// Returns:   void
+//
+//+----------------------------------------------------------------------------
+void 
+HalInterruptInstallHandler(ULONG uInterruptNumber,
+                           INTERRUPT_HANDLER pHandler)
+{
+    ASSERT(uInterruptNumber < ARRAY_LENGTH(g_InterruptHandlerTable));
+    
+    g_InterruptHandlerTable[uInterruptNumber] = pHandler;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:  InterruptInitialize
+//
+// Synopsis:  Initialize the interrupt system
+//
+// Arguments: void
+//            
+// Returns:   void
+//
+//+----------------------------------------------------------------------------
+void 
+HalInitializeInterrupts(void)
+{
+    ULONG uPreambleEntrySize = (ULONG)&HalInterruptHandlerPreambleAfter;
+    ULONG u;
+    ULONG uDpl;
+    USHORT uLimitAndBase[3];
+    BYTE *p;
+
+    //
+    // Determine the size of an interrupt preamble table entry.
+    //
+    uPreambleEntrySize -= (ULONG)&HalInterruptHandlerPreambleBefore;
+
+    //
+    // Set the base interrupt number for each PIC.  See comments in
+    // intsupport.asm.
+    //
+    HalInterruptInitializePICs();
+
+    //
+    // Build interrupt descriptor table
+    //
+    for (u = 0, p = &HalInterruptHandlerPreamble;
+         u < ARRAY_LENGTH(g_IDT);
+         u++, p += uPreambleEntrySize)
+    {
+        uDpl = (u == 0x2E) ? USER_PRIVILEGE : KERNEL_PRIVILEGE;
+
+        HalInterruptInitializeGate(&(g_IDT[u]), p, uDpl);
+        HalInterruptInstallHandler(u, HalDoNothing);
+    }
+
+    //
+    // Install the IDT
+    //
+    u = (ULONG)&(g_IDT);
+    uLimitAndBase[0] = 8 * NUM_IDT_ENTRIES;
+    uLimitAndBase[1] = (USHORT)(u & 0xffff);
+    uLimitAndBase[2] = (USHORT)(u >> 16);
+    
+    HalInterruptLoadIDTR((void *)uLimitAndBase);
+
+    //
+    // Install interrupt handlers
+    //
+    HalInterruptInstallHandler(IRQ0, HalTimerInt);
+    HalInterruptInstallHandler(IRQ1, HalKeyboardInt);
+
+    out(0x21, 0xFC);                          // turn on keyboard and timer
+
+    //
+    // Enable interrupts
+    //
+    HalEnableInterrupts();
+}
+
diff --git a/kernel/hal/interrupts.h b/kernel/hal/interrupts.h
new file mode 100644 (file)
index 0000000..673b13b
--- /dev/null
@@ -0,0 +1,92 @@
+//+----------------------------------------------------------------------------
+//
+// File:     interrupts.h
+//
+// Module:   
+//
+// Synopsis: 
+//
+// Created:  sgasch  6 Jul 2003
+//
+//+----------------------------------------------------------------------------
+
+#ifndef _INTERRUPTS_H_
+#define _INTERRUPTS_H_
+
+#define NUM_IDT_ENTRIES          (256)
+
+// Exceptions range from 0x00..0x11
+#define FIRST_EXCEPTION 0x00
+#define LAST_EXCEPTION  0x11
+#define NUM_EXCEPTIONS  18
+
+// External IRQs range from 0x30..0x3F
+#define FIRST_EXTERNAL_INT 0x30
+#define LAST_EXTERNAL_INT  0x3F
+#define IRQ0               0x30
+#define IRQ1               0x31
+#define IRQ2               0x39
+#define IRQ3               0x33
+#define IRQ4               0x34
+#define IRQ5               0x35
+#define IRQ6               0x36
+#define IRQ7               0x37
+#define IRQ8               0x38
+#define IRQ9               0x39
+#define IRQ10              0x3A
+#define IRQ11              0x3B
+#define IRQ12              0x3C
+#define IRQ13              0x3D
+#define IRQ14              0x3E
+#define IRQ15              0x3F
+#define NUM_EXTERNAL_INTS  16
+
+typedef struct _INTERRUPT_GATE
+{
+    USHORT offsetLow;
+    USHORT segmentSelector;
+    USHORT reserved  : 5;
+    USHORT signature : 8;
+    USHORT dpl       : 2;
+    USHORT present   : 1;
+    USHORT offsetHigh;
+} 
+INTERRUPT_GATE;
+
+typedef union _IDT_ENTRY
+{
+    INTERRUPT_GATE i;
+    // In theory we could have members for trap gates
+    // and task gates if we wanted.
+}
+IDT_ENTRY;
+
+//
+// Defined in intsupport.asm
+//
+extern void HalInterruptInitializePICs(void);
+extern void HalInterruptLoadIDTR(void *uLimitAndBase);
+extern void HalIoDelay(void);
+extern BYTE HalInterruptHandlerPreamble;
+extern BYTE HalInterruptHandlerPreambleBefore;
+extern BYTE HalInterruptHandlerPreambleAfter;
+
+//
+// Defined in interrupts.c
+//
+extern void HalDisableInterrupts(void);
+extern void HalEnableInterrupts(void);
+
+
+//
+// Defined in keyboard.c
+//
+extern void HalKeyboardInt(INTERRUPT_STATE *is);
+
+//
+// Defined in timer.c
+//
+extern void HalTimerInt(INTERRUPT_STATE *is);
+
+#endif
+
diff --git a/kernel/hal/intsupport.asm b/kernel/hal/intsupport.asm
new file mode 100644 (file)
index 0000000..3d1fcc8
--- /dev/null
@@ -0,0 +1,326 @@
+[BITS 32]
+
+FIRST_EXTERNAL_INT equ 0x30
+LAST_EXTERNAL_INT equ 0x30+15
+        
+GLOBAL HalInterruptLoadIDTR
+GLOBAL HalInterruptGenericHandler
+GLOBAL HalInterruptHandlerPreamble
+GLOBAL HalInterruptHandlerPreambleBefore
+GLOBAL HalInterruptHandlerPreambleAfter
+GLOBAL HalInterruptInitializePICs
+GLOBAL HalIoDelay
+        
+EXTERN g_InterruptHandlerTable
+EXTERN HalVideoPrint
+EXTERN HalInterruptSendIrqEoi
+                
+;;  Save registers prior to calling a handler function.
+;;  This must be kept up to date with:
+;;    - Interrupt_State struct in int.h
+;;    - Setup_Initial_Thread_Context() in kthread.c
+%macro SAVE_REGISTERS 0
+        push eax
+        push ebx
+        push ecx
+        push edx
+        push esi
+        push edi
+        push ebp
+        push ds
+        push es
+        push fs
+        push gs
+%endmacro
+
+;;  Restore registers and clean up the stack after calling a handler function
+;;  (i.e., just before we return from the interrupt via an iret instruction).
+%macro RESTORE_REGISTERS 0
+        pop gs
+        pop fs
+        pop es
+        pop ds
+        pop ebp
+        pop edi
+        pop esi
+        pop edx
+        pop ecx
+        pop ebx
+        pop eax
+        add esp, 8
+%endmacro
+
+%macro INT_NO_ERROR 1
+align 8
+        push 0xffffffff         ; fake the error code
+        push %1                 ; push the int number
+        jmp HalInterruptGenericHandler; 
+%endmacro
+
+%macro INT_WITH_ERROR 1
+align 8
+        push %1                 ; error code already pushed, just push int num
+        jmp HalInterruptGenericHandler
+%endmacro
+        
+[SECTION .text]
+;;;
+;;; void
+;;; InterruptLoadIDTR(IDT *p)
+;;; 
+;;; Function to load the interrupt descriptor table register (IDTR)
+;;; callable from C.
+;;; 
+HalInterruptLoadIDTR:
+        mov eax, [esp+4]        ; p
+        lidt [eax]
+        ret
+
+;;;
+;;; The following is code to initialize the master and slave 8259 
+;;; programmable interrupt controllers (PICs).
+;;;
+;;; For ISA machines there are two 8259's, a master and a slave.  Each has
+;;; eight interrupt request (IR) pins and one interrupt (INT) pin.  The
+;;; master's INT pin is tied to the INT line of the microprocessor.  The
+;;; slave's INT pin is tied to the master's IR2 line.  Thus the master's
+;;; IR0, IR1, and IR3..7 are real devices.  But the master's IR2 means
+;;; that some IR pin on the slave is asserted.  So the system IRQs are: 
+;;;
+;;;    (highest default priority)
+;;;    IRQ0 = master IR0 [IRQ0 = system timer]
+;;;    IRQ1 = master IR1 [IRQ1 = keyboard]
+;;;    IRQ2 = master IR2 --> IRQ8..IRQ15 = slave IR0..7
+;;;                          [IRQ8 = rt. timer][IRQ13 = coproc.]
+;;;    IRQ3 = master IR3
+;;;    IRQ4 = master IR4
+;;;    IRQ5 = master IR5
+;;;    IRQ6 = master IR6
+;;;    IRQ7 = master IR7
+;;;    (lowest default priority)
+;;;
+;;; By default these IRQs raise the following interrupt numbers:
+;;;
+;;;    IRQ0   = int 0x8     [collides with double exception]
+;;;    IRQ1   = int 0x9     [collides with coprocessor exception]
+;;;    IRQ2/9 = int 0x71
+;;;    IRQ3   = int 0xb     [collides with segment not present exception]
+;;;    IRQ4   = int 0xc     [collides with stack fault exception]
+;;;    IRQ5   = int 0xd     [collides with general protection exception]
+;;;    IRQ6   = int 0xe     [collides with page fault]
+;;;    IRQ7   = int 0xf
+;;;    IRQ8   = int 0x70
+;;;    IRQ10  = int 0x72
+;;;    IRQ11  = int 0x73
+;;;    IRQ12  = int 0x74
+;;;    IRQ13  = int 0x75
+;;;    IRQ14  = int 0x76
+;;;    IRQ15  = int 0x77
+;;; 
+;;; So the problem is that IRQ0, IRQ1, IRQ3..6 all, by default, map to
+;;; interrupt numbers that collide with interrupts raised by the cpu
+;;; as a result of a software exception.  The solution to this problem 
+;;; is to remap what interrupts are raised by these IRQs by reprogramming
+;;; the 8259 PICs to raise new interrupt numbers.
+;;;
+;;; This is accomplished by sending initialization command words (ICWs)
+;;; to I/O ports 0x20-0x21 (master PIC) and 0xA0-0xA1 (slave PIC).  By doing
+;;; so we can remap the interrupt numbers raised by IRQs so that:
+;;;
+;;;    IRQ0   = 0x30       IRQ8  = 0x38
+;;;    IRQ1   = 0x31       IRQ10 = 0x3A
+;;;    IRQ2/9 = 0x39       IRQ11 = 0x3B
+;;;    IRQ3   = 0x33       IRQ12 = 0x3C
+;;;    IRQ4   = 0x34       IRQ13 = 0x3D
+;;;    IRQ5   = 0x35       IRQ14 = 0x3E
+;;;    IRQ6   = 0x36       IRQ15 = 0x3F
+;;;    IRQ7   = 0x37
+;;;
+;;; ICW1 is the same for both the master and slave PIC.  Here's the meaning
+;;; of the individual bits in the word:
+;;; 
+;;;   F  E  D  C  B  A  9  8  |  7  6  5  4  3  2  1  0
+;;;              (not used)               |  |  |  |  |__ 1=expect ICW4
+;;;                                       |  |  |  |_____ 0=cascade 1=single
+;;;                                       |  |  |________ 0=interval-4, 1=8
+;;;                                       |  |___________ 0=edge triggered
+;;;                                       |               1=level triggered
+;;;                                       |______________ must be 1
+;;; 
+;;;
+BOTH_ICW1 equ 0x11              ; expect ICW4, cascade mode, call address
+                                ; interval=8, edge triggered mode
+
+;;;
+;;; ICW2 tells the PICs their base interrupt number.  For example, the
+;;; default base interrupt for the master PIC is 0x8.  Thus IRQ0=0x8,
+;;; IRQ1=0x9 ... IRQ7=0xF.  As stated, we want to relocate these.
+;;;
+MASTER_ICW2 equ 0x30            ; use ints 0x30..0x37
+SLAVE_ICW2 equ 0x38             ; use ints 0x38..0x3F
+
+;;;
+;;; ICW3 to the master tells it which of its IR pins is connected to the
+;;; slave PIC.  ICW3 to the slave tells its id number.
+;;;
+MASTER_ICW3 equ 0x04            ; slave on IR pin 2
+SLAVE_ICW3 equ 0x02             ; slave id=2
+
+;;;
+;;; ICW4 to both PICs is another bitvector to set some features:
+;;;
+;;; 
+;;;   F  E  D  C  B  A  9  8  |  7  6  5  4  3  2  1  0
+;;;              (not used)               |  ----  |  |__ 0=MCS80/85 1=8086/88 
+;;;                                       |    |   |_____ 0=normal 1=auto EOI
+;;;                                       |    |_________ 00=non-buf mode
+;;;                                       |               10=buf mode, slave
+;;;                                       |               11=buf mode, master
+;;;                                       |______________ 0=!nested 1=nested
+;;; 
+BOTH_ICW4 equ 0x01
+
+HalInterruptInitializePICs:
+        mov    al, BOTH_ICW1
+        out    0x20, al            ; ICW1 to master PIC
+        call HalIoDelay
+        out    0xA0, al            ; ICW1 to slave PIC
+        call HalIoDelay
+        
+        mov    al, MASTER_ICW2
+        out    0x21, al            ; ICW2 to master PIC
+        call HalIoDelay
+        mov    al, SLAVE_ICW2      
+        out    0xA1, al            ; ICW2 to slave PIC
+        call HalIoDelay
+        
+        mov    al, MASTER_ICW3
+        out    0x21, al            ; ICW3 to master PIC
+        call HalIoDelay
+        mov    al, SLAVE_ICW3
+        out    0xA1, al            ; ICW3 to slave PIC
+        call HalIoDelay
+        
+        mov    al, BOTH_ICW4
+        out    0x21, al            ; ICW4 to master PIC
+        call HalIoDelay
+        out    0xA1, al            ; ICW4 to slave PIC
+        call HalIoDelay
+
+;;;
+;;; After the four ICW sequence has been completed any subsequent writes
+;;; to port 0x21 or 0xA1 set the IRQ mask for the master/slave PIC.  If
+;;; this mask is 0xFF all IRQs are disabled.  If this mask is 0x00
+;;; all IRQs are enabled.
+;;; 
+        mov    al, 0xff            ; slave PIC cannot interrupt
+        out    0xA1, al
+        call HalIoDelay
+        mov    al, 0xfb            ; mask all IRQs but 2 (the slave PIC) in master
+        out    0x21, al
+        call HalIoDelay
+        ret
+
+;;;
+;;; When doing I/O operations this routine can be used to "delay" long
+;;; enough to let the external controller keep up with the cpu.
+;;;
+HalIoDelay:
+        jmp    .done
+.done: ret
+
+;;;
+;;; This is the start of the main interrupt handler code.  The first section
+;;; of this code is called the InterruptHandlerPreamble.  It consists of
+;;; 256 entry points in a table (one per possible interrupt number).  These
+;;; preamble entry points push the interrupt number and (when needed for
+;;; interrupt numbers that the processor doesn't automatically push an error
+;;; code for) a fake error code.  Then they jump to the main generic interrupt
+;;; handling routing: InterruptGenericHandler.  Thus the stack is always layed
+;;; out in the same way when control passes to the generic handler:
+;;;
+;;;          saved ss             (pushed by cpu for system calls)
+;;;          saved esp            (pushed by cpu for system calls)
+;;;          ------------
+;;;          saved eflags         (pushed by cpu)
+;;;          saved CS             (pushed by cpu)
+;;;          saved IP             (pushed by cpu)
+;;;          error code           (pushed by preamble or cpu)
+;;;          interrupt number     (pushed by preamble)
+;;; esp -->  return address       (pushed by jmp InteruptGenericHandler)
+;;;
+;;; The first thing InterruptGenericHandler does is push the rest of the
+;;; registers onto the stack.
+;;; 
+align 8
+HalInterruptHandlerPreamble:
+HalInterruptHandlerPreambleBefore: 
+        INT_NO_ERROR    0
+        align 8
+HalInterruptHandlerPreambleAfter:  
+        INT_NO_ERROR    1
+        INT_NO_ERROR    2
+        INT_NO_ERROR    3
+        INT_NO_ERROR    4
+        INT_NO_ERROR    5
+        INT_NO_ERROR    6
+        INT_NO_ERROR    7
+        INT_WITH_ERROR  8
+        INT_NO_ERROR    9
+        INT_WITH_ERROR  10
+        INT_WITH_ERROR  11
+        INT_WITH_ERROR  12
+        INT_WITH_ERROR  13
+        INT_WITH_ERROR  14
+        INT_NO_ERROR    15
+        INT_NO_ERROR    16
+        INT_WITH_ERROR  17
+
+;;;
+;;; The rest of the interrupt numbers are INT_NO_ERRORs.  Use nasm's
+;;; %rep command to do them all at once.
+;;; 
+%assign intNum 18
+%rep (256 - 18)
+        INT_NO_ERROR    intNum
+%assign intNum intNum + 1
+%endrep
+    
+;;;
+;;; This is the generic interrupt handler which is called by the preambles
+;;; above.  It's job is to save the registers on the stack and then transfer
+;;; control to a specific per-interrupt handler.  It finds the address of
+;;; the per-interrupt handler to call by indexing into g_InterruptHandlerTable
+;;; 
+align 8
+HalInterruptGenericHandler:
+        SAVE_REGISTERS
+
+        ;; Ensure that we're using the kernel data segment
+        mov ax, (2<<3)
+        mov ds, ax
+        mov es, ax
+        mov fs, ax
+        mov gs, ax
+
+        ;; Get interrupt number the preamble pushed for us
+        mov esi, [esp+44]
+
+        ;; Get the address of the handler function from the
+        ;; table of handler functions.
+        mov eax, g_InterruptHandlerTable
+        mov ebx, [eax+esi*4]
+
+        ;; Call the handler.  The argument passed is a pointer to
+        ;; INTERRUPT_STATE.  Interrupts are enabled at this point
+        ;; so if the handler is non-reentrant it must disable them.
+        push esp
+        call ebx
+        add esp, 4
+
+        push esp
+        call HalInterruptSendIrqEoi
+        add esp, 4
+
+        RESTORE_REGISTERS
+        iret
diff --git a/kernel/hal/io.c b/kernel/hal/io.c
new file mode 100644 (file)
index 0000000..d97a211
--- /dev/null
@@ -0,0 +1,40 @@
+#include "kernel.h"
+
+// Write a byte to an I/O port.
+void 
+out(WORD port, BYTE value )
+{
+    __asm__ __volatile__ (
+       "outb %b0, %w1"
+       :
+       : "a" (value), "Nd" (port)
+    );
+}
+
+// Read a byte from an I/O port.
+BYTE 
+in(WORD port)
+{
+    BYTE value;
+
+    __asm__ __volatile__ (
+       "inb %w1, %b0"
+       : "=a" (value)
+       : "Nd" (port)
+    );
+
+    return value;
+}
+
+// Short delay.  May be needed when talking to some
+// (slow) I/O devices.
+void 
+iodelay(void)
+{
+    BYTE value = 0;
+    __asm__ __volatile__ (
+       "outb %0, $0x80"
+       :
+       : "a" (value)
+    );
+}
diff --git a/kernel/hal/timer.c b/kernel/hal/timer.c
new file mode 100644 (file)
index 0000000..3c82691
--- /dev/null
@@ -0,0 +1,43 @@
+//+----------------------------------------------------------------------------
+//
+// File:     timer.c
+//
+// Module:   
+//
+// Synopsis: 
+//
+// Created:  sgasch  21 Oct 2003
+//
+//+----------------------------------------------------------------------------
+
+#include "kernel.h"
+#include "hal.h"
+#include "rtl.h"
+#include "interrupts.h"
+
+void
+HalTimerInt(INTERRUPT_STATE *is)
+{
+    static CHAR whee[] = "|/-\\\0";
+    static ULONG u = 0;
+    static BYTE b = 0;
+    static unsigned int foo;
+    BYTE *p = (BYTE *)0x000B8000;
+
+    out(0x61, 0x80);
+    u++;
+
+    CURRENT_STAMP(&foo);
+
+    if ((u % 500) == 0)
+    {
+        b++;
+        if (whee[b] == '\0')
+        {
+            b = 0;
+        }
+        *(p + 158) = whee[b];
+        *(p + 159) = ' ';
+    }
+}
+
diff --git a/kernel/hal/timestamp.asm b/kernel/hal/timestamp.asm
new file mode 100644 (file)
index 0000000..b56bedb
--- /dev/null
@@ -0,0 +1,19 @@
+
+        [BITS 32]
+
+GLOBAL HalReadTimestampCounter
+EXTERN g_ullTimeStampCounter        
+        
+[SECTION .text]
+;;;
+;;; ULONGLONG
+;;; HalReadTimestampCounter(void)
+;;; 
+;;; Function to read the processor's timestamp counter
+;;;
+HalReadTimestampCounter:
+        ALIGN 4
+        rdtsc
+        mov [g_ullTimeStampCounter], edx
+        mov [g_ullTimeStampCounter+4], eax
+        ret
diff --git a/kernel/hal/video.h b/kernel/hal/video.h
new file mode 100644 (file)
index 0000000..dcd7b01
--- /dev/null
@@ -0,0 +1,15 @@
+//+----------------------------------------------------------------------------
+//
+// File:     video.h
+//
+// Module:   
+//
+// Synopsis: 
+//
+// Created:  sgasch  5 Jul 2003
+//
+//+----------------------------------------------------------------------------
+#ifndef VIDEO_H
+#define VIDEO_H
+
+#endif // VIDEO_H
diff --git a/kernel/inc/constants.h b/kernel/inc/constants.h
new file mode 100644 (file)
index 0000000..13f47bd
--- /dev/null
@@ -0,0 +1,50 @@
+//+----------------------------------------------------------------------------
+//
+// File:     constants.h
+//
+// Module:   
+//
+// Synopsis: 
+//
+// Copyright (C) 2003 
+//
+// Created:  sgasch  10 Oct 2003
+//
+//+----------------------------------------------------------------------------
+
+#ifndef _CONSTANTS_H_
+#define _CONSTANTS_H_
+
+//
+// Constants
+// 
+#define YES                               (1)
+#define NO                                (0)
+#ifndef TRUE
+#define TRUE                          (YES)
+#endif
+#ifndef FALSE
+#define FALSE                         (NO)
+#endif
+
+#define NULL                       ((void *)0)
+
+#define ASCII_ESC        (0x1B)
+#define ASCII_BS         (0x08)
+
+#define USER_PRIVILEGE   (3)
+#define KERNEL_PRIVILEGE (0)
+
+//
+// Device driver constants
+//
+#define DEVICE_DRIVER_INITIALIZATION (1)
+#define DEVICE_IO_CONTROL            (2)
+#define DEVICE_READ                  (3)
+#define DEVICE_WRITE                 (4)
+#define DEVICE_DETATCH               (6)
+#define DEVICE_DRIVER_SHUTDOWN       (7)
+#endif /* _CONSTANTS_H_ */
+
+
diff --git a/kernel/inc/hal.h b/kernel/inc/hal.h
new file mode 100644 (file)
index 0000000..9a52a4e
--- /dev/null
@@ -0,0 +1,104 @@
+//+----------------------------------------------------------------------------
+//
+// File:     hal.h
+//
+// Module:   
+//
+// Synopsis: 
+//
+// Created:  sgasch  5 Jul 2003
+//
+//+----------------------------------------------------------------------------
+#ifndef HAL_H
+#define HAL_H
+
+//
+// Video/CRT driver
+//
+#define BLACK         (0)
+#define BLUE          (1)
+#define GREEN         (2)
+#define CYAN          (3)
+#define RED           (4)
+#define MAGENTA       (5)
+#define YELLOW        (6)
+#define GRAY          (7)
+#define HIGH          (8)
+#define WHITE         (HIGH | GRAY)
+
+void
+HalVideoSetCurrentColorAttribute(BYTE bFg, BYTE bBg);
+
+void
+HalVideoClearScreen(void);
+
+void
+HalVideoGetCursorPosition(BYTE *pbLine, BYTE *pbCol);
+
+void
+HalVideoSetCursorPosition(BYTE bLine, BYTE bCol);
+
+void
+HalVideoPutNullTerminatedString(BYTE *s);
+
+void
+HalVideoInitialize(BIOS_HARDWARE_BLOCK *phw);
+
+void 
+HalVideoPrint(CHAR *szFormat, ...);
+
+//
+// Keyboard driver
+//
+#define KB_IRQ          (1)
+typedef WORD KEYCODE;
+
+typedef struct _INTERRUPT_STATE
+{
+    // The register contents at the time of the exception.
+    // We save these explicitly.
+    ULONG gs;
+    ULONG fs;
+    ULONG es;
+    ULONG ds;
+    ULONG ebp;
+    ULONG edi; 
+    ULONG esi;
+    ULONG edx;
+    ULONG ecx; 
+    ULONG ebx;
+    ULONG eax;
+
+    // We explicitly push the interrupt number.
+    // This makes it easy for the handler function to determine
+    // which interrupt occurred.
+    ULONG uIntNum;
+
+    // This may be pushed by the processor; if not, we push
+    // a dummy error code, so the stack layout is the same
+    // for every type of interrupt.
+    ULONG uErrorCode;
+
+    // These are always pushed on the stack by the processor.
+    ULONG eip;
+    ULONG cs;
+    ULONG eflags;
+}
+INTERRUPT_STATE;
+
+typedef void (*INTERRUPT_HANDLER)(INTERRUPT_STATE *pState);
+
+void HalInitializeInterrupts(void);
+void HalInterruptInstallHandler(ULONG uIntNum, INTERRUPT_HANDLER p);
+void HalInterruptDisable();
+void HalInterruptEnable();
+
+void HalIoDelay();
+
+void HalTimerInt(INTERRUPT_STATE *p);
+void HalKeyboardInt(INTERRUPT_STATE *p);
+
+extern UINT64 g_ullTimeStampCounter;
+ULONG HalReadTimestampCounter(void);
+
+#endif // HAL_H
diff --git a/kernel/inc/kernel.h b/kernel/inc/kernel.h
new file mode 100644 (file)
index 0000000..7172401
--- /dev/null
@@ -0,0 +1,43 @@
+//+----------------------------------------------------------------------------
+//
+// File:     kernel.h
+//
+// Module:   
+//
+// Synopsis: 
+//
+// Created:  sgasch  5 Jul 2003
+//
+//+----------------------------------------------------------------------------
+
+#ifndef _KERNEL_H_
+#define _KERNEL_H_
+
+#include "types.h"
+#include "constants.h"
+#include "macros.h"
+
+//
+// Shared data structures
+//
+typedef struct _BIOS_HARDWARE_BLOCK
+{
+    BYTE bDisplayType;
+    BYTE bFontSize;
+    WORD wEquipmentBitvector;
+    WORD wMemorySize;
+    WORD wSystemClock;
+}
+BIOS_HARDWARE_BLOCK;
+
+// Write a byte to an I/O port.
+void
+out(WORD port, BYTE value);
+
+BYTE
+in(WORD port);
+
+void
+iodelay(void);
+
+#endif /* _KERNEL_H_ */
diff --git a/kernel/inc/macros.h b/kernel/inc/macros.h
new file mode 100644 (file)
index 0000000..21340ad
--- /dev/null
@@ -0,0 +1,43 @@
+//+----------------------------------------------------------------------------
+//
+// File:     macros.h
+//
+// Module:   
+//
+// Synopsis: 
+//
+// Copyright (C) 2003 
+//
+// Created:  sgasch  10 Oct 2003
+//
+//+----------------------------------------------------------------------------
+
+#ifndef _MACROS_H_
+#define _MACROS_H_
+
+//
+// Macros
+//
+#define ARRAY_LENGTH(a)            (sizeof((a)) / sizeof((a)[0]))
+#define MIN(x, y)                  (((x) < (y)) ? (x) : (y))
+#define MAX(x, y)                  (((x) > (y)) ? (x) : (y))
+
+#if 1
+void _assert(CHAR *, CHAR *, ULONG);
+void VideoPrint(CHAR *, ...);
+#define ASSERT(x)                  if (x)    \
+                                   { ; }     \
+                                   else      \
+                                   { _assert(__FUNCTION__ , \
+                                             __FILE__ , \
+                                             __LINE__); }
+#define TRACE(f, ...)              VideoPrint("%s:%u> " ##f , __FUNCTION__ , \
+                                              __LINE__ , ##__VA_ARGS__)
+#else
+#define ASSERT(x)                     ;
+#define TRACE(f, ...)              ;
+#endif // DEBUG
+
+#define CURRENT_STAMP(a)           asm volatile("rdtsc" : "=a"(((unsigned int *)(a))[0]), "=d"(((unsigned int *)a)[1]))
+
+#endif /* _MACROS_H_ */
diff --git a/kernel/inc/rtl.h b/kernel/inc/rtl.h
new file mode 100644 (file)
index 0000000..3aff129
--- /dev/null
@@ -0,0 +1,33 @@
+//+----------------------------------------------------------------------------
+//
+// File:     rtl.h
+//
+// Module:   
+//
+// Synopsis: 
+//
+// Copyright (C) 2003 Scott Gasch
+//
+// Created:  sgasch  5 Jul 2003
+//
+//+----------------------------------------------------------------------------
+
+#ifndef _RTL_H_
+#define _RTL_H_
+
+void 
+RtlSetMemory(void *pStart, 
+             BYTE bFill,
+             ULONG uLength);
+
+CHAR *
+RtlIntToAscii(INT i,
+              CHAR *buf,
+              ULONG uBufLen,
+              ULONG uBase);
+
+#endif /* _RTL_H_ */
+
+
+
+
diff --git a/kernel/inc/types.h b/kernel/inc/types.h
new file mode 100644 (file)
index 0000000..b3379e5
--- /dev/null
@@ -0,0 +1,80 @@
+//+----------------------------------------------------------------------------
+//
+// File:     types.h
+//
+// Module:   
+//
+// Synopsis: 
+//
+// Created:  sgasch  10 Oct 2003
+//
+//+----------------------------------------------------------------------------
+
+#ifndef _TYPES_H_
+#define _TYPES_H_
+
+//
+// Datatype wrappers
+// 
+#define MIN_CHAR                   (0x80)
+#define MAX_CHAR                   (0x7f)
+typedef char                       CHAR;
+
+#define MIN_BYTE                   (0x00)
+#define MAX_BYTE                   (0xff)
+typedef unsigned char              BYTE;
+
+#define MIN_UCHAR                  (0x00)
+#define MAX_UCHAR                  (0xff)
+typedef unsigned char              UCHAR;
+
+#define MIN_SHORT                  (0x8000)
+#define MAX_SHORT                  (0x7fff)
+typedef signed short               SHORT;
+
+#define MIN_USHORT                 (0x0000)
+#define MAX_USHORT                 (0xffff)
+typedef unsigned short             USHORT;
+
+#define MIN_WORD                   (0x0000)
+#define MAX_WORD                   (0xffff)
+typedef unsigned short             WORD;
+
+#define MIN_INT                    (0x80000000)
+#define MAX_INT                    (0x7fffffff)
+typedef signed int                 INT;
+
+#define MIN_UINT                   (0x00000000)
+#define MAX_UINT                   (0xffffffff)
+typedef unsigned int               UINT;
+
+#define MIN_LONG                   (0x80000000)
+#define MAX_LONG                   (0x7fffffff)
+typedef signed int                 LONG;
+
+#define MIN_ULONG                  (0x00000000)
+#define MAX_ULONG                  (0xffffffff)
+typedef unsigned long              ULONG;
+
+#define MIN_INT64                  (0x8000000000000000)
+#define MAX_INT64                  (0x7fffffffffffffff)
+typedef signed long long           INT64;
+
+#define MIN_UINT64                 (0x0000000000000000)
+#define MAX_UINT64                 (0xffffffffffffffff)
+typedef unsigned long long         UINT64;
+
+#define MIN_BITV                   MIN_UINT
+#define MAX_BITV                   MAX_UINT
+typedef unsigned int               BITV;
+
+#define MIN_BOOL                   MIN_UCHAR
+#define MAX_BOOL                   MAX_UCHAR
+typedef unsigned char              BOOL;
+
+typedef unsigned int               STATUS;
+#define STATUS_SUCCESS             (0)
+
+#define SIZE_T                     ULONG
+
+#endif /* _TYPES_H_ */
diff --git a/kernel/init/Makefile b/kernel/init/Makefile
new file mode 100644 (file)
index 0000000..815dc69
--- /dev/null
@@ -0,0 +1,20 @@
+CC=                    gcc
+CFLAGS=                -Wall -imacros ../defines -I../inc
+OBJS=                  main.o entry.o
+RM=                    /bin/rm
+NASM=                  nasm
+NASMFLAGS=             -f elf
+
+.SUFFIXES: .c .asm .o
+
+all: $(OBJS)
+
+.c.o:
+       $(CC) $(CFLAGS) -c $<
+
+.asm.o:
+       $(NASM) $(NASMFLAGS) -o $*.o $<
+
+clean:
+       $(RM) -f $(OBJS) *~ #*# .#*
+
diff --git a/kernel/init/entry.asm b/kernel/init/entry.asm
new file mode 100644 (file)
index 0000000..afb0434
--- /dev/null
@@ -0,0 +1,23 @@
+[BITS 32]
+
+EXTERN KernelEntry
+GLOBAL StartOfKernelImage
+GLOBAL IdleLoop
+                
+;;; 
+;;; I put "entry.o" first in line at the linker so I am sure this function
+;;; gets put first in the kernel image.  This is good because:
+;;;
+;;;     1. We know there is valid code at 0x00010000 when we jump here
+;;;     2. We can use the address of this function as the start of image
+;;;     3. We don't have to make sure main (or KernelEntry or whatever) 
+;;;        is always the first function in main.c
+;;; 
+StartOfKernelImage:
+        jmp KernelEntry
+        ret
+
+IdleLoop:
+        sti
+        hlt
+        jmp IdleLoop
diff --git a/kernel/init/main.c b/kernel/init/main.c
new file mode 100644 (file)
index 0000000..22fd14a
--- /dev/null
@@ -0,0 +1,67 @@
+//+----------------------------------------------------------------------------
+//
+// File:     main.c
+//
+// Module:   
+//
+// Synopsis: 
+//
+// Created:  sgasch  4 Jul 2003
+//
+//+----------------------------------------------------------------------------
+
+#include "kernel.h"
+#include "hal.h"
+#include "rtl.h"
+
+extern char __bss_start;
+extern char end;
+
+void
+ZeroBSS(void)
+{
+    BYTE *pBssStart, *pBssEnd;
+
+    pBssStart = &__bss_start;
+    pBssEnd = &end;
+
+    // Fill .bss section with zero
+    RtlSetMemory((void *)pBssStart, '\0', (pBssEnd - pBssStart));
+}
+
+void
+_assert(CHAR *szFunction, CHAR *szFile, ULONG uLine)
+{
+    HalVideoSetCursorPosition(0, 0);
+    HalVideoPrint("ASSERTION in %s at %s line %u.\n",
+               szFunction, szFile, uLine);
+    while(1)
+    {
+        ;
+    }
+}
+
+//
+// Entry point of the kernel.  Not called main because I don't care to 
+// listen to gcc's warnings about argc and argv anymore.
+//
+int
+KernelEntry(BIOS_HARDWARE_BLOCK *phw)
+{
+    ZeroBSS();
+
+    HalVideoInitialize(phw);
+    HalInitializeInterrupts();
+
+    HalVideoPrint("Interrupts initialized.\n");
+    
+ hang:
+    HalReadTimestampCounter();
+    HalVideoPrint("Timestamp Counter: %u%u\n", 
+                  ((g_ullTimeStampCounter >> 32) & 0xffffffff),
+                  (g_ullTimeStampCounter & 0xffffffff));
+    goto hang;
+
+    return(-1);
+}
+
diff --git a/kernel/kernel.bin b/kernel/kernel.bin
new file mode 100755 (executable)
index 0000000..d6b13b4
Binary files /dev/null and b/kernel/kernel.bin differ
diff --git a/kernel/kernel.map b/kernel/kernel.map
new file mode 100644 (file)
index 0000000..2d15ed2
--- /dev/null
@@ -0,0 +1,370 @@
+
+Allocating common symbols
+Common symbol       size              file
+
+g_IDT               0x800             hal/interrupts.o
+g_InterruptHandlerTable
+                    0x400             hal/interrupts.o
+
+Memory Configuration
+
+Name             Origin             Length             Attributes
+*default*        0x00000000         0xffffffff
+
+Linker script and memory map
+
+Address of section .text set to 0x10000
+LOAD init/entry.o
+LOAD init/main.o
+LOAD hal/video.o
+LOAD hal/io.o
+LOAD rtl/string.o
+LOAD rtl/memory.o
+LOAD hal/intsupport.o
+LOAD hal/interrupts.o
+LOAD hal/timer.o
+LOAD hal/keyboard.o
+LOAD hal/timestamp.o
+LOAD hal/counters.o
+                0x08048074                . = (0x8048000 +  SIZEOF_HEADERS )
+
+.interp
+ *(.interp)
+
+.hash
+ *(.hash)
+
+.dynsym
+ *(.dynsym)
+
+.dynstr
+ *(.dynstr)
+
+.gnu.version
+ *(.gnu.version)
+
+.gnu.version_d
+ *(.gnu.version_d)
+
+.gnu.version_r
+ *(.gnu.version_r)
+
+.rel.init
+ *(.rel.init)
+
+.rela.init
+ *(.rela.init)
+
+.rel.text       0x08048074        0x0
+ *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
+
+.rela.text
+ *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+
+.rel.fini
+ *(.rel.fini)
+
+.rela.fini
+ *(.rela.fini)
+
+.rel.rodata
+ *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
+
+.rela.rodata
+ *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+
+.rel.data
+ *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
+
+.rela.data
+ *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+
+.rel.ctors
+ *(.rel.ctors)
+
+.rela.ctors
+ *(.rela.ctors)
+
+.rel.dtors
+ *(.rel.dtors)
+
+.rela.dtors
+ *(.rela.dtors)
+
+.rel.got
+ *(.rel.got)
+
+.rela.got
+ *(.rela.got)
+
+.rel.bss
+ *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
+
+.rela.bss
+ *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+
+.rel.plt
+ *(.rel.plt)
+
+.rela.plt
+ *(.rela.plt)
+
+.init
+ *(.init)
+
+.plt
+ *(.plt)
+
+.text           0x00010000     0x20b0
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ .text          0x00010000        0xa init/entry.o
+                0x00010000                StartOfKernelImage
+                0x00010006                IdleLoop
+ *fill*         0x0001000a        0x2 2425393296
+ .text          0x0001000c      0x104 init/main.o
+                0x0001003c                _assert
+                0x00010078                KernelEntry
+                0x0001000c                ZeroBSS
+ .text          0x00010110      0x814 hal/video.o
+                0x000105cc                HalVideoGetCursorPosition
+                0x00010110                HalVideoSetHardwareCursor
+                0x000106b0                HalVideoPrint
+                0x00010298                HalVideoClearScreen
+                0x0001051c                HalVideoPutNullTerminatedString
+                0x00010260                HalVideoSetCurrentColorAttribute
+                0x0001032c                HalVideoScroll
+                0x00010578                HalVideoSetCursorPosition
+                0x0001044c                HalVideoPutChar
+                0x000105e8                HalVideoInitialize
+ .text          0x00010924       0x58 hal/io.o
+                0x00010944                in
+                0x00010924                out
+                0x00010968                iodelay
+ .text          0x0001097c      0x220 rtl/string.o
+                0x00010a10                RtlIntToAscii
+                0x0001097c                strncpy
+                0x000109e0                strlen
+ .text          0x00010b9c       0x34 rtl/memory.o
+                0x00010b9c                RtlSetMemory
+ .text          0x00010bd0     0x10b6 hal/intsupport.o
+                0x00011c38                HalInterruptGenericHandler
+                0x00010bd8                HalInterruptInitializePICs
+                0x00010bd0                HalInterruptLoadIDTR
+                0x00010c38                HalInterruptHandlerPreamble
+                0x00010c2f                HalIoDelay
+                0x00010c48                HalInterruptHandlerPreambleAfter
+                0x00010c38                HalInterruptHandlerPreambleBefore
+ *fill*         0x00011c86        0x2 2425393296
+ .text          0x00011c88      0x2f4 hal/interrupts.o
+                0x00011cbc                HalDisableInterrupts
+                0x00011e80                HalInitializeInterrupts
+                0x00011cf8                HalInterruptSendIrqEoi
+                0x00011cf0                HalDoNothing
+                0x00011dd8                HalInterruptInitializeGate
+                0x00011c88                HalEnableInterrupts
+                0x00011e38                HalInterruptInstallHandler
+ .text          0x00011f7c       0xbc hal/timer.o
+                0x00011f7c                HalTimerInt
+ .text          0x00012038       0x5c hal/keyboard.o
+                0x00012038                HalKeyboardInt
+ *fill*         0x00012094        0xc 2425393296
+ .text          0x000120a0        0xe hal/timestamp.o
+                0x000120a0                HalReadTimestampCounter
+ *fill*         0x000120ae        0x2 2425393296
+ *(.gnu.warning)
+
+.fini
+ *(.fini)
+                0x000120b0                PROVIDE (__etext, .)
+                0x000120b0                PROVIDE (_etext, .)
+                0x000120b0                PROVIDE (etext, .)
+
+.rodata         0x000120c0      0x246
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ .rodata        0x000120c0       0x60 init/main.o
+ .rodata        0x00012120      0x156 hal/video.o
+ *fill*         0x00012276        0x2
+ .rodata        0x00012278       0x18 rtl/string.o
+ .rodata        0x00012290       0x68 hal/interrupts.o
+ .rodata        0x000122f8        0xe hal/keyboard.o
+
+.rodata1
+ *(.rodata1)
+
+.eh_frame_hdr
+ *(.eh_frame_hdr)
+                0x00013306                . = ( ALIGN (0x1000) + (. & 0xfff))
+                0x00012308                . =  ALIGN (0x4)
+                0x00012306                PROVIDE (__preinit_array_start, .)
+
+.preinit_array
+ *(.preinit_array)
+                0x00012306                PROVIDE (__preinit_array_end, .)
+                0x00012306                PROVIDE (__init_array_start, .)
+
+.init_array
+ *(.init_array)
+                0x00012306                PROVIDE (__init_array_end, .)
+                0x00012306                PROVIDE (__fini_array_start, .)
+
+.fini_array
+ *(.fini_array)
+                0x00012306                PROVIDE (__fini_array_end, .)
+
+.data           0x00013308       0xc4
+ *(.data .data.* .gnu.linkonce.d.*)
+ .data          0x00013308       0xa8 hal/video.o
+                0x0001330e                g_bSoftCursor
+                0x00013308                g_pVideoMemory
+                0x0001330c                g_bScreenResolution
+                0x00013310                g_bColorAttribute
+ .data          0x000133b0        0x4 hal/interrupts.o
+                0x000133b0                g_uInterruptsEnabled
+ .data          0x000133b4       0x10 hal/timer.o
+ .data          0x000133c4        0x8 hal/counters.o
+                0x000133c4                g_ullTimeStampCounter
+
+.data1
+ *(.data1)
+
+.eh_frame
+ *(.eh_frame)
+
+.gcc_except_table
+ *(.gcc_except_table)
+
+.dynamic
+ *(.dynamic)
+
+.ctors
+ *crtbegin.o(.ctors)
+ *(EXCLUDE_FILE(*crtend.o) .ctors)
+ *(SORT(.ctors.*))
+ *(.ctors)
+
+.dtors
+ *crtbegin.o(.dtors)
+ *(EXCLUDE_FILE(*crtend.o) .dtors)
+ *(SORT(.dtors.*))
+ *(.dtors)
+
+.jcr
+ *(.jcr)
+
+.got
+ *(.got.plt)
+ *(.got)
+                0x000133cc                _edata = .
+                0x000133cc                PROVIDE (edata, .)
+                0x000133cc                __bss_start = .
+
+.bss            0x000133e0      0xc20
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ .bss           0x000133e0        0x4 hal/timer.o
+ *(COMMON)
+ *fill*         0x000133e4       0x1c
+ COMMON         0x00013400      0xc00 hal/interrupts.o
+                                  0x0 (size before relaxing)
+                0x00013400                g_IDT
+                0x00013c00                g_InterruptHandlerTable
+                0x00014000                . =  ALIGN (0x4)
+                0x00014000                . =  ALIGN (0x4)
+                0x00014000                _end = .
+                0x00014000                PROVIDE (end, .)
+
+.stab
+ *(.stab)
+
+.stabstr
+ *(.stabstr)
+
+.stab.excl
+ *(.stab.excl)
+
+.stab.exclstr
+ *(.stab.exclstr)
+
+.stab.index
+ *(.stab.index)
+
+.stab.indexstr
+ *(.stab.indexstr)
+
+.comment        0x00000000      0x1c5
+ *(.comment)
+ .comment       0x00000000       0x1f init/entry.o
+ .comment       0x0000001f       0x28 init/main.o
+ .comment       0x00000047       0x28 hal/video.o
+ .comment       0x0000006f       0x28 hal/io.o
+ .comment       0x00000097       0x28 rtl/string.o
+ .comment       0x000000bf       0x28 rtl/memory.o
+ .comment       0x000000e7       0x1f hal/intsupport.o
+ .comment       0x00000106       0x28 hal/interrupts.o
+ .comment       0x0000012e       0x28 hal/timer.o
+ .comment       0x00000156       0x28 hal/keyboard.o
+ .comment       0x0000017e       0x1f hal/timestamp.o
+ .comment       0x0000019d       0x28 hal/counters.o
+
+.debug
+ *(.debug)
+
+.line
+ *(.line)
+
+.debug_srcinfo
+ *(.debug_srcinfo)
+
+.debug_sfnames
+ *(.debug_sfnames)
+
+.debug_aranges
+ *(.debug_aranges)
+
+.debug_pubnames
+ *(.debug_pubnames)
+
+.debug_info
+ *(.debug_info .gnu.linkonce.wi.*)
+
+.debug_abbrev
+ *(.debug_abbrev)
+
+.debug_line
+ *(.debug_line)
+
+.debug_frame
+ *(.debug_frame)
+
+.debug_str
+ *(.debug_str)
+
+.debug_loc
+ *(.debug_loc)
+
+.debug_macinfo
+ *(.debug_macinfo)
+
+.debug_weaknames
+ *(.debug_weaknames)
+
+.debug_funcnames
+ *(.debug_funcnames)
+
+.debug_typenames
+ *(.debug_typenames)
+
+.debug_varnames
+ *(.debug_varnames)
+OUTPUT(kernel.tmp elf32-i386)
+
+.note           0x00000000       0xb4
+ .note          0x00000000       0x14 init/main.o
+ .note          0x00000014       0x14 hal/video.o
+ .note          0x00000028       0x14 hal/io.o
+ .note          0x0000003c       0x14 rtl/string.o
+ .note          0x00000050       0x14 rtl/memory.o
+ .note          0x00000064       0x14 hal/interrupts.o
+ .note          0x00000078       0x14 hal/timer.o
+ .note          0x0000008c       0x14 hal/keyboard.o
+ .note          0x000000a0       0x14 hal/counters.o
diff --git a/kernel/rtl/Makefile b/kernel/rtl/Makefile
new file mode 100644 (file)
index 0000000..1767c0a
--- /dev/null
@@ -0,0 +1,19 @@
+CC=                    gcc
+CFLAGS=                -Wall -imacros ../defines -I../inc
+OBJS=                  string.o memory.o
+RM=                    /bin/rm
+NASM=                  nasm
+NASMFLAGS=
+
+.SUFFIXES: .c .o .asm
+
+all: $(OBJS)
+
+.c.o:
+       $(CC) $(CFLAGS) -c $<
+
+.asm.o:
+       $(NASM) $(NASMFLAGS) -o $*.o $<
+
+clean:
+       $(RM) -f $(OBJS) *~ #*# .#*
diff --git a/kernel/rtl/memory.c b/kernel/rtl/memory.c
new file mode 100644 (file)
index 0000000..f4f845e
--- /dev/null
@@ -0,0 +1,29 @@
+//+----------------------------------------------------------------------------
+//
+// File:     memory.c
+//
+// Module:   
+//
+// Synopsis: 
+//
+// Copyright (C) Scott Gasch
+//
+// Created:  sgasch  5 Jul 2003
+//
+//+----------------------------------------------------------------------------
+
+#include "kernel.h"
+
+void 
+RtlSetMemory(void *pStart, 
+             BYTE bFill,
+             ULONG uLength)
+{
+    BYTE *p = (BYTE *)pStart;
+
+    while(uLength > 0)
+    {
+        *p++ = bFill;
+        uLength--;
+    }
+}
diff --git a/kernel/rtl/string.c b/kernel/rtl/string.c
new file mode 100644 (file)
index 0000000..da42000
--- /dev/null
@@ -0,0 +1,138 @@
+//+----------------------------------------------------------------------------
+//
+// File:     string.c
+//
+// Module:   
+//
+// Synopsis: 
+//
+// Copyright (C) 2003 Scott Gasch
+//
+// Created:  sgasch  5 Jul 2003
+//
+//+----------------------------------------------------------------------------
+
+#include "kernel.h"
+
+CHAR *
+strncpy(CHAR *pDest, CHAR *pSrc, SIZE_T u)
+{
+    char *p = pDest;
+    ULONG v = 0;
+
+    while ((v < u) && (*pSrc))
+    {
+        *pDest = *pSrc;
+        pDest++; pSrc++; v++;
+    }
+
+    //
+    // If we ran out of space, null terminate the dest buffer
+    //
+    if ((*pSrc) && (u > 0))
+    {
+        *(pDest - 1) = 0;
+    }
+    
+    return(p);
+}
+
+SIZE_T
+strlen(CHAR *p)
+{
+    ULONG i = 0;
+    while(*p)
+    {
+        i++;
+        p++;
+    }
+    return(i);
+}
+
+CHAR *
+RtlIntToAscii(INT i,
+              CHAR *buf,
+              ULONG uBufLen,
+              ULONG uBase)
+{
+    CHAR *p = (buf + uBufLen);
+    ULONG uSpaceLeft = uBufLen;
+    ULONG uMagnitude;
+    BOOL fNeg = FALSE;
+
+    //
+    // null terminate the workspace buffer
+    //
+    if (uSpaceLeft == 0) 
+    {
+        return(NULL);
+    }
+    *p = '\0';
+    p--;
+    uSpaceLeft--;
+
+    //
+    // Get the int's sign
+    //
+    if (i < 0)
+    {
+        fNeg = TRUE;
+        uMagnitude = -i;
+    }
+    else
+    {
+        uMagnitude = i;
+    }
+    
+    //
+    // Based on base, do the conversion.  Build the string backwards from
+    // less significant digits.  Stop if we finish or if we run out of
+    // uSpaceLeft.
+    //
+    switch(uBase)
+    {
+        case 10:
+            do
+            {
+                *p = (uMagnitude % 10) + '0';
+                p--;
+                uSpaceLeft--;
+                uMagnitude /= 10;
+            } 
+            while((uSpaceLeft > 0) && (uMagnitude != 0));
+            break;
+        case 16:
+            do
+            {
+                *p = "0123456789ABCDEF"[uMagnitude & 15];
+                p--;
+                uSpaceLeft--;
+                uMagnitude >>= 4;
+            } 
+            while((uSpaceLeft > 0) && (uMagnitude != 0));
+            break;
+        case 8:
+            do 
+            {
+                *p = (uMagnitude & 7) + '0';
+                p--;
+                uSpaceLeft--;
+                uMagnitude >>= 3;
+            } 
+            while((uSpaceLeft > 0) && (uMagnitude != 0));
+            break;
+    }
+
+    if (TRUE == fNeg)
+    {
+        if (uSpaceLeft > 0)
+        {
+            *p = '-';
+        }
+    }
+    else
+    {
+        p++;
+    }
+    return(p);
+}