Fixing conflicts.

This commit is contained in:
Alex 2017-06-27 00:11:03 -05:00
commit 25ef17eb6e
101 changed files with 4581 additions and 457 deletions

1
.gitignore vendored
View file

@ -2,3 +2,4 @@ Abraham Silberschatz-Operating System Concepts (9th,2012.12).pdf
DevEnv/
*.o
*.bin
bochsout.txt

View file

@ -1,171 +0,0 @@
00000000000i[ ] Bochs x86 Emulator 2.6.9
00000000000i[ ] Built from SVN snapshot on April 9, 2017
00000000000i[ ] Compiled on Apr 21 2017 at 23:41:40
00000000000i[ ] System configuration
00000000000i[ ] processors: 1 (cores=1, HT threads=1)
00000000000i[ ] A20 line support: yes
00000000000i[ ] IPS is set to 4000000
00000000000i[ ] CPU configuration
00000000000i[ ] SMP support: yes, quantum=16
00000000000i[ ] level: 6
00000000000i[ ] APIC support: xapic
00000000000i[ ] FPU support: yes
00000000000i[ ] MMX support: yes
00000000000i[ ] 3dnow! support: yes
00000000000i[ ] SEP support: yes
00000000000i[ ] SIMD support: sse2
00000000000i[ ] XSAVE support: no
00000000000i[ ] AES support: no
00000000000i[ ] SHA support: no
00000000000i[ ] MOVBE support: no
00000000000i[ ] ADX support: no
00000000000i[ ] x86-64 support: yes
00000000000i[ ] 1G paging support: no
00000000000i[ ] MWAIT support: yes
00000000000i[ ] Optimization configuration
00000000000i[ ] RepeatSpeedups support: no
00000000000i[ ] Fast function calls: no
00000000000i[ ] Handlers Chaining speedups: no
00000000000i[ ] Devices configuration
00000000000i[ ] PCI support: i440FX i430FX
00000000000i[ ] Networking: no
00000000000i[ ] Sound support: no
00000000000i[ ] USB support: UHCI
00000000000i[ ] VGA extension support: vbe
00000000000i[MEM0 ] allocated memory at 0x7fdd59689010. after alignment, vector=0x7fdd5968a000
00000000000i[MEM0 ] 32.00MB
00000000000i[MEM0 ] mem block size = 0x00020000, blocks=256
00000000000i[MEM0 ] rom at 0xfffe0000/131072 ('BIOS-bochs-latest')
00000000000i[CPU0 ] WARNING: 3DNow! is not implemented yet !
00000000000i[PLUGIN] init_dev of 'pci' plugin device by virtual method
00000000000i[DEV ] i440FX PMC present at device 0, function 0
00000000000i[PLUGIN] init_dev of 'pci2isa' plugin device by virtual method
00000000000i[DEV ] PIIX3 PCI-to-ISA bridge present at device 1, function 0
00000000000i[PLUGIN] init_dev of 'cmos' plugin device by virtual method
00000000000i[CMOS ] Using local time for initial clock
00000000000i[CMOS ] Setting initial clock to: Sun Jun 18 17:24:37 2017 (time0=1497824677)
00000000000i[PLUGIN] init_dev of 'dma' plugin device by virtual method
00000000000i[DMA ] channel 4 used by cascade
00000000000i[PLUGIN] init_dev of 'pic' plugin device by virtual method
00000000000i[PLUGIN] init_dev of 'pit' plugin device by virtual method
00000000000i[PLUGIN] init_dev of 'vga' plugin device by virtual method
00000000000i[MEM0 ] Register memory access handlers: 0x0000000a0000 - 0x0000000bffff
00000000000i[VGA ] interval=200000, mode=realtime
00000000000i[MEM0 ] Register memory access handlers: 0x0000e0000000 - 0x0000e0ffffff
00000000000i[BXVGA ] VBE Bochs Display Extension Enabled
00000000000i[XGUI ] test_alloc_colors: 16 colors available out of 16 colors tried
00000000000i[XGUI ] font 8 wide x 16 high, display depth = 24
00000000000i[MEM0 ] rom at 0xc0000/38400 ('VGABIOS-lgpl-latest')
00000000000i[PLUGIN] init_dev of 'floppy' plugin device by virtual method
00000000000i[DMA ] channel 2 used by Floppy Drive
00000000000i[FLOPPY] fd0: 'dev_kernel_grub.img' ro=0, h=2,t=80,spt=18
00000000000i[FLOPPY] Using boot sequence floppy, none, none
00000000000i[FLOPPY] Floppy boot signature check is enabled
00000000000i[PLUGIN] init_dev of 'acpi' plugin device by virtual method
00000000000i[DEV ] ACPI Controller present at device 1, function 3
00000000000i[PLUGIN] init_dev of 'ioapic' plugin device by virtual method
00000000000i[IOAPIC] initializing I/O APIC
00000000000i[MEM0 ] Register memory access handlers: 0x0000fec00000 - 0x0000fec00fff
00000000000i[IOAPIC] IOAPIC enabled (base address = 0xfec00000)
00000000000i[PLUGIN] init_dev of 'keyboard' plugin device by virtual method
00000000000i[KBD ] will paste characters every 400 keyboard ticks
00000000000i[PLUGIN] init_dev of 'harddrv' plugin device by virtual method
00000000000i[PLUGIN] init_dev of 'pci_ide' plugin device by virtual method
00000000000i[DEV ] PIIX3 PCI IDE controller present at device 1, function 1
00000000000i[PLUGIN] init_dev of 'unmapped' plugin device by virtual method
00000000000i[PLUGIN] init_dev of 'biosdev' plugin device by virtual method
00000000000i[PLUGIN] init_dev of 'speaker' plugin device by virtual method
00000000000e[PCSPK ] Failed to open /dev/console: Permission denied
00000000000e[PCSPK ] Deactivating beep on console
00000000000i[PLUGIN] init_dev of 'extfpuirq' plugin device by virtual method
00000000000i[PLUGIN] init_dev of 'parallel' plugin device by virtual method
00000000000i[PAR ] parallel port 1 at 0x0378 irq 7
00000000000i[PLUGIN] init_dev of 'serial' plugin device by virtual method
00000000000i[SER ] com1 at 0x03f8 irq 4 (mode: null)
00000000000i[PLUGIN] init_dev of 'iodebug' plugin device by virtual method
00000000000i[PLUGIN] init_dev of 'usb_uhci' plugin device by virtual method
00000000000i[DEV ] USB UHCI present at device 1, function 2
00000000000i[UHCI ] USB UHCI initialized
00000000000i[PLUGIN] register state of 'pci' plugin device by virtual method
00000000000i[PLUGIN] register state of 'pci2isa' plugin device by virtual method
00000000000i[PLUGIN] register state of 'cmos' plugin device by virtual method
00000000000i[PLUGIN] register state of 'dma' plugin device by virtual method
00000000000i[PLUGIN] register state of 'pic' plugin device by virtual method
00000000000i[PLUGIN] register state of 'pit' plugin device by virtual method
00000000000i[PLUGIN] register state of 'vga' plugin device by virtual method
00000000000i[PLUGIN] register state of 'floppy' plugin device by virtual method
00000000000i[PLUGIN] register state of 'unmapped' plugin device by virtual method
00000000000i[PLUGIN] register state of 'biosdev' plugin device by virtual method
00000000000i[PLUGIN] register state of 'speaker' plugin device by virtual method
00000000000i[PLUGIN] register state of 'extfpuirq' plugin device by virtual method
00000000000i[PLUGIN] register state of 'parallel' plugin device by virtual method
00000000000i[PLUGIN] register state of 'serial' plugin device by virtual method
00000000000i[PLUGIN] register state of 'iodebug' plugin device by virtual method
00000000000i[PLUGIN] register state of 'usb_uhci' plugin device by virtual method
00000000000i[PLUGIN] register state of 'acpi' plugin device by virtual method
00000000000i[PLUGIN] register state of 'ioapic' plugin device by virtual method
00000000000i[PLUGIN] register state of 'keyboard' plugin device by virtual method
00000000000i[PLUGIN] register state of 'harddrv' plugin device by virtual method
00000000000i[PLUGIN] register state of 'pci_ide' plugin device by virtual method
00000000000i[SYS ] bx_pc_system_c::Reset(HARDWARE) called
00000000000i[CPU0 ] cpu hardware reset
00000000000i[APIC0 ] allocate APIC id=0 (MMIO enabled) to 0x0000fee00000
00000000000i[CPU0 ] CPU[0] is the bootstrap processor
00000000000i[CPU0 ] CPUID[0x00000000]: 00000005 68747541 444d4163 69746e65
00000000000i[CPU0 ] CPUID[0x00000001]: 00000633 00010800 00002008 17cbfbff
00000000000i[CPU0 ] CPUID[0x00000002]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x00000003]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x00000004]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x00000005]: 00000040 00000040 00000003 00000020
00000000000i[CPU0 ] CPUID[0x80000000]: 80000008 68747541 444d4163 69746e65
00000000000i[CPU0 ] CPUID[0x80000001]: 00000633 00000000 00000101 ebd3f3ff
00000000000i[CPU0 ] CPUID[0x80000002]: 20444d41 6c687441 74286e6f 7020296d
00000000000i[CPU0 ] CPUID[0x80000003]: 65636f72 726f7373 00000000 00000000
00000000000i[CPU0 ] CPUID[0x80000004]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x80000005]: 01ff01ff 01ff01ff 40020140 40020140
00000000000i[CPU0 ] CPUID[0x80000006]: 00000000 42004200 02008140 00000000
00000000000i[CPU0 ] CPUID[0x80000007]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x80000008]: 00003028 00000000 00000000 00000000
00000000000i[PLUGIN] reset of 'pci' plugin device by virtual method
00000000000i[PLUGIN] reset of 'pci2isa' plugin device by virtual method
00000000000i[PLUGIN] reset of 'cmos' plugin device by virtual method
00000000000i[PLUGIN] reset of 'dma' plugin device by virtual method
00000000000i[PLUGIN] reset of 'pic' plugin device by virtual method
00000000000i[PLUGIN] reset of 'pit' plugin device by virtual method
00000000000i[PLUGIN] reset of 'vga' plugin device by virtual method
00000000000i[PLUGIN] reset of 'floppy' plugin device by virtual method
00000000000i[PLUGIN] reset of 'acpi' plugin device by virtual method
00000000000i[PLUGIN] reset of 'ioapic' plugin device by virtual method
00000000000i[PLUGIN] reset of 'keyboard' plugin device by virtual method
00000000000i[PLUGIN] reset of 'harddrv' plugin device by virtual method
00000000000i[PLUGIN] reset of 'pci_ide' plugin device by virtual method
00000000000i[PLUGIN] reset of 'unmapped' plugin device by virtual method
00000000000i[PLUGIN] reset of 'biosdev' plugin device by virtual method
00000000000i[PLUGIN] reset of 'speaker' plugin device by virtual method
00000000000i[PLUGIN] reset of 'extfpuirq' plugin device by virtual method
00000000000i[PLUGIN] reset of 'parallel' plugin device by virtual method
00000000000i[PLUGIN] reset of 'serial' plugin device by virtual method
00000000000i[PLUGIN] reset of 'iodebug' plugin device by virtual method
00000000000i[PLUGIN] reset of 'usb_uhci' plugin device by virtual method
00000000000i[ ] set SIGINT handler to bx_debug_ctrlc_handler
00000000000i[ ] dbg: Quit
00000000000i[CPU0 ] CPU is in real mode (active)
00000000000i[CPU0 ] CS.mode = 16 bit
00000000000i[CPU0 ] SS.mode = 16 bit
00000000000i[CPU0 ] EFER = 0x00000000
00000000000i[CPU0 ] | EAX=00000000 EBX=00000000 ECX=00000000 EDX=00000000
00000000000i[CPU0 ] | ESP=00000000 EBP=00000000 ESI=00000000 EDI=00000000
00000000000i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of df if tf sf zf af pf cf
00000000000i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00000000000i[CPU0 ] | CS:f000( 1e00| 0| 0) ffff0000 0000ffff 0 0
00000000000i[CPU0 ] | DS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00000000000i[CPU0 ] | SS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00000000000i[CPU0 ] | ES:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00000000000i[CPU0 ] | FS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00000000000i[CPU0 ] | GS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00000000000i[CPU0 ] | EIP=0000fff0 (0000fff0)
00000000000i[CPU0 ] | CR0=0x60000010 CR2=0x00000000
00000000000i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00000000000i[CMOS ] Last time is 1497824677 (Sun Jun 18 17:24:37 2017)
00000000000i[XGUI ] Exit
00000000000i[SIM ] quit_sim called with exit code 0

View file

@ -1,236 +0,0 @@
00000000000i[ ] Bochs x86 Emulator 2.4.6
00000000000i[ ] Build from CVS snapshot, on February 22, 2011
00000000000i[ ] Compiled at Nov 11 2011, 09:31:18
00000000000i[ ] System configuration
00000000000i[ ] processors: 1 (cores=1, HT threads=1)
00000000000i[ ] A20 line support: yes
00000000000i[ ] CPU configuration
00000000000i[ ] level: 6
00000000000i[ ] SMP support: no
00000000000i[ ] APIC support: yes
00000000000i[ ] FPU support: yes
00000000000i[ ] MMX support: yes
00000000000i[ ] 3dnow! support: no
00000000000i[ ] SEP support: yes
00000000000i[ ] SSE support: sse2
00000000000i[ ] XSAVE support: no
00000000000i[ ] AES support: no
00000000000i[ ] MOVBE support: no
00000000000i[ ] x86-64 support: yes
00000000000i[ ] 1G paging support: no
00000000000i[ ] VMX support: no
00000000000i[ ] Optimization configuration
00000000000i[ ] RepeatSpeedups support: yes
00000000000i[ ] Trace cache support: yes
00000000000i[ ] Fast function calls: yes
00000000000i[ ] Devices configuration
00000000000i[ ] ACPI support: yes
00000000000i[ ] NE2000 support: yes
00000000000i[ ] PCI support: yes, enabled=yes
00000000000i[ ] SB16 support: yes
00000000000i[ ] USB support: yes
00000000000i[ ] VGA extension support: vbe
00000000000i[MEM0 ] allocated memory at 0x7f3ed8511010. after alignment, vector=0x7f3ed8512000
00000000000i[MEM0 ] 32.00MB
00000000000i[MEM0 ] mem block size = 0x00100000, blocks=32
00000000000i[MEM0 ] rom at 0xfffe0000/131072 ('BIOS-bochs-latest')
00000000000i[MEM0 ] rom at 0xc0000/38400 ('VGABIOS-lgpl-latest')
00000000000i[VTIME] using 'realtime pit' synchronization method
00000000000i[ ] lt_dlhandle is 0x3837560
00000000000i[PLGIN] loaded plugin libbx_cmos.so
00000000000i[ ] lt_dlhandle is 0x3837f80
00000000000i[PLGIN] loaded plugin libbx_dma.so
00000000000i[ ] lt_dlhandle is 0x38389e0
00000000000i[PLGIN] loaded plugin libbx_pic.so
00000000000i[ ] lt_dlhandle is 0x3839220
00000000000i[PLGIN] loaded plugin libbx_pit.so
00000000000i[ ] lt_dlhandle is 0x3839b90
00000000000i[PLGIN] loaded plugin libbx_vga.so
00000000000i[ ] lt_dlhandle is 0x383a2c0
00000000000i[PLGIN] loaded plugin libbx_hdimage.so
00000000000i[ ] lt_dlhandle is 0x383ab80
00000000000i[PLGIN] loaded plugin libbx_floppy.so
00000000000i[ ] lt_dlhandle is 0x383b770
00000000000i[PLGIN] loaded plugin libbx_soundmod.so
00000000000i[ ] lt_dlhandle is 0x383cdc0
00000000000i[PLGIN] loaded plugin libbx_pci.so
00000000000i[ ] lt_dlhandle is 0x383d9f0
00000000000i[PLGIN] loaded plugin libbx_pci2isa.so
00000000000i[ ] lt_dlhandle is 0x383e2d0
00000000000i[PLGIN] loaded plugin libbx_usb_common.so
00000000000i[ ] lt_dlhandle is 0x383eb30
00000000000i[PLGIN] loaded plugin libbx_unmapped.so
00000000000i[ ] lt_dlhandle is 0x383f3a0
00000000000i[PLGIN] loaded plugin libbx_biosdev.so
00000000000i[ ] lt_dlhandle is 0x383fcd0
00000000000i[PLGIN] loaded plugin libbx_speaker.so
00000000000i[ ] lt_dlhandle is 0x3840500
00000000000i[PLGIN] loaded plugin libbx_extfpuirq.so
00000000000i[ ] lt_dlhandle is 0x3840d70
00000000000i[PLGIN] loaded plugin libbx_gameport.so
00000000000i[ ] lt_dlhandle is 0x38416e0
00000000000i[PLGIN] loaded plugin libbx_pci_ide.so
00000000000i[ ] lt_dlhandle is 0x38420b0
00000000000i[PLGIN] loaded plugin libbx_acpi.so
00000000000i[ ] lt_dlhandle is 0x38429f0
00000000000i[PLGIN] loaded plugin libbx_ioapic.so
00000000000i[ ] lt_dlhandle is 0x38433a0
00000000000i[PLGIN] loaded plugin libbx_keyboard.so
00000000000i[ ] lt_dlhandle is 0x3843ba0
00000000000i[PLGIN] loaded plugin libbx_harddrv.so
00000000000i[ ] lt_dlhandle is 0x3855c70
00000000000i[PLGIN] loaded plugin libbx_serial.so
00000000000i[ ] lt_dlhandle is 0x3856ae0
00000000000i[PLGIN] loaded plugin libbx_parallel.so
00000000000i[CMOS ] Using specified time for initial clock
00000000000i[CMOS ] Setting initial clock to: Fri Dec 31 17:00:00 1999 (time0=946681200)
00000000000i[DMA ] channel 4 used by cascade
00000000000i[DMA ] channel 2 used by Floppy Drive
00000000000i[FDD ] fd0: 'dev_kernel_grub.img' ro=0, h=2,t=80,spt=18
00000000000i[PCI ] 440FX Host bridge present at device 0, function 0
00000000000i[PCI ] PIIX3 PCI-to-ISA bridge present at device 1, function 0
00000000000i[VGA ] interval=50000
00000000000i[MEM0 ] Register memory access handlers: 0x00000000000a0000 - 0x00000000000bffff
00000000000i[XGUI ] test_alloc_colors: 16 colors available out of 16 colors tried
00000000000i[XGUI ] font 8 wide x 16 high, display depth = 24
00000000000i[MEM0 ] Register memory access handlers: 0x00000000e0000000 - 0x00000000e0ffffff
00000000000i[VGA ] VBE Bochs Display Extension Enabled
00000000000i[PLGIN] init_dev of 'unmapped' plugin device by virtual method
00000000000i[PLGIN] init_dev of 'biosdev' plugin device by virtual method
00000000000i[PLGIN] init_dev of 'speaker' plugin device by virtual method
00000000000i[SPEAK] Failed to open /dev/console: Resource temporarily unavailable
00000000000i[SPEAK] Deactivating beep on console
00000000000i[PLGIN] init_dev of 'extfpuirq' plugin device by virtual method
00000000000i[PLGIN] init_dev of 'gameport' plugin device by virtual method
00000000000i[PLGIN] init_dev of 'pci_ide' plugin device by virtual method
00000000000i[PCI ] PIIX3 PCI IDE controller present at device 1, function 1
00000000000i[PLGIN] init_dev of 'acpi' plugin device by virtual method
00000000000i[PCI ] ACPI Controller present at device 1, function 3
00000000000i[PLGIN] init_dev of 'ioapic' plugin device by virtual method
00000000000i[IOAP ] initializing I/O APIC
00000000000i[MEM0 ] Register memory access handlers: 0x00000000fec00000 - 0x00000000fec00fff
00000000000i[PLGIN] init_dev of 'keyboard' plugin device by virtual method
00000000000i[KBD ] will paste characters every 1000 keyboard ticks
00000000000i[PLGIN] init_dev of 'harddrv' plugin device by virtual method
00000000000i[HD ] Using boot sequence floppy, none, none
00000000000i[HD ] Floppy boot signature check is enabled
00000000000i[PLGIN] init_dev of 'serial' plugin device by virtual method
00000000000i[SER ] com1 at 0x03f8 irq 4
00000000000i[PLGIN] init_dev of 'parallel' plugin device by virtual method
00000000000i[PAR ] parallel port 1 at 0x0378 irq 7
00000000000i[PLGIN] register state of 'unmapped' plugin device by virtual method
00000000000i[PLGIN] register state of 'biosdev' plugin device by virtual method
00000000000i[PLGIN] register state of 'speaker' plugin device by virtual method
00000000000i[PLGIN] register state of 'extfpuirq' plugin device by virtual method
00000000000i[PLGIN] register state of 'gameport' plugin device by virtual method
00000000000i[PLGIN] register state of 'pci_ide' plugin device by virtual method
00000000000i[PLGIN] register state of 'acpi' plugin device by virtual method
00000000000i[PLGIN] register state of 'ioapic' plugin device by virtual method
00000000000i[PLGIN] register state of 'keyboard' plugin device by virtual method
00000000000i[PLGIN] register state of 'harddrv' plugin device by virtual method
00000000000i[PLGIN] register state of 'serial' plugin device by virtual method
00000000000i[PLGIN] register state of 'parallel' plugin device by virtual method
00000000000i[SYS ] bx_pc_system_c::Reset(HARDWARE) called
00000000000i[CPU0 ] cpu hardware reset
00000000000i[APIC0] allocate APIC id=0 (MMIO enabled) to 0x00000000fee00000
00000000000i[CPU0 ] CPUID[0x00000000]: 00000003 756e6547 6c65746e 49656e69
00000000000i[CPU0 ] CPUID[0x00000001]: 00000f23 00000800 00002000 07cbfbff
00000000000i[CPU0 ] CPUID[0x00000002]: 00410601 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x00000003]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x00000004]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x00000007]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x80000000]: 80000008 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x80000001]: 00000000 00000000 00000001 2a100800
00000000000i[CPU0 ] CPUID[0x80000002]: 20202020 20202020 20202020 6e492020
00000000000i[CPU0 ] CPUID[0x80000003]: 286c6574 50202952 69746e65 52286d75
00000000000i[CPU0 ] CPUID[0x80000004]: 20342029 20555043 20202020 00202020
00000000000i[CPU0 ] CPUID[0x80000006]: 00000000 42004200 02008140 00000000
00000000000i[CPU0 ] CPUID[0x80000007]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x80000008]: 00003028 00000000 00000000 00000000
00000000000i[PLGIN] reset of 'unmapped' plugin device by virtual method
00000000000i[PLGIN] reset of 'biosdev' plugin device by virtual method
00000000000i[PLGIN] reset of 'speaker' plugin device by virtual method
00000000000i[PLGIN] reset of 'extfpuirq' plugin device by virtual method
00000000000i[PLGIN] reset of 'gameport' plugin device by virtual method
00000000000i[PLGIN] reset of 'pci_ide' plugin device by virtual method
00000000000i[PLGIN] reset of 'acpi' plugin device by virtual method
00000000000i[PLGIN] reset of 'ioapic' plugin device by virtual method
00000000000i[PLGIN] reset of 'keyboard' plugin device by virtual method
00000000000i[PLGIN] reset of 'harddrv' plugin device by virtual method
00000000000i[PLGIN] reset of 'serial' plugin device by virtual method
00000000000i[PLGIN] reset of 'parallel' plugin device by virtual method
00000000000i[XGUI ] [x] Mouse off
00000003302i[BIOS ] $Revision: 1.209 $ $Date: 2008/06/02 20:08:10 $
00000318057i[KBD ] reset-disable command received
00000438667i[VBIOS] VGABios $Id: vgabios.c,v 1.67 2008/01/27 09:44:12 vruppert Exp $
00000438738i[VGA ] VBE known Display Interface b0c0
00000438770i[VGA ] VBE known Display Interface b0c4
00000441695i[VBIOS] VBE Bios $Id: vbe.c,v 1.60 2008/03/02 07:47:21 vruppert Exp $
00000600000i[XGUI ] charmap update. Font Height is 16
00000764696i[BIOS ] Starting rombios32
00000765523i[BIOS ] ram_size=0x02000000
00000776678i[BIOS ] Found 1 cpu(s)
00000792979i[BIOS ] bios_table_addr: 0x000fb778 end=0x000fcc00
00000793046i[PCI ] 440FX PMC write to PAM register 59 (TLB Flush)
00001251853i[PCI ] 440FX PMC write to PAM register 59 (TLB Flush)
00001711340i[P2I ] PCI IRQ routing: PIRQA# set to 0x0b
00001711387i[P2I ] PCI IRQ routing: PIRQB# set to 0x09
00001711434i[P2I ] PCI IRQ routing: PIRQC# set to 0x0b
00001711481i[P2I ] PCI IRQ routing: PIRQD# set to 0x09
00001711497i[P2I ] write: ELCR2 = 0x0a
00001712434i[BIOS ] PIIX3 init: elcr=00 0a
00001732689i[BIOS ] PCI: bus=0 devfn=0x00: vendor_id=0x8086 device_id=0x1237
00001735926i[BIOS ] PCI: bus=0 devfn=0x08: vendor_id=0x8086 device_id=0x7000
00001738659i[BIOS ] PCI: bus=0 devfn=0x09: vendor_id=0x8086 device_id=0x7010
00001739120i[PIDE ] new BM-DMA address: 0xc000
00001740003i[BIOS ] region 4: 0x0000c000
00001742579i[BIOS ] PCI: bus=0 devfn=0x0b: vendor_id=0x8086 device_id=0x7113
00001743079i[ACPI ] new irq line = 11
00001743116i[ACPI ] new PM base address: 0xb000
00001743178i[ACPI ] new SM base address: 0xb100
00001743646i[CPU0 ] Enter to System Management Mode
00001743656i[CPU0 ] RSM: Resuming from System Management Mode
00001743690i[PCI ] setting SMRAM control register to 0x4a
00001743972i[PCI ] setting SMRAM control register to 0x0a
00001767253i[BIOS ] MP table addr=0x000fb850 MPC table addr=0x000fb780 size=0xd0
00001769456i[BIOS ] SMBIOS table addr=0x000fb860
00001772500i[BIOS ] ACPI tables: RSDP addr=0x000fb970 ACPI DATA addr=0x01ff0000 size=0x9d8
00001792033i[PCI ] 440FX PMC write to PAM register 59 (TLB Flush)
00001793045i[BIOS ] bios_table_cur_addr: 0x000fb994
00374348939i[BIOS ] Booting from 0000:7c00
00384200000i[XGUI ] charmap update. Font Height is 16
00423200000i[XGUI ] charmap update. Font Height is 16
00430800000i[XGUI ] charmap update. Font Height is 16
00431000000i[XGUI ] charmap update. Font Height is 16
00794756000p[XGUI ] >>PANIC<< POWER button turned off.
00794756000i[CPU0 ] CPU is in protected mode (active)
00794756000i[CPU0 ] CS.d_b = 32 bit
00794756000i[CPU0 ] SS.d_b = 32 bit
00794756000i[CPU0 ] EFER = 0x00000000
00794756000i[CPU0 ] | RAX=0000000000000000 RBX=0000000000026260
00794756000i[CPU0 ] | RCX=00000000000b8000 RDX=00000000000003d4
00794756000i[CPU0 ] | RSP=0000000000102f68 RBP=0000000000102f68
00794756000i[CPU0 ] | RSI=00000000000263d3 RDI=00000000000263df
00794756000i[CPU0 ] | R8=0000000000000000 R9=0000000000000000
00794756000i[CPU0 ] | R10=0000000000000000 R11=0000000000000000
00794756000i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
00794756000i[CPU0 ] | R14=0000000000000000 R15=0000000000000000
00794756000i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of df if tf sf ZF af PF cf
00794756000i[CPU0 ] | SEG selector base limit G D
00794756000i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00794756000i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 ffffffff 1 1
00794756000i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00794756000i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00794756000i[CPU0 ] | ES:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00794756000i[CPU0 ] | FS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00794756000i[CPU0 ] | GS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00794756000i[CPU0 ] | MSR_FS_BASE:0000000000000000
00794756000i[CPU0 ] | MSR_GS_BASE:0000000000000000
00794756000i[CPU0 ] | RIP=0000000000100033 (0000000000100033)
00794756000i[CPU0 ] | CR0=0x60000011 CR2=0x0000000000000000
00794756000i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00794756000i[CPU0 ] 0x0000000000100033>> jmp .-2 (0x00100033) : EBFE
00794756000i[CMOS ] Last time is 946681398 (Fri Dec 31 17:03:18 1999)
00794756000i[XGUI ] Exit
00794756000i[ ] restoring default signal behavior
00794756000i[CTRL ] quit_sim called with exit code 1

View file

@ -148,9 +148,6 @@ ContFramePool::ContFramePool(unsigned long _base_frame_no,
nFreeFrames = _n_frames;
info_frame_no = _info_frame_no;
n_info_frames = _n_info_frames;
pools[nPools] = *this;
nPools += 1;
// If _info_frame_no is zero then we keep management info in the first
// frame(s), else we use the provided frame(s) to keep management info
@ -186,23 +183,27 @@ ContFramePool::ContFramePool(unsigned long _base_frame_no,
{
unsigned int i = info_frame_no / 4;
unsigned int r = info_frame_no % 4;
unsigned char mask = 0xC0;
unsigned char mask = 0x80;
mask = mask >> r*2;
unsigned int c = 0;
while(c < n_info_frames)
{
bitmap[i] = bitmap[i] ^ mask;
bitmap[i] = bitmap[i] ^ (mask >> 1);
if(mask == 0x02)
{
i++;
mask = 0xC0;
mask = 0x80;
}
c++;
nFreeFrames--;
}
nFreeFrames--;
}
pools[nPools] = *this;
nPools += 1;
Console::puts("Frame Pool initialized\n");
}
@ -211,7 +212,7 @@ unsigned long ContFramePool::get_frames(unsigned int _n_frames)
{
// Are there enough frames left to allocate?
assert(nFreeFrames > _n_frames);
// Find a frame that is not being used and return its frame index.
// Mark that frame as being used in the bitmap.
// NOTE: Must be updated to find a sequence of contiguous frames
@ -226,69 +227,60 @@ unsigned long ContFramePool::get_frames(unsigned int _n_frames)
unsigned int j = 0;
unsigned int c = 0;
// used as a simple way to check if we failed to find a free
// frame for an index i in the bitmap.
bool failed = false;
while (true)
{
unsigned char mask = 0x80;
unsigned char mask = 0x80 >> (j*2);
// check every 2 bits for a free frame in the bitmap
while((mask & bitmap[i]) == 0 || ((mask >> 1) & bitmap[i]) == 0)
{
if(mask != 0x02)
{
j++;
mask >> 2;
mask = mask >> 2;
}
else
{
failed = true;
i++;
j = 0;
break;
mask = 0x80;
}
}
// if frame is found, start checking for sequence
if(!failed)
unsigned int temp = i;
c++;
while(c < _n_frames)
{
unsigned int temp = i;
c++;
while(c < _n_frames)
if(mask != 0x02)
{
if(mask != 0x02)
{
mask >> 2;
}
else
{
temp++;
mask = 0x80;
}
if((mask & bitmap[temp]) != 0 && ((mask >> 1) & bitmap[temp]) != 0)
{
c++;
}
else
{
c = 0;
break;
}
mask = mask >> 2;
}
if(c == _n_frames)
else
{
nFreeFrames -= _n_frames;
temp++;
mask = 0x80;
}
if((mask & bitmap[temp]) != 0 && ((mask >> 1) & bitmap[temp]) != 0)
{
c++;
}
else
{
c = 0;
break;
}
}
failed = false;
if(c == _n_frames)
{
nFreeFrames -= _n_frames;
break;
}
}
frame_no += i*4 + j;
// Update bitmap
// First: clear most significant bit to mark head of sequence.
bitmap[i] = bitmap[i] ^ (0x80 >> j*2);
bitmap[i] = bitmap[i] ^ (0x80 >> (j*2));
// Second: clear both bits for all remaining frames in the sequence.
c = 1;
unsigned char mask = 0x80 >> j*2;
@ -297,7 +289,7 @@ unsigned long ContFramePool::get_frames(unsigned int _n_frames)
{
if(mask != 0x02)
{
mask >> 2;
mask = mask >> 2;
}
else
{
@ -346,7 +338,7 @@ void ContFramePool::release_frames(unsigned long _frame_no)
unsigned int i = 0;
while(i < nPools)
{
if(_frame_no < pools[i].base_frame_no || _frame_no > (pools[i].base_frame_no + pools[i].nframes))
if(_frame_no <= pools[i].base_frame_no || _frame_no > (pools[i].base_frame_no + pools[i].nframes))
{
i++;
}
@ -364,19 +356,24 @@ void ContFramePool::release_frames_here(unsigned long _first_frame_no)
unsigned int bitmap_index = (_first_frame_no - base_frame_no) / 4;
unsigned char mask = 0x80 >> ((_first_frame_no - base_frame_no) % 4) * 2;
if((bitmap[bitmap_index] & mask) != 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0)
if(!((bitmap[bitmap_index] & mask) == 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0))
{
Console::puts("Error, Frame being released is not being used\n");
if((bitmap[bitmap_index] & mask) != 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0)
{
Console::puts("Error, Frame being released is not being used\n");
assert(false);
}
Console::puts("Error, Frame being released is not head of sequence\n");
assert(false);
}
bitmap[bitmap_index] ^= mask;
nFreeFrames++;
if(mask != 0x02)
{
mask >> 2;
mask = mask >> 2;
}
else
{
@ -388,6 +385,15 @@ void ContFramePool::release_frames_here(unsigned long _first_frame_no)
{
bitmap[bitmap_index] ^= mask;
bitmap[bitmap_index] ^= (mask >> 1);
if(mask != 0x02)
{
mask = mask >> 2;
}
else
{
mask = 0x80;
bitmap_index++;
}
nFreeFrames++;
}
}

Binary file not shown.

View file

@ -75,7 +75,6 @@ int main() {
/* ---- PROCESS POOL -- */
/*
unsigned long n_info_frames = ContFramePool::needed_info_frames(PROCESS_POOL_SIZE);
unsigned long process_mem_pool_info_frame = kernel_mem_pool.get_frames(n_info_frames);
@ -86,7 +85,7 @@ int main() {
n_info_frames);
process_mem_pool.mark_inaccessible(MEM_HOLE_START_FRAME, MEM_HOLE_SIZE);
*/
/* -- MOST OF WHAT WE NEED IS SETUP. THE KERNEL CAN START. */
Console::puts("Hello World!\n");

BIN
MP2/design.odt Normal file

Binary file not shown.

BIN
MP2/design.pdf Normal file

Binary file not shown.

BIN
MP2/mp2.zip Normal file

Binary file not shown.

404
MP2/mp2/cont_frame_pool.C Normal file
View file

@ -0,0 +1,404 @@
/*
File: ContFramePool.C
Author:
Date :
*/
/*--------------------------------------------------------------------------*/
/*
POSSIBLE IMPLEMENTATION
-----------------------
The class SimpleFramePool in file "simple_frame_pool.H/C" describes an
incomplete vanilla implementation of a frame pool that allocates
*single* frames at a time. Because it does allocate one frame at a time,
it does not guarantee that a sequence of frames is allocated contiguously.
This can cause problems.
The class ContFramePool has the ability to allocate either single frames,
or sequences of contiguous frames. This affects how we manage the
free frames. In SimpleFramePool it is sufficient to maintain the free
frames.
In ContFramePool we need to maintain free *sequences* of frames.
This can be done in many ways, ranging from extensions to bitmaps to
free-lists of frames etc.
IMPLEMENTATION:
One simple way to manage sequences of free frames is to add a minor
extension to the bitmap idea of SimpleFramePool: Instead of maintaining
whether a frame is FREE or ALLOCATED, which requires one bit per frame,
we maintain whether the frame is FREE, or ALLOCATED, or HEAD-OF-SEQUENCE.
The meaning of FREE is the same as in SimpleFramePool.
If a frame is marked as HEAD-OF-SEQUENCE, this means that it is allocated
and that it is the first such frame in a sequence of frames. Allocated
frames that are not first in a sequence are marked as ALLOCATED.
NOTE: If we use this scheme to allocate only single frames, then all
frames are marked as either FREE or HEAD-OF-SEQUENCE.
NOTE: In SimpleFramePool we needed only one bit to store the state of
each frame. Now we need two bits. In a first implementation you can choose
to use one char per frame. This will allow you to check for a given status
without having to do bit manipulations. Once you get this to work,
revisit the implementation and change it to using two bits. You will get
an efficiency penalty if you use one char (i.e., 8 bits) per frame when
two bits do the trick.
DETAILED IMPLEMENTATION:
How can we use the HEAD-OF-SEQUENCE state to implement a contiguous
allocator? Let's look a the individual functions:
Constructor: Initialize all frames to FREE, except for any frames that you
need for the management of the frame pool, if any.
get_frames(_n_frames): Traverse the "bitmap" of states and look for a
sequence of at least _n_frames entries that are FREE. If you find one,
mark the first one as HEAD-OF-SEQUENCE and the remaining _n_frames-1 as
ALLOCATED.
release_frames(_first_frame_no): Check whether the first frame is marked as
HEAD-OF-SEQUENCE. If not, something went wrong. If it is, mark it as FREE.
Traverse the subsequent frames until you reach one that is FREE or
HEAD-OF-SEQUENCE. Until then, mark the frames that you traverse as FREE.
mark_inaccessible(_base_frame_no, _n_frames): This is no different than
get_frames, without having to search for the free sequence. You tell the
allocator exactly which frame to mark as HEAD-OF-SEQUENCE and how many
frames after that to mark as ALLOCATED.
needed_info_frames(_n_frames): This depends on how many bits you need
to store the state of each frame. If you use a char to represent the state
of a frame, then you need one info frame for each FRAME_SIZE frames.
A WORD ABOUT RELEASE_FRAMES():
When we releae a frame, we only know its frame number. At the time
of a frame's release, we don't know necessarily which pool it came
from. Therefore, the function "release_frame" is static, i.e.,
not associated with a particular frame pool.
This problem is related to the lack of a so-called "placement delete" in
C++. For a discussion of this see Stroustrup's FAQ:
http://www.stroustrup.com/bs_faq2.html#placement-delete
*/
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "cont_frame_pool.H"
#include "console.H"
#include "utils.H"
#include "assert.H"
/*--------------------------------------------------------------------------*/
/* DATA STRUCTURES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* CONSTANTS */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* FORWARDS */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* METHODS FOR CLASS C o n t F r a m e P o o l */
/*--------------------------------------------------------------------------*/
ContFramePool* ContFramePool::pools = (ContFramePool *) FRAME_SIZE; // List of frame pools, managed by the class
unsigned int ContFramePool::nPools = 0; // Number of pools being managed
ContFramePool::ContFramePool(unsigned long _base_frame_no,
unsigned long _n_frames,
unsigned long _info_frame_no,
unsigned long _n_info_frames)
{
// Bitmap must fit in a single frame!
// NOTE: In theory, we don't need to make the bitmap any larger,
// since as stated in the instructions it is already big enough to
// hold for 128MB of memory with one bit per frame, so should still
// be enough for 64MB of memory with 2 bits per frame.
// Assertion changed to match max size of frames allowed.
assert(_n_frames <= FRAME_SIZE * 4);
base_frame_no = _base_frame_no;
nframes = _n_frames;
nFreeFrames = _n_frames;
info_frame_no = _info_frame_no;
n_info_frames = _n_info_frames;
// If _info_frame_no is zero then we keep management info in the first
// frame(s), else we use the provided frame(s) to keep management info
// NOTE: bitmap needs to be allocated with n_info_frames if specified.
if(info_frame_no == 0)
{
bitmap = (unsigned char *) (base_frame_no * FRAME_SIZE);
}
else
{
bitmap = (unsigned char *) (info_frame_no * FRAME_SIZE * n_info_frames);
}
// Number of frames must "fill" the bitmap!
assert ((nframes % 8 ) == 0);
// Everything ok. Proceed to mark all bits in the bitmap
// NOTE: changed to reflect that I need 2 bits per frame now
for(int i=0; i*4 < _n_frames; i++)
{
bitmap[i] = 0xFF;
}
// Mark the first frame as being used if it is being used
// NOTE: need to mark multiple frames if needed.
if(info_frame_no == 0)
{
bitmap[0] = 0x3F;
nFreeFrames--;
}
else
{
unsigned int i = info_frame_no / 4;
unsigned int r = info_frame_no % 4;
unsigned char mask = 0x80;
mask = mask >> r*2;
unsigned int c = 0;
while(c < n_info_frames)
{
bitmap[i] = bitmap[i] ^ mask;
bitmap[i] = bitmap[i] ^ (mask >> 1);
if(mask == 0x02)
{
i++;
mask = 0x80;
}
c++;
nFreeFrames--;
}
}
pools[nPools] = *this;
nPools += 1;
Console::puts("Frame Pool initialized\n");
}
unsigned long ContFramePool::get_frames(unsigned int _n_frames)
{
// Are there enough frames left to allocate?
assert(nFreeFrames > _n_frames);
// Find a frame that is not being used and return its frame index.
// Mark that frame as being used in the bitmap.
// NOTE: Must be updated to find a sequence of contiguous frames
// that are not being used and return the index of the head.
unsigned int frame_no = base_frame_no;
// i is being used as the frame_no / 4
// j is frame_no % 4
// together, they will give the actual frame_no.
// c is used as a counter to count a squence of free frames.
unsigned int i = 0;
unsigned int j = 0;
unsigned int c = 0;
while (true)
{
unsigned char mask = 0x80 >> (j*2);
// check every 2 bits for a free frame in the bitmap
while((mask & bitmap[i]) == 0 || ((mask >> 1) & bitmap[i]) == 0)
{
if(mask != 0x02)
{
j++;
mask = mask >> 2;
}
else
{
i++;
j = 0;
mask = 0x80;
}
}
// if frame is found, start checking for sequence
unsigned int temp = i;
c++;
while(c < _n_frames)
{
if(mask != 0x02)
{
mask = mask >> 2;
}
else
{
temp++;
mask = 0x80;
}
if((mask & bitmap[temp]) != 0 && ((mask >> 1) & bitmap[temp]) != 0)
{
c++;
}
else
{
c = 0;
break;
}
}
if(c == _n_frames)
{
nFreeFrames -= _n_frames;
break;
}
}
frame_no += i*4 + j;
// Update bitmap
// First: clear most significant bit to mark head of sequence.
bitmap[i] = bitmap[i] ^ (0x80 >> (j*2));
// Second: clear both bits for all remaining frames in the sequence.
c = 1;
unsigned char mask = 0x80 >> j*2;
unsigned int temp = i;
while(c < _n_frames)
{
if(mask != 0x02)
{
mask = mask >> 2;
}
else
{
temp++;
mask = 0x80;
}
bitmap[temp] = bitmap[temp] ^ mask;
bitmap[temp] = bitmap[temp] ^ (mask >> 1);
c++;
}
return (frame_no);
}
void ContFramePool::mark_inaccessible(unsigned long _base_frame_no,
unsigned long _n_frames)
{
// Mark all frames in the range as being used.
int i ;
for(i = _base_frame_no; i < _base_frame_no + _n_frames; i++){
mark_inaccessible(i);
}
nFreeFrames -= _n_frames;
}
void ContFramePool::mark_inaccessible(unsigned long _frame_no)
{
// Let's first do a range check.
assert ((_frame_no >= base_frame_no) && (_frame_no < base_frame_no + nframes));
unsigned int bitmap_index = (_frame_no - base_frame_no) / 4;
unsigned char mask = 0x80 >> ((_frame_no - base_frame_no) % 4) * 2;
// Is the frame being used already?
assert(((bitmap[bitmap_index] & mask) != 0) && (bitmap[bitmap_index] & (mask >> 1)) != 0);
// Update bitmap
bitmap[bitmap_index] ^= mask;
bitmap[bitmap_index] ^= mask >> 1;
nFreeFrames--;
}
void ContFramePool::release_frames(unsigned long _frame_no)
{
unsigned int i = 0;
while(i < nPools)
{
if(_frame_no <= pools[i].base_frame_no || _frame_no > (pools[i].base_frame_no + pools[i].nframes))
{
i++;
}
else
{
pools[i].release_frames_here(_frame_no);
return;
}
}
}
void ContFramePool::release_frames_here(unsigned long _first_frame_no)
{
unsigned char * bitmap = this->bitmap;
unsigned int bitmap_index = (_first_frame_no - base_frame_no) / 4;
unsigned char mask = 0x80 >> ((_first_frame_no - base_frame_no) % 4) * 2;
if(!((bitmap[bitmap_index] & mask) == 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0))
{
if((bitmap[bitmap_index] & mask) != 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0)
{
Console::puts("Error, Frame being released is not being used\n");
assert(false);
}
Console::puts("Error, Frame being released is not head of sequence\n");
assert(false);
}
bitmap[bitmap_index] ^= mask;
nFreeFrames++;
if(mask != 0x02)
{
mask = mask >> 2;
}
else
{
mask = 0x80;
bitmap_index++;
}
while(bitmap[bitmap_index] & mask == 0 && (bitmap[bitmap_index] & (mask >> 1)) == 0)
{
bitmap[bitmap_index] ^= mask;
bitmap[bitmap_index] ^= (mask >> 1);
if(mask != 0x02)
{
mask = mask >> 2;
}
else
{
mask = 0x80;
bitmap_index++;
}
nFreeFrames++;
}
}
unsigned long ContFramePool::needed_info_frames(unsigned long _n_frames)
{
return (_n_frames / (FRAME_SIZE * 4)) + (_n_frames % (FRAME_SIZE * 4) > 0 ? 1 : 0);
}

132
MP2/mp2/cont_frame_pool.H Executable file
View file

@ -0,0 +1,132 @@
/*
File: cont_frame_pool.H
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 17/02/04
Description: Management of the CONTIGUOUS Free-Frame Pool.
As opposed to a non-contiguous free-frame pool, here we can allocate
a sequence of CONTIGUOUS frames.
*/
#ifndef _CONT_FRAME_POOL_H_ // include file only once
#define _CONT_FRAME_POOL_H_
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "machine.H"
/*--------------------------------------------------------------------------*/
/* DATA STRUCTURES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* C o n t F r a m e P o o l */
/*--------------------------------------------------------------------------*/
class ContFramePool {
private:
/* -- DEFINE YOUR CONT FRAME POOL DATA STRUCTURE(s) HERE. */
unsigned char * bitmap; // Remember the bitmap here needs 2 bits per frame
unsigned int nFreeFrames; //
unsigned long base_frame_no; // Where does the frame pool start in phys mem?
unsigned long nframes; // Size of the frame pool
unsigned long info_frame_no; // Where do we store the management information?
unsigned long n_info_frames; // Number of frames needed to store management info
static ContFramePool* pools; // List of frame pools, managed by the class
static unsigned int nPools; // Number of pools being managed
void mark_inaccessible(unsigned long _frame_no); // Should be a frame marked as
// a head, otherwise fails
void release_frames_here(unsigned long _frame_no); // non-static member function
public:
// The frame size is the same as the page size, duh...
static const unsigned int FRAME_SIZE = Machine::PAGE_SIZE;
ContFramePool(unsigned long _base_frame_no,
unsigned long _n_frames,
unsigned long _info_frame_no,
unsigned long _n_info_frames);
/*
Initializes the data structures needed for the management of this
frame pool.
_base_frame_no: Number of first frame managed by this frame pool.
_n_frames: Size, in frames, of this frame pool.
EXAMPLE: If _base_frame_no is 16 and _n_frames is 4, this frame pool manages
physical frames numbered 16, 17, 18 and 19.
_info_frame_no: Number of the first frame that should be used to store the
management information for the frame pool.
NOTE: If _info_frame_no is 0, the frame pool is free to
choose any frames from the pool to store management information.
_n_info_frames: If _info_frame_no is 0, this argument specifies the
number of consecutive frames needed to store the management information
for the frame pool.
EXAMPLE: If _info_frame_no is 699 and _n_info_frames is 3,
then Frames 699, 700, and 701 are used to store the management information
for the frame pool.
NOTE: This function must be called before the paging system
is initialized.
*/
unsigned long get_frames(unsigned int _n_frames);
/*
Allocates a number of contiguous frames from the frame pool.
_n_frames: Size of contiguous physical memory to allocate,
in number of frames.
If successful, returns the frame number of the first frame.
If fails, returns 0.
*/
void mark_inaccessible(unsigned long _base_frame_no,
unsigned long _n_frames);
/*
Marks a contiguous area of physical memory, i.e., a contiguous
sequence of frames, as inaccessible.
_base_frame_no: Number of first frame to mark as inaccessible.
_n_frames: Number of contiguous frames to mark as inaccessible.
*/
static void release_frames(unsigned long _frame_no);
/*
Releases a previously allocated contiguous sequence of frames
back to its frame pool.
The frame sequence is identified by the number of the first frame.
NOTE: This function is static because there may be more than one frame pool
defined in the system, and it is unclear which one this frame belongs to.
This function must first identify the correct frame pool and then call the frame
pool's release_frame function.
*/
static unsigned long needed_info_frames(unsigned long _n_frames);
/*
Returns the number of frames needed to manage a frame pool of size _n_frames.
The number returned here depends on the implementation of the frame pool and
on the frame size.
EXAMPLE: For FRAME_SIZE = 4096 and a bitmap with a single bit per frame
(not appropriate for contiguous allocation) one would need one frame to manage a
frame pool with up to 8 * 4096 = 32k frames = 128MB of memory!
This function would therefore return the following value:
_n_frames / 32k + (_n_frames % 32k > 0 ? 1 : 0) (always round up!)
Other implementations need a different number of info frames.
The exact number is computed in this function..
*/
};
#endif

BIN
MP2/mp2/design.pdf Normal file

Binary file not shown.

BIN
MP3/MP3_Sources.zip Normal file

Binary file not shown.

BIN
MP3/MP3_Sources/BIOS-bochs-latest Executable file

Binary file not shown.

101
MP3/MP3_Sources/README.TXT Executable file
View file

@ -0,0 +1,101 @@
CSCE 410/611/613: MP2 -- README.TXT
This file describes the content of this directory.
A file marked with (*) may be of some interest to the
student, and he/she may want to have a look at it.
A file marked with (**) is important for this MP, and the
student is strongly encouraged to study the contents of this file.
BOCH Environment:
=================
FILE: DESCRIPTION:
BIOS-bochs-latest BIOS file.
VGABIOS-lgpl-latest BIOS file for the graphics system.
dev_kernel_grub.img Image file of the boot floopy.
bochsrc.bxrc Description file for the system.
Type 'bochs -f bochsrc.bxrc' to
start emulation.
COMPILATION:
===========
FILE: DESCRIPTION:
makefile (**) Makefile for Linux 64-bit environment.
Works with the provided linux image.
Type "make" to create the kernel.
linker.ld The linker script.
OS COMPONENTS:
=============
FILE: DESCRIPTION:
start.asm (*) The bootloader starts code in this file, which in turn
jumps to the main entry in File "kernel.C".
kernel.C (**) Main file, where the OS components are set up, and the
system gets going.
assert.H/C Implements the "assert()" utility.
utils.H/C Various utilities (e.g. memcpy, strlen,
port I/O, etc.)
console.H/C Routines to print to the screen.
machine.H (*) Definitions of some system constants and low-level
machine operations.
(Primarily memory sizes, register set, and
enable/disable interrupts)
gdt.H/C Global Descriptor Table.
gdt_low.asm Low-level GDT code, included in "start.asm".
idt.H/C Interrupt Descriptor Table.
idt_low.asm Low-level IDT code, included in "start.asm".
irq.H/C mapping of IRQ's into the IDT.
irq_low.asm Low-level IRQ stuff. (Primarily the interrupt service
routines and the routine stub that branches out to the
interrupt dispatcher in "interrupts.C". Included in
"start.asm".
exceptions.H/C (*) The exception dispatcher.
interrupts.H/C The interrupt dispatcher.
console.H/C Routines to print to the screen.
simple_timer.H/C (*) Routines to control the periodic interval
timer. This is an example of an interrupt
handler.
simple_keyboard.H/C(*) Routines to access the keyboard. Primarily as
way to wait until user presses key.
machine_low.H/asm Various low-level x86 specific stuff.
paging_low.H/asm (**) Low-level code to control the registers needed for
memory paging.
page_table.H/C (**) Definition and empty implementation of a
page table manager. In addition to interface,
the .H file defines a few private members that
should guide the implementation.
cont_frame_pool.H/C(**) Definition and empty implementation of a
physical frame memory manager that
supports contiguous
allocation. NOTE that the comments in
the implementation file give a recipe
of how to implement such a frame pool.
UTILITIES:
==========
FILE: DESCRIPTION:
copykernel.sh (**) Simple script to copy the kernel onto
the floppy image.
The script mounts the floppy image, copies the kernel
image onto it, and then unmounts the floppy image again.
In rare cases the paths in the file may need to be
edited to make them reflect the student's environment.

Binary file not shown.

45
MP3/MP3_Sources/assert.C Executable file
View file

@ -0,0 +1,45 @@
/*
File: assert.C
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 05/01/23
Implementation of the assert() function.
*/
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "assert.H"
#include "utils.H"
#include "console.H"
/*--------------------------------------------------------------------------*/
/* _assert() FUNCTION: gets called when assert() macro fails. */
/*--------------------------------------------------------------------------*/
void _assert (const char* _file, const int _line, const char* _message ) {
/* Prints current file, line number, and failed assertion. */
char temp[15];
Console::puts("Assertion failed at file: ");
Console::puts(_file);
Console::puts(" line: ");
int2str(_line, temp);
Console::puts(temp);
Console::puts(" assertion: ");
Console::puts(_message);
Console::puts("\n");
abort();
}/* end _assert */

56
MP3/MP3_Sources/assert.H Executable file
View file

@ -0,0 +1,56 @@
/*
File: assert.H
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 05/01/23
Header file for the "assert" macro.
*/
#ifndef __assert_H__
#define __assert_H__
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "utils.H"
/*--------------------------------------------------------------------------*/
/* DATA STRUCTURES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* CONSTANTS */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* "ASSERT" MACRO */
/*--------------------------------------------------------------------------*/
/* NOTE: The "assert" macros can be turned off by giving the -DNDEBUG
argument when compiling. */
#ifdef assert
# undef assert
#endif
void _assert ( const char* _file, const int _line, const char* _message );
#ifdef NDEBUG
# define assert( m ) ( ( void ) 0 )
#else
# define assert( m ) \
if ( !(m) ) _assert( __FILE__, __LINE__, #m );
#endif
#endif

48
MP3/MP3_Sources/bochsrc.bxrc Executable file
View file

@ -0,0 +1,48 @@
###############################################################
# bochsrc.txt file for DLX Linux disk image.
###############################################################
# how much memory the emulated machine will have
megs: 32
# filename of ROM images
romimage: file=BIOS-bochs-latest
vgaromimage: file=VGABIOS-lgpl-latest
# what disk images will be used
floppya: 1_44=dev_kernel_grub.img, status=inserted
#floppyb: 1_44=floppyb.img, status=inserted
# hard disk
#ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
#ata0-master: type=disk, path="c.img", cylinders=306, heads=4, spt=17
# choose the boot disk.
boot: floppy
# default config interface is textconfig.
#config_interface: textconfig
#config_interface: wx
#display_library: x
# other choices: win32 sdl wx carbon amigaos beos macintosh nogui rfb term svga
# where do we send log messages?
log: bochsout.txt
# disable the mouse
mouse: enabled=0
# enable key mapping, using US layout as default.
#
# NOTE: In Bochs 1.4, keyboard mapping is only 100% implemented on X windows.
# However, the key mapping tables are used in the paste function, so
# in the DLX Linux example I'm enabling keyboard_mapping so that paste
# will work. Cut&Paste is currently implemented on win32 and X windows only.
#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-us.map
#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-fr.map
#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-de.map
#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-es.map
clock: sync=realtime, time0=946681200 # Sat Jan 1 00:00:00 2000

213
MP3/MP3_Sources/console.C Executable file
View file

@ -0,0 +1,213 @@
/*
File: Console.C
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 09/02/2009
*/
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
#define CONSOLE_START_ADDRESS (unsigned short *)0xB8000
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "console.H"
#include "utils.H"
#include "machine.H"
/*--------------------------------------------------------------------------*/
/* DATA STRUCTURES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* CONSTANTS */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* FORWARDS */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* METHODS FOR CLASS C o n s o l e */
/*--------------------------------------------------------------------------*/
/* -- GLOBAL VARIABLES -- */
int Console::attrib; /* background and foreground color */
int Console::csr_x; /* position of cursor */
int Console::csr_y;
unsigned short * Console::textmemptr; /* text pointer */
/* -- CONSTRUCTOR -- */
void Console::init(unsigned char _fore_color,
unsigned char _back_color) {
set_TextColor(_fore_color, _back_color);
csr_x = 0;
csr_y = 0;
textmemptr = CONSOLE_START_ADDRESS;
cls();
}
void Console::scroll() {
/* A blank is defined as a space... we need to give it
* backcolor too */
unsigned blank = 0x20 | (attrib << 8);
/* Row 25 is the end, this means we need to scroll up */
if(csr_y >= 25)
{
/* Move the current text chunk that makes up the screen
* back in the buffer by a line */
unsigned temp = csr_y - 25 + 1;
memcpy ((char*)textmemptr, (char*)(textmemptr + temp * 80), (25 - temp) * 80 * 2);
/* Finally, we set the chunk of memory that occupies
* the last line of text to our 'blank' character */
memsetw (textmemptr + (25 - temp) * 80, blank, 80);
csr_y = 25 - 1;
}
}
void Console::move_cursor() {
/* The equation for finding the index in a linear
* chunk of memory can be represented by:
* Index = [(y * width) + x] */
unsigned temp = csr_y * 80 + csr_x;
/* This sends a command to indicies 14 and 15 in the
* Console Control Register of the VGA controller. These
* are the high and low bytes of the index that show
* where the hardware cursor is to be 'blinking'. To
* learn more, you should look up some VGA specific
* programming documents. A great start to graphics:
* http://www.brackeen.com/home/vga */
Machine::outportb(0x3D4, (char)14);
//outportb(0x3D5, temp >> 8);
Machine::outportb(0x3D4, 15);
//outportb(0x3D5, (char)temp);
}
/* Clear the screen */
void Console::cls() {
/* Again, we need the 'short' that will be used to
* represent a space with color */
unsigned blank = 0x20 | (attrib << 8);
/* Sets the entire screen to spaces in our current
* color */
for(int i = 0; i < 25; i++)
memsetw (textmemptr + i * 80, blank, 80);
/* Update out virtual cursor, and then move the
* hardware cursor */
csr_x = 0;
csr_y = 0;
move_cursor();
}
/* Puts a single character on the screen */
void Console::putch(const char _c){
/* Handle a backspace, by moving the cursor back one space */
if(_c == 0x08)
{
if(csr_x != 0) csr_x--;
}
/* Handles a tab by incrementing the cursor's x, but only
* to a point that will make it divisible by 8 */
else if(_c == 0x09)
{
csr_x = (csr_x + 8) & ~(8 - 1);
}
/* Handles a 'Carriage Return', which simply brings the
* cursor back to the margin */
else if(_c == '\r')
{
csr_x = 0;
}
/* We handle our newlines the way DOS and the BIOS do: we
* treat it as if a 'CR' was also there, so we bring the
* cursor to the margin and we increment the 'y' value */
else if(_c == '\n')
{
csr_x = 0;
csr_y++;
}
/* Any character greater than and including a space, is a
* printable character. The equation for finding the index
* in a linear chunk of memory can be represented by:
* Index = [(y * width) + x] */
else if(_c >= ' ')
{
unsigned short * where = textmemptr + (csr_y * 80 + csr_x);
*where = _c | (attrib << 8); /* Character AND attributes: color */
csr_x++;
}
/* If the cursor has reached the edge of the screen's width, we
* insert a new line in there */
if(csr_x >= 80)
{
csr_x = 0;
csr_y++;
}
/* Scroll the screen if needed, and finally move the cursor */
scroll();
move_cursor();
}
/* Uses the above routine to output a string... */
void Console::puts(const char * _s) {
for (int i = 0; i < strlen(_s); i++) {
putch(_s[i]);
}
}
void Console::puti(const int _n) {
char foostr[15];
int2str(_n, foostr);
puts(foostr);
}
void Console::putui(const unsigned int _n) {
char foostr[15];
uint2str(_n, foostr);
putch('<');
puts(foostr);
putch('>');
}
/* -- COLOR CONTROL -- */
void Console::set_TextColor(const unsigned char _forecolor,
const unsigned char _backcolor) {
/* Top 4 bytes are the background, bottom 4 bytes
* are the foreground color */
attrib = (_backcolor << 4) | (_forecolor & 0x0F);
}

113
MP3/MP3_Sources/console.H Executable file
View file

@ -0,0 +1,113 @@
/*
File: Console.H
Author : R. Bettati
Department of Computer Science
Texas A&M University
Date : 09/02/12
The class Console encapsulates the output operations ot the console
screen. Since the console is initialized at the very beginning of the
boot-up of the operating system, when no memory management is available
yet, all functions and storage for the console are static.
The console is initialized with an "init" function instead of a
constructor. (We don't want to deal with constructors that are called
before the "main()" function.)
By making all functions static, we can access them across all object
files without having to declare a global Console object or pass pointers
to a locally declared object.
*/
#ifndef _Console_H_ // include file only once
#define _Console_H_
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
/* -- (none -- */
/*--------------------------------------------------------------------------*/
/* DATA STRUCTURES */
/*--------------------------------------------------------------------------*/
typedef enum {
BLACK = 0,
BLUE = 1,
GREEN = 2,
CYAN = 3,
RED = 4,
MAGENTA = 5,
BROWN = 6,
LIGHT_GREY = 7,
DARK_GREY = 8,
LIGHT_BLUE = 9,
LIGHT_GREEN = 10,
LIGHT_CYAN = 11,
LIGHT_RED = 12,
LIGHT_MAGENTA = 13,
LIGHT_BROWN = 14,
WHITE = 15
} COLOR_CODE;
/*--------------------------------------------------------------------------*/
/* FORWARDS */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* CLASS C o n s o l e */
/*--------------------------------------------------------------------------*/
class Console {
private:
static int attrib; /* background and foreground color */
static int csr_x; /* position of cursor */
static int csr_y;
static unsigned short * textmemptr; /* text pointer */
public:
/* -- INITIALIZER (we have no constructor, there is no memory mgmt yet.) */
static void init(unsigned char _fore_color = WHITE,
unsigned char _back_color = BLACK);
static void scroll();
static void move_cursor();
/* Update the hardware cursor. */
static void cls();
/* Clear the screen. */
static void putch(const char _c);
/* Put a single character on the screen. */
static void puts(const char * _s);
/* Display a NULL-terminated string on the screen.*/
static void puti(const int _i);
/* Display a integer on the screen.*/
static void putui(const unsigned int _u);
/* Display a unsigned integer on the screen.*/
static void set_TextColor(unsigned char _fore_color, unsigned char _back_color);
/* Set the color of the foreground and background. */
};
#endif

View file

@ -0,0 +1,404 @@
/*
File: ContFramePool.C
Author:
Date :
*/
/*--------------------------------------------------------------------------*/
/*
POSSIBLE IMPLEMENTATION
-----------------------
The class SimpleFramePool in file "simple_frame_pool.H/C" describes an
incomplete vanilla implementation of a frame pool that allocates
*single* frames at a time. Because it does allocate one frame at a time,
it does not guarantee that a sequence of frames is allocated contiguously.
This can cause problems.
The class ContFramePool has the ability to allocate either single frames,
or sequences of contiguous frames. This affects how we manage the
free frames. In SimpleFramePool it is sufficient to maintain the free
frames.
In ContFramePool we need to maintain free *sequences* of frames.
This can be done in many ways, ranging from extensions to bitmaps to
free-lists of frames etc.
IMPLEMENTATION:
One simple way to manage sequences of free frames is to add a minor
extension to the bitmap idea of SimpleFramePool: Instead of maintaining
whether a frame is FREE or ALLOCATED, which requires one bit per frame,
we maintain whether the frame is FREE, or ALLOCATED, or HEAD-OF-SEQUENCE.
The meaning of FREE is the same as in SimpleFramePool.
If a frame is marked as HEAD-OF-SEQUENCE, this means that it is allocated
and that it is the first such frame in a sequence of frames. Allocated
frames that are not first in a sequence are marked as ALLOCATED.
NOTE: If we use this scheme to allocate only single frames, then all
frames are marked as either FREE or HEAD-OF-SEQUENCE.
NOTE: In SimpleFramePool we needed only one bit to store the state of
each frame. Now we need two bits. In a first implementation you can choose
to use one char per frame. This will allow you to check for a given status
without having to do bit manipulations. Once you get this to work,
revisit the implementation and change it to using two bits. You will get
an efficiency penalty if you use one char (i.e., 8 bits) per frame when
two bits do the trick.
DETAILED IMPLEMENTATION:
How can we use the HEAD-OF-SEQUENCE state to implement a contiguous
allocator? Let's look a the individual functions:
Constructor: Initialize all frames to FREE, except for any frames that you
need for the management of the frame pool, if any.
get_frames(_n_frames): Traverse the "bitmap" of states and look for a
sequence of at least _n_frames entries that are FREE. If you find one,
mark the first one as HEAD-OF-SEQUENCE and the remaining _n_frames-1 as
ALLOCATED.
release_frames(_first_frame_no): Check whether the first frame is marked as
HEAD-OF-SEQUENCE. If not, something went wrong. If it is, mark it as FREE.
Traverse the subsequent frames until you reach one that is FREE or
HEAD-OF-SEQUENCE. Until then, mark the frames that you traverse as FREE.
mark_inaccessible(_base_frame_no, _n_frames): This is no different than
get_frames, without having to search for the free sequence. You tell the
allocator exactly which frame to mark as HEAD-OF-SEQUENCE and how many
frames after that to mark as ALLOCATED.
needed_info_frames(_n_frames): This depends on how many bits you need
to store the state of each frame. If you use a char to represent the state
of a frame, then you need one info frame for each FRAME_SIZE frames.
A WORD ABOUT RELEASE_FRAMES():
When we releae a frame, we only know its frame number. At the time
of a frame's release, we don't know necessarily which pool it came
from. Therefore, the function "release_frame" is static, i.e.,
not associated with a particular frame pool.
This problem is related to the lack of a so-called "placement delete" in
C++. For a discussion of this see Stroustrup's FAQ:
http://www.stroustrup.com/bs_faq2.html#placement-delete
*/
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "cont_frame_pool.H"
#include "console.H"
#include "utils.H"
#include "assert.H"
/*--------------------------------------------------------------------------*/
/* DATA STRUCTURES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* CONSTANTS */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* FORWARDS */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* METHODS FOR CLASS C o n t F r a m e P o o l */
/*--------------------------------------------------------------------------*/
ContFramePool* ContFramePool::pools = (ContFramePool *) FRAME_SIZE; // List of frame pools, managed by the class
unsigned int ContFramePool::nPools = 0; // Number of pools being managed
ContFramePool::ContFramePool(unsigned long _base_frame_no,
unsigned long _n_frames,
unsigned long _info_frame_no,
unsigned long _n_info_frames)
{
// Bitmap must fit in a single frame!
// NOTE: In theory, we don't need to make the bitmap any larger,
// since as stated in the instructions it is already big enough to
// hold for 128MB of memory with one bit per frame, so should still
// be enough for 64MB of memory with 2 bits per frame.
// Assertion changed to match max size of frames allowed.
assert(_n_frames <= FRAME_SIZE * 4);
base_frame_no = _base_frame_no;
nframes = _n_frames;
nFreeFrames = _n_frames;
info_frame_no = _info_frame_no;
n_info_frames = _n_info_frames;
// If _info_frame_no is zero then we keep management info in the first
// frame(s), else we use the provided frame(s) to keep management info
// NOTE: bitmap needs to be allocated with n_info_frames if specified.
if(info_frame_no == 0)
{
bitmap = (unsigned char *) (base_frame_no * FRAME_SIZE);
}
else
{
bitmap = (unsigned char *) (info_frame_no * FRAME_SIZE * n_info_frames);
}
// Number of frames must "fill" the bitmap!
assert ((nframes % 8 ) == 0);
// Everything ok. Proceed to mark all bits in the bitmap
// NOTE: changed to reflect that I need 2 bits per frame now
for(int i=0; i*4 < _n_frames; i++)
{
bitmap[i] = 0xFF;
}
// Mark the first frame as being used if it is being used
// NOTE: need to mark multiple frames if needed.
if(info_frame_no == 0)
{
bitmap[0] = 0x3F;
nFreeFrames--;
}
else
{
unsigned int i = info_frame_no / 4;
unsigned int r = info_frame_no % 4;
unsigned char mask = 0x80;
mask = mask >> r*2;
unsigned int c = 0;
while(c < n_info_frames)
{
bitmap[i] = bitmap[i] ^ mask;
bitmap[i] = bitmap[i] ^ (mask >> 1);
if(mask == 0x02)
{
i++;
mask = 0x80;
}
c++;
nFreeFrames--;
}
}
pools[nPools] = *this;
nPools += 1;
Console::puts("Frame Pool initialized\n");
}
unsigned long ContFramePool::get_frames(unsigned int _n_frames)
{
// Are there enough frames left to allocate?
assert(nFreeFrames > _n_frames);
// Find a frame that is not being used and return its frame index.
// Mark that frame as being used in the bitmap.
// NOTE: Must be updated to find a sequence of contiguous frames
// that are not being used and return the index of the head.
unsigned int frame_no = base_frame_no;
// i is being used as the frame_no / 4
// j is frame_no % 4
// together, they will give the actual frame_no.
// c is used as a counter to count a squence of free frames.
unsigned int i = 0;
unsigned int j = 0;
unsigned int c = 0;
while (true)
{
unsigned char mask = 0x80 >> (j*2);
// check every 2 bits for a free frame in the bitmap
while((mask & bitmap[i]) == 0 || ((mask >> 1) & bitmap[i]) == 0)
{
if(mask != 0x02)
{
j++;
mask = mask >> 2;
}
else
{
i++;
j = 0;
mask = 0x80;
}
}
// if frame is found, start checking for sequence
unsigned int temp = i;
c++;
while(c < _n_frames)
{
if(mask != 0x02)
{
mask = mask >> 2;
}
else
{
temp++;
mask = 0x80;
}
if((mask & bitmap[temp]) != 0 && ((mask >> 1) & bitmap[temp]) != 0)
{
c++;
}
else
{
c = 0;
break;
}
}
if(c == _n_frames)
{
nFreeFrames -= _n_frames;
break;
}
}
frame_no += i*4 + j;
// Update bitmap
// First: clear most significant bit to mark head of sequence.
bitmap[i] = bitmap[i] ^ (0x80 >> (j*2));
// Second: clear both bits for all remaining frames in the sequence.
c = 1;
unsigned char mask = 0x80 >> j*2;
unsigned int temp = i;
while(c < _n_frames)
{
if(mask != 0x02)
{
mask = mask >> 2;
}
else
{
temp++;
mask = 0x80;
}
bitmap[temp] = bitmap[temp] ^ mask;
bitmap[temp] = bitmap[temp] ^ (mask >> 1);
c++;
}
return (frame_no);
}
void ContFramePool::mark_inaccessible(unsigned long _base_frame_no,
unsigned long _n_frames)
{
// Mark all frames in the range as being used.
int i ;
for(i = _base_frame_no; i < _base_frame_no + _n_frames; i++){
mark_inaccessible(i);
}
nFreeFrames -= _n_frames;
}
void ContFramePool::mark_inaccessible(unsigned long _frame_no)
{
// Let's first do a range check.
assert ((_frame_no >= base_frame_no) && (_frame_no < base_frame_no + nframes));
unsigned int bitmap_index = (_frame_no - base_frame_no) / 4;
unsigned char mask = 0x80 >> ((_frame_no - base_frame_no) % 4) * 2;
// Is the frame being used already?
assert(((bitmap[bitmap_index] & mask) != 0) && (bitmap[bitmap_index] & (mask >> 1)) != 0);
// Update bitmap
bitmap[bitmap_index] ^= mask;
bitmap[bitmap_index] ^= mask >> 1;
nFreeFrames--;
}
void ContFramePool::release_frames(unsigned long _frame_no)
{
unsigned int i = 0;
while(i < nPools)
{
if(_frame_no <= pools[i].base_frame_no || _frame_no > (pools[i].base_frame_no + pools[i].nframes))
{
i++;
}
else
{
pools[i].release_frames_here(_frame_no);
return;
}
}
}
void ContFramePool::release_frames_here(unsigned long _first_frame_no)
{
unsigned char * bitmap = this->bitmap;
unsigned int bitmap_index = (_first_frame_no - base_frame_no) / 4;
unsigned char mask = 0x80 >> ((_first_frame_no - base_frame_no) % 4) * 2;
if(!((bitmap[bitmap_index] & mask) == 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0))
{
if((bitmap[bitmap_index] & mask) != 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0)
{
Console::puts("Error, Frame being released is not being used\n");
assert(false);
}
Console::puts("Error, Frame being released is not head of sequence\n");
assert(false);
}
bitmap[bitmap_index] ^= mask;
nFreeFrames++;
if(mask != 0x02)
{
mask = mask >> 2;
}
else
{
mask = 0x80;
bitmap_index++;
}
while(bitmap[bitmap_index] & mask == 0 && (bitmap[bitmap_index] & (mask >> 1)) == 0)
{
bitmap[bitmap_index] ^= mask;
bitmap[bitmap_index] ^= (mask >> 1);
if(mask != 0x02)
{
mask = mask >> 2;
}
else
{
mask = 0x80;
bitmap_index++;
}
nFreeFrames++;
}
}
unsigned long ContFramePool::needed_info_frames(unsigned long _n_frames)
{
return (_n_frames / (FRAME_SIZE * 4)) + (_n_frames % (FRAME_SIZE * 4) > 0 ? 1 : 0);
}

132
MP3/MP3_Sources/cont_frame_pool.H Executable file
View file

@ -0,0 +1,132 @@
/*
File: cont_frame_pool.H
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 17/02/04
Description: Management of the CONTIGUOUS Free-Frame Pool.
As opposed to a non-contiguous free-frame pool, here we can allocate
a sequence of CONTIGUOUS frames.
*/
#ifndef _CONT_FRAME_POOL_H_ // include file only once
#define _CONT_FRAME_POOL_H_
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "machine.H"
/*--------------------------------------------------------------------------*/
/* DATA STRUCTURES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* C o n t F r a m e P o o l */
/*--------------------------------------------------------------------------*/
class ContFramePool {
private:
/* -- DEFINE YOUR CONT FRAME POOL DATA STRUCTURE(s) HERE. */
unsigned char * bitmap; // Remember the bitmap here needs 2 bits per frame
unsigned int nFreeFrames; //
unsigned long base_frame_no; // Where does the frame pool start in phys mem?
unsigned long nframes; // Size of the frame pool
unsigned long info_frame_no; // Where do we store the management information?
unsigned long n_info_frames; // Number of frames needed to store management info
static ContFramePool* pools; // List of frame pools, managed by the class
static unsigned int nPools; // Number of pools being managed
void mark_inaccessible(unsigned long _frame_no); // Should be a frame marked as
// a head, otherwise fails
void release_frames_here(unsigned long _frame_no); // non-static member function
public:
// The frame size is the same as the page size, duh...
static const unsigned int FRAME_SIZE = Machine::PAGE_SIZE;
ContFramePool(unsigned long _base_frame_no,
unsigned long _n_frames,
unsigned long _info_frame_no,
unsigned long _n_info_frames);
/*
Initializes the data structures needed for the management of this
frame pool.
_base_frame_no: Number of first frame managed by this frame pool.
_n_frames: Size, in frames, of this frame pool.
EXAMPLE: If _base_frame_no is 16 and _n_frames is 4, this frame pool manages
physical frames numbered 16, 17, 18 and 19.
_info_frame_no: Number of the first frame that should be used to store the
management information for the frame pool.
NOTE: If _info_frame_no is 0, the frame pool is free to
choose any frames from the pool to store management information.
_n_info_frames: If _info_frame_no is 0, this argument specifies the
number of consecutive frames needed to store the management information
for the frame pool.
EXAMPLE: If _info_frame_no is 699 and _n_info_frames is 3,
then Frames 699, 700, and 701 are used to store the management information
for the frame pool.
NOTE: This function must be called before the paging system
is initialized.
*/
unsigned long get_frames(unsigned int _n_frames);
/*
Allocates a number of contiguous frames from the frame pool.
_n_frames: Size of contiguous physical memory to allocate,
in number of frames.
If successful, returns the frame number of the first frame.
If fails, returns 0.
*/
void mark_inaccessible(unsigned long _base_frame_no,
unsigned long _n_frames);
/*
Marks a contiguous area of physical memory, i.e., a contiguous
sequence of frames, as inaccessible.
_base_frame_no: Number of first frame to mark as inaccessible.
_n_frames: Number of contiguous frames to mark as inaccessible.
*/
static void release_frames(unsigned long _frame_no);
/*
Releases a previously allocated contiguous sequence of frames
back to its frame pool.
The frame sequence is identified by the number of the first frame.
NOTE: This function is static because there may be more than one frame pool
defined in the system, and it is unclear which one this frame belongs to.
This function must first identify the correct frame pool and then call the frame
pool's release_frame function.
*/
static unsigned long needed_info_frames(unsigned long _n_frames);
/*
Returns the number of frames needed to manage a frame pool of size _n_frames.
The number returned here depends on the implementation of the frame pool and
on the frame size.
EXAMPLE: For FRAME_SIZE = 4096 and a bitmap with a single bit per frame
(not appropriate for contiguous allocation) one would need one frame to manage a
frame pool with up to 8 * 4096 = 32k frames = 128MB of memory!
This function would therefore return the following value:
_n_frames / 32k + (_n_frames % 32k > 0 ? 1 : 0) (always round up!)
Other implementations need a different number of info frames.
The exact number is computed in this function..
*/
};
#endif

5
MP3/MP3_Sources/copykernel.sh Executable file
View file

@ -0,0 +1,5 @@
# Replace "/mnt/floppy" with the whatever directory is appropriate.
sudo mount -o loop dev_kernel_grub.img /mnt/floppy
sudo cp kernel.bin /mnt/floppy
sleep 1s
sudo umount /mnt/floppy

Binary file not shown.

183
MP3/MP3_Sources/exceptions.C Executable file
View file

@ -0,0 +1,183 @@
/*
File: exceptions.C
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 12/09/05
*/
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "assert.H"
#include "utils.H"
#include "console.H"
#include "idt.H"
#include "exceptions.H"
/*--------------------------------------------------------------------------*/
/* EXTERNS */
/*--------------------------------------------------------------------------*/
/* The low-level functions (defined in file 'IDT::low.s') that handle the
32 Intel-defined CPU exceptions.
These functions are actually merely stubs that put the error code and
the exception code on the stack and then call a low-level function, which
in turn calls the exception dispatcher (defined in 'exceptions.H').
Yes, there are more efficient ways to handle exceptions, but they require more
code replication.
*/
extern "C" void isr0();
extern "C" void isr1();
extern "C" void isr2();
extern "C" void isr3();
extern "C" void isr4();
extern "C" void isr5();
extern "C" void isr6();
extern "C" void isr7();
extern "C" void isr8();
extern "C" void isr9();
extern "C" void isr10();
extern "C" void isr11();
extern "C" void isr12();
extern "C" void isr13();
extern "C" void isr14();
extern "C" void isr15();
extern "C" void isr16();
extern "C" void isr17();
extern "C" void isr18();
extern "C" void isr19();
extern "C" void isr20();
extern "C" void isr21();
extern "C" void isr22();
extern "C" void isr23();
extern "C" void isr24();
extern "C" void isr25();
extern "C" void isr26();
extern "C" void isr27();
extern "C" void isr28();
extern "C" void isr29();
extern "C" void isr30();
extern "C" void isr31();
extern "C" void lowlevel_dispatch_exception(REGS * _r) {
ExceptionHandler::dispatch_exception(_r);
}
/*--------------------------------------------------------------------------*/
/* STATIC VARIABLES */
/*--------------------------------------------------------------------------*/
ExceptionHandler * ExceptionHandler::handler_table[ExceptionHandler::EXCEPTION_TABLE_SIZE];
/*--------------------------------------------------------------------------*/
/* EXPORTED EXCEPTION DISPATCHER FUNCTIONS */
/*--------------------------------------------------------------------------*/
void ExceptionHandler::init_dispatcher() {
/* -- INITIALIZE LOW-LEVEL EXCEPTION HANDLERS */
/* Add any new ISRs to the IDT here using IDT::set_gate */
IDT::set_gate( 0, (unsigned) isr0, 0x08, 0x8E);
IDT::set_gate( 1, (unsigned) isr1, 0x08, 0x8E);
IDT::set_gate( 2, (unsigned) isr2, 0x08, 0x8E);
IDT::set_gate( 3, (unsigned) isr3, 0x08, 0x8E);
IDT::set_gate( 4, (unsigned) isr4, 0x08, 0x8E);
IDT::set_gate( 5, (unsigned) isr5, 0x08, 0x8E);
IDT::set_gate( 6, (unsigned) isr6, 0x08, 0x8E);
IDT::set_gate( 7, (unsigned) isr7, 0x08, 0x8E);
IDT::set_gate( 8, (unsigned) isr8, 0x08, 0x8E);
IDT::set_gate( 9, (unsigned) isr9, 0x08, 0x8E);
IDT::set_gate(10, (unsigned)isr10, 0x08, 0x8E);
IDT::set_gate(11, (unsigned)isr11, 0x08, 0x8E);
IDT::set_gate(12, (unsigned)isr12, 0x08, 0x8E);
IDT::set_gate(13, (unsigned)isr13, 0x08, 0x8E);
IDT::set_gate(14, (unsigned)isr14, 0x08, 0x8E);
IDT::set_gate(15, (unsigned)isr15, 0x08, 0x8E);
IDT::set_gate(16, (unsigned)isr16, 0x08, 0x8E);
IDT::set_gate(17, (unsigned)isr17, 0x08, 0x8E);
IDT::set_gate(18, (unsigned)isr18, 0x08, 0x8E);
IDT::set_gate(19, (unsigned)isr19, 0x08, 0x8E);
IDT::set_gate(20, (unsigned)isr20, 0x08, 0x8E);
IDT::set_gate(21, (unsigned)isr21, 0x08, 0x8E);
IDT::set_gate(22, (unsigned)isr22, 0x08, 0x8E);
IDT::set_gate(23, (unsigned)isr23, 0x08, 0x8E);
IDT::set_gate(24, (unsigned)isr24, 0x08, 0x8E);
IDT::set_gate(25, (unsigned)isr25, 0x08, 0x8E);
IDT::set_gate(26, (unsigned)isr26, 0x08, 0x8E);
IDT::set_gate(27, (unsigned)isr27, 0x08, 0x8E);
IDT::set_gate(28, (unsigned)isr28, 0x08, 0x8E);
IDT::set_gate(29, (unsigned)isr29, 0x08, 0x8E);
IDT::set_gate(30, (unsigned)isr30, 0x08, 0x8E);
IDT::set_gate(31, (unsigned)isr31, 0x08, 0x8E);
/* -- INITIALIZE THE HIGH-LEVEL EXCEPTION HANDLER */
int i;
for(i = 0; i < EXCEPTION_TABLE_SIZE; i++) {
handler_table[i] = NULL;
}
}
void ExceptionHandler::dispatch_exception(REGS * _r) {
/* -- EXCEPTION NUMBER */
unsigned int exc_no = _r->int_no;
Console::puts("EXCEPTION DISPATCHER: exc_no = ");
Console::putui(exc_no);
Console::puts("\n");
assert((exc_no >= 0) && (exc_no < EXCEPTION_TABLE_SIZE));
/* -- HAS A HANDLER BEEN REGISTERED FOR THIS EXCEPTION NO? */
ExceptionHandler * handler = handler_table[exc_no];
if (!handler) {
/* --- NO HANDLER HAS BEEN REGISTERED. SIMPLY RETURN AN ERROR. */
Console::puts("NO DEFAULT EXCEPTION HANDLER REGISTERED\n");
abort();
}
else {
/* -- HANDLE THE EXCEPTION OR INTERRUPT */
handler->handle_exception(_r);
}
}
void ExceptionHandler::register_handler(unsigned int _isr_code,
ExceptionHandler * _handler) {
assert(_isr_code >= 0 && _isr_code < EXCEPTION_TABLE_SIZE);
handler_table[_isr_code] = _handler;
Console::puts("Installed exception handler at ISR ");
Console::putui(_isr_code);
Console::puts("\n");
}
void ExceptionHandler::deregister_handler(unsigned int _isr_code) {
assert(_isr_code >= 0 && _isr_code < EXCEPTION_TABLE_SIZE);
handler_table[_isr_code] = NULL;
Console::puts("UNINSTALLED exception handler at ISR ");
Console::putui(_isr_code);
Console::puts("\n");
}

86
MP3/MP3_Sources/exceptions.H Executable file
View file

@ -0,0 +1,86 @@
/*
File: exceptions.h
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 12/09/05
Description: High-level exception handling.
CPU exceptions are caught by low-level exception and interrupt
handler stubs, which all eventually cause the high-level
exception dispatcher to be called (see 'dispatch_exception() below).
The dispatcher then looks up the appropriate exception handler
for the given exception, and calls it.
Specific exception handlers are installed by registering an exception handler
object of a class appropriately derived from class 'ExceptionHandler'. The
functionality of the exception handler is then implemented in function
'handle_exception(REGS * _regs)'.
*/
#ifndef _exceptions_H_ // include file only once
#define _exceptions_H_
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "assert.H"
#include "machine.H"
/*--------------------------------------------------------------------------*/
/* E x c e p t i o n H a n d l e r */
/*--------------------------------------------------------------------------*/
class ExceptionHandler {
private:
/* The Exception Handler Table */
const static int EXCEPTION_TABLE_SIZE = 32;
static ExceptionHandler * handler_table[EXCEPTION_TABLE_SIZE];
public:
/* -- POPULATE DISPATCHER TABLE */
static void register_handler(unsigned int _isr_code,
ExceptionHandler * _handler);
/* This function allows to install an exception handler for the given
exception code. The handler is a function pointer defined above.
Interrupt handlers are installed as exception handlers as well.
The 'register_interrupt' function uses irq2isr to map the IRQ
number to the code. */
static void deregister_handler(unsigned int _isr_code);
/* -- DISPATCHER */
static void init_dispatcher();
/* This function is called to initialize the high-level exception handling.
No high level exception handlers are installed yet. If an exception
occurs at this point, the system displays an error message and
terminates. */
static void dispatch_exception(REGS * _r);
/* This is the high-level exception dispatcher. It dispatches the exception
to the previously registered exception handler.
This function is called by the low-level function
"lowlevel_dispatch_exception(REGS * _r)".*/
/* -- MANAGE INSTANCES OF EXCEPTION HANDLERS */
virtual void handle_exception(REGS * _regs) {
assert(false); // sometimes pure virtual functions dont link correctly.
}
/* Different exception handlers are derived from the base class ExceptionHandler
and their functionality is implemented in this function.*/
};
#endif

124
MP3/MP3_Sources/gdt.C Executable file
View file

@ -0,0 +1,124 @@
/*
File: gdt.C
Date : 09/03/02
Description: Management of the Global Descriptor Table (GDT)
The GDT describes memory access priviledges for memory segments.
While the table is initialized by GRUB already, it may be a good idea to
do this again in the kernel code.
For details see Section 5 of Brandon Friesen's Tutorial
on OS Kernel Development.
URL: http://www.osdever.net/bkerndev/Docs/title.htm
* bkerndev - Bran's Kernel Development Tutorial
* By: Brandon F. (friesenb@gmail.com)
* Desc: Interrupt Descriptor Table management
*
* Notes: No warranty expressed or implied. Use at own risk.
*/
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
//#include "assert.H"
#include "utils.H"
#include "gdt.H"
/*--------------------------------------------------------------------------*/
/* DATA STRUCTURES */
/*--------------------------------------------------------------------------*/
/* Defines a GDT entry. We use the 'packed' directive to prevent the
compiler from optimizing by aligning structure elements at word
boundaries. */
struct gdt_entry {
unsigned short limit_low;
unsigned short base_low;
unsigned char base_middle;
unsigned char access;
unsigned char granularity;
unsigned char base_high;
} __attribute__((packed));
/* Special pointer that includes the limit: The max bytes
taken up by the GDT, minus 1. Again, this NEEDS to be packed. */
struct gdt_ptr {
unsigned short limit;
unsigned int base;
} __attribute__((packed));
/*--------------------------------------------------------------------------*/
/* VARIABLES */
/*--------------------------------------------------------------------------*/
static struct gdt_entry gdt[GDT::SIZE];
struct gdt_ptr gp;
/*--------------------------------------------------------------------------*/
/* EXTERNS */
/*--------------------------------------------------------------------------*/
/* This function is defined in 'gdt_low.asm', which in turn is included in
'start.asm'. */
extern "C" void gdt_flush();
/*--------------------------------------------------------------------------*/
/* EXPORTED FUNCTIONS */
/*--------------------------------------------------------------------------*/
/* Use this function to set up an entry in the GDT. */
void GDT::set_gate(int num,
unsigned long base, unsigned long limit,
unsigned char access, unsigned char gran) {
/* Setup the descriptor base address */
gdt[num].base_low = (base & 0xFFFF);
gdt[num].base_middle = (base >> 16) & 0xFF;
gdt[num].base_high = (base >> 24) & 0xFF;
/* Setup the descriptor limits */
gdt[num].limit_low = (limit & 0xFFFF);
gdt[num].granularity = ((limit >> 16) & 0x0F);
/* Finally, set up the granularity and access flags */
gdt[num].granularity |= (gran & 0xF0);
gdt[num].access = access;
}
/* Installs the GDT */
void GDT::init() {
/* Sets up the special GDT pointer. */
gp.limit = (sizeof (struct gdt_entry) * SIZE) - 1;
gp.base = (unsigned int)&gdt;
/* Our NULL descriptor */
set_gate(0, 0, 0, 0, 0);
/* The second entry is our Code Segment. The base address
is 0, the limit is 4GByte, it uses 4kB granularity,
uses 32-bit opcodes, and is a Code Segment descriptor.
Please check the GDT section in Bran's Kernel Development
tutorial to see exactly what each value means. */
set_gate(1, 0, 0xFFFFFFFF, 0x9a, 0xCF);
/* The third entry is our Data Segment. It's EXACTLY the
same as the code segment, but the descriptor type in
this entry's access byte says it's a Data Segment. */
set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
/* Flush out the old GDT, and install the new changes. */
gdt_flush();
}

48
MP3/MP3_Sources/gdt.H Executable file
View file

@ -0,0 +1,48 @@
/*
File: gdt.H
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 09/03/02
Description: Management of the Global Descriptor Table (GDT)
The GDT describes memory access priviledges for memory segments.
While the table is initialized by GRUB already, it may be a good idea to
do this again in the kernel code.
For details see Section 5 of Brandon Friesen's Tutotial
on OS Kernel Development.
URL: http://www.osdever.net/bkerndev/Docs/title.htm
*/
#ifndef _GDT_H_ // include file only once
#define _GDT_H_
/*--------------------------------------------------------------------------*/
/* GDT */
/*--------------------------------------------------------------------------*/
class GDT {
private:
/* Use this function to set up an entry in the GDT. */
static void set_gate(int num,
unsigned long base, unsigned long limit,
unsigned char access, unsigned char gran);
public:
static const unsigned int SIZE = 3;
static void init();
/* Initialize the GDT to have a null segment, a code segment,
and one data segment. */
};
#endif

18
MP3/MP3_Sources/gdt_low.asm Executable file
View file

@ -0,0 +1,18 @@
; This will set up our new segment registers. We need to do
; something special in order to set CS. We do what is called a
; far jump. A jump that includes a segment as well as an offset.
; This is declared in C as 'extern void gdt_flush();'
global _gdt_flush ; Allows the C code to link to this.
extern _gp ; Says that '_gp' is in another file
_gdt_flush:
lgdt[_gp] ; Load the GDT with our '_gp', a special pointer
mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; mov ss, ax
jmp 0x08:flush2 ; 0x08 is the offset to our code segment: FAR JUMP!
flush2:
ret ; Returns back to the C code!

108
MP3/MP3_Sources/idt.C Executable file
View file

@ -0,0 +1,108 @@
/*
File: idt.C
Date : 09/03/02
*/
/* Based largely on
* bkerndev - Bran's Kernel Development Tutorial
* By: Brandon F. (friesenb@gmail.com)
* Desc: Interrupt Descriptor Table management
*
* Notes: No warranty expressed or implied. Use at own risk. */
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
//#include "assert.H"
#include "utils.H"
#include "idt.H"
#include "console.H"
/*--------------------------------------------------------------------------*/
/* EXTERNS */
/*--------------------------------------------------------------------------*/
/* Used to load our IDT, defined in 'idt_low.s' */
extern "C" void idt_load();
/*--------------------------------------------------------------------------*/
/* DATA STRUCTURES */
/*--------------------------------------------------------------------------*/
struct idt_entry
{
unsigned short base_lo;
unsigned short sel;
unsigned char always0;
unsigned char flags;
unsigned short base_hi;
} __attribute__((packed));
struct idt_ptr
{
unsigned short limit;
unsigned int base;
} __attribute__((packed));
/*--------------------------------------------------------------------------*/
/* VARIABLES */
/*--------------------------------------------------------------------------*/
/* Declare an IDT of IDT_SIZE entries. We use only the first 32
entries. If any undefined IDT entry is hit, it normally
cause an "Unhandled Interrupt" exception. Any descriptor
for which the 'presence' bit is cleared will generate an
"Unhandled Interrupt" exception. */
struct idt_entry idt[IDT::SIZE];
struct idt_ptr idtp;
/*--------------------------------------------------------------------------*/
/* HOOKING UP THE LOW-LEVEL EXCEPTION HANDLER TO EXCEPTIONDISPATCHER. */
/*--------------------------------------------------------------------------*/
/* Use this function to set an entry in the IDT. */
void IDT::set_gate(unsigned char num, unsigned long base,
unsigned short sel, unsigned char flags) {
Console::puts("Installing handler in IDT position ");
Console::puti((int)num);
Console::puts("\n");
/* The interrupt routine's base address */
idt[num].base_lo = (base & 0xFFFF);
idt[num].base_hi = (base >> 16) & 0xFFFF;
/* The segment or 'selector' that this IDT entry will use
* is set here, along with any access flags */
idt[num].sel = sel;
idt[num].always0 = 0;
idt[num].flags = flags;
}
/* Installs the IDT */
void IDT::init() {
/* Sets the special IDT pointer up. */
idtp.limit = (sizeof (struct idt_entry) * 256) - 1;
idtp.base = (unsigned int)&idt;
/* Clear out the entire IDT, initializing it to zeros. */
memset(&idt, 0, sizeof(struct idt_entry) * 256);
/* Points the processor's internal register to the new IDT */
idt_load();
}

57
MP3/MP3_Sources/idt.H Executable file
View file

@ -0,0 +1,57 @@
/*
File: idt.H
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 09/03/02
Description: the Interrupt Description Table (IDT)
The IDT contains pointer to low-level exception and interrupt handlers.
The way the exception handling is set up, all low-level handlers route
the exception to a single exception dispatcher, which in turn
calls a high-level exception dispatcher (see file 'exceptions.H').
For details see Section 6 of Brandon Friesen's Tutorial
on OS Kernel Development.
URL: http://www.osdever.net/bkerndev/Docs/title.htm
*/
#ifndef _IDT_H_ // include file only once
#define _IDT_H_
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
//#define IDT_SIZE 256
/*--------------------------------------------------------------------------*/
/* Class IDT */
/*--------------------------------------------------------------------------*/
class IDT {
public:
static const int SIZE = 256;
static void init();
/* Initialize the IDT, and fill the 32 first entries with pointers to handle
the 32 Intel-defined exceptions. After initializing the IDT, these exceptions
are routed to the exception dispatcher (see 'exceptions.H'). At this point,
no exception handlers are installed yet.
*/
static void set_gate(unsigned char num, unsigned long base,
unsigned short sel, unsigned char flags);
/* Used to install a low-level exception handler in the IDT. For high-level
exception handlers, use the exception management framework defined in
file 'exceptions.H'.
*/
};
#endif

279
MP3/MP3_Sources/idt_low.asm Executable file
View file

@ -0,0 +1,279 @@
; This is the exception de-multiplexer code.
; All low-level exception handling routines do the following:
; 1. disable interrupts
; 2. push error code on the stack (if the exception did not already
; do so! (Some exceptions automatically push the error code onto the
; stack.)
; 3. push the number of the exception onto the stack.
; 4. call the common interrupt service routine function, which then
; branches back out based on the exception number on the stack.
; (We do this because we don't want to replicate again and again the code
; to save the processor state.)
;
; Here come the interrupt service routines for the 32 exceptions.
global _isr0
global _isr1
global _isr2
global _isr3
global _isr4
global _isr5
global _isr6
global _isr7
global _isr8
global _isr9
global _isr10
global _isr11
global _isr12
global _isr13
global _isr14
global _isr15
global _isr16
global _isr17
global _isr18
global _isr19
global _isr20
global _isr21
global _isr22
global _isr23
global _isr24
global _isr25
global _isr26
global _isr27
global _isr28
global _isr29
global _isr30
global _isr31
extern _promptA
extern _promptB
extern _promptC
; 0: Divide By Zero Exception
_isr0:
push byte 0
push byte 0
jmp isr_common_stub
; 1: Debug Exception
_isr1:
push byte 0
push byte 1
jmp isr_common_stub
; 2: Non Maskable Interrupt Exception
_isr2:
push byte 0
push byte 2
jmp isr_common_stub
; 3: Int 3 Exception
_isr3:
push byte 0
push byte 3
jmp isr_common_stub
; 4: INTO Exception
_isr4:
push byte 0
push byte 4
jmp isr_common_stub
; 5: Out of Bounds Exception
_isr5:
push byte 0
push byte 5
jmp isr_common_stub
; 6: Invalid Opcode Exception
_isr6:
push byte 0
push byte 6
jmp isr_common_stub
; 7: Coprocessor Not Available Exception
_isr7:
push byte 0
push byte 7
jmp isr_common_stub
; 8: Double Fault Exception (With Error Code!)
_isr8:
push byte 8
jmp isr_common_stub
; 9: Coprocessor Segment Overrun Exception
_isr9:
push byte 0
push byte 9
jmp isr_common_stub
; 10: Bad TSS Exception (With Error Code!)
_isr10:
push byte 10
jmp isr_common_stub
; 11: Segment Not Present Exception (With Error Code!)
_isr11:
push byte 11
jmp isr_common_stub
; 12: Stack Fault Exception (With Error Code!)
_isr12:
push byte 12
jmp isr_common_stub
; 13: General Protection Fault Exception (With Error Code!)
_isr13:
push byte 13
jmp isr_common_stub
; 14: Page Fault Exception (With Error Code!)
_isr14:
push byte 14
jmp isr_common_stub
; 15: Reserved Exception
_isr15:
push byte 0
push byte 15
jmp isr_common_stub
; 16: Floating Point Exception
_isr16:
push byte 0
push byte 16
jmp isr_common_stub
; 17: Alignment Check Exception
_isr17:
push byte 0
push byte 17
jmp isr_common_stub
; 18: Machine Check Exception
_isr18:
push byte 0
push byte 18
jmp isr_common_stub
; 19: Reserved
_isr19:
push byte 0
push byte 19
jmp isr_common_stub
; 20: Reserved
_isr20:
push byte 0
push byte 20
jmp isr_common_stub
; 21: Reserved
_isr21:
push byte 0
push byte 21
jmp isr_common_stub
; 22: Reserved
_isr22:
push byte 0
push byte 22
jmp isr_common_stub
; 23: Reserved
_isr23:
push byte 0
push byte 23
jmp isr_common_stub
; 24: Reserved
_isr24:
push byte 0
push byte 24
jmp isr_common_stub
; 25: Reserved
_isr25:
push byte 0
push byte 25
jmp isr_common_stub
; 26: Reserved
_isr26:
push byte 0
push byte 26
jmp isr_common_stub
; 27: Reserved
_isr27:
push byte 0
push byte 27
jmp isr_common_stub
; 28: Reserved
_isr28:
push byte 0
push byte 28
jmp isr_common_stub
; 29: Reserved
_isr29:
push byte 0
push byte 29
jmp isr_common_stub
; 30: Reserved
_isr30:
push byte 0
push byte 30
jmp isr_common_stub
; 31: Reserved
_isr31:
push byte 0
push byte 31
jmp isr_common_stub
; The common stub below will pun out into C. Let the
; assembler know that the function is defined in 'exceptions.C'.
extern _lowlevel_dispatch_exception
; This is the common low-level stub for the exception handler.
; It saves the processor state, sets up for kernel mode
; segments, calls the C-level exception handler,
; and finally restores the stack frame.
isr_common_stub:
pusha
push ds
push es
push fs
push gs
mov eax, esp ; Push us the stack
push eax
mov eax, _lowlevel_dispatch_exception
call eax ; A special call, preserves the 'eip' register
pop eax
pop gs
pop fs
pop es
pop ds
popa
add esp, 8 ; Ceans up the pushed error code and pushed ISR number
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP1
; load the IDT defined in '_idtp' into the processor.
; This is declared in C as 'extern void _idt_load();'
; In turn, the variable '_idtp' is defined in file 'idt.C'.
global _idt_load
extern _idtp
_idt_load:
lidt [_idtp]
ret

172
MP3/MP3_Sources/interrupts.C Executable file
View file

@ -0,0 +1,172 @@
/*
File: interrupts.C
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 12/09/05
*/
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
/* (none) */
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "assert.H"
#include "utils.H"
#include "console.H"
#include "idt.H"
#include "irq.H"
#include "exceptions.H"
#include "interrupts.H"
/*--------------------------------------------------------------------------*/
/* EXTERNS */
/*--------------------------------------------------------------------------*/
/* The low-level functions (defined in file 'irq_low.s') that handle the
16 PIC-generated interrupts.
These functions are actually merely stubs that put the error code and
the exception code on the stack and then call a low-level function, which
in turn calls the interrupt dispatcher.
Yes, there are more efficient ways to handle exceptions, but they require more
code replication.
*/
extern "C" void irq0();
extern "C" void irq1();
extern "C" void irq2();
extern "C" void irq3();
extern "C" void irq4();
extern "C" void irq5();
extern "C" void irq6();
extern "C" void irq7();
extern "C" void irq8();
extern "C" void irq9();
extern "C" void irq10();
extern "C" void irq11();
extern "C" void irq12();
extern "C" void irq13();
extern "C" void irq14();
extern "C" void irq15();
extern "C" void lowlevel_dispatch_interrupt(REGS * _r) {
InterruptHandler::dispatch_interrupt(_r);
}
/*--------------------------------------------------------------------------*/
/* LOCAL VARIABLES */
/*--------------------------------------------------------------------------*/
InterruptHandler * InterruptHandler::handler_table[InterruptHandler::IRQ_TABLE_SIZE];
/*--------------------------------------------------------------------------*/
/* EXPORTED INTERRUPT DISPATCHER FUNCTIONS */
/*--------------------------------------------------------------------------*/
void InterruptHandler::init_dispatcher() {
/* -- INITIALIZE LOW-LEVEL INTERRUPT HANDLERS */
/* Add any new ISRs to the IDT here using IDT::set_gate */
IDT::set_gate( 0+ IRQ_BASE, (unsigned) irq0, 0x08, 0x8E);
IDT::set_gate( 1+ IRQ_BASE, (unsigned) irq1, 0x08, 0x8E);
IDT::set_gate( 2+ IRQ_BASE, (unsigned) irq2, 0x08, 0x8E);
IDT::set_gate( 3+ IRQ_BASE, (unsigned) irq3, 0x08, 0x8E);
IDT::set_gate( 4+ IRQ_BASE, (unsigned) irq4, 0x08, 0x8E);
IDT::set_gate( 5+ IRQ_BASE, (unsigned) irq5, 0x08, 0x8E);
IDT::set_gate( 6+ IRQ_BASE, (unsigned) irq6, 0x08, 0x8E);
IDT::set_gate( 7+ IRQ_BASE, (unsigned) irq7, 0x08, 0x8E);
IDT::set_gate( 8+ IRQ_BASE, (unsigned) irq8, 0x08, 0x8E);
IDT::set_gate( 9+ IRQ_BASE, (unsigned) irq9, 0x08, 0x8E);
IDT::set_gate(10+ IRQ_BASE, (unsigned)irq10, 0x08, 0x8E);
IDT::set_gate(11+ IRQ_BASE, (unsigned)irq11, 0x08, 0x8E);
IDT::set_gate(12+ IRQ_BASE, (unsigned)irq12, 0x08, 0x8E);
IDT::set_gate(13+ IRQ_BASE, (unsigned)irq13, 0x08, 0x8E);
IDT::set_gate(14+ IRQ_BASE, (unsigned)irq14, 0x08, 0x8E);
IDT::set_gate(15+ IRQ_BASE, (unsigned)irq15, 0x08, 0x8E);
/* -- INITIALIZE THE HIGH-LEVEL INTERRUPT HANDLER */
int i;
for(i = 0; i < IRQ_TABLE_SIZE; i++) {
handler_table[i] = NULL;
}
}
bool InterruptHandler::generated_by_slave_PIC(unsigned int int_no) {
return int_no > 7;
}
void InterruptHandler::dispatch_interrupt(REGS * _r) {
/* -- INTERRUPT NUMBER */
unsigned int int_no = _r->int_no - IRQ_BASE;
//Console::puts("INTERRUPT DISPATCHER: int_no = ");
//Console::putui(int_no);
//Console::puts("\n");
assert((int_no >= 0) && (int_no < IRQ_TABLE_SIZE));
/* -- HAS A HANDLER BEEN REGISTERED FOR THIS INTERRUPT NO? */
InterruptHandler * handler = handler_table[int_no];
if (!handler) {
/* --- NO DEFAULT HANDLER HAS BEEN REGISTERED. SIMPLY RETURN AN ERROR. */
Console::puts("INTERRUPT NO: ");
Console::puti(int_no);
Console::puts("\n");
Console::puts("NO DEFAULT INTERRUPT HANDLER REGISTERED\n");
// abort();
}
else {
/* -- HANDLE THE INTERRUPT */
handler->handle_interrupt(_r);
}
/* This is an interrupt that was raised by the interrupt controller. We need
to send and end-of-interrupt (EOI) signal to the controller after the
interrupt has been handled. */
/* Check if the interrupt was generated by the slave interrupt controller.
If so, send an End-of-Interrupt (EOI) message to the slave controller. */
if (generated_by_slave_PIC(int_no)) {
Machine::outportb(0xA0, 0x20);
}
/* Send an EOI message to the master interrupt controller. */
Machine::outportb(0x20, 0x20);
}
void InterruptHandler::register_handler(unsigned int _irq_code,
InterruptHandler * _handler) {
assert(_irq_code >= 0 && _irq_code < IRQ_TABLE_SIZE);
handler_table[_irq_code] = _handler;
Console::puts("Installed interrupt handler at IRQ ");
Console::putui(_irq_code);
Console::puts("\n");
}
void InterruptHandler::deregister_handler(unsigned int _irq_code) {
assert(_irq_code >= 0 && _irq_code < IRQ_TABLE_SIZE);
handler_table[_irq_code] = NULL;
Console::puts("UNINSTALLED interrupt handler at IRQ ");
Console::putui(_irq_code);
Console::puts("\n");
}

90
MP3/MP3_Sources/interrupts.H Executable file
View file

@ -0,0 +1,90 @@
/*
File: interrupts.H
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 11/11/10
Description: High-level interrupt handling.
CPU exceptions are caught by low-level exception and interrupt
handler stubs, which all eventually cause the high-level
exception dispatcher to be called (see 'dispatch_exception() below).
The dispatcher then looks up the appropriate exception handler
for the given exception, and calls it.
Specific exception handlers are installed by registering an exception handler
object of a class appropriately derived from class 'ExceptionHandler'. The
functionality of the exception handler is then implemented in function
'handle_exception(REGS * _regs)'.
*/
#ifndef _interrupts_H_ // include file only once
#define _interrupts_H_
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "assert.H"
#include "machine.H"
#include "exceptions.H"
/*--------------------------------------------------------------------------*/
/* I n t e r r u p t H a n d l e r */
/*--------------------------------------------------------------------------*/
class InterruptHandler {
private:
/* The Interrupt Handler Table */
const static int IRQ_TABLE_SIZE = 16;
const static int IRQ_BASE = 32;
static InterruptHandler * handler_table[IRQ_TABLE_SIZE];
static bool generated_by_slave_PIC(unsigned int int_no);
/* Has the particular interupt been generated by the Slave PIC? */
public:
/* -- POPULATE INTERRUPT-DISPATCHER TABLE */
static void register_handler(unsigned int _irq_code,
InterruptHandler * _handler);
/* This function allows to install an interrupt handler for the given
Interrupt code. The handler is a function pointer defined above.
Interrupt handlers are installed as Interrupt handlers as well.
The 'register_interrupt' function uses irq2isr to map the IRQ
number to the code. */
static void deregister_handler(unsigned int _irq_code);
/* -- INITIALIZER */
static void init_dispatcher();
/* This function is called to initialize the high-level interrupt
handling. No high level interrupt handlers are installed yet.
If an interrupt occurs at this point, the system displays an error
message and terminates. */
static void dispatch_interrupt(REGS * _r);
/* This is the high-level interrupt dispatcher. It dispatches the interrupt
to the previously registered interrupt handler.
This function is called by the low-level function
"lowlevel_dispatch_interrupt(REGS * _r)".*/
/* -- MANAGE INSTANCES OF INTERRUPT HANDLERS */
virtual void handle_interrupt(REGS * _regs) {
assert(false); // sometimes pure virtual functions don't link correctly.
}
/* Different interrupt handlers are derived from the base class
InterruptHandler, and their functionality is implemented in
this function.*/
};
#endif

60
MP3/MP3_Sources/irq.C Executable file
View file

@ -0,0 +1,60 @@
/*
File: irq.C
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 09/03/05
This code borrows heavily from Brandon Friesen's the code in Brandon
Friesen's OS Development Tutorial.
*/
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
#define IRQ_BASE 32
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "machine.H"
#include "irq.H"
/*--------------------------------------------------------------------------*/
/* LOCAL FUNCTIONS . */
/*--------------------------------------------------------------------------*/
/* Normally, IRQs 0 to 7 are mapped to IDT entries 8 to 15.
For a variety of reasons it is a good idea to re-map these
IRQs to different locations
We send a sequence of commands to the PICs - 8259's - in order
to have IRQ0 to IRQ15 be remapped to IDT entries 32 to 47.
*/
static void irq_remap()
{
Machine::outportb(0x20, 0x11);
Machine::outportb(0xA0, 0x11);
Machine::outportb(0x21, 0x20);
Machine::outportb(0xA1, 0x28);
Machine::outportb(0x21, 0x04);
Machine::outportb(0xA1, 0x02);
Machine::outportb(0x21, 0x01);
Machine::outportb(0xA1, 0x01);
Machine::outportb(0x21, 0x0);
Machine::outportb(0xA1, 0x0);
}
/*--------------------------------------------------------------------------*/
/* EXPORTED FUNCTIONS . */
/*--------------------------------------------------------------------------*/
void IRQ::init() {
irq_remap();
}

38
MP3/MP3_Sources/irq.H Executable file
View file

@ -0,0 +1,38 @@
/*
File: irq.H
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 09/03/02
Description: Interrupt Table (IRQ)
For details see Section 7 of Brandon Friesen's Tutorial
on OS Kernel Development.
URL: http://www.osdever.net/bkerndev/Docs/title.htm
*/
#ifndef _IRQ_H_ // include file only once
#define _IRQ_H_
/*--------------------------------------------------------------------------*/
/* */
/*--------------------------------------------------------------------------*/
class IRQ {
public:
static void init();
/* Initialize the IRQ handlers, i.e. fill 16 entries with pointers to handle
the PIC generated interrupts. These interrupts are routed to the exception
dispatcher (see 'exceptions.H'). At this point, no exception handlers are
installed yet.
*/
};
#endif

136
MP3/MP3_Sources/irq_low.asm Executable file
View file

@ -0,0 +1,136 @@
global _irq0
global _irq1
global _irq2
global _irq3
global _irq4
global _irq5
global _irq6
global _irq7
global _irq8
global _irq9
global _irq10
global _irq11
global _irq12
global _irq13
global _irq14
global _irq15
; 32: IRQ0
_irq0:
push byte 0
push byte 32
jmp irq_common_stub
; 33: IRQ1
_irq1:
push byte 0
push byte 33
jmp irq_common_stub
; 34: IRQ2
_irq2:
push byte 0
push byte 34
jmp irq_common_stub
; 35: IRQ3
_irq3:
push byte 0
push byte 35
jmp irq_common_stub
; 36: IRQ4
_irq4:
push byte 0
push byte 36
jmp irq_common_stub
; 37: IRQ5
_irq5:
push byte 0
push byte 37
jmp irq_common_stub
; 38: IRQ6
_irq6:
push byte 0
push byte 38
jmp irq_common_stub
; 39: IRQ7
_irq7:
push byte 0
push byte 39
jmp irq_common_stub
; 40: IRQ8
_irq8:
push byte 0
push byte 40
jmp irq_common_stub
; 41: IRQ9
_irq9:
push byte 0
push byte 41
jmp irq_common_stub
; 42: IRQ10
_irq10:
push byte 0
push byte 42
jmp irq_common_stub
; 43: IRQ11
_irq11:
push byte 0
push byte 43
jmp irq_common_stub
; 44: IRQ12
_irq12:
push byte 0
push byte 44
jmp irq_common_stub
; 45: IRQ13
_irq13:
push byte 0
push byte 45
jmp irq_common_stub
; 46: IRQ14
_irq14:
push byte 0
push byte 46
jmp irq_common_stub
; 47: IRQ15
_irq15:
push byte 0
push byte 47
jmp irq_common_stub
extern _lowlevel_dispatch_interrupt
irq_common_stub:
pusha
push ds
push es
push fs
push gs
mov eax, esp
push eax
mov eax, _lowlevel_dispatch_interrupt
call eax
pop eax
pop gs
pop fs
pop es
pop ds
popa
add esp, 8
iret

196
MP3/MP3_Sources/kernel.C Executable file
View file

@ -0,0 +1,196 @@
/*
File: kernel.C
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 12/09/03
This file has the main entry point to the operating system.
*/
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "machine.H" /* LOW-LEVEL STUFF */
#include "console.H"
#include "gdt.H"
#include "idt.H" /* LOW-LEVEL EXCEPTION MGMT. */
#include "irq.H"
#include "exceptions.H"
#include "interrupts.H"
#include "simple_keyboard.H" /* SIMPLE KB DRIVER */
#include "simple_timer.H" /* TIMER MANAGEMENT */
#include "page_table.H"
#include "paging_low.H"
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
#define MB * (0x1 << 20)
#define KB * (0x1 << 10)
#define KERNEL_POOL_START_FRAME ((2 MB) / Machine::PAGE_SIZE)
#define KERNEL_POOL_SIZE ((2 MB) / Machine::PAGE_SIZE)
#define PROCESS_POOL_START_FRAME ((4 MB) / Machine::PAGE_SIZE)
#define PROCESS_POOL_SIZE ((28 MB) / Machine::PAGE_SIZE)
/* definition of the kernel and process memory pools */
#define MEM_HOLE_START_FRAME ((15 MB) / Machine::PAGE_SIZE)
#define MEM_HOLE_SIZE ((1 MB) / Machine::PAGE_SIZE)
/* we have a 1 MB hole in physical memory starting at address 15 MB */
#define FAULT_ADDR (4 MB)
/* used in the code later as address referenced to cause page faults. */
#define NACCESS ((1 MB) / 4)
/* NACCESS integer access (i.e. 4 bytes in each access) are made starting at address FAULT_ADDR */
/*--------------------------------------------------------------------------*/
/* MAIN ENTRY INTO THE OS */
/*--------------------------------------------------------------------------*/
int main() {
GDT::init();
Console::init();
IDT::init();
ExceptionHandler::init_dispatcher();
IRQ::init();
InterruptHandler::init_dispatcher();
/* -- EXAMPLE OF AN EXCEPTION HANDLER: Division-by-Zero -- */
class DBZ_Handler : public ExceptionHandler {
/* We derive Division-by-Zero handler from ExceptionHandler
and overload the method handle_exception. */
public:
virtual void handle_exception(REGS * _regs) {
Console::puts("DIVISION BY ZERO!\n");
for(;;);
}
} dbz_handler;
/* Register the DBZ handler for exception no.0
with the exception dispatcher. */
ExceptionHandler::register_handler(0, &dbz_handler);
/* -- EXAMPLE OF AN INTERRUPT HANDLER: Very simple timer -- */
SimpleTimer timer(100); /* timer ticks every 10ms. */
/* ---- Register timer handler for interrupt no.0
with the interrupt dispatcher. */
InterruptHandler::register_handler(0, &timer);
/* NOTE: The timer chip starts periodically firing as
soon as we enable interrupts.
It is important to install a timer handler, as we
would get a lot of uncaptured interrupts otherwise. */
/* -- INSTALL INTERRUPT HANDLER FOR SIMPLE KEYBOARD -- */
SimpleKeyboard::init();
/* NOTE: In the SimpleKeyboard::init() a private static object of
type SimpleKeyboard is created and its interrupt handler is
registered with the interrupt dispatcher. Subsequent calls to the
static function SimpleKeyboard::wait() look until a key is pressed.*/
/* -- ENABLE INTERRUPTS -- */
Machine::enable_interrupts();
/* -- INITIALIZE FRAME POOLS -- */
ContFramePool kernel_mem_pool(KERNEL_POOL_START_FRAME,
KERNEL_POOL_SIZE,
0,
0);
unsigned long n_info_frames = ContFramePool::needed_info_frames(PROCESS_POOL_SIZE);
unsigned long process_mem_pool_info_frame = kernel_mem_pool.get_frames(n_info_frames);
ContFramePool process_mem_pool(PROCESS_POOL_START_FRAME,
PROCESS_POOL_SIZE,
process_mem_pool_info_frame,
n_info_frames);
/* Take care of the hole in the memory. */
process_mem_pool.mark_inaccessible(MEM_HOLE_START_FRAME, MEM_HOLE_SIZE);
/* -- INITIALIZE MEMORY (PAGING) -- */
/* ---- INSTALL PAGE FAULT HANDLER -- */
class PageFault_Handler : public ExceptionHandler {
/* We derive the page fault handler from ExceptionHandler
and overload the method handle_exception. */
public:
virtual void handle_exception(REGS * _regs) {
PageTable::handle_fault(_regs);
}
} pagefault_handler;
/* ---- Register the page fault handler for exception no.14
with the exception dispatcher. */
ExceptionHandler::register_handler(14, &pagefault_handler);
/* ---- INITIALIZE THE PAGE TABLE -- */
PageTable::init_paging(&kernel_mem_pool,
&process_mem_pool,
4 MB); /* We share the first 4MB */
PageTable pt;
pt.load();
PageTable::enable_paging();
Console::puts("WE TURNED ON PAGING!\n");
Console::puts("If we see this message, the page tables have been\n");
Console::puts("set up mostly correctly.\n");
/* -- MOST OF WHAT WE NEED IS SETUP. THE KERNEL CAN START. */
Console::puts("Hello World!\n");
/* -- GENERATE MEMORY REFERENCES */
int *foo = (int *) FAULT_ADDR;
int i;
for (i=0; i<NACCESS; i++) {
foo[i] = i;
}
Console::puts("DONE WRITING TO MEMORY. Now testing...\n");
for (i=0; i<NACCESS; i++) {
if(foo[i] != i) {
Console::puts("TEST FAILED for access number:");
Console::putui(i);
Console::puts("\n");
break;
}
}
if(i == NACCESS) {
Console::puts("TEST PASSED\n");
}
/* -- STOP HERE */
Console::puts("YOU CAN SAFELY TURN OFF THE MACHINE NOW.\n");
for(;;);
/* -- WE DO THE FOLLOWING TO KEEP THE COMPILER HAPPY. */
return 1;
}

36
MP3/MP3_Sources/linker.ld Executable file
View file

@ -0,0 +1,36 @@
OUTPUT_FORMAT("binary")
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text)
*(.gnu.linkonce.t.*)
*(.gnu.linkonce.r.*)
*(.rodata)
. = ALIGN(4096);
}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
start_ctors = .;
*(.ctor*)
end_ctors = .;
start_dtors = .;
*(.dtor*)
end_dtors = .;
*(.gnu.linkonce.d.*)
. = ALIGN(4096);
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
*(.gnu.linkonce.b.*)
. = ALIGN(4096);
}
end = .;
}

70
MP3/MP3_Sources/machine.C Executable file
View file

@ -0,0 +1,70 @@
/*
File: machine.C
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 12/09/04
LOW-LEVEL MACHINE FUNCTIONS.
*/
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "machine.H"
#include "machine_low.H"
#include "assert.H"
/*--------------------------------------------------------------------------*/
/* INTERRUPTS */
/*--------------------------------------------------------------------------*/
bool Machine::interrupts_enabled() {
/* We check the IF flag (INTERRUPT ENABLE) in the EFLAGS status register. */
return get_EFLAGS() & (1 << 9);
}
void Machine::enable_interrupts() {
assert(!interrupts_enabled());
__asm__ __volatile__ ("sti");
}
void Machine::disable_interrupts() {
assert(interrupts_enabled());
__asm__ __volatile__ ("cli");
}
/*--------------------------------------------------------------------------*/
/* PORT I/O OPERATIONS */
/*--------------------------------------------------------------------------*/
/* We will use this later on for reading from the I/O ports to get data
* from devices such as the keyboard. We are using what is called
* 'inline assembly' in these routines to actually do the work */
char Machine::inportb (unsigned short _port) {
unsigned char rv;
__asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port));
return rv;
}
unsigned short Machine::inportw (unsigned short _port) {
unsigned short rv;
__asm__ __volatile__ ("inw %1, %0" : "=a" (rv) : "dN" (_port));
return rv;
}
/* We will use this to write to I/O ports to send bytes to devices. This
* will be used in the next tutorial for changing the textmode cursor
* position. Again, we use some inline assembly for the stuff that simply
* cannot be done in C */
void Machine::outportb (unsigned short _port, char _data) {
__asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
}
void Machine::outportw (unsigned short _port, unsigned short _data) {
__asm__ __volatile__ ("outw %1, %0" : : "dN" (_port), "a" (_data));
}

123
MP3/MP3_Sources/machine.H Executable file
View file

@ -0,0 +1,123 @@
/*
File: machine.H
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 12/09/05
Description: Low-level definitions for x86 architecture.
- Register context
- Data and code segment for kernel.
- Interrupt enable/disable.
*/
#ifndef _machine_H_ // include file only once
#define _machine_H_
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* DATA STRUCTURES */
/*--------------------------------------------------------------------------*/
/* REGISTER CONTEXT ON THE STACK WHEN EXCEPTION/INTERRUPT REACHES EXCEPTION
DISPATCHER OR INTERRUPT DISPATCHER.
THIS IS ALSO USED IN THREAD SCHEDULING (for context switching) */
typedef struct regs {
/* segment descriptors */
unsigned int gs;
unsigned int fs;
unsigned int es;
unsigned int ds;
/* General purpose registers, managed by pusha/popa in x86. */
unsigned int edi;
unsigned int esi;
unsigned int ebp;
unsigned int esp;
unsigned int ebx;
unsigned int edx;
unsigned int ecx;
unsigned int eax;
/* In the low-level handlers (i.e. before we call the
exception or interrupt dispatcher) we push number
of the interrupt and error code onto the stack. */
unsigned int int_no;
unsigned int err_code;
/* These registers are pushed on the stack when
the exception occurs. */
unsigned int eip;
unsigned int cs;
unsigned int eflags;
/* These registers are pushed on the stack only when
the exception occured in user mode.
As long as you are in kernel mode, the register context
is 68 bytes long, and not 76! */
unsigned int useresp;
unsigned int ss;
} REGS;
/*--------------------------------------------------------------------------*/
/* CLASS M a c h i n e */
/*--------------------------------------------------------------------------*/
class Machine {
public:
/*---------------------------------------------------------------*/
/* MEMORY MANAGEMENT */
/*---------------------------------------------------------------*/
static const unsigned int PAGE_SIZE = 4096;
static const unsigned int PT_ENTRIES_PER_PAGE = 1024;
/*---------------------------------------------------------------*/
/* INTERRUPTS */
/*---------------------------------------------------------------*/
/*
This is done by checking the Interrupt Enabled flag in the
EFLAG status register and by issuing STI/CLI instructions.
(NOTE: If we have multiple threads, each has its own status register.)
*/
static bool interrupts_enabled();
/* Returns whether interrupts are enabled. */
static void enable_interrupts();
static void disable_interrupts();
/* Issue CLI/STI instructions. */
/*---------------------------------------------------------------*/
/* PORT I/O OPERATIONS */
/*---------------------------------------------------------------*/
static char inportb (unsigned short _port);
static unsigned short inportw (unsigned short _port);
/* Read data from input port _port.*/
static void outportb (unsigned short _port, char _data);
static void outportw (unsigned short _port, unsigned short _data);
/* Write _data to output port _port.*/
};
#endif

31
MP3/MP3_Sources/machine_low.H Executable file
View file

@ -0,0 +1,31 @@
/*
File: machine_low.H
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 12/09/03
Low-level CPU operations.
*/
#ifndef _machine_low_H_ // include file only once
#define _machine_low_H_
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
/* (none) */
/*--------------------------------------------------------------------------*/
/* LOW-LEVER CPU OPERATIONS */
/*--------------------------------------------------------------------------*/
extern "C" unsigned long get_EFLAGS();
/* Return value of the EFLAGS status register. */
#endif

18
MP3/MP3_Sources/machine_low.asm Executable file
View file

@ -0,0 +1,18 @@
; File: machine_low.asm
;
; Low level CPU handling functions.
;
; September 3, 2012
; ----------------------------------------------------------------------
; get_EFLAGS()
;
; Returns value of the EFLAGS status register.
;
; ----------------------------------------------------------------------
global _get_EFLAGS
; this function is exported.
_get_EFLAGS:
pushfd ; push eflags
pop eax ; pop contents into eax
ret

78
MP3/MP3_Sources/makefile Executable file
View file

@ -0,0 +1,78 @@
CPP = gcc
CPP_OPTIONS = -m32 -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector -fleading-underscore -fno-asynchronous-unwind-tables
all: kernel.bin
clean:
rm -f *.o *.bin
start.o: start.asm gdt_low.asm idt_low.asm irq_low.asm
nasm -f aout -o start.o start.asm
utils.o: utils.C utils.H
$(CPP) $(CPP_OPTIONS) -c -o utils.o utils.C
assert.o: assert.C assert.H
$(CPP) $(CPP_OPTIONS) -c -o assert.o assert.C
# ==== VARIOUS LOW-LEVEL STUFF =====
gdt.o: gdt.C gdt.H
$(CPP) $(CPP_OPTIONS) -c -o gdt.o gdt.C
machine.o: machine.C machine.H
$(CPP) $(CPP_OPTIONS) -c -o machine.o machine.C
machine_low.o: machine_low.asm machine_low.H
nasm -f aout -o machine_low.o machine_low.asm
# ==== EXCEPTIONS AND INTERRUPTS =====
idt.o: idt.C idt.H
$(CPP) $(CPP_OPTIONS) -c -o idt.o idt.C
irq.o: irq.C irq.H
$(CPP) $(CPP_OPTIONS) -c -o irq.o irq.C
exceptions.o: exceptions.C exceptions.H
$(CPP) $(CPP_OPTIONS) -c -o exceptions.o exceptions.C
interrupts.o: interrupts.C interrupts.H
$(CPP) $(CPP_OPTIONS) -c -o interrupts.o interrupts.C
# ==== DEVICES =====
console.o: console.C console.H
$(CPP) $(CPP_OPTIONS) -c -o console.o console.C
simple_timer.o: simple_timer.C simple_timer.H
$(CPP) $(CPP_OPTIONS) -c -o simple_timer.o simple_timer.C
simple_keyboard.o: simple_keyboard.C simple_keyboard.H
$(CPP) $(CPP_OPTIONS) -c -o simple_keyboard.o simple_keyboard.C
# ==== MEMORY =====
paging_low.o: paging_low.asm paging_low.H
nasm -f aout -o paging_low.o paging_low.asm
page_table.o: page_table.C page_table.H paging_low.H
$(CPP) $(CPP_OPTIONS) -c -o page_table.o page_table.C
cont_frame_pool.o: cont_frame_pool.C cont_frame_pool.H
$(CPP) $(CPP_OPTIONS) -c -o cont_frame_pool.o cont_frame_pool.C
# ==== KERNEL MAIN FILE =====
kernel.o: kernel.C console.H simple_timer.H page_table.H
$(CPP) $(CPP_OPTIONS) -c -o kernel.o kernel.C
kernel.bin: start.o utils.o kernel.o assert.o console.o gdt.o idt.o irq.o exceptions.o \
interrupts.o simple_timer.o simple_keyboard.o paging_low.o page_table.o cont_frame_pool.o machine.o \
machine_low.o
ld -melf_i386 -T linker.ld -o kernel.bin start.o utils.o kernel.o assert.o console.o \
gdt.o idt.o irq.o exceptions.o \
interrupts.o simple_timer.o simple_keyboard.o paging_low.o page_table.o cont_frame_pool.o machine.o \
machine_low.o

View file

@ -0,0 +1,91 @@
#include "assert.H"
#include "exceptions.H"
#include "console.H"
#include "paging_low.H"
#include "page_table.H"
PageTable * PageTable::current_page_table = NULL;
unsigned int PageTable::paging_enabled = 0;
ContFramePool * PageTable::kernel_mem_pool = NULL;
ContFramePool * PageTable::process_mem_pool = NULL;
unsigned long PageTable::shared_size = 0;
void PageTable::init_paging(ContFramePool * _kernel_mem_pool,
ContFramePool * _process_mem_pool,
const unsigned long _shared_size)
{
kernel_mem_pool = _kernel_mem_pool;
process_mem_pool = process_mem_pool;
shared_size = _shared_size;
Console::puts("\nInitialized Paging System\n");
}
PageTable::PageTable()
{
//kernel_mem_pool->get_frames(1); // Need to take one frame for page directory.
//page_directory = (unsigned long *) 0x32000; // Should be the starting address after 1st 2MB
page_directory = (unsigned long *) kernel_mem_pool->get_frames(1); // Should I get the address like this???
//unsigned long * page_table = (unsigned long *) 0x33000; // Should be 4kb after the page directory.
unsigned long * page_table = page_directory + 0x1000; // Might be able to just do this.
unsigned long tempaddr; // Temporary address iterator.
// We need to map the first 4MB.
for(unsigned int i = 0; i < 1024; i++)
{
page_table[i] = tempaddr | 3; // set bits 0 and 1 to present and read/write respectively
tempaddr += 4096; // 4096 = 4kb
}
// Fill first entry of page directory.
page_directory[0] = *page_table;
page_directory[0] = page_directory[0] | 3;
for(unsigned int j = 1; j < 1024; j++)
{
page_directory[j] = 0 | 2;
}
current_page_table = this;
Console::puts("\nConstructed Page Table object\n");
}
void PageTable::load()
{
write_cr3(*page_directory);
current_page_table = this;
Console::puts("\nLoaded page table\n");
}
void PageTable::enable_paging()
{
write_cr3(*current_page_table->page_directory);
write_cr0(read_cr0() | 0x80000000);
paging_enabled = read_cr0();
Console::puts("\nEnabled paging\n");
}
void PageTable::handle_fault(REGS * _r)
{
/*
unsigned long tempframe = process_mem_pool->get_frames(1);
Console::puts("\nerror code: ");
Console::puti(_r->err_code);
unsigned char mask = 0x00;
read_cr2();
*/
assert(false);
Console::puts("\nhandled page fault\n");
}

91
MP3/MP3_Sources/page_table.H Executable file
View file

@ -0,0 +1,91 @@
/*
File: page_table.H
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 16/12/07
Description: Basic Paging.
*/
#ifndef _page_table_H_ // include file only once
#define _page_table_H_
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "machine.H"
#include "exceptions.H"
#include "cont_frame_pool.H"
/*--------------------------------------------------------------------------*/
/* FORWARDS */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* P A G E - T A B L E */
/*--------------------------------------------------------------------------*/
class PageTable {
private:
/* THESE MEMBERS ARE COMMON TO ENTIRE PAGING SUBSYSTEM */
static PageTable * current_page_table; /* pointer to currently loaded page table object */
static unsigned int paging_enabled; /* is paging turned on (i.e. are addresses logical)? */
static ContFramePool * kernel_mem_pool; /* Frame pool for the kernel memory */
static ContFramePool * process_mem_pool; /* Frame pool for the process memory */
static unsigned long shared_size; /* size of shared address space */
/* DATA FOR CURRENT PAGE TABLE */
unsigned long * page_directory; /* where is page directory located? */
public:
static const unsigned int PAGE_SIZE = Machine::PAGE_SIZE;
/* in bytes */
static const unsigned int ENTRIES_PER_PAGE = Machine::PT_ENTRIES_PER_PAGE;
/* in entries, duh! */
static void init_paging(ContFramePool * _kernel_mem_pool,
ContFramePool * _process_mem_pool,
const unsigned long _shared_size);
/* Set the global parameters for the paging subsystem. */
PageTable();
/* Initializes a page table with a given location for the directory and the
page table proper.
NOTE: The PageTable object still needs to be stored somewhere!
Probably it is best to have it on the stack, as there is no
memory manager yet...
NOTE2: It may also be simpler to create the first page table *before*
paging has been enabled.
*/
void load();
/* Makes the given page table the current table. This must be done once during
system startup and whenever the address space is switched (e.g. during
process switching). */
static void enable_paging();
/* Enable paging on the CPU. Typically, a CPU start with paging disabled, and
memory is accessed by addressing physical memory directly. After paging is
enabled, memory is addressed logically. */
static void handle_fault(REGS * _r);
/* The page fault handler. */
};
#endif

51
MP3/MP3_Sources/paging_low.H Executable file
View file

@ -0,0 +1,51 @@
/*
File: paging_low.H
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 09/03/28
Low-level register operations for x86 paging subsystem.
*/
#ifndef _paging_low_H_ // include file only once
#define _paging_low_H_
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
/* -- none -- */
/*--------------------------------------------------------------------------*/
/* FORWARDS */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* LOW-LEVEL PAGING ROUTINES */
/*--------------------------------------------------------------------------*/
/* The low-level functions (defined in file 'paging_low.asm') that handle the
low-level function to manage the page tables. */
/* -- CR0 -- */
extern "C" unsigned long read_cr0();
extern "C" void write_cr0(unsigned long _val);
/* -- CR2 -- */
extern "C" unsigned long read_cr2();
/* -- CR3 -- */
extern "C" unsigned long read_cr3();
extern "C" void write_cr3(unsigned long _val);
#endif

32
MP3/MP3_Sources/paging_low.asm Executable file
View file

@ -0,0 +1,32 @@
global _read_cr0
_read_cr0:
mov eax, cr0
retn
global _write_cr0
_write_cr0:
push ebp
mov ebp, esp
mov eax, [ebp+8]
mov cr0, eax
pop ebp
retn
global _read_cr2
_read_cr2:
mov eax, cr2
retn
global _read_cr3
_read_cr3:
mov eax, cr3
retn
global _write_cr3
_write_cr3:
push ebp
mov ebp, esp
mov eax, [ebp+8]
mov cr3, eax
pop ebp
retn

View file

@ -0,0 +1,79 @@
/*
File: simple_keyboard.C
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 2017/06/30
Simple control of the keyboard.
*/
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
/* (none) */
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "assert.H"
#include "machine.H"
#include "console.H"
#include "interrupts.H"
#include "simple_keyboard.H"
/*--------------------------------------------------------------------------*/
/* CONSTRUCTOR */
/*--------------------------------------------------------------------------*/
SimpleKeyboard::SimpleKeyboard() {
key_pressed = false;
}
/*--------------------------------------------------------------------------*/
/* METHODS FOR CLASS S i m p l e K e y b o a r d */
/*--------------------------------------------------------------------------*/
void SimpleKeyboard::handle_interrupt(REGS *_r) {
/* What to do when keyboard interrupt occurs? In this case, we update
"key_pressed". */
unsigned char status = Machine::inportb(STATUS_PORT);
/* lowest bit of status will be set if buffer is not empty. */
if (status & 0x01) {
char kc = Machine::inportb(DATA_PORT);
if (kc >= 0) {
key_pressed = true;
key_code = kc;
}
}
}
void SimpleKeyboard::wait() {
/* Loop until the user presses a key. */
kb.key_pressed = false;
while(kb.key_pressed == false);
}
char SimpleKeyboard::read() {
/* Loop until the user presses a key, and then return the keycode. */
kb.key_pressed = false;
while (kb.key_pressed == false);
return kb.key_code;
}
SimpleKeyboard SimpleKeyboard::kb;
void SimpleKeyboard::init() {
InterruptHandler::register_handler(1, &kb);
}

View file

@ -0,0 +1,68 @@
/*
File: simple_keyboard.H
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 2017/02/17
Implements an interrupt handler for the keyboard.
The function is implemented in 'handle_interrupt'.
*/
#ifndef _SIMPLE_KEYBOARD_H_
#define _SIMPLE_KEYBOARD_H_
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "interrupts.H"
/*--------------------------------------------------------------------------*/
/* S I M P L E K E Y B O A R D */
/*--------------------------------------------------------------------------*/
class SimpleKeyboard : public InterruptHandler {
public :
SimpleKeyboard();
/* Initialize the simple keyboard. */
virtual void handle_interrupt(REGS *_r);
/* This must be installed as the interrupt handler for the keyboard
when the system gets initialized. (e.g. in "kernel.C")
*/
static void init();
static void wait();
/* Wait until keyboard is pressed. The implementation is based
on busy looping! */
static char read();
/* Wait until keyboard is pressed and return the keycode.
Note: The keycode is not the same as the character!
Note2: This is a very "approximate" implementation. Not complete,
and likely not correct. Use only under duress!
The implementation is based on busy looping! */
private:
bool key_pressed;
char key_code;
static SimpleKeyboard kb;
static const unsigned short STATUS_PORT = 0x64;
static const unsigned short DATA_PORT = 0x60;
};
#endif

100
MP3/MP3_Sources/simple_timer.C Executable file
View file

@ -0,0 +1,100 @@
/*
File: simple_timer.C
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 09/03/19
Simple control of the
*/
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "assert.H"
#include "utils.H"
#include "console.H"
#include "interrupts.H"
#include "simple_timer.H"
/*--------------------------------------------------------------------------*/
/* CONSTRUCTOR */
/*--------------------------------------------------------------------------*/
SimpleTimer::SimpleTimer(int _hz) {
/* How long has the system been running? */
seconds = 0;
ticks = 0; /* ticks since last "seconds" update. */
/* At what frequency do we update the ticks counter? */
/* hz = 18; */
/* Actually, by defaults it is 18.22Hz.
In this way, a 16-bit counter wraps
around every hour. */
set_frequency(_hz);
}
/*--------------------------------------------------------------------------*/
/* METHODS FOR CLASS S i m p l e T i m e r */
/*--------------------------------------------------------------------------*/
void SimpleTimer::handle_interrupt(REGS *_r) {
/* What to do when timer interrupt occurs? In this case, we update "ticks",
and maybe update "seconds".
This must be installed as the interrupt handler for the timer in the
when the system gets initialized. (e.g. in "kernel.C") */
/* Increment our "ticks" count */
ticks++;
/* Whenever a second is over, we update counter accordingly. */
if (ticks >= hz )
{
seconds++;
ticks = 0;
Console::puts("One second has passed\n");
}
}
void SimpleTimer::set_frequency(int _hz) {
/* Set the interrupt frequency for the simple timer.
Preferably set this before installing the timer handler! */
hz = _hz; /* Remember the frequency. */
int divisor = 1193180 / _hz; /* The input clock runs at 1.19MHz */
Machine::outportb(0x43, 0x34); /* Set command byte to be 0x36. */
Machine::outportb(0x40, divisor & 0xFF); /* Set low byte of divisor. */
Machine::outportb(0x40, divisor >> 8); /* Set high byte of divisor. */
}
void SimpleTimer::current(unsigned long * _seconds, int * _ticks) {
/* Return the current "time" since the system started. */
*_seconds = seconds;
*_ticks = ticks;
}
void SimpleTimer::wait(unsigned long _seconds) {
/* Wait for a particular time to be passed. This is based on busy looping! */
unsigned long now_seconds;
int now_ticks;
current(&now_seconds, &now_ticks);
unsigned long then_seconds = now_seconds + _seconds;
while((seconds <= then_seconds) && (ticks < now_ticks));
}

70
MP3/MP3_Sources/simple_timer.H Executable file
View file

@ -0,0 +1,70 @@
/*
File: simple_timer.H
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 09/03/19
This is a simple example of a hardware interrupt handler.
As an example, this implements a timer, which in turn
triggers a function to be called at the given frequency.
The function is implemented in 'handle_interrupt'.
*/
#ifndef _SIMPLE_TIMER_H_
#define _SIMPLE_TIMER_H_
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "interrupts.H"
/*--------------------------------------------------------------------------*/
/* S I M P L E T I M E R */
/*--------------------------------------------------------------------------*/
class SimpleTimer : public InterruptHandler {
private:
/* How long has the system been running? */
unsigned long seconds;
int ticks; /* ticks since last "seconds" update. */
/* At what frequency do we update the ticks counter? */
int hz; /* Actually, by defaults it is 18.22Hz.
In this way, a 16-bit counter wraps
around every hour. */
void set_frequency(int _hz);
/* Set the interrupt frequency for the simple timer. */
public :
SimpleTimer(int _hz);
/* Initialize the simple timer, and set its frequency. */
virtual void handle_interrupt(REGS *_r);
/* This must be installed as the interrupt handler for the timer
when the system gets initialized. (e.g. in "kernel.C")
*/
void current(unsigned long * _seconds, int * _ticks);
/* Return the current "time" since the system started. */
void wait(unsigned long _seconds);
/* Wait for a particular time to be passed. The implementation is based
on busy looping! */
};
#endif

110
MP3/MP3_Sources/start.asm Executable file
View file

@ -0,0 +1,110 @@
; bkerndev - Bran's Kernel Development Tutorial
; By: Brandon F. (friesenb@gmail.com)
; Desc: Kernel entry point, stack, and Interrupt Service Routines.
;
; Notes: No warranty expressed or implied. Use at own risk.
;
; This is the kernel's entry point. We could either call main here,
; or we can use this to setup the stack or other nice stuff, like
; perhaps setting up the GDT and segments. Please note that interrupts
; are disabled at this point: More on interrupts later!
[BITS 32]
global start
start:
mov esp, _sys_stack ; This points the stack to our new stack area
jmp stublet
; This part MUST be 4byte aligned, so we solve that issue using 'ALIGN 4'
ALIGN 4
mboot:
; Multiboot macros to make a few lines later more readable
MULTIBOOT_PAGE_ALIGN equ 1<<0
MULTIBOOT_MEMORY_INFO equ 1<<1
MULTIBOOT_AOUT_KLUDGE equ 1<<16
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
EXTERN code, bss, end
; This is the GRUB Multiboot header. A boot signature
dd MULTIBOOT_HEADER_MAGIC
dd MULTIBOOT_HEADER_FLAGS
dd MULTIBOOT_CHECKSUM
; AOUT kludge - must be physical addresses. Make a note of these:
; The linker script fills in the data for these ones!
dd mboot ; header_addr:
; address corresponding to the multiboot header
dd code ; load_addr:
; physical address of the beginning of the text segment
dd bss ; load_end_addr:
; physical address of the end of the data segment
; (load_end_addr - load_addr) specifies how much data to load.
dd end ; bss_end_addr:
; pysical address of end of bss segment.
; boot loader initializes this area to zero,
; and reserves the memory
dd start ; entry_addr:
; physical address to which the boot loader should jump
; to start running the OS
stublet:
; Initilization of static global objects. This goes through each object
; in the ctors section of the object file, where the global constructors
; created by C++ are put, and calls it. Normally C++ compilers add some code
; to do this, but that code is in the standard library - which we do not
; include
; See linker.ld to see where we tell the linker to put them.
extern start_ctors, end_ctors, start_dtors, end_dtors
static_ctors_loop:
mov ebx, start_ctors
jmp .test
.body:
call [ebx]
add ebx,4
.test:
cmp ebx, end_ctors
jb .body
; Entering the kernel proper.
extern _main
call _main
; Deinitialization of static global objects. This goes through each object
; in the dtors section of the object file, where the global destructors
; created by C++ are put, and calls it. Normally C++ compilers add some code
; to do this, but that code is in the standard library - which we do not include.
; See linker.ld to see where we tell the linker to put them.
static_dtors_loop:
mov ebx, start_dtors
jmp .test
.body:
call [ebx]
add ebx,4
.test:
cmp ebx, end_dtors
jb .body
; Enter an endless loop here in order to stop.
jmp $
; Set up Global Descriptor Table
%include "gdt_low.asm"
; Set up Low-level Exception Handling
%include "idt_low.asm"
; Set up Low-level Interrupt Handling
%include "irq_low.asm"
; Here is the definition of our BSS section. Right now, we'll use
; it just to store the stack. Remember that a stack actually grows
; downwards, so we declare the size of the data before declaring
; the identifier '_sys_stack'
SECTION .bss
resb 8192 ; This reserves 8KBytes of memory here
_sys_stack:

167
MP3/MP3_Sources/utils.C Executable file
View file

@ -0,0 +1,167 @@
/*
File: utils.C
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 09/02/12
*/
/* Some of the code comes from Brandon Friesens OS Tutorial:
* bkerndev - Bran's Kernel Development Tutorial
* By: Brandon F. (friesenb@gmail.com)
* Desc: Interrupt Descriptor Table management
*
* Notes: No warranty expressed or implied. Use at own risk. */
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
/* -- (none ) -- */
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "utils.H"
/*--------------------------------------------------------------------------*/
/* DATA STRUCTURES */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* CONSTANTS */
/*--------------------------------------------------------------------------*/
/* -- (none) -- */
/*--------------------------------------------------------------------------*/
/* ABORT (USED e.g. IN _ASSERT() */
/*--------------------------------------------------------------------------*/
void abort() {
for(;;);
}
/*--------------------------------------------------------------------------*/
/* MEMORY OPERATIONS */
/*--------------------------------------------------------------------------*/
void *memcpy(void *dest, const void *src, int count)
{
const char *sp = (const char *)src;
char *dp = (char *)dest;
for(; count != 0; count--) *dp++ = *sp++;
return dest;
}
void *memset(void *dest, char val, int count)
{
char *temp = (char *)dest;
for( ; count != 0; count--) *temp++ = val;
return dest;
}
unsigned short *memsetw(unsigned short *dest, unsigned short val, int count)
{
unsigned short *temp = (unsigned short *)dest;
for( ; count != 0; count--) *temp++ = val;
return dest;
}
/*--------------------------------------------------------------------------*/
/* STRING OPERATIONS */
/*--------------------------------------------------------------------------*/
int strlen(const char *_str) {
/* This loops through character array 'str', returning how
* many characters it needs to check before it finds a 0.
* In simple words, it returns the length in bytes of a string */
int len = 0;
while (*_str != 0) {
_str++;
len++;
}
return len;
}
void strcpy(char* _dst, char* _src) {
while (*_src != 0) {
*_dst = *_src;
_dst++;
_src++;
}
*_dst = 0; // put terminating 0 at end.
}
void int2str(int _num, char * _str) {
/* -- THIS IMPLEMENTATION IS ONE PRETTY BAD HACK. */
int i;
char temp[11];
temp[0] = '\0';
for(i = 1; i <= 10; i++) {
temp[i] = _num % 10 + '0';
_num /= 10;
}
for(i = 10; temp[i] == '0'; i--);
if( i == 0 )
i++;
while( i >= 0 )
*_str++ = temp[i--];
}
void uint2str(unsigned int _num, char * _str) {
/* -- THIS IS A BAD HACK AS WELL. */
int i;
char temp[11];
temp[0] = '\0';
for(i = 1; i <= 10; i++) {
temp[i] = _num % 10 + '0';
_num /= 10;
}
for(i = 10; temp[i] == '0'; i--);
if( i == 0 )
i++;
while( i >= 0 )
*_str++ = temp[i--];
}
/*--------------------------------------------------------------------------*/
/* POERT I/O OPERATIONS */
/*--------------------------------------------------------------------------*/
/* We will use this later on for reading from the I/O ports to get data
* from devices such as the keyboard. We are using what is called
* 'inline assembly' in these routines to actually do the work */
char inportb (unsigned short _port) {
unsigned char rv;
__asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port));
return rv;
}
unsigned short inportw (unsigned short _port) {
unsigned short rv;
__asm__ __volatile__ ("inw %1, %0" : "=a" (rv) : "dN" (_port));
return rv;
}
/* We will use this to write to I/O ports to send bytes to devices. This
* will be used in the next tutorial for changing the textmode cursor
* position. Again, we use some inline assembly for the stuff that simply
* cannot be done in C */
void outportb (unsigned short _port, char _data) {
__asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
}
void outportw (unsigned short _port, unsigned short _data) {
__asm__ __volatile__ ("outw %1, %0" : : "dN" (_port), "a" (_data));
}

62
MP3/MP3_Sources/utils.H Executable file
View file

@ -0,0 +1,62 @@
/*
File : utils.H
Author : Riccardo Bettati
Modified : 2017/05/02
Description : Various definitions (NULL) and
utility functions (e.g. abort, memory and
string functions).
*/
#ifndef _utils_h_
#define _utils_h_
/*---------------------------------------------------------------*/
/* GENERAL CONSTANTS */
/*---------------------------------------------------------------*/
#ifndef NULL
# define NULL 0
#endif
/*---------------------------------------------------------------*/
/* ABORT */
/*---------------------------------------------------------------*/
void abort();
/* Stop execution. */
/*---------------------------------------------------------------*/
/* SIMPLE MEMORY OPERATIONS */
/*---------------------------------------------------------------*/
void *memcpy(void *dest, const void *src, int count);
/* Copy _count bytes from _src to _dest. (No check for uverlapping) */
void *memset(void *dest, char val, int count);
/* Set _count bytes to value _val, starting from location _dest. */
unsigned short *memsetw(unsigned short *dest, unsigned short val, int count);
/* Same as above, but operations are 16-bit wide. */
/*---------------------------------------------------------------*/
/* SIMPLE STRING OPERATIONS (STRINGS ARE NULL-TERMINATED) */
/*---------------------------------------------------------------*/
int strlen(const char * _str);
/* Determine the length of null-terminated string. */
void strcpy(char * _dst, char * _src);
/* Copy null-terminated string from _src to _dst. */
void int2str(int _num, char * _str);
/* Convert int to null-terminated string. */
void uint2str(unsigned int _num, char * _str);
/* Convert unsigned int to null-terminated string. */
#endif

BIN
MP3/__MACOSX/._MP3_Sources Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show more