├── .gitignore
├── Disk.vmdk
├── MBR2GPT.vbox
├── MBR2GPT.vmx
├── MBR2GPT.vmxf
├── README.md
├── bbp
├── README.md
├── bbp.ld
├── bbp.vcxproj
├── boot
│ ├── README.md
│ ├── bios.asm
│ ├── boot.asm
│ ├── boot.ld
│ ├── common16.h
│ ├── common32.h
│ ├── main16.c
│ ├── main16.h
│ ├── main32.c
│ ├── main32.h
│ └── makefile
├── buildimg.bat
├── config.h
├── kernel
│ ├── README.md
│ ├── acpi.c
│ ├── acpi.h
│ ├── ahci.c
│ ├── ahci.h
│ ├── apic.c
│ ├── apic.h
│ ├── common.h
│ ├── cpuid.h
│ ├── debug_print.c
│ ├── debug_print.h
│ ├── interrupts.asm
│ ├── interrupts.c
│ ├── interrupts.h
│ ├── io.h
│ ├── kernel.ld
│ ├── kmain.c
│ ├── kmain.h
│ ├── lib.c
│ ├── lib.h
│ ├── makefile
│ ├── msr.h
│ ├── paging.c
│ ├── paging.h
│ ├── pci.c
│ └── pci.h
└── makefile
├── bochsrc.bxrc
├── bochsrc_debug.bxrc
├── mbr
├── README.md
├── main.asm
├── main.inc
├── makefile
└── mbr.vcxproj
├── mbr2gpt.sln
├── run_bochs.bat
├── run_bochs_debug.bat
└── run_qemu.bat
/.gitignore:
--------------------------------------------------------------------------------
1 | *.user
2 | *.filter
3 | *.o
4 | /*.suo
5 | /*.sdf
6 | /bochsdbg.txt
7 | /bochsout.txt
8 | /Release
9 | /ipch
10 | /bbp/Release
11 | /mbr/Release
12 | /doc
13 | /Logs
14 | /*.vbox-prev
15 | /*.vmsd
16 | /*.nvram
17 | /vmware*
18 |
19 | /bbp/kernel/acpica
20 |
--------------------------------------------------------------------------------
/Disk.vmdk:
--------------------------------------------------------------------------------
1 | # Disk DescriptorFile
2 | version=1
3 | CID=bc86b9fe
4 | parentCID=ffffffff
5 | createType="monolithicFlat"
6 |
7 | # Extent description
8 | RW 10080 FLAT "Release/disk.img" 0
9 |
10 | # The disk Data Base
11 | #DDB
12 |
13 | ddb.virtualHWVersion = "4"
14 | ddb.adapterType="ide"
15 | ddb.uuid.image="6530d803-6ee0-4ecd-a3fb-c218a8f6e4aa"
16 | ddb.uuid.parent="00000000-0000-0000-0000-000000000000"
17 | ddb.uuid.modification="00000000-0000-0000-0000-000000000000"
18 | ddb.uuid.parentmodification="00000000-0000-0000-0000-000000000000"
19 | ddb.geometry.cylinders="10"
20 | ddb.geometry.heads="16"
21 | ddb.geometry.sectors="63"
22 | ddb.geometry.biosCylinders="10"
23 | ddb.geometry.biosHeads="16"
24 | ddb.geometry.biosSectors="63"
25 |
--------------------------------------------------------------------------------
/MBR2GPT.vbox:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
--------------------------------------------------------------------------------
/MBR2GPT.vmx:
--------------------------------------------------------------------------------
1 | .encoding = "UTF-8"
2 | config.version = "8"
3 | virtualHW.version = "8"
4 | vcpu.hotadd = "FALSE"
5 | sched.swap.vmxSwapEnabled = "FALSE"
6 | memsize = "256"
7 | mem.hotadd = "FALSE"
8 | nvram = "Memory.nvram"
9 | floppy0.startConnected = "FALSE"
10 | floppy0.fileName = ""
11 | floppy0.autodetect = "TRUE"
12 | ethernet0.present = "TRUE"
13 | ethernet0.connectionType = "nat"
14 | ethernet0.virtualDev = "e1000"
15 | ethernet0.wakeOnPcktRcv = "FALSE"
16 | ethernet0.addressType = "generated"
17 | usb.present = "TRUE"
18 | ehci.present = "TRUE"
19 | sound.present = "TRUE"
20 | sound.startConnected = "TRUE"
21 | sound.fileName = "-1"
22 | sound.autodetect = "TRUE"
23 | pciBridge0.present = "TRUE"
24 | pciBridge4.present = "TRUE"
25 | pciBridge4.virtualDev = "pcieRootPort"
26 | pciBridge4.functions = "8"
27 | pciBridge5.present = "TRUE"
28 | pciBridge5.virtualDev = "pcieRootPort"
29 | pciBridge5.functions = "8"
30 | pciBridge6.present = "TRUE"
31 | pciBridge6.virtualDev = "pcieRootPort"
32 | pciBridge6.functions = "8"
33 | pciBridge7.present = "TRUE"
34 | pciBridge7.virtualDev = "pcieRootPort"
35 | pciBridge7.functions = "8"
36 | vmci0.present = "TRUE"
37 | hpet0.present = "TRUE"
38 | usb.vbluetooth.startConnected = "TRUE"
39 | displayName = "MBR2GPT"
40 | guestOS = "other-64"
41 | virtualHW.productCompatibility = "hosted"
42 | gui.exitOnCLIHLT = "FALSE"
43 | powerType.powerOff = "hard"
44 | powerType.powerOn = "hard"
45 | powerType.suspend = "hard"
46 | powerType.reset = "hard"
47 | extendedConfigFile = "MBR2GPT.vmxf"
48 | ethernet0.generatedAddress = "00:0c:29:d2:7f:24"
49 | vmci0.id = "-1934875086"
50 | uuid.location = "56 4d d9 14 44 2e 2d ab-20 2a 0e 53 2d d2 7f 24"
51 | uuid.bios = "56 4d d9 14 44 2e 2d ab-20 2a 0e 53 2d d2 7f 24"
52 | #bios.bootdelay = 10000
53 | cleanShutdown = "TRUE"
54 | replay.supported = "FALSE"
55 | replay.filename = ""
56 | pciBridge0.pciSlotNumber = "17"
57 | pciBridge4.pciSlotNumber = "21"
58 | pciBridge5.pciSlotNumber = "22"
59 | pciBridge6.pciSlotNumber = "23"
60 | pciBridge7.pciSlotNumber = "24"
61 | scsi0.pciSlotNumber = "16"
62 | usb.pciSlotNumber = "32"
63 | ethernet0.pciSlotNumber = "33"
64 | sound.pciSlotNumber = "34"
65 | ehci.pciSlotNumber = "35"
66 | vmci0.pciSlotNumber = "36"
67 | usb:1.present = "TRUE"
68 | ethernet0.generatedAddressOffset = "0"
69 | vmotion.checkpointFBSize = "5242880"
70 | usb:1.speed = "2"
71 | usb:1.deviceType = "hub"
72 | usb:1.port = "1"
73 | usb:1.parent = "-1"
74 | svga.autodetect = "FALSE"
75 | svga.maxWidth = "1280"
76 | svga.maxHeight = "1024"
77 | svga.vramSize = "5242880"
78 | tools.syncTime = "FALSE"
79 | unity.wasCapable = "FALSE"
80 | tools.remindInstall = "FALSE"
81 | softPowerOff = "FALSE"
82 | numvcpus = "2"
83 | ide0:0.present = "TRUE"
84 | ide0:0.fileName = "Disk.vmdk"
85 | monitor.virtual_mmu = "software"
86 | monitor.virtual_exec = "hardware"
87 | ide0:0.redo = ""
88 | scsi0.present = "TRUE"
89 | scsi0.virtualDev = "lsilogic"
90 | tools.upgrade.policy = "manual"
91 | mks.keyboardFilter = "allow"
92 | ide0:1.present = "FALSE"
93 | scsi0:0.present = "FALSE"
94 | ide1:0.present = "FALSE"
95 | scsi0:1.present = "FALSE"
96 | serial0.present = "FALSE"
97 | usb:0.present = "TRUE"
98 | usb:0.deviceType = "hid"
99 | usb:0.port = "0"
100 | usb:0.parent = "-1"
101 |
--------------------------------------------------------------------------------
/MBR2GPT.vmxf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 52 ea 1c 7e 7b ec 13 53-f8 b0 85 63 fc 28 d6 a4
5 |
6 |
7 |
8 | MBR2GPT.vmx02
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | mbr2gpt
2 | =======
3 |
4 | MBR bootcode to read GPT headers and load bootloader from BIOS Boot Partition
5 |
6 | mbr
7 | ---
8 |
9 | Master Boot Record code
10 |
11 | bbp
12 | ---
13 |
14 | Test BIOS Boot Partition code (my playground to write an OS)
15 |
16 | Virtual Machines
17 | ----------------
18 |
19 | * MBR2GPT.vbox - VirtualBox test machine
20 | * MBR2GPT.vmx - VMWare Player test machine
21 | * run_bochs.bat - launch Bochs test machine
22 | * run_bochs_debug.bat - launch Bochs test machine with GUI debugger
23 | * run_qemu.bat - launch QEMU test machine
24 |
25 | Other files
26 | -----------
27 |
28 | * bochsrc.bxrc - Bochs configuration file
29 | * bochsrc_debug.bxrc - Bochs configuration file (with GUI debugger)
30 | * Disk.vmdk - VMDK disk image header for VirtualBox and VMWare Player test machines
31 |
32 | Build Requirements
33 | ------------------
34 |
35 | You'll need:
36 | * MinGW Cross-compiler that's capable of building ELF files. See how to build one here: http://gusc.lv/2012/12/myos-mingw-cross-compiler/
37 | * Netwide Assembler from: http://www.nasm.us/
38 | * DiskUtils from: https://github.com/gusc/diskutils
39 | * Microsoft Visual Studio Express 2010
40 |
--------------------------------------------------------------------------------
/bbp/README.md:
--------------------------------------------------------------------------------
1 | BIOS Boot Partition
2 | ===================
3 |
4 | This is the BBP bootcode that get's loaded by MBR.
5 |
6 | File list
7 | ---------
8 |
9 | Main entry files:
10 | * boot/boot.asm - main BBP entry code (real mode code)
11 | * boot/ - Real Mode -> Protected Mode -> Long Mode bootstrap code
12 | * kernel/ - Kernel code
13 |
14 | Build files:
15 | * bbp.ld - BBP linker script
16 | * bbp.vcxproj - Visual Studio 2010 project file
17 | * buildimg.bat - Bach script to merge MBR and BBP code into Bochs disk image file using DiskUtils
18 | * config.h - global configuration file (compile-time configuration)
19 | * makefile - Make build script
20 |
21 |
22 | Requirements
23 | ------------
24 |
25 | * MinGW Cross-compiler that's capable of building ELF64 files. See how to build one here: http://gusc.lv/2012/12/myos-mingw-cross-compiler/
26 | * Netwide Assembler from: http://www.nasm.us/
27 | * DiskUtils from: https://github.com/gusc/diskutils
28 | * Microsoft Visual Studio Express 2010
29 |
--------------------------------------------------------------------------------
/bbp/bbp.ld:
--------------------------------------------------------------------------------
1 | /*OUTPUT_FORMAT(elf64-x86-64)*/
2 | OUTPUT_FORMAT(binary)
3 | ENTRY(start16)
4 | SECTIONS {
5 | .text 0x7C00 : AT( 0x7C00 ) {
6 | boot.o(.text);
7 | *(.text);
8 | }
9 | .rodata : {
10 | *(.rodata);
11 | }
12 | .data : {
13 | *(.data);
14 | }
15 | .bss : {
16 | *(.bss);
17 | }
18 | /DISCARD/ : {
19 | *(.eh_frame);
20 | }
21 | . = ALIGN(4096);
22 | }
--------------------------------------------------------------------------------
/bbp/bbp.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Release
6 | Win32
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | {3D779CE6-A610-49F7-AC07-992AEEB4115D}
76 | kernel
77 | bbp
78 |
79 |
80 |
81 | Makefile
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | C:\MinGW\bin;C:\MinGW\msys\1.0\bin;C:\Program Files\Netwide Assembler;C:\cross-gcc\i786-elf\bin;C:\cross-gcc\x86_64-elf\bin
90 | make -C "$(ProjectDir)"
91 | buildimg.bat
92 | $(NMakeBuildCommandLine)
93 | del *.o "boot\*.o" "kernel\*.o" "..\Release\bbp.img" "..\Release\disk.img"
94 |
95 |
96 |
97 |
98 |
99 | bbp.img
100 |
101 |
102 |
--------------------------------------------------------------------------------
/bbp/boot/README.md:
--------------------------------------------------------------------------------
1 | Boot
2 | ====
3 |
4 | This is the main bootstrap code
5 |
6 | File list
7 | ---------
8 |
9 | Main entry files:
10 | * boot.asm - This file is compiled at the top of BBP binary image and receives control from MBR
11 |
12 | Helper files:
13 | * bios.asm - BIOS wrapper routines used by main16.c
14 | * common16.h - Real Mode data types (also directs GCC to emmit 16bit assembly)
15 | * common32.h - Protected Mode data types
16 | * main16.* - Real Mode initialization code
17 | * main32.* - Protected Mode initialization code
18 |
19 | Build files:
20 | * boot.ld - Bootstrap linker script
21 | * makefile - Make build script
22 |
--------------------------------------------------------------------------------
/bbp/boot/bios.asm:
--------------------------------------------------------------------------------
1 | ;
2 | ; BIOS utility subroutines
3 | ; ========================
4 | ;
5 | ; This file contains wrappers for BIOS funciton calls to be used in C.
6 | ; All the functions are written with cdecl calling convention
7 | ;
8 | ; License (BSD-3)
9 | ; ===============
10 | ;
11 | ; Copyright (c) 2013, Gusts 'gusC' Kaksis
12 | ; All rights reserved.
13 | ;
14 | ; Redistribution and use in source and binary forms, with or without
15 | ; modification, are permitted provided that the following conditions are met:
16 | ; * Redistributions of source code must retain the above copyright
17 | ; notice, this list of conditions and the following disclaimer.
18 | ; * Redistributions in binary form must reproduce the above copyright
19 | ; notice, this list of conditions and the following disclaimer in the
20 | ; documentation and/or other materials provided with the distribution.
21 | ; * Neither the name of the nor the
22 | ; names of its contributors may be used to endorse or promote products
23 | ; derived from this software without specific prior written permission.
24 | ;
25 | ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
26 | ; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 | ; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 | ; DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
29 | ; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 | ; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 | ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32 | ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 | ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 | ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 | ;
36 |
37 | [section .text]
38 | [global set_video_mode] ; Export void set_video_mode(uint16 mode) to C
39 | [global set_svga_mode] ; Export void set_svga_mode(uint16 mode) to C
40 | [global enable_a20] ; Export void enable_a20() to C
41 | [global check_a20] ; Export uint16 check_a20() to C
42 | [global read_e820] ; Export void read_e820(e820map_t *mem_map) to C
43 |
44 | [bits 16] ; Real mode
45 |
46 | set_video_mode: ; Set video mode
47 | push bp ; save base pointer
48 | mov bp, sp ; set stack pointer as our base pointer
49 | add bp, 4 ; increment base pointer (as the first 2 values
50 | ; on the stack are the old base pointer and
51 | ; old instruction pointer)
52 | add bp, 2 ; if using .code16gcc add 2 more bytes, as GCC pushes 32bit values on the stack
53 | mov ax, word [bp] ; get video mode parameter
54 | mov ah, 0x00 ; command: change video mode
55 | int 0x10 ; call video interrupt
56 | pop bp ; restore the old base pointer
57 | ret ; return to callee
58 |
59 | set_svga_mode: ; Set SuperVGA video mode
60 | push bp ; save base pointer
61 | mov bp, sp ; set stack pointer as our base pointer
62 | add bp, 4 ; increment base pointer (as the first 2 values
63 | ; on the stack are the old base pointer and
64 | ; old instruction pointer)
65 | add bp, 2 ; if using .code16gcc add 2 more bytes, as GCC pushes 32bit values on the stack
66 | mov bx, word [bp] ; get video mode parameter
67 | mov ax, 4F02h ; command: set SuperVGA video mode
68 | int 0x10 ; call video interrupt
69 | pop bp ; restore the old base pointer
70 | ret ; return to callee
71 |
72 | enable_a20: ; Enable A20 Gate to access high memory in protected mode (Fast A20)
73 | in al, 0x92 ; read from io port 0x92
74 | mov cl, al
75 | and cl, 2 ; test if bit 2 is not set
76 | jnz .ret ; if it's set, then we're skipping
77 | or al, 2 ; set 2nd bit to 1
78 | out 0x92, al ; write back to port 0x92
79 | .ret:
80 | ret ; return to callee
81 |
82 | read_e820: ; Read E820 Memory map
83 | push bp ; save base pointer
84 | mov bp, sp ; set stack pointer as our base pointer
85 | add bp, 4 ; increment base pointer (as the first 2 values
86 | ; on the stack are the old base pointer and
87 | ; old instruction pointer + 2 more bytes, as GCC pushes 32bit values on the stack)
88 | add bp, 2 ; if using .code16gcc add 2 more bytes, as GCC pushes 32bit values on the stack
89 |
90 | mov di, word [bp] ; set DI to location where we'll read E820 map (a pointer argument from C)
91 | add di, 4 ; first word is reserved for array size
92 | ; second word is the size of the size of the first entry
93 |
94 | xor eax, eax ; initially we have no entries in the table
95 | push ax ; store current count on the stack
96 | xor ebx, ebx ; clear ebx
97 |
98 | .read_more:
99 | mov eax, 0x0000E820 ; command: E820 map
100 | mov ecx, 0x18 ; set ECX to value of 24 - the max size of entry (only ACPI 3.0 has 24 byte entries)
101 | mov edx, 0x534D4150 ; set EDX to magic number "SMAP"
102 |
103 | int 0x15 ; call memory interrupt
104 | jc .end ; if carry flag set, then we failed
105 | cmp eax, 0x534D4150 ; should be the magic number "SMAP", is it?
106 | jne .end ; if magic number is not set, then we failed
107 |
108 | cmp ebx, 0x0 ; test EBX for 0
109 | je .end ; if EBX is 0, this was the last entry
110 |
111 | pop ax ; pop array size from the stack
112 | inc ax ; increment it by 1
113 | push ax ; push it back on the stack
114 |
115 | mov [di - 2], cx ; save entry size
116 | add di, 0x1A ; increment DI by 26
117 |
118 | jmp .read_more ; read some more
119 |
120 | .end:
121 | pop ax ; get entry count
122 | mov di, [bp] ; move back to the beginning of the array
123 | mov [di], ax ; no entries on E820 map
124 | pop bp ; restore the old base pointer
125 | ret ; return to callee
126 |
--------------------------------------------------------------------------------
/bbp/boot/boot.asm:
--------------------------------------------------------------------------------
1 | ;
2 | ; BBP programm entry
3 | ; ==================
4 | ;
5 | ; This file contains entry point and glue code between real mode and long mode
6 | ;
7 | ; Program flow:
8 | ; 1. setup registers
9 | ; 2. execute C main16() function that sets up everything to enter protected mode
10 | ; 3. enter Protected Mode
11 | ; 4. execute C main32() function that sets up everything to enter long mode
12 | ; 3. enter Long Mode
13 | ; 4. execute C kmain() function that starts up the kernel
14 | ;
15 | ; License (BSD-3)
16 | ; ===============
17 | ;
18 | ; Copyright (c) 2013, Gusts 'gusC' Kaksis
19 | ; All rights reserved.
20 | ;
21 | ; Redistribution and use in source and binary forms, with or without
22 | ; modification, are permitted provided that the following conditions are met:
23 | ; * Redistributions of source code must retain the above copyright
24 | ; notice, this list of conditions and the following disclaimer.
25 | ; * Redistributions in binary form must reproduce the above copyright
26 | ; notice, this list of conditions and the following disclaimer in the
27 | ; documentation and/or other materials provided with the distribution.
28 | ; * Neither the name of the nor the
29 | ; names of its contributors may be used to endorse or promote products
30 | ; derived from this software without specific prior written permission.
31 | ;
32 | ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33 | ; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 | ; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 | ; DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
36 | ; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 | ; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 | ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39 | ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 | ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 | ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 | ;
43 |
44 | ; Definitions:
45 | %define ORG_LOC 0x7C00 ; Initial position in memory (where MBR loads us)
46 |
47 | [section .text]
48 | [global start16] ; Export start16 to linker
49 | [extern main16] ; Import main16() from C
50 | [extern main32] ; Import main32() from C
51 | [extern kmain] ; Import kmain() from C
52 |
53 | ; Remember in NASM it's:
54 | ; instruction destination, source
55 |
56 | [bits 16] ; Real mode
57 |
58 | start16: ; Boot entry point
59 | ; Setup registers
60 | xor eax, eax ; clear EAX
61 | xor ebx, ebx ; clear EBX
62 | xor ecx, ecx ; clear ECX
63 | xor edx, edx ; clear EDX
64 | xor esi, esi ; clear ESI
65 | xor edi, edi ; clear EDI
66 | xor ebp, ebp ; clear EBP
67 | mov ds, ax ; zero out data segment register (DS)
68 | mov es, ax ; zero out extra segment register (ES)
69 | mov ss, ax ; zero out stack segment register (SS)
70 | mov fs, ax ; zero out general purpose data segment register (FS)
71 | mov gs, ax ; zero out general purpose data segment register (FS)
72 | mov sp, ORG_LOC ; set stack pointer to the begining of MBR location in memory
73 |
74 | ; Call Real Mode initialization
75 | cli ; disable all maskable interrupts
76 | call main16 ; call C function main16() (see: boot/main16.c)
77 |
78 | ; Enter Protected mode
79 | lgdt [gdt32_ptr] ; load 32bit GDT pointer
80 |
81 | mov eax, cr0 ; read from CR0
82 | or eax, 0x00000001 ; set Protected Mode bit
83 | mov cr0, eax ; write to CR0
84 |
85 | jmp 0x08:start32 ; do the magic jump to finalize Protected Mode setup
86 |
87 | [bits 32] ; Protected mode
88 |
89 | start32: ; Protected mode entry point
90 | ; Setup segment registers
91 | mov eax, 0x10 ; selector 0x10 - data descriptor
92 | xor ebx, ebx ; clear EBX
93 | xor ecx, ecx ; clear ECX
94 | xor edx, edx ; clear EDX
95 | xor esi, esi ; clear ESI
96 | xor edi, edi ; clear EDI
97 | xor ebp, ebp ; clear EBP
98 | mov esp, ORG_LOC ; clear the stack
99 | mov ss, ax ; set stack segment
100 | mov ds, ax ; set data segment
101 | mov es, ax ; set extra segment
102 | mov fs, ax ; set general purpose data Segment
103 | mov gs, ax ; set general purpose data Segment
104 |
105 | ; Call Protected Mode Initialization
106 | call main32 ; call C function main32() (see: boot/main32.c)
107 |
108 | ; Disable all IRQs
109 | mov al, 0xFF ; set out 0xFF to 0xA1 and 0x21 to disable all IRQs
110 | out 0xA1, al
111 | out 0x21, al
112 |
113 | ; Setup long mode.
114 | mov eax, cr0 ; read from CR0
115 | and eax, 0x7FFFFFFF ; clear paging bit
116 | mov cr0, eax ; write to CR0
117 |
118 | mov eax, cr4 ; read from CR4
119 | or eax, 0x000000A0 ; set the PAE and PGE bit
120 | mov cr4, eax ; write to CR4
121 |
122 | mov eax, [pml4_ptr32] ; point eax to PML4 pointer location
123 | or eax, 0x0000000B ; enable write-through
124 | mov cr3, eax ; save PML4 pointer into CR3
125 |
126 | mov ecx, 0xC0000080 ; read from the EFER MSR
127 | rdmsr ; read MSR
128 | or eax, 0x00000101 ; set the LME and SYSCALL/SYSRET bits
129 | wrmsr ; write MSR
130 |
131 | lgdt [gdt64_ptr] ; load 64bit GDT pointer
132 |
133 | mov eax, cr0 ; read from CR0
134 | or eax, 0x80000000 ; set paging bit
135 | mov cr0, eax ; write to CR0
136 | jmp 0x08:start64 ; do the magic jump to Long Mode
137 |
138 | align 16
139 | [bits 64] ; Long mode
140 |
141 | start64: ; Long Mode entry point
142 | ; Register cleanup
143 | xor rax, rax ; aka r0
144 | xor rbx, rbx ; aka r1
145 | xor rcx, rcx ; aka r2
146 | xor rdx, rdx ; aka r3
147 | xor rsi, rsi ; aka r4
148 | xor rdi, rdi ; aka r5
149 | xor rbp, rbp ; aka r6
150 | mov rsp, ORG_LOC ; aka r7 and clear the stack
151 | xor r8, r8
152 | xor r9, r9
153 | xor r10, r10
154 | xor r11, r11
155 | xor r12, r12
156 | xor r13, r13
157 | xor r14, r14
158 | xor r15, r15
159 | mov ds, ax ; clear the legacy segment registers
160 | mov es, ax
161 | mov ss, ax
162 | mov fs, ax
163 | mov gs, ax
164 |
165 | call kmain ; call C function kmain() (see: kernel/kmain.c)
166 | cli ; disable interrupts
167 | jmp $ ; hang
168 |
169 | [section .data]
170 |
171 | [global pml4_ptr32] ; Make PML4 pointer accessible from C
172 |
173 | ; PML4 pointer (for 32bit CR3)
174 | pml4_ptr32:
175 | dd 0 ; Dummy entry - we'll populate it in main32 and later in kmain
176 | pml4_ptr32_end:
177 |
178 | [section .rodata]
179 |
180 | ; Global Descriptor Table (GDT) used to do the Protected Mode jump (this is read-only as we don't need to update it)
181 | gdt32:
182 | ; Null Descriptor (selector: 0x00)
183 | .null_desc:
184 | dw 0x0000
185 | dw 0x0000
186 | db 0x00
187 | db 0x00
188 | db 0x00
189 | db 0x00
190 |
191 | ; Code Descriptor (selector: 0x08)
192 | .code_desc:
193 | dw 0xffff ; 0:15 - Limit
194 | dw 0x0000 ; 16:31 - Base (low word)
195 | db 0x00 ; 32:39 - Base (high word low byte)
196 | db 10011010b ; 40:47 - Access byte
197 | db 11001111b ; 48:55 - Limit (high nibble) + Flags (4 bits)
198 | db 0x00 ; 56:64 - Base (high word high byte)
199 |
200 | ; Data Descriptor (selector: 0x10)
201 | .data_desc:
202 | dw 0xffff ; 0:15 - Limit
203 | dw 0x0000 ; 16:31 - Base (low word)
204 | db 0x00 ; 32:39 - Base (high word low byte)
205 | db 10010010b ; 40:47 - Access byte
206 | db 11001111b ; 48:55 - Limit (high nibble) + Flags (4 bits)
207 | db 0x00 ; 56:64 - Base (high word high byte)
208 | gdt32_end:
209 |
210 | ; GDT pointer (this get's passed to LGDT)
211 | gdt32_ptr:
212 | dw (gdt32_end - gdt32 - 1) ; Limit (size)
213 | dd (gdt32 + 0x000000000000) ; Base (location)
214 | gdt32_ptr_end:
215 |
216 | ; 64bit GDT
217 | align 16
218 | gdt64:
219 | ; Null Descriptor (selector: 0x00)
220 | .null_desc:
221 | dw 0x0000
222 | dw 0x0000
223 | db 0x00
224 | db 0x00
225 | db 0x00
226 | db 0x00
227 |
228 | ; Code Descriptor (selector: 0x08)
229 | .code_desc:
230 | dw 0x0000 ; 0:15 - Limit
231 | dw 0x0000 ; 16:31 - Base (low word)
232 | db 0x00 ; 32:39 - Base (high word low byte)
233 | ; P|DPL|DPL|1|1|C|R|A
234 | db 10011100b ; 40:47 - Access byte
235 | ; G|D|L|AVL|0|0|0|0
236 | db 00100000b ; 48:55 - Limit (high nibble) + Flags (4 bits)
237 | db 0x00 ; 56:64 - Base (high word high byte)
238 |
239 | ; Data Descriptor (selector: 0x10)
240 | .data_desc:
241 | dw 0x0000 ; 0:15 - Limit
242 | dw 0x0000 ; 16:31 - Base (low word)
243 | db 0x00 ; 32:39 - Base (high word low byte)
244 | db 10010000b ; 40:47 - Access byte
245 | db 00100000b ; 48:55 - Limit (high nibble) + Flags (4 bits)
246 | db 0x00 ; 56:64 - Base (high word high byte)
247 | gdt64_end:
248 |
249 | align 16
250 | gdt64_ptr:
251 | dw (gdt64_end - gdt64 - 1) ; Limit (size)
252 | dq (gdt64 + 0x0000000000000000) ; Base (location)
253 | gdt64_ptr_end:
254 |
--------------------------------------------------------------------------------
/bbp/boot/boot.ld:
--------------------------------------------------------------------------------
1 | OUTPUT_FORMAT(elf64-x86-64)
2 | SECTIONS {
3 | .text : {
4 | boot.s.o(.text);
5 | bios.s.o(.text);
6 | main16.c64.o(.text);
7 | *(.text);
8 | }
9 | .rodata : {
10 | *(.rodata);
11 | }
12 | .data : {
13 | *(.data);
14 | }
15 | .bss : {
16 | *(.bss);
17 | }
18 | . = ALIGN(4096);
19 | }
--------------------------------------------------------------------------------
/bbp/boot/common16.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Common data types (real mode)
4 | =============================
5 |
6 | This file contains type definitions and helper structures.
7 |
8 | The idea of this file is to keep a precise control over data type sizes, so
9 | instead of int and long, we should have int32 or int64.
10 |
11 | Maybe in the future we'll introduce memory pointer type intptr or simply ptr,
12 | that will reference the largest integer type for memory access of the machine.
13 | That is, a 64bit int for x86_64 architecture and 32bit int for x86.
14 |
15 | License (BSD-3)
16 | ===============
17 |
18 | Copyright (c) 2013, Gusts 'gusC' Kaksis
19 | All rights reserved.
20 |
21 | Redistribution and use in source and binary forms, with or without
22 | modification, are permitted provided that the following conditions are met:
23 | * Redistributions of source code must retain the above copyright
24 | notice, this list of conditions and the following disclaimer.
25 | * Redistributions in binary form must reproduce the above copyright
26 | notice, this list of conditions and the following disclaimer in the
27 | documentation and/or other materials provided with the distribution.
28 | * Neither the name of the nor the
29 | names of its contributors may be used to endorse or promote products
30 | derived from this software without specific prior written permission.
31 |
32 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
36 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 |
43 | */
44 |
45 | #ifndef __common16_h
46 | #define __common16_h
47 |
48 | // Make this C output 16-bit
49 | asm(".code16gcc\n");
50 | //asm(".code16\n");
51 |
52 | #define __INLINE __attribute__((always_inline))
53 | #define __NORETURN __attribute__((noreturn))
54 | #define __PACKED __attribute__((packed))
55 | #define __ALIGN(x) __attribute__((aligned(x)))
56 |
57 | #define BREAK() asm volatile ("xchg %bx, %bx")
58 | #define HANG() asm volatile ("int $0x18") // go to BASIC :)
59 | #define STOP() while(true){}
60 |
61 | // If we use .code16 then all ret and leave functions behave as in 16bit mode,
62 | // but the function entries are still behaving as in 32bit mode (GCC bug?)
63 | // So this is the fix - we move base pointer 2 bytes further thus leave cleans out
64 | // the stack frame correctly
65 | #define RET16() asm volatile ("add $2, %bp")
66 | // If we use .code16gcc then all ret and leave functions behave as in 32bit mode,
67 | // so right after leave (which is 0x66 prefixed) we do a magic switch to
68 | // 16-bit mode so that ret does not do a far jump.
69 | #define RET32() asm volatile ("leave\n\
70 | .code16\n\
71 | ret\n\
72 | .code16gcc\n");
73 |
74 | // Default types
75 | typedef unsigned char uchar;
76 |
77 | typedef unsigned char uint8;
78 | typedef unsigned short uint16;
79 | typedef unsigned int uint32;
80 | typedef unsigned long long uint64;
81 |
82 | typedef char int8;
83 | typedef short int16;
84 | typedef int int32;
85 | typedef long long int64;
86 |
87 | typedef float float32;
88 | typedef double float64;
89 |
90 | typedef void *handle_t;
91 | #define null 0
92 | #define true 1
93 | #define false 0
94 |
95 | #endif /* __common16_h */
96 |
--------------------------------------------------------------------------------
/bbp/boot/common32.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Common data types (protected mode)
4 | ==================================
5 |
6 | This file contains type definitions and helper structures.
7 |
8 | The idea of this file is to keep a precise control over data type sizes, so
9 | instead of int and long, we should have int32 or int64.
10 |
11 | Maybe in the future we'll introduce memory pointer type intptr or simply ptr,
12 | that will reference the largest integer type for memory access of the machine.
13 | That is, a 64bit int for x86_64 architecture and 32bit int for x86.
14 |
15 | License (BSD-3)
16 | ===============
17 |
18 | Copyright (c) 2013, Gusts 'gusC' Kaksis
19 | All rights reserved.
20 |
21 | Redistribution and use in source and binary forms, with or without
22 | modification, are permitted provided that the following conditions are met:
23 | * Redistributions of source code must retain the above copyright
24 | notice, this list of conditions and the following disclaimer.
25 | * Redistributions in binary form must reproduce the above copyright
26 | notice, this list of conditions and the following disclaimer in the
27 | documentation and/or other materials provided with the distribution.
28 | * Neither the name of the nor the
29 | names of its contributors may be used to endorse or promote products
30 | derived from this software without specific prior written permission.
31 |
32 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
36 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 |
43 | */
44 |
45 | #ifndef __common32_h
46 | #define __common32_h
47 |
48 | #define __INLINE __attribute__((always_inline))
49 | #define __NORETURN __attribute__((noreturn))
50 | #define __PACKED __attribute__((packed))
51 | #define __ALIGN(x) __attribute__((aligned(x)))
52 |
53 | #define BREAK() asm volatile ("xchg %bx, %bx")
54 | #define HANG() while(true){}
55 |
56 | // Default types
57 | typedef unsigned char uchar;
58 |
59 | typedef unsigned char uint8;
60 | typedef unsigned short uint16;
61 | typedef unsigned int uint32;
62 | typedef unsigned long long uint64;
63 |
64 | typedef char int8;
65 | typedef short int16;
66 | typedef int int32;
67 | typedef long long int64;
68 |
69 | typedef float float32;
70 | typedef double float64;
71 |
72 | typedef void *handle_t;
73 | #define null 0
74 | #define true 1
75 | #define false 0
76 |
77 | #endif /* __common32_h */
78 |
--------------------------------------------------------------------------------
/bbp/boot/main16.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Real Mode initialization
4 | =============================
5 |
6 | This file contains initialization code real mode (preparation to switch to
7 | protected mode).
8 |
9 | It does:
10 | * video mode switch
11 | * memory mapping
12 |
13 | License (BSD-3)
14 | ===============
15 |
16 | Copyright (c) 2013, Gusts 'gusC' Kaksis
17 | All rights reserved.
18 |
19 | Redistribution and use in source and binary forms, with or without
20 | modification, are permitted provided that the following conditions are met:
21 | * Redistributions of source code must retain the above copyright
22 | notice, this list of conditions and the following disclaimer.
23 | * Redistributions in binary form must reproduce the above copyright
24 | notice, this list of conditions and the following disclaimer in the
25 | documentation and/or other materials provided with the distribution.
26 | * Neither the name of the nor the
27 | names of its contributors may be used to endorse or promote products
28 | derived from this software without specific prior written permission.
29 |
30 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
31 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
33 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
34 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
37 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 |
41 | */
42 |
43 | #include "main16.h"
44 | #include "../config.h"
45 |
46 | /**
47 | * Set video mode
48 | * @see bios.asm
49 | * @param mode - BIOS video mode
50 | */
51 | extern void set_video_mode(uint16 mode);
52 | /**
53 | * Set video mode SuperVGA
54 | * @see bios.asm
55 | * @param mode - SuperVGA video mode
56 | */
57 | extern void set_svga_mode(uint16 mode);
58 | /**
59 | * Enable A20 gate
60 | * @see bios.asm
61 | */
62 | extern void enable_a20();
63 | /**
64 | * Check if A20 gate is open already
65 | * @see bios.asm
66 | */
67 | extern uint16 check_a20();
68 | /**
69 | * Read E820 memory map
70 | * @see bios.asm
71 | * @param mem_map - e820 memory map structure pointer
72 | * @return status code (1 - ok, 0 - failed)
73 | */
74 | extern uint32 read_e820(e820map_t *mem_map);
75 |
76 | /**
77 | * Initialize Real Mode
78 | */
79 | void main16(){
80 | // This a static location (see config.h)
81 | e820map_t *mem_map = (e820map_t *)E820_LOC;
82 |
83 | // Setup video mode
84 | #if DEBUG == 1
85 | #if VIDEOMODE == 1
86 | set_video_mode(0x03); // Teletype
87 | #elif VIDEOMODE == 2
88 | set_svga_mode(0x011B); // 1280x1024 (24 bit)
89 | #endif
90 | #endif
91 |
92 | // Enable A20 gate
93 | enable_a20();
94 | // Read E820 map
95 | read_e820(mem_map);
96 |
97 | // Exit like we want it!
98 | // It's uggly, but as we can not control the entry of this function
99 | // at least we can control the exit.
100 | RET32();
101 | }
102 |
--------------------------------------------------------------------------------
/bbp/boot/main16.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Real Mode initialization
4 | =============================
5 |
6 | This file contains initialization code real mode (preparation to switch to
7 | protected mode).
8 |
9 | It does:
10 | * video mode switch
11 | * memory mapping
12 |
13 | License (BSD-3)
14 | ===============
15 |
16 | Copyright (c) 2013, Gusts 'gusC' Kaksis
17 | All rights reserved.
18 |
19 | Redistribution and use in source and binary forms, with or without
20 | modification, are permitted provided that the following conditions are met:
21 | * Redistributions of source code must retain the above copyright
22 | notice, this list of conditions and the following disclaimer.
23 | * Redistributions in binary form must reproduce the above copyright
24 | notice, this list of conditions and the following disclaimer in the
25 | documentation and/or other materials provided with the distribution.
26 | * Neither the name of the nor the
27 | names of its contributors may be used to endorse or promote products
28 | derived from this software without specific prior written permission.
29 |
30 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
31 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
33 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
34 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
37 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 |
41 | */
42 |
43 | #ifndef __main16_h
44 | #define __main16_h
45 |
46 | #include "common16.h"
47 |
48 | /**
49 | * E820 memory map entry structure
50 | */
51 | struct e820entry_struct {
52 | uint16 entry_size; // if 24, then it has attributes
53 | uint64 base;
54 | uint64 length;
55 | uint32 type;
56 | uint32 attributes; // ACPI 3.0 only
57 | } __PACKED;
58 | typedef struct e820entry_struct e820entry_t;
59 | /**
60 | * E820 memory map structure
61 | */
62 | struct e820map_struct {
63 | uint16 size;
64 | e820entry_t entries[];
65 | } __PACKED;
66 | typedef struct e820map_struct e820map_t;
67 |
68 | #endif /* __main16_h */
69 |
--------------------------------------------------------------------------------
/bbp/boot/main32.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Protected Mode initialization
4 | =============================
5 |
6 | This file contains initialization code protected mode (preparation to switch to
7 | long mode).
8 |
9 | It does:
10 | * page setup and initialization
11 |
12 | License (BSD-3)
13 | ===============
14 |
15 | Copyright (c) 2013, Gusts 'gusC' Kaksis
16 | All rights reserved.
17 |
18 | Redistribution and use in source and binary forms, with or without
19 | modification, are permitted provided that the following conditions are met:
20 | * Redistributions of source code must retain the above copyright
21 | notice, this list of conditions and the following disclaimer.
22 | * Redistributions in binary form must reproduce the above copyright
23 | notice, this list of conditions and the following disclaimer in the
24 | documentation and/or other materials provided with the distribution.
25 | * Neither the name of the nor the
26 | names of its contributors may be used to endorse or promote products
27 | derived from this software without specific prior written permission.
28 |
29 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
30 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
32 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
33 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
36 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
38 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 |
40 | */
41 |
42 | #include "main32.h"
43 | #include "../config.h"
44 |
45 | /**
46 | * PML4 pointer (to be passed over to CR3)
47 | * @see boot.asm
48 | */
49 | extern uint32 pml4_ptr32;
50 |
51 | /**
52 | * Clear memory region
53 | * @param dest - destination address (pointer to destination buffer)
54 | * @param len - length to clear
55 | */
56 | static void mem_clear(uint8 *dest, uint32 len){
57 | while(len--){
58 | *dest++ = 0;
59 | }
60 | }
61 | /**
62 | * Setup PML4 pages to enter Long Mode
63 | * @param ammount - ammount of memory to map
64 | */
65 | static void setup_pages(uint64 ammount){
66 | uint64 p;
67 | uint64 t;
68 | uint64 d;
69 | uint64 dr;
70 | uint64 ptr;
71 |
72 | // Single page (PML1 entry) holds 4KB of RAM
73 | uint64 page_count = ammount / PAGE_SIZE;
74 | if (ammount % PAGE_SIZE > 0){
75 | page_count ++;
76 | }
77 | // Single table (PML2 entry) holds 2MB of RAM
78 | uint64 table_count = page_count / 512;
79 | if (page_count % 512 > 0){
80 | table_count ++;
81 | }
82 | // Single directory (PML3 entry, directory table pointer) holds 1GB of RAM
83 | uint64 directory_count = table_count / 512;
84 | if (table_count % 512 > 0){
85 | directory_count ++;
86 | }
87 | // Single drawer (PML4 entry) holds 512GB of RAM
88 | uint64 drawer_count = directory_count / 512;
89 | if (directory_count % 512 > 0){
90 | drawer_count ++;
91 | }
92 |
93 | // Position the page table structures in memory
94 |
95 | // Located at 0x00100000 (1MB mark, see config.h)
96 | // a.k.a. PML4T (512GB per entry = 256TB total, this is a page cabinet)
97 | // Holds 512 entries, only 1st is active - enough to map 512GB
98 | pm_t *pml4 = (pm_t*)PT_LOC;
99 | // Located at PML4 + (8 * 512)
100 | // a.k.a. PDPT (page directory pointer table, 1GB per entry, let's call this a page drawer)
101 | // Holds 512 entries, each entry maps up to 1GB, table = 512GB
102 | pm_t *pml3 = (pm_t*)(((uint32)pml4) + (sizeof(pm_t) * 512));
103 | // Located at PML3 + (8 * 512 * drawer_count)
104 | // a.k.a. PD (page directory, 2MB per entry)
105 | // Holds 512 entries * directory_count, each entry maps up to 2MB, table = 1GB
106 | pm_t *pml2 = (pm_t*)(((uint32)pml3) + (sizeof(pm_t) * 512 * (uint32)drawer_count));
107 | // Located at PML2 + (8 * 512 * directory_count)
108 | // a.k.a. PT (page table, 4KB per entry)
109 | // Holds 512 entries * table_count, each entry maps 4KB, table = 2MB
110 | pm_t *pml1 = (pm_t*)(((uint32)pml2) + (sizeof(pm_t) * 512 * (uint32)directory_count));
111 |
112 | // Clear memory region where the page tables will reside
113 | mem_clear((uint8 *)pml4, sizeof(pm_t) * 512);
114 | mem_clear((uint8 *)pml3, sizeof(pm_t) * 512 * drawer_count);
115 | mem_clear((uint8 *)pml2, sizeof(pm_t) * 512 * directory_count);
116 | mem_clear((uint8 *)pml1, sizeof(pm_t) * 512 * table_count);
117 |
118 | // Set up pages, tables, directories and drawers in the cabinet :)
119 | for (p = 0; p < page_count; p ++){
120 | ptr = (uint64)(p * PAGE_SIZE);
121 | pml1[p].raw = ptr & PAGE_MASK;
122 | pml1[p].s.present = 1;
123 | pml1[p].s.writable = 1;
124 | pml1[p].s.write_through = 1;
125 | //pml1[p].s.cache_disable = 1;
126 | //pml1[p].s.global = 1;
127 | }
128 | for (t = 0; t < table_count; t ++){
129 | ptr = (uint64)(((uint32)pml1) + (sizeof(pm_t) * 512 * t));
130 | pml2[t].raw = ptr & PAGE_MASK;
131 | pml2[t].s.present = 1;
132 | pml2[t].s.writable = 1;
133 | pml2[t].s.write_through = 1;
134 | //pml2[t].s.cache_disable = 1;
135 | }
136 | for (d = 0; d < directory_count; d ++){
137 | ptr = (uint64)(((uint32)pml2) + (sizeof(pm_t) * 512 * d));
138 | pml3[d].raw = ptr & PAGE_MASK;
139 | pml3[d].s.present = 1;
140 | pml3[d].s.writable = 1;
141 | pml3[d].s.write_through = 1;
142 | //pml3[d].s.cache_disable = 1;
143 | }
144 | for (dr = 0; dr < drawer_count; dr ++){
145 | ptr = (uint64)(((uint32)pml3) + (sizeof(pm_t) * 512 * dr));
146 | pml4[dr].raw = ptr & PAGE_MASK;
147 | pml4[dr].s.present = 1;
148 | pml4[dr].s.writable = 1;
149 | pml4[dr].s.write_through = 1;
150 | //pml4[dr].s.cache_disable = 1;
151 | }
152 |
153 | // Set PML4 pointer address
154 | pml4_ptr32 = (uint32)pml4; // Point to our cabinet :)
155 | }
156 |
157 | /**
158 | * Initialize Protected Mode
159 | */
160 | void main32(){
161 | // Page map some memory (identity map)
162 | setup_pages(INIT_MEM);
163 | }
164 |
--------------------------------------------------------------------------------
/bbp/boot/main32.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Protected Mode initialization
4 | =============================
5 |
6 | This file contains initialization code protected mode (preparation to switch to
7 | long mode).
8 |
9 | It does:
10 | * page setup and initialization
11 |
12 | License (BSD-3)
13 | ===============
14 |
15 | Copyright (c) 2013, Gusts 'gusC' Kaksis
16 | All rights reserved.
17 |
18 | Redistribution and use in source and binary forms, with or without
19 | modification, are permitted provided that the following conditions are met:
20 | * Redistributions of source code must retain the above copyright
21 | notice, this list of conditions and the following disclaimer.
22 | * Redistributions in binary form must reproduce the above copyright
23 | notice, this list of conditions and the following disclaimer in the
24 | documentation and/or other materials provided with the distribution.
25 | * Neither the name of the nor the
26 | names of its contributors may be used to endorse or promote products
27 | derived from this software without specific prior written permission.
28 |
29 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
30 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
32 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
33 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
36 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
38 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 |
40 | */
41 |
42 | #ifndef __main32_h
43 | #define __main32_h
44 |
45 | #include "common32.h"
46 |
47 | /**
48 | * 64-bit page table/directory/level3/level4 entry structure
49 | */
50 |
51 | typedef union {
52 | struct {
53 | uint64 present : 1; // Is the page present in memory?
54 | uint64 writable : 1; // Is the page writable?
55 | uint64 user : 1; // Is the page for userspace?
56 | uint64 write_through : 1; // Do we want write-trough? (when cached, this also writes to memory)
57 | uint64 cache_disable : 1; // Disable cache on this page?
58 | uint64 accessed : 1; // Has the page been accessed by software?
59 | uint64 dirty : 1; // Has the page been written to since last refresh?
60 | uint64 pat : 1; // Is the page a PAT? (dunno what it is)
61 | uint64 global : 1; // Is the page global? (dunno what it is)
62 | uint64 data : 3; // Available for kernel use (do what you want?)
63 | uint64 frame : 52; // Frame address (shifted right 12 bits)
64 | } s;
65 | uint64 raw; // Raw value
66 | } pm_t;
67 |
68 | #define PAGE_MASK 0xFFFFFFFFF000;
69 |
70 | #endif /* __main32_h */
71 |
--------------------------------------------------------------------------------
/bbp/boot/makefile:
--------------------------------------------------------------------------------
1 | AS = nasm -felf64 -O0
2 | CC = x86_64-pc-elf-gcc -m32 -march=i686 -nostartfiles -nostdlib -nodefaultlibs -fno-builtin -Wno-attributes
3 | LD = x86_64-pc-elf-ld -i
4 | OC = x86_64-pc-elf-objcopy -I elf32-i386 -O elf64-x86-64
5 | OBJECTS = boot.s.o bios.s.o main16.c64.o main32.c64.o
6 |
7 | all: boot.o
8 |
9 | boot.o: $(OBJECTS)
10 | $(LD) -T boot.ld $(OBJECTS) -o ../boot.o
11 |
12 | %.s.o: %.asm
13 | $(AS) -o $@ $<
14 |
15 | %.c.o: %.c
16 | $(CC) -c $< -o $@
17 |
18 | %.c64.o: %.c.o
19 | $(OC) $< $@
20 |
21 | clean:
22 | rm -f *.o
--------------------------------------------------------------------------------
/bbp/buildimg.bat:
--------------------------------------------------------------------------------
1 | ::@ECHO OFF
2 |
3 | ::REM 10 tracs, 16 heads, 63 sectors-per-track = 10080 sectors
4 | SET maxbytes=5160960
5 | SET mbr=..\Release\mbr.img
6 | SET bbp=..\Release\bbp.img
7 | SET output=..\Release\disk.img
8 |
9 | ..\..\diskutils\Release\buildimg.exe -m %mbr% -b %bbp% -s %maxbytes% %output%
10 |
11 | ECHO Cleanup
12 | ::DEL %mbr%
13 | ::DEL %bbp%
14 |
15 | ::PAUSE
--------------------------------------------------------------------------------
/bbp/config.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Global configuration
4 | ====================
5 |
6 | This file contains global configuration used at compile-time.
7 |
8 | License (BSD-3)
9 | ===============
10 |
11 | Copyright (c) 2013, Gusts 'gusC' Kaksis
12 | All rights reserved.
13 |
14 | Redistribution and use in source and binary forms, with or without
15 | modification, are permitted provided that the following conditions are met:
16 | * Redistributions of source code must retain the above copyright
17 | notice, this list of conditions and the following disclaimer.
18 | * Redistributions in binary form must reproduce the above copyright
19 | notice, this list of conditions and the following disclaimer in the
20 | documentation and/or other materials provided with the distribution.
21 | * Neither the name of the nor the
22 | names of its contributors may be used to endorse or promote products
23 | derived from this software without specific prior written permission.
24 |
25 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
26 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
29 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 |
36 | */
37 |
38 |
39 | #ifndef __config_h
40 | #define __config_h
41 |
42 | //
43 | // Global settings
44 | //
45 |
46 | // Video mode
47 | // 0 - none, leave it as is
48 | // 1 - teletype
49 | // 2 - VGA
50 | #define VIDEOMODE 1
51 | // Enable debug output
52 | #define DEBUG 1
53 | // Initial memory size to map to enter Long Mode
54 | // we don't need more than this, but it should be more than 1MB
55 | // as the PMLx structures will be located at the 1MB mark
56 | #define INIT_MEM 0x200000 // 2MB
57 | // Default page size
58 | #define PAGE_SIZE 0x1000
59 |
60 | //
61 | // Hard-coded memory locations
62 | //
63 |
64 | // E820 memory map location
65 | #define E820_LOC 0x0800
66 | // Memory location where to store PMLx page tables
67 | #define PT_LOC 0x00100000
68 |
69 | #if VIDEOMODE == 1
70 | // Teletype video memory location
71 | // This can be used only in 32+ bit modes
72 | #define VIDEOMEM_LOC 0xB8000
73 | #elif VIDEOMODE == 2
74 | // VGA video memory location
75 | // This can be used only in 32+ bit modes
76 | #define VIDEOMEM_LOC 0xA0000
77 | #else
78 | // Null address
79 | #define VIDEOMEM_LOC 0x0
80 | #endif
81 |
82 | #endif
83 |
--------------------------------------------------------------------------------
/bbp/kernel/README.md:
--------------------------------------------------------------------------------
1 | Kernel
2 | ======
3 |
4 | This is the Long Mode BBP kernel code
5 |
6 | File list
7 | ---------
8 |
9 | Main entry files:
10 | * kmain.c - C entry point that get's called by ../boot/boot.asm
11 |
12 | Helper files:
13 | * acpi.* - ACPI table lokup implementation
14 | * ahci.* - AHCI driver
15 | * apic.* - APIC/xAPIC/x2APIC initialization
16 | * common.h - data type definitions
17 | * cpuid.h - inline assembly definition for CPUID instruction
18 | * interrupts.c - interrupt inititialization
19 | * interrupts.asm - interrupt service routines
20 | * interrupts.h - intterupt service routine import in C
21 | * io.h - legacy IO instruction inline definitions
22 | * lib.* - tiny C helper library
23 | * msr.h - Model Specific Register (MSR) instructions inline definitions
24 | * paging.* - Paging functions
25 | * pci.* - PCI operation functions
26 | * debug_print.* - Debug output to text-mode video
27 |
28 | Build files:
29 | * kernel.ld - Kernel linker script
30 | * makefile - Make build script
31 |
--------------------------------------------------------------------------------
/bbp/kernel/acpi.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | ACPI functions
4 | ==============
5 |
6 | License (BSD-3)
7 | ===============
8 |
9 | Copyright (c) 2012, Gusts 'gusC' Kaksis
10 | All rights reserved.
11 |
12 | Redistribution and use in source and binary forms, with or without
13 | modification, are permitted provided that the following conditions are met:
14 | * Redistributions of source code must retain the above copyright
15 | notice, this list of conditions and the following disclaimer.
16 | * Redistributions in binary form must reproduce the above copyright
17 | notice, this list of conditions and the following disclaimer in the
18 | documentation and/or other materials provided with the distribution.
19 | * Neither the name of the nor the
20 | names of its contributors may be used to endorse or promote products
21 | derived from this software without specific prior written permission.
22 |
23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
27 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 |
34 | */
35 |
36 | #include "../config.h"
37 | #include "acpi.h"
38 | #include "lib.h"
39 | #include "paging.h"
40 | #include "io.h"
41 | #if DEBUG == 1
42 | #include "debug_print.h"
43 | #endif
44 |
45 | RSDP_t *_rsdp = null;
46 |
47 | /**
48 | * Calculate ACPI checksum
49 | * @param [in] block - memory address of a first byte of ACPI structure
50 | * @param len - structure size in memory
51 | * @return checksum value
52 | */
53 | static uint8 acpi_checksum(uint8 *block, uint64 len){
54 | uint32 sum = 0;
55 | while (len--){
56 | sum += *(block++);
57 | }
58 | return (uint8)(sum);
59 | }
60 | /**
61 | * Find root system descriptor pointer (RSDP)
62 | * @retun true if found
63 | */
64 | static bool acpi_find(){
65 | const char sign[9] = "RSD PTR ";
66 | if (_rsdp == null){
67 | _rsdp = (RSDP_t *)0x80000; // We start at the beginning of EBDA
68 | do {
69 | if (mem_compare((uint8 *)_rsdp->signature, (uint8 *)sign, 8)){
70 | if (_rsdp->revision == 0){
71 | if (acpi_checksum((uint8 *)_rsdp, sizeof(uint8) * 20) == 0){ // Revision 1.0 checksum
72 | // Map RSDT address
73 | page_map_mmio((uint64)_rsdp->RSDT_address);
74 | return true;
75 | }
76 | } else {
77 | if (acpi_checksum((uint8 *)_rsdp, sizeof(RSDP_t)) == 0){ // Revision 2.0+ checksum
78 | // Map XSDT address
79 | page_map_mmio(_rsdp->XSDT_address);
80 | return true;
81 | }
82 | }
83 | }
84 | _rsdp = (RSDP_t *)((uint64)_rsdp + 0x10);
85 | } while ((uint64)_rsdp < 0x100000); // Up until 1MB mark
86 | _rsdp = null;
87 | }
88 | return false;
89 | }
90 | /**
91 | * Map pages to ACPI tables
92 | */
93 | static void acpi_map(){
94 | if (_rsdp != null){
95 | SDTHeader_t *th;
96 | uint64 i;
97 | uint64 j;
98 | uint64 count;
99 | uint64 ptr;
100 | if (_rsdp->revision == 0){
101 | // ACPI version 1.0
102 | RSDT_t *rsdt = (RSDT_t *)((uint64)_rsdp->RSDT_address);
103 | // Get count of other table pointers
104 | count = (rsdt->h.length - sizeof(SDTHeader_t)) / 4;
105 | for (i = 0; i < count; i ++){
106 | // Get an address of table pointer array
107 | ptr = (uint64)&rsdt->ptr;
108 | // Move on to entry i (32bits = 4 bytes) in table pointer array
109 | ptr += (i * 4);
110 | // Map the page
111 | page_map_mmio(ptr);
112 | // Get the pointer of table in table pointer array
113 | th = (SDTHeader_t *)((uint64)(*((uint32 *)ptr)));
114 | // If the length is greater than a page, map additional pages
115 | if (th->length > PAGE_SIZE){
116 | for (j = (ptr & PAGE_MASK) + PAGE_SIZE; j < ((ptr + th->length) & PAGE_MASK); j += PAGE_SIZE){
117 | page_map_mmio(j);
118 | }
119 | }
120 | }
121 | } else {
122 | // ACPI version 2.0+
123 | XSDT_t *xsdt = (XSDT_t *)_rsdp->XSDT_address;
124 | // Get count of other table pointers
125 | count = (xsdt->h.length - sizeof(SDTHeader_t)) / 8;
126 | for (i = 0; i < count; i ++){
127 | // Get an address of table pointer array
128 | ptr = (uint64)&xsdt->ptr;
129 | // Move on to entry i (64bits = 8 bytes) in table pointer array
130 | ptr += (i * 8);
131 | // Map the page
132 | page_map_mmio(ptr);
133 | // Get the pointer of table in table pointer array
134 | th = (SDTHeader_t *)(*((uint64 *)ptr));
135 | // If the length is greater than a page, map additional pages
136 | if (th->length > PAGE_SIZE){
137 | for (j = (ptr & PAGE_MASK) + PAGE_SIZE; j < ((ptr + th->length) & PAGE_MASK); j += PAGE_SIZE){
138 | page_map_mmio(j);
139 | }
140 | }
141 | }
142 | }
143 | }
144 | }
145 |
146 | bool acpi_init(){
147 | if (acpi_find()){
148 | // Map pages to ACPI tables, so we don't get page faults
149 | acpi_map();
150 |
151 | char facp[4] = {'F', 'A', 'C', 'P'};
152 | FADT_t *fadt = (FADT_t *)acpi_table(facp);
153 | if (fadt != null){
154 | // Enable ACPI
155 | if ((fadt->pm1a_control_block & 0x1) == 0){ // Only if SCI_EN is not set
156 | if (fadt->smi_command_port > 0){ // and SMI_CMD is set
157 | if (fadt->acpi_enable > 0){ // and ACPI_ENABLE is set
158 | outb((uint16)fadt->smi_command_port, fadt->acpi_enable);
159 | }
160 | }
161 | }
162 |
163 | //FACS_t *facs = (FACS_t *)((uint64)fadt->firmware_ctrl);
164 |
165 | //DSDT_t *dsdt = (DSDT_t *)((uint64)fadt->dsdt);
166 | // TODO: parse DSDT
167 |
168 | //char ssdt_sig[4] = {'S', 'S', 'D', 'T'};
169 | //SSDT_t *ssdt = (SSDT_t *)acpi_table(ssdt_sig);
170 | //if (ssdt != null){
171 | // TODO: parse SSDT
172 | //}
173 |
174 | return true;
175 | }
176 | }
177 | return false;
178 | }
179 |
180 | RSDP_t *acpi_rsdp(){
181 | return _rsdp;
182 | }
183 |
184 | SDTHeader_t *acpi_table(const char signature[4]){
185 | if (_rsdp != null){
186 | SDTHeader_t *th;
187 | uint32 i;
188 | uint32 count;
189 | uint64 ptr;
190 | if (_rsdp->revision == 0){
191 | // ACPI version 1.0
192 | RSDT_t *rsdt = (RSDT_t *)((uint64)_rsdp->RSDT_address);
193 | // Get count of other table pointers
194 | count = (rsdt->h.length - sizeof(SDTHeader_t)) / 4;
195 | for (i = 0; i < count; i ++){
196 | // Get an address of table pointer array
197 | ptr = (uint64)&rsdt->ptr;
198 | // Move on to entry i (32bits = 4 bytes) in table pointer array
199 | ptr += (i * 4);
200 | // Get the pointer of table in table pointer array
201 | th = (SDTHeader_t *)((uint64)(*((uint32 *)ptr)));
202 | if (mem_compare((uint8 *)th->signature, (uint8 *)signature, 4)){
203 | if (acpi_checksum((uint8 *)th, th->length) == 0){
204 | return th;
205 | }
206 | }
207 | }
208 | } else {
209 | // ACPI version 2.0+
210 | XSDT_t *xsdt = (XSDT_t *)_rsdp->XSDT_address;
211 | // Get count of other table pointers
212 | count = (xsdt->h.length - sizeof(SDTHeader_t)) / 8;
213 | for (i = 0; i < count; i ++){
214 | // Get an address of table pointer array
215 | ptr = (uint64)&xsdt->ptr;
216 | // Move on to entry i (64bits = 8 bytes) in table pointer array
217 | ptr += (i * 8);
218 | // Get the pointer of table in table pointer array
219 | th = (SDTHeader_t *)(*((uint64 *)ptr));
220 | if (mem_compare((uint8 *)th->signature, (uint8 *)signature, 4)){
221 | if (acpi_checksum((uint8 *)th, th->length) == 0){
222 | return th;
223 | }
224 | }
225 | }
226 | }
227 | }
228 | return null;
229 | }
230 |
231 | #if DEBUG == 1
232 | void acpi_list(){
233 | if (_rsdp != null){
234 | SDTHeader_t *th;
235 | uint32 i;
236 | uint32 count;
237 | char sign[5] = "";
238 |
239 | debug_print(DC_WB, "RSDP @%x", (uint64)_rsdp);
240 |
241 | if (_rsdp->revision == 0){
242 | // ACPI version 1.0
243 | debug_print(DC_WB, "ACPI v1.0");
244 | debug_print(DC_WB, "XSDT @%x", (uint64)_rsdp->RSDT_address);
245 |
246 | RSDT_t *rsdt = (RSDT_t *)((uint64)_rsdp->RSDT_address);
247 | uint64 ptr;
248 | // Get count of other table pointers
249 | count = (rsdt->h.length - sizeof(SDTHeader_t)) / 4;
250 | for (i = 0; i < count; i ++){
251 | // Get an address of table pointer array
252 | ptr = (uint64)&rsdt->ptr;
253 | // Move on to entry i (32bits = 4 bytes) in table pointer array
254 | ptr += (i * 4);
255 | // Get the pointer of table in table pointer array
256 | th = (SDTHeader_t *)((uint64)(*((uint32 *)ptr)));
257 | mem_fill((uint8 *)sign, 5, 0);
258 | mem_copy((uint8 *)sign, 4, (uint8 *)th->signature);
259 | debug_print(DC_WB, "%s @%x", sign, (uint64)th);
260 | }
261 | } else {
262 | // ACPI version 2.0+
263 | debug_print(DC_WB, "ACPI v%d", (uint32)_rsdp->revision);
264 | debug_print(DC_WB, "XSDT @%x", _rsdp->XSDT_address);
265 |
266 | XSDT_t *xsdt = (XSDT_t *)_rsdp->XSDT_address;
267 | uint64 ptr;
268 | // Get count of other table pointers
269 | count = (xsdt->h.length - sizeof(SDTHeader_t)) / 8;
270 | for (i = 0; i < count; i ++){
271 | // Get an address of table pointer array
272 | ptr = (uint64)&xsdt->ptr;
273 | // Move on to entry i (64bits = 8 bytes) in table pointer array
274 | ptr += (i * 8);
275 | // Get the pointer of table in table pointer array
276 | th = (SDTHeader_t *)(*((uint64 *)ptr));
277 | mem_fill((uint8 *)sign, 5, 0);
278 | mem_copy((uint8 *)sign, 4, (uint8 *)th->signature);
279 | debug_print(DC_WB, "%s @%x", sign, (uint64)th);
280 | }
281 | }
282 | }
283 | }
284 | #endif
--------------------------------------------------------------------------------
/bbp/kernel/acpi.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | ACPI functions
4 | ==============
5 |
6 | License (BSD-3)
7 | ===============
8 |
9 | Copyright (c) 2012, Gusts 'gusC' Kaksis
10 | All rights reserved.
11 |
12 | Redistribution and use in source and binary forms, with or without
13 | modification, are permitted provided that the following conditions are met:
14 | * Redistributions of source code must retain the above copyright
15 | notice, this list of conditions and the following disclaimer.
16 | * Redistributions in binary form must reproduce the above copyright
17 | notice, this list of conditions and the following disclaimer in the
18 | documentation and/or other materials provided with the distribution.
19 | * Neither the name of the nor the
20 | names of its contributors may be used to endorse or promote products
21 | derived from this software without specific prior written permission.
22 |
23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
27 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 |
34 | */
35 |
36 | #ifndef __acpi_h
37 | #define __acpi_h
38 |
39 | #include "common.h"
40 | #include "../config.h"
41 |
42 | /**
43 | * Root System Descriptor Pointer
44 | * See ACPI specs
45 | */
46 | struct RSDP_struct {
47 | // Version 1.0
48 | char signature[8];
49 | uint8 checksum;
50 | char oem_id[6];
51 | uint8 revision;
52 | uint32 RSDT_address;
53 | // Version 2.0
54 | uint32 length;
55 | uint64 XSDT_address;
56 | uint8 extended_checksum;
57 | uint8 reserved[3];
58 | } __PACKED;
59 | typedef struct RSDP_struct RSDP_t;
60 | /**
61 | * Standard System Descriptor Table header structure
62 | * This is common to all ACPI tables
63 | */
64 | struct SDTHeader_struct {
65 | char signature[4];
66 | uint32 length;
67 | uint8 revision;
68 | uint8 checksum;
69 | char oem_id[6];
70 | char oem_table_id[8];
71 | uint32 oem_revision;
72 | uint32 creator_id;
73 | uint32 creator_revision;
74 | } __PACKED;
75 | typedef struct SDTHeader_struct SDTHeader_t;
76 | /**
77 | * Root System Descriptor table
78 | */
79 | struct RSDT_struct {
80 | SDTHeader_t h; // Standard ACPI header
81 | uint32 ptr; // This actually is an array, we're using only first entry
82 | } __PACKED;
83 | typedef struct RSDT_struct RSDT_t;
84 | /**
85 | * eXtended System Descriptor Table
86 | */
87 | struct XSDT_struct {
88 | SDTHeader_t h; // Standard ACPI header
89 | uint64 ptr; // This actually is an array, we're using only first entry
90 | } __PACKED;
91 | typedef struct XSDT_struct XSDT_t;
92 | /**
93 | * Secondary System Descriptor table
94 | */
95 | struct SSDT_struct {
96 | SDTHeader_t h; // Standard ACPI header
97 | uint8 ptr; // AML bytecode
98 | } __PACKED;
99 | typedef struct SSDT_struct SSDT_t;
100 | /**
101 | * Differentiated System Descriptor table
102 | */
103 | struct DSDT_struct {
104 | SDTHeader_t h; // Standard ACPI header
105 | uint8 ptr; // AML bytecode
106 | } __PACKED;
107 | typedef struct DSDT_struct DSDT_t;
108 | /**
109 | * Firmware ACPI Control Structure
110 | */
111 | struct FACS_struct {
112 | char signature[4];
113 | uint32 length;
114 | uint32 hw_signature;
115 | uint32 fw_vector;
116 | uint32 global_lock;
117 | uint32 flags;
118 |
119 | uint64 x_fw_vector;
120 | uint8 version;
121 | uint8 reserved[3];
122 | uint32 ospm_flags;
123 | uint8 reserved2[24];
124 | } __PACKED;
125 | typedef struct FACS_struct FACS_t;
126 | /**
127 | * Generic Address structure
128 | */
129 | struct GAS_struct {
130 | uint8 address_space;
131 | uint8 bit_width;
132 | uint8 bit_offset;
133 | uint8 access_size;
134 | uint64 address;
135 | } __PACKED;
136 | typedef struct GAS_struct GAS_t;
137 | /**
138 | * Fixed ACPI Description Table structure
139 | */
140 | struct FADT_struct {
141 | SDTHeader_t h; // Standard ACPI header
142 | uint32 firmware_ctrl; // Pointer to FACS table
143 | uint32 dsdt; // Pointer to DSDT table
144 |
145 | // field used in ACPI 1.0; no longer in use, for compatibility only
146 | uint8 reserved;
147 |
148 | uint8 pref_pmp;
149 | uint16 sci_interrupt;
150 | uint32 smi_command_port;
151 | uint8 acpi_enable;
152 | uint8 acpi_disable;
153 | uint8 s4_bios_req;
154 | uint8 pstate_control;
155 | uint32 pm1a_event_block;
156 | uint32 pm1b_event_block;
157 | uint32 pm1a_control_block;
158 | uint32 pm1b_control_block;
159 | uint32 pm2_control_block;
160 | uint32 pm_timer_block;
161 | uint32 gpe0_block;
162 | uint32 gpe1_block;
163 | uint8 pm1_event_length;
164 | uint8 pm1_control_length;
165 | uint8 pm2_control_length;
166 | uint8 pm_timer_length;
167 | uint8 gpe0_length;
168 | uint8 gpe1_length;
169 | uint8 gpe1_base;
170 | uint8 cstate_control;
171 | uint16 worst_c2_latency;
172 | uint16 worst_c3_latency;
173 | uint16 flush_size;
174 | uint16 flush_stride;
175 | uint8 duty_offset;
176 | uint8 duty_width;
177 | uint8 day_alarm;
178 | uint8 month_alarm;
179 | uint8 century;
180 |
181 | // reserved in ACPI 1.0; used since ACPI 2.0+
182 | uint16 boot_arch_flags;
183 |
184 | uint8 reserved2;
185 | uint32 flags;
186 |
187 | // 12 byte structure; see below for details
188 | GAS_t reset_reg;
189 |
190 | uint8 reset_value;
191 | uint8 reserved3[3];
192 |
193 | // 64bit pointers - Available on ACPI 2.0+
194 | uint64 x_firmware_control;
195 | uint64 x_dsdt;
196 |
197 | GAS_t x_pm1a_event_block;
198 | GAS_t x_pm1b_event_block;
199 | GAS_t x_pm1a_control_block;
200 | GAS_t x_pm1b_control_block;
201 | GAS_t x_pm2_control_block;
202 | GAS_t x_pm_timer_block;
203 | GAS_t x_gpe0_block;
204 | GAS_t x_gpe1_block;
205 | } __PACKED;
206 | typedef struct FADT_struct FADT_t;
207 | /**
208 | * Multiple APIC Description Table structure
209 | */
210 | struct MADT_struct {
211 | SDTHeader_t h;
212 | uint32 lapic_addr; // Physical address of local APIC
213 | uint32 flags; // Flags
214 | uint32 ptr; // Local, IO and other APIC structures (we use it as an offset)
215 | } __PACKED;
216 | typedef struct MADT_struct MADT_t;
217 | /**
218 | * ACPI APIC structure header
219 | */
220 | struct APICHeader_struct {
221 | uint8 type;
222 | uint8 length;
223 | } __PACKED;
224 | typedef struct APICHeader_struct APICHeader_t;
225 | /**
226 | * Local APIC structure
227 | */
228 | struct LocalAPIC_struct {
229 | APICHeader_t h;
230 | uint8 processor_id;
231 | uint8 apic_id;
232 | uint32 flags;
233 | } __PACKED;
234 | typedef struct LocalAPIC_struct LocalAPIC_t;
235 | /**
236 | * I/O APIC strcuture
237 | */
238 | struct IOAPIC_struct {
239 | APICHeader_t h;
240 | uint8 apic_id;
241 | uint8 reserved;
242 | uint32 apic_addr;
243 | uint32 gsi_base;
244 | } __PACKED;
245 | typedef struct IOAPIC_struct IOAPIC_t;
246 | /**
247 | * Non Maskable Interrupt (NMI) structure
248 | */
249 | struct NMI_struct {
250 | APICHeader_t h;
251 | uint16 flags;
252 | uint32 gsi;
253 | } __PACKED;
254 | typedef struct NMI_struct NMI_t;
255 | /**
256 | * Local APIC structure
257 | */
258 | struct LocalNMI_struct {
259 | APICHeader_t h;
260 | uint8 processor_id;
261 | uint16 flags;
262 | uint8 lint;
263 | } __PACKED;
264 | typedef struct LocalNMI_struct LocalNMI_t;
265 |
266 | /**
267 | * Initialize ACPI
268 | * @return true on success, false on failure (if ACPI is not supported)
269 | */
270 | bool acpi_init();
271 | /**
272 | * Get the RSDP pointer
273 | * @return RSDP pointer or null if ACPI is not initialized or failed to initialize
274 | */
275 | RSDP_t *acpi_rsdp();
276 | /**
277 | * Locate ACPI table - you must run acpi_init() first
278 | * @param [in] signature - table signature (table name)
279 | * @return pointer to table header (from here on you can locate all the other data)
280 | */
281 | SDTHeader_t *acpi_table(const char signature[4]);
282 |
283 | #if DEBUG == 1
284 | /**
285 | * List available ACPI tables on screen
286 | */
287 | void acpi_list();
288 | #endif
289 |
290 | #endif
291 |
--------------------------------------------------------------------------------
/bbp/kernel/ahci.c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gusc/mbr2gpt/45302b4709e892bb3e0ba951235af5d2ab25bc98/bbp/kernel/ahci.c
--------------------------------------------------------------------------------
/bbp/kernel/ahci.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | AHCI driver
4 | ===========
5 |
6 |
7 | License (BSD-3)
8 | ===============
9 |
10 | Copyright (c) 2012, Gusts 'gusC' Kaksis
11 | All rights reserved.
12 |
13 | Redistribution and use in source and binary forms, with or without
14 | modification, are permitted provided that the following conditions are met:
15 | * Redistributions of source code must retain the above copyright
16 | notice, this list of conditions and the following disclaimer.
17 | * Redistributions in binary form must reproduce the above copyright
18 | notice, this list of conditions and the following disclaimer in the
19 | documentation and/or other materials provided with the distribution.
20 | * Neither the name of the nor the
21 | names of its contributors may be used to endorse or promote products
22 | derived from this software without specific prior written permission.
23 |
24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 |
35 | */
36 |
37 | #ifndef __ahci_h
38 | #define __ahci_h
39 |
40 | #include "common.h"
41 | #include "../config.h"
42 |
43 | /**
44 | * Initialize AHCI driver
45 | * @return false if no AHCI controller has been found
46 | */
47 | bool ahci_init();
48 | /**
49 | * Get the number of AHCI devices connected
50 | * @return number of devices available
51 | */
52 | uint64 ahci_num_dev();
53 | /**
54 | * Read data from AHCI drive
55 | * @param idx - device index in the device list
56 | * @param buff - byte buffer to write into
57 | * @param len - number of bytes to read
58 | * @todo implement
59 | * @return false if read failed
60 | */
61 | bool ahci_read(uint64 idx, uint8 *buff, uint64 len);
62 | /**
63 | * Write data to AHCI drive
64 | * @param idx - device index in the device list
65 | * @param buff - byte buffer to read from
66 | * @param len - number of bytes to write
67 | * @todo implement
68 | * @return false if write failed
69 | */
70 | bool ahci_write(uint64 idx, uint8 *buff, uint64 len);
71 |
72 | #endif
73 |
--------------------------------------------------------------------------------
/bbp/kernel/apic.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | APIC, xAPIC, x2APIC functions
4 | =============================
5 |
6 | License (BSD-3)
7 | ===============
8 |
9 | Copyright (c) 2012, Gusts 'gusC' Kaksis
10 | All rights reserved.
11 |
12 | Redistribution and use in source and binary forms, with or without
13 | modification, are permitted provided that the following conditions are met:
14 | * Redistributions of source code must retain the above copyright
15 | notice, this list of conditions and the following disclaimer.
16 | * Redistributions in binary form must reproduce the above copyright
17 | notice, this list of conditions and the following disclaimer in the
18 | documentation and/or other materials provided with the distribution.
19 | * Neither the name of the nor the
20 | names of its contributors may be used to endorse or promote products
21 | derived from this software without specific prior written permission.
22 |
23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
27 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 |
34 | */
35 |
36 | #include "../config.h"
37 | #include "apic.h"
38 | #include "msr.h"
39 | #include "acpi.h"
40 | #include "paging.h"
41 | #if DEBUG == 1
42 | #include "debug_print.h"
43 | #endif
44 |
45 | static LocalAPIC_t *_lapic[256];
46 | static uint64 _lapic_count = 0;
47 | static uint64 _lapic_addr;
48 |
49 | static IOAPIC_t *_ioapic[256];
50 | static uint64 _ioapic_count = 0;
51 |
52 | static void lapic_init(){
53 | apic_base_t apic = apic_get_base();
54 | // Address is 4KB aligned
55 | _lapic_addr = (apic.raw & PAGE_MASK);
56 | #if DEBUG == 1
57 | debug_print(DC_WB, "Local APIC @%x", _lapic_addr);
58 | if (apic.s.bsp){
59 | debug_print(DC_WB, "Boot CPU");
60 | }
61 | #endif
62 | // Map pages to Local APIC and disable cache
63 | pm_t pe;
64 | uint64 i;
65 | page_map_mmio(_lapic_addr);
66 | for (i = 0; i < 4; i ++){
67 | pe = page_get_pml_entry(_lapic_addr, i);
68 | pe.s.cache_disable = 1;
69 | page_set_pml_entry(_lapic_addr, i, pe);
70 | }
71 |
72 | // Initialize Local APIC
73 | uint32 val = apic_read_reg(APIC_LAPIC_VERSION);
74 | #if DEBUG == 1
75 | debug_print(DC_WBL, "Version: %d", val);
76 | #endif
77 |
78 | // Initialize Other Local APICs if this is a bootstrap processor
79 | if (apic.s.bsp){
80 | for (i = 0; i < _lapic_count; i ++){
81 | #if DEBUG == 1
82 | debug_print(DC_WBL, "CPU_ID:APIC_ID = %d:%d", _lapic[i]->processor_id, _lapic[i]->apic_id);
83 | #endif
84 | //TODO: signal other CPUs to start
85 | }
86 | }
87 | }
88 |
89 | static void ioapic_init(){
90 | // Address is 4KB aligned
91 | uint64 i;
92 | for (i = 0; i < _ioapic_count; i ++){
93 | uint64 ioapic_addr = (_ioapic[i]->apic_addr & PAGE_MASK);
94 | #if DEBUG == 1
95 | debug_print(DC_WB, "IO APIC @%x", ioapic_addr);
96 | debug_print(DC_WB, "IOAPIC ID:%d", _ioapic[i]->apic_id);
97 | #endif
98 | // Map pages to Local APIC and disable cache
99 | pm_t pe;
100 | uint64 l;
101 | page_map_mmio(ioapic_addr);
102 | for (l = 0; l < 4; l ++){
103 | pe = page_get_pml_entry(ioapic_addr, i);
104 | pe.s.cache_disable = 1;
105 | page_set_pml_entry(ioapic_addr, i, pe);
106 | }
107 |
108 | // TODO: setup IRQs
109 | }
110 | }
111 |
112 | bool apic_init(){
113 | char apic[4] = {'A', 'P', 'I', 'C'};
114 | MADT_t *madt = (MADT_t *)acpi_table(apic);
115 | if (madt != null){
116 | // Gather Local and IO APIC(s)
117 | _lapic_addr = (uint64)madt->lapic_addr;
118 |
119 | // Enumerate APICs
120 | uint64 length = (madt->h.length - sizeof(MADT_t) + 4);
121 | APICHeader_t *ah = (APICHeader_t *)(&madt->ptr);
122 | while (length > 0){
123 | #if DEBUG == 1
124 | //debug_print(DC_WGR, "APIC type: %d", ah->type);
125 | #endif
126 | switch (ah->type){
127 | case APIC_TYPE_LAPIC:
128 | // Test if it's enabled - if not - don't touch it
129 | if ((((LocalAPIC_t *)ah)->flags & 1) != 0){
130 | _lapic[_lapic_count] = (LocalAPIC_t *)ah;
131 | _lapic_count ++;
132 | }
133 | break;
134 | case APIC_TYPE_IOAPIC:
135 | _ioapic[_ioapic_count] = (IOAPIC_t *)ah;
136 | _ioapic_count ++;
137 | break;
138 | }
139 | length -= ah->length;
140 | ah = (APICHeader_t *)(((uint64)ah) + ah->length);
141 | }
142 | #if DEBUG == 1
143 | debug_print(DC_WB, "CPU count:%d", _lapic_count);
144 | #endif
145 |
146 | // Initialize Local APIC
147 | lapic_init();
148 | // Initialize IO APIC
149 | ioapic_init();
150 | }
151 | }
152 |
153 | apic_base_t apic_get_base(){
154 | apic_base_t addr;
155 | msr_read(MSR_IA32_APIC_BASE, &addr.raw);
156 | return addr;
157 | }
158 | void apic_set_base(apic_base_t addr){
159 | msr_write(MSR_IA32_APIC_BASE, addr.raw);
160 | }
161 |
162 | uint32 apic_read_reg(uint64 reg){
163 | uint32 volatile *apic = (uint32 volatile *)(_lapic_addr + reg);
164 | return *apic;
165 | }
166 | void apic_write_reg(uint64 reg, uint32 value){
167 | uint32 volatile *apic = (uint32 volatile *)(_lapic_addr + reg);
168 | (*apic) = value;
169 | }
170 |
171 | uint32 apic_read_ioapic(uint64 addr, uint32 reg){
172 | uint32 volatile *ioapic = (uint32 volatile *)(addr);
173 | ioapic[0] = (reg & 0xFFFF);
174 | return ioapic[4];
175 | }
176 | void apic_write_ioapic(uint64 addr, uint32 reg, uint32 data){
177 | uint32 volatile *ioapic = (uint32 volatile *)(addr);
178 | ioapic[0] = (reg & 0xFFFF);
179 | ioapic[4] = data;
180 | }
181 |
--------------------------------------------------------------------------------
/bbp/kernel/apic.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | APIC, xAPIC, x2APIC functions
4 | =============================
5 |
6 | License (BSD-3)
7 | ===============
8 |
9 | Copyright (c) 2012, Gusts 'gusC' Kaksis
10 | All rights reserved.
11 |
12 | Redistribution and use in source and binary forms, with or without
13 | modification, are permitted provided that the following conditions are met:
14 | * Redistributions of source code must retain the above copyright
15 | notice, this list of conditions and the following disclaimer.
16 | * Redistributions in binary form must reproduce the above copyright
17 | notice, this list of conditions and the following disclaimer in the
18 | documentation and/or other materials provided with the distribution.
19 | * Neither the name of the nor the
20 | names of its contributors may be used to endorse or promote products
21 | derived from this software without specific prior written permission.
22 |
23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
27 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 |
34 | */
35 |
36 | #ifndef __apic_h
37 | #define __apic_h
38 |
39 | #include "common.h"
40 |
41 | //
42 | // APIC register selector definitions
43 | //
44 |
45 | #define APIC_LAPIC_ID 0x20 // Local APIC ID Register (Read/Write)
46 | #define APIC_LAPIC_VERSION 0x30 // Local APIC Version Register (Read Only)
47 | #define APIC_TPR 0x80 // Task Priority Register (Read/Write)
48 | #define APIC_APR 0x90 // Arbitration Priority Register (Read Only)
49 | #define APIC_PPR 0xA0 // Processor Priority Register (Read Only)
50 | #define APIC_EOIR 0xB0 // EOI Register (Write Only)
51 | #define APIC_RRR 0xC0 // Remote Read Register (Read Only)
52 | #define APIC_LDR 0xD0 // Logical Destination Register (Read/Write)
53 | #define APIC_DFR 0xE0 // Destination Format Register (Read/Write)
54 | #define APIC_SIVR 0xF0 // Spurious Interrupt Vector Register (Read/Write)
55 | #define APIC_ISR1 0x0100 // In-Service Register bits 31:0 (Read Only)
56 | #define APIC_ISR2 0x0110 // In-Service Register bits 63:32 (Read Only)
57 | #define APIC_ISR3 0x0120 // In-Service Register bits 95:64 (Read Only)
58 | #define APIC_ISR4 0x0130 // In-Service Register bits 127:96 (Read Only)
59 | #define APIC_ISR5 0x0140 // In-Service Register bits 159:128 (Read Only)
60 | #define APIC_ISR6 0x0150 // In-Service Register bits 191:160 (Read Only)
61 | #define APIC_ISR7 0x0160 // In-Service Register bits 223:192 (Read Only)
62 | #define APIC_ISR8 0x0170 // In-Service Register bits 255:224 (Read Only)
63 | #define APIC_TMR1 0x0180 // Trigger Mode Register bits 31:0 (Read Only)
64 | #define APIC_TMR2 0x0190 // Trigger Mode Register bits 63:32 (Read Only)
65 | #define APIC_TMR3 0x01A0 // Trigger Mode Register bits 95:64 (Read Only)
66 | #define APIC_TMR4 0x01B0 // Trigger Mode Register bits 127:96 (Read Only)
67 | #define APIC_TMR5 0x01C0 // Trigger Mode Register bits 159:128 (Read Only)
68 | #define APIC_TMR6 0x01D0 // Trigger Mode Register bits 191:160 (Read Only)
69 | #define APIC_TMR7 0x01E0 // Trigger Mode Register bits 223:192 (Read Only)
70 | #define APIC_TMR8 0x01F0 // Trigger Mode Register bits 255:224 (Read Only)
71 | #define APIC_IRR1 0x0200 // Interrupt Request Register bits 31:0 (Read Only)
72 | #define APIC_IRR2 0x0210 // Interrupt Request Register bits 63:32 (Read Only)
73 | #define APIC_IRR3 0x0220 // Interrupt Request Register bits 95:64 (Read Only)
74 | #define APIC_IRR4 0x0230 // Interrupt Request Register bits 127:96 (Read Only)
75 | #define APIC_IRR5 0x0240 // Interrupt Request Register bits 159:128 (Read Only)
76 | #define APIC_IRR6 0x0250 // Interrupt Request Register bits 191:160 (Read Only)
77 | #define APIC_IRR7 0x0260 // Interrupt Request Register bits 223:192 (Read Only)
78 | #define APIC_IRR8 0x0270 // Interrupt Request Register bits 255:224 (Read Only)
79 | #define APIC_ESR 0x0280 // Error Status Register (Read Only)
80 | #define APIC_LVT_CMCI 0x02F0 // LVT CMCI Register (Read/Write)
81 | #define APIC_ICR1 0x0300 // Interrupt Command Register bits 0-31 (Read/Write)
82 | #define APIC_ICR2 0x0310 // Interrupt Command Register bits 32-63 (Read/Write)
83 | #define APIC_LVT_TIMER 0x0320 // LVT Timer Register (Read/Write)
84 | #define APIC_LVT_THERMAL 0x0330 // LVT Thermal Sensor Register (Read/Write)
85 | #define APIC_LVT_PMC 0x0340 // LVT Performance Monitoring Counters Register (Read/Write)
86 | #define APIC_LVT_LINT0 0x0350 // LVT LINT0 Register (Read/Write)
87 | #define APIC_LVT_LINT1 0x0360 // LVT LINT1 Register (Read/Write)
88 | #define APIC_LVT_EREG 0x0370 // LVT Error Register (Read/Write)
89 | #define APIC_INIT_COUNT 0x0380 // Initial Count Register (for Timer) (Read/Write)
90 | #define APIC_CURR_COUNT 0x0390 // Current Count Register (for Timer) (Read Only)
91 | #define APIC_DIV_CONF 0x03E0 // Divide Configuration Register (for Timer) (Read/Write)
92 |
93 | //
94 | // APIC entry types from ACPI MADT table
95 | //
96 |
97 | #define APIC_TYPE_LAPIC 0 // Local APIC
98 | #define APIC_TYPE_IOAPIC 1 // IO APIC
99 | #define APIC_TYPE_ISO 2 // Interrupt Service Override
100 | #define APIC_TYPE_NMI 3 // Non-Maskable Interrupt Source
101 | #define APIC_TYPE_LAPIC_NMI 4 // Local APIC NMI
102 | #define APIC_TYPE_LAPIC_AO 5 // Local APIC Adress Override
103 | #define APIC_TYPE_IOSAPIC 6 // IO SAPIC
104 | #define APIC_TYPE_LSAPIC 7 // Local SAPIC
105 | #define APIC_TYPE_PIS 8 // Platform Interrupt Sources
106 | #define APIC_TYPE_Lx2APIC 9 // Local x2APIC
107 | #define APIC_TYPE_Lx2APIC_NMI 10 // Local x2APIC NMI
108 |
109 | /**
110 | * APIC base MSR structure
111 | */
112 | typedef union {
113 | struct {
114 | uint64 reserved1 : 8; // Reserved
115 | uint64 bsp : 1; // Bootstrap processor
116 | uint64 reserved2 : 2; // Reserved
117 | uint64 enable : 1; // Global APIC enable/disable bit
118 | uint64 base_addr : 24; // APIC base address (4 KByte aligned)
119 | uint64 reserved : 28; // Reserved
120 | } s;
121 | uint64 raw;
122 | } apic_base_t;
123 |
124 | /**
125 | * Initialize APIC(s)
126 | * @return true on success, false on failure
127 | */
128 | bool apic_init();
129 | /**
130 | * Get APIC base address
131 | * @return physical address of APIC memory maped registers
132 | */
133 | apic_base_t apic_get_base();
134 | /**
135 | * Set APIC base address
136 | * @param addr - physical address of APIC memory maped registers
137 | */
138 | void apic_set_base(apic_base_t addr);
139 |
140 | /**
141 | * Read Local APIC register
142 | * @param reg - APIC register selector
143 | * @return data stored in register
144 | */
145 | uint32 apic_read_reg(uint64 reg);
146 | /**
147 | * Write Local APIC register
148 | * @param reg - APIC register selector
149 | * @param data - data to be stored in register
150 | */
151 | void apic_write_reg(uint64 reg, uint32 value);
152 |
153 | /**
154 | * Read IOAPIC value
155 | * @param addr - APIC base address
156 | * @param reg - IOAPIC register selector
157 | * @return data stored in register
158 | */
159 | uint32 apic_read_ioapic(uint64 addr, uint32 reg);
160 | /**
161 | * Write IOAPIC value
162 | * @param addr - APIC base address
163 | * @param reg - IOAPIC register selector
164 | * @param data - data to be stored in register
165 | */
166 | void apic_write_ioapic(uint64 addr, uint32 reg, uint32 data);
167 |
168 | #endif /* __apic_h */
169 |
--------------------------------------------------------------------------------
/bbp/kernel/common.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Common data types (long mode)
4 | =============================
5 |
6 | This file contains type definitions and helper structures.
7 |
8 | The idea of this file is to keep a precise control over data type sizes, so
9 | instead of int and long, we should have int32 or int64.
10 |
11 | Maybe in the future we'll introduce memory pointer type intptr or simply ptr,
12 | that will reference the largest integer type for memory access of the machine.
13 | That is, a 64bit int for x86_64 architecture and 32bit int for x86.
14 |
15 | License (BSD-3)
16 | ===============
17 |
18 | Copyright (c) 2012, Gusts 'gusC' Kaksis
19 | All rights reserved.
20 |
21 | Redistribution and use in source and binary forms, with or without
22 | modification, are permitted provided that the following conditions are met:
23 | * Redistributions of source code must retain the above copyright
24 | notice, this list of conditions and the following disclaimer.
25 | * Redistributions in binary form must reproduce the above copyright
26 | notice, this list of conditions and the following disclaimer in the
27 | documentation and/or other materials provided with the distribution.
28 | * Neither the name of the nor the
29 | names of its contributors may be used to endorse or promote products
30 | derived from this software without specific prior written permission.
31 |
32 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
36 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 |
43 | */
44 |
45 | #ifndef __common_h
46 | #define __common_h
47 |
48 | #define __NOINLINE __attribute__((noinline))
49 | #define __INLINE __attribute__((always_inline))
50 | #define __REGPARM __attribute__((regparm(3)))
51 | #define __NORETURN __attribute__((noreturn))
52 | #define __PACKED __attribute__((packed))
53 | #define __ALIGN(x) __attribute__((aligned(x)))
54 |
55 | #define BREAK() asm volatile ("xchg %bx, %bx")
56 | #define HANG() while(true){}
57 |
58 | // Default types
59 | typedef unsigned char uchar;
60 |
61 | typedef unsigned char uint8;
62 | typedef unsigned short uint16;
63 | typedef unsigned int uint32;
64 | typedef unsigned long long uint64;
65 |
66 | typedef char int8;
67 | typedef short int16;
68 | typedef int int32;
69 | typedef long long int64;
70 |
71 | #define null 0
72 | #define true 1
73 | #define false 0
74 | #define bool uint64
75 |
76 | // Variadic funciton arguments
77 | #define va_list __builtin_va_list
78 | #define va_start(v, f) __builtin_va_start(v, f)
79 | #define va_end(v) __builtin_va_end(v)
80 | #define va_arg(v, a) __builtin_va_arg(v, a)
81 |
82 | typedef struct {
83 | uint32 low;
84 | uint32 high;
85 | } split_uint64_t;
86 |
87 | #endif /* __common_h */
88 |
--------------------------------------------------------------------------------
/bbp/kernel/cpuid.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Helper function for CPUID operations
4 | ====================================
5 |
6 | ASM wrappers
7 |
8 | License (BSD-3)
9 | ===============
10 |
11 | Copyright (c) 2012, Gusts 'gusC' Kaksis
12 | All rights reserved.
13 |
14 | Redistribution and use in source and binary forms, with or without
15 | modification, are permitted provided that the following conditions are met:
16 | * Redistributions of source code must retain the above copyright
17 | notice, this list of conditions and the following disclaimer.
18 | * Redistributions in binary form must reproduce the above copyright
19 | notice, this list of conditions and the following disclaimer in the
20 | documentation and/or other materials provided with the distribution.
21 | * Neither the name of the nor the
22 | names of its contributors may be used to endorse or promote products
23 | derived from this software without specific prior written permission.
24 |
25 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
26 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
29 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 |
36 | */
37 | #ifndef __cpuid_h
38 | #define __cpuid_h
39 |
40 | #include "common.h"
41 |
42 | /**
43 | * Read CPUID
44 | * @param type - initial EAX value (information type to get from CPUID)
45 | * @param [out] eax - EAX value returned by CPUID
46 | * @param [out] ebx - EBX value returned by CPUID
47 | * @param [out] ecx - ECX value returned by CPUID
48 | * @param [out] edx - EDX value returned by CPUID
49 | * @return void
50 | */
51 | static void cpuid(uint32 type, uint32 *eax, uint32 *ebx, uint32 *ecx, uint32 *edx){
52 | asm volatile("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(type));
53 | }
54 |
55 | #endif
56 |
--------------------------------------------------------------------------------
/bbp/kernel/debug_print.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Helper functions for operations with teletype (text mode) screen
4 | ================================================================
5 |
6 | Teletype video functions:
7 | * clear screen
8 | * print a formated string on the screen
9 |
10 | License (BSD-3)
11 | ===============
12 |
13 | Copyright (c) 2012, Gusts 'gusC' Kaksis
14 | All rights reserved.
15 |
16 | Redistribution and use in source and binary forms, with or without
17 | modification, are permitted provided that the following conditions are met:
18 | * Redistributions of source code must retain the above copyright
19 | notice, this list of conditions and the following disclaimer.
20 | * Redistributions in binary form must reproduce the above copyright
21 | notice, this list of conditions and the following disclaimer in the
22 | documentation and/or other materials provided with the distribution.
23 | * Neither the name of the nor the
24 | names of its contributors may be used to endorse or promote products
25 | derived from this software without specific prior written permission.
26 |
27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
28 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
30 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
31 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
34 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 |
38 | */
39 |
40 | #include "../config.h"
41 | #include "debug_print.h"
42 | #include "lib.h"
43 |
44 | // Video screen size
45 | static uint64 _columns = 80;
46 | static uint64 _rows = 25;
47 | // Global cursor
48 | static uint64 _x = 0;
49 | static uint64 _y = 0;
50 | static uint8 _base_color = 0x00;
51 |
52 | static void __debug_print_f(uint8 x, uint8 y, uint8 color, const char *format, va_list args);
53 |
54 | void debug_clear(uint8 color){
55 | char *vidmem = (char *)VIDEOMEM_LOC;
56 | _base_color = color;
57 | _y = 0;
58 | _x = 0;
59 | uint16 fill = (_base_color << 8) + ' ';
60 | // Fast clear line
61 | asm volatile ("rep\n\tstosw" : : "a"(fill), "c"(_columns * _rows), "D"(vidmem));
62 | }
63 |
64 | void debug_scroll(){
65 | char *vidmem = (char *)VIDEOMEM_LOC;
66 | uint16 row_len = _columns * 2;
67 | uint16 last_row_char = (_rows - 1) * _columns;
68 | uint16 fill = (_base_color << 8) + ' ';
69 | // Fast scroll
70 | asm volatile ("rep\n\tmovsw" : : "c"(last_row_char), "S"(vidmem + row_len), "D"(vidmem));
71 | // Fast clear line
72 | asm volatile ("rep\n\tstosw" : : "a"(fill), "c"(_columns), "D"(vidmem + (last_row_char * 2)));
73 | }
74 |
75 | void debug_print_at(uint8 x, uint8 y, uint8 color, const char *format, ...){
76 | va_list args;
77 | va_start(args, format);
78 | __debug_print_f(x, y, color, format, args);
79 | va_end(args);
80 | }
81 |
82 | void debug_print(uint8 color, const char *format, ...){
83 | if (_y >= _rows){
84 | debug_scroll();
85 | _y = _rows - 1;
86 | }
87 | va_list args;
88 | va_start(args, format);
89 | __debug_print_f(_x, _y, color, format, args);
90 | va_end(args);
91 | _y ++;
92 | }
93 |
94 | static void __debug_print_f(uint8 x, uint8 y, uint8 color, const char *format, va_list args){
95 | char *vidmem = (char *)VIDEOMEM_LOC;
96 | static char str[2001];
97 | mem_fill((uint8 *)str, 2001, 0);
98 | uint16 i;
99 | // Keep everything in bounds
100 | if (__write_f(str, 2000, format, args)){
101 | char *s = (char *)str;
102 | while (*s != 0){
103 | if (*s == 0x0A || x >= _columns){ // New line (a.k.a \n) or forced wrap
104 | x = 0;
105 | y ++;
106 | if (y >= _rows){
107 | debug_scroll();
108 | y = _rows - 1;
109 | }
110 | }
111 | if (*s >= 0x20 && *s <= 0x7E){ // Only valid ASCII chars
112 | i = (y * _columns * 2) + (x * 2);
113 | vidmem[i] = *s;
114 | vidmem[i + 1] = color;
115 | x ++;
116 | }
117 | s++;
118 | }
119 | }
120 | }
--------------------------------------------------------------------------------
/bbp/kernel/debug_print.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Helper functions for operations with teletype (text mode) screen
4 | ================================================================
5 |
6 | Teletype video functions:
7 | * clear screen
8 | * print a formated string on the screen
9 |
10 | License (BSD-3)
11 | ===============
12 |
13 | Copyright (c) 2012, Gusts 'gusC' Kaksis
14 | All rights reserved.
15 |
16 | Redistribution and use in source and binary forms, with or without
17 | modification, are permitted provided that the following conditions are met:
18 | * Redistributions of source code must retain the above copyright
19 | notice, this list of conditions and the following disclaimer.
20 | * Redistributions in binary form must reproduce the above copyright
21 | notice, this list of conditions and the following disclaimer in the
22 | documentation and/or other materials provided with the distribution.
23 | * Neither the name of the nor the
24 | names of its contributors may be used to endorse or promote products
25 | derived from this software without specific prior written permission.
26 |
27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
28 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
30 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
31 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
34 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 |
38 | */
39 |
40 | #ifndef __video_h
41 | #define __video_h
42 |
43 | #include "common.h"
44 |
45 | // Some fancy color definitions :)
46 | #define DC_WB 0xF0
47 | #define DC_BW 0x0F
48 | #define DC_WLG 0xF7
49 | #define DC_WDG 0xF8
50 | #define DC_WBL 0xF1
51 | #define DC_WGR 0xF2
52 | #define DC_WRD 0xF4
53 |
54 | /**
55 | * Clear the teletype (text mode) screen
56 | * @param color - color byte
57 | * @return void
58 | */
59 | void debug_clear(uint8 color);
60 | /**
61 | * Scroll whole video buffer upwards
62 | * @return void
63 | */
64 | void debug_scroll();
65 | /**
66 | * Print a formated string on the teletype (text mode) screen
67 | * @param x coordinate (a.k.a. column 0-79)
68 | * @param y coordinate (a.k.a. line 0-24)
69 | * @param color - color byte
70 | * @param [in] format - standard C printf format string
71 | * @param [in] ... - additional arguments
72 | * @return void
73 | */
74 | void debug_print_at(uint8 x, uint8 y, uint8 color, const char *format, ...);
75 | /**
76 | * Print a formated string on the teletype (text mode) screen
77 | * @param color - color byte
78 | * @param [in] format - standard C printf format string
79 | * @param [in] ... - additional arguments
80 | * @return void
81 | */
82 | void debug_print(uint8 color, const char *format, ...);
83 |
84 | #endif /* __video_h */
85 |
--------------------------------------------------------------------------------
/bbp/kernel/interrupts.asm:
--------------------------------------------------------------------------------
1 | ;
2 | ; Helper functions for operations interrupts
3 | ; ==================
4 | ;
5 | ; This contains imports from ASM stub subroutines that catch all the neccessary
6 | ; exception interrupts and calls a C function interrupt_handler().
7 | ; It also contains LIDT wrapper function.
8 | ;
9 | ; License (BSD-3)
10 | ; ===============
11 | ;
12 | ; Copyright (c) 2013, Gusts 'gusC' Kaksis
13 | ; All rights reserved.
14 | ;
15 | ; Redistribution and use in source and binary forms, with or without
16 | ; modification, are permitted provided that the following conditions are met:
17 | ; * Redistributions of source code must retain the above copyright
18 | ; notice, this list of conditions and the following disclaimer.
19 | ; * Redistributions in binary form must reproduce the above copyright
20 | ; notice, this list of conditions and the following disclaimer in the
21 | ; documentation and/or other materials provided with the distribution.
22 | ; * Neither the name of the nor the
23 | ; names of its contributors may be used to endorse or promote products
24 | ; derived from this software without specific prior written permission.
25 | ;
26 | ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
27 | ; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28 | ; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29 | ; DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
30 | ; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31 | ; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 | ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
33 | ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 | ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 | ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 | ;
37 |
38 | [section .text]
39 | [bits 64]
40 | [extern isr_handler] ; Import int_handler from C
41 | [extern irq_handler] ; Import irq_handler from C
42 | [global idt_set] ; Export void idt_set(idt_ptr_t *idt) to C
43 |
44 | ; Macro to create an intterupt service routine for interrupts that do not pass error codes
45 | %macro INT_NO_ERR 1
46 | [global isr%1]
47 | isr%1:
48 | cli ; disable interrupts
49 | push qword 0 ; set error code to 0
50 | push qword %1 ; set interrupt number
51 | call isr_handler ; call void isr_handler(int_stack_t args)
52 | sti ; enable interrupts
53 | add rsp, 16 ; cleanup stack
54 | iretq ; return from interrupt handler
55 | %endmacro
56 |
57 | ; Macro to create an interrupt service routine for interrupts that DO pass an error code
58 | %macro INT_HAS_ERR 1
59 | [global isr%1]
60 | isr%1:
61 | cli ; disable interrupts
62 | push qword %1 ; set interrupt number
63 | call isr_handler ; call void isr_handler(int_stack_t args)
64 | sti ; enable interrupts
65 | add rsp, 16 ; cleanup stack
66 | iretq ; return from interrupt handler
67 | %endmacro
68 |
69 | ; Macro to create an IRQ interrupt service routine
70 | ; First parameter is the IRQ number
71 | ; Second parameter is the interrupt number it is remapped to
72 | %macro IRQ 2
73 | [global irq%1]
74 | irq%1:
75 | cli ; disable interrupts
76 | push qword %1 ; set IRQ number in the place of error code (see registers_t in interrupts.h)
77 | push qword %2 ; set interrupt number
78 | call irq_handler ; calls void irq_handler(int_stack_t args)
79 | sti ; enable interrupts
80 | add rsp, 16 ; cleanup stack
81 | iretq ; return from interrupt handler
82 | %endmacro
83 |
84 | idt_set: ; prototype: void idt_set(uint32 idt_ptr)
85 | cli ; disable interrupts
86 | lidt [rdi] ; load the IDT (x86_64 calling convention - 1st argument goes into RDI)
87 | sti ; enable interrupts
88 | ret ; return to C
89 |
90 | ; Setup all the neccessary service routines with macros
91 | INT_NO_ERR 0
92 | INT_NO_ERR 1
93 | INT_NO_ERR 2
94 | INT_NO_ERR 3
95 | INT_NO_ERR 4
96 | INT_NO_ERR 5
97 | INT_NO_ERR 6
98 | INT_NO_ERR 7
99 | INT_NO_ERR 8 ; By all specs int 8 is double fault WITH error message, but not in Bochs, WHY?
100 | INT_NO_ERR 9
101 | INT_HAS_ERR 10
102 | INT_HAS_ERR 11
103 | INT_HAS_ERR 12
104 | INT_HAS_ERR 13
105 | INT_HAS_ERR 14
106 | INT_NO_ERR 15
107 | INT_NO_ERR 16
108 | INT_NO_ERR 17
109 | INT_NO_ERR 18
110 | INT_NO_ERR 19
111 | INT_NO_ERR 20
112 | INT_NO_ERR 21
113 | INT_NO_ERR 22
114 | INT_NO_ERR 23
115 | INT_NO_ERR 24
116 | INT_NO_ERR 25
117 | INT_NO_ERR 26
118 | INT_NO_ERR 27
119 | INT_NO_ERR 28
120 | INT_NO_ERR 29
121 | INT_NO_ERR 30
122 | INT_NO_ERR 31
123 | IRQ 0, 32
124 | IRQ 1, 33
125 | IRQ 2, 34
126 | IRQ 3, 35
127 | IRQ 4, 36
128 | IRQ 5, 37
129 | IRQ 6, 38
130 | IRQ 7, 39
131 | IRQ 8, 40
132 | IRQ 9, 41
133 | IRQ 10, 42
134 | IRQ 11, 43
135 | IRQ 12, 44
136 | IRQ 13, 45
137 | IRQ 14, 46
138 | IRQ 15, 47
139 |
--------------------------------------------------------------------------------
/bbp/kernel/interrupts.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Helper functions for operations interrupts
4 | ==========================================
5 |
6 | This contains imports from ASM stub subroutines that catch all the neccessary
7 | exception interrupts and calls a C function interrupt_handler().
8 | It also contains LIDT wrapper function and C functions to handle interrupts.
9 |
10 | License (BSD-3)
11 | ===============
12 |
13 | Copyright (c) 2012, Gusts 'gusC' Kaksis
14 | All rights reserved.
15 |
16 | Redistribution and use in source and binary forms, with or without
17 | modification, are permitted provided that the following conditions are met:
18 | * Redistributions of source code must retain the above copyright
19 | notice, this list of conditions and the following disclaimer.
20 | * Redistributions in binary form must reproduce the above copyright
21 | notice, this list of conditions and the following disclaimer in the
22 | documentation and/or other materials provided with the distribution.
23 | * Neither the name of the nor the
24 | names of its contributors may be used to endorse or promote products
25 | derived from this software without specific prior written permission.
26 |
27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
28 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
30 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
31 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
34 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 |
38 | */
39 |
40 | #include "../config.h"
41 | #include "interrupts.h"
42 | #include "lib.h"
43 | #include "io.h"
44 | #include "paging.h"
45 | #if DEBUG == 1
46 | #include "debug_print.h"
47 | #endif
48 |
49 | /**
50 | * Exception names
51 | */
52 | static char *ints[] = {
53 | "Division by zero",
54 | "Debug exception",
55 | "NMI interrupt",
56 | "Breakpoint",
57 | "INTO overflow",
58 | "BOUND exception",
59 | "Invalid opcode",
60 | "No FPU",
61 | "Double Fault!",
62 | "FPU segment overrun",
63 | "Bad TSS",
64 | "Segment not present",
65 | "Stack fault",
66 | "GPF",
67 | "Page fault",
68 | "",
69 | "FPU Exception",
70 | "Alignament check exception",
71 | "Machine check exception"
72 | };
73 | /**
74 | * Interrupt Descriptor Table
75 | */
76 | idt_entry_t idt[256];
77 | /**
78 | * Interrupt Descriptor Table pointer
79 | */
80 | idt_ptr_t idt_ptr;
81 |
82 | static void idt_set_entry(uint8 num, uint64 addr, uint16 flags){
83 | idt[num].offset_lo = (uint16)(addr & 0xFFFF);
84 | idt[num].offset_hi = (uint16)((addr >> 16) & 0xFFFF);
85 | idt[num].offset_64 = (uint32)((addr >> 32) & 0xFFFFFFFFF);
86 | idt[num].segment = 0x08; // Allways a code selector
87 | idt[num].flags.raw = flags;
88 | idt[num].reserved = 0; // Zero out
89 | }
90 |
91 | void interrupt_init(){
92 | mem_fill((uint8 *)&idt, sizeof(idt_entry_t) * 256, 0);
93 |
94 | // Remap the IRQ table.
95 | outb(0x20, 0x11); // Initialize master PIC
96 | outb(0xA0, 0x11); // Initialize slave PIC
97 | outb(0x21, 0x20); // Master PIC vector offset (IRQ0 target interrupt number)
98 | outb(0xA1, 0x28); // Slave PIC vector offset (IRQ8 landing interrupt number)
99 | outb(0x21, 0x04); // Tell Master PIC that Slave PIC is at IRQ2
100 | outb(0xA1, 0x02); // Tell Slave PIC that it's cascaded to IRQ2
101 | outb(0x21, 0x01); // Enable 8085 mode (whatever that means)
102 | outb(0xA1, 0x01); // Enable 8085 mode (whatever that means)
103 | outb(0x21, 0x0); // Clear masks
104 | outb(0xA1, 0x0); // Clear masks
105 |
106 | idt_set_entry( 0, (uint64)isr0 , 0x8E00); // Division by zero exception
107 | idt_set_entry( 1, (uint64)isr1 , 0x8E00); // Debug exception
108 | idt_set_entry( 2, (uint64)isr2 , 0x8E00); // Non maskable (external) interrupt
109 | idt_set_entry( 3, (uint64)isr3 , 0x8E00); // Breakpoint exception
110 | idt_set_entry( 4, (uint64)isr4 , 0x8E00); // INTO instruction overflow exception
111 | idt_set_entry( 5, (uint64)isr5 , 0x8E00); // Out of bounds exception (BOUND instruction)
112 | idt_set_entry( 6, (uint64)isr6 , 0x8E00); // Invalid opcode exception
113 | idt_set_entry( 7, (uint64)isr7 , 0x8E00); // No coprocessor exception
114 | idt_set_entry( 8, (uint64)isr8 , 0x8E00); // Double fault (pushes an error code)
115 | idt_set_entry( 9, (uint64)isr9 , 0x8E00); // Coprocessor segment overrun
116 | idt_set_entry(10, (uint64)isr10, 0x8E00); // Bad TSS (pushes an error code)
117 | idt_set_entry(11, (uint64)isr11, 0x8E00); // Segment not present (pushes an error code)
118 | idt_set_entry(12, (uint64)isr12, 0x8E00); // Stack fault (pushes an error code)
119 | idt_set_entry(13, (uint64)isr13, 0x8E00); // General protection fault (pushes an error code)
120 | idt_set_entry(14, (uint64)isr14, 0x8E00); // Page fault (pushes an error code)
121 | idt_set_entry(15, (uint64)isr15, 0x8E00); // Reserved
122 | idt_set_entry(16, (uint64)isr16, 0x8E00); // FPU exception
123 | idt_set_entry(17, (uint64)isr17, 0x8E00); // Alignment check exception
124 | idt_set_entry(18, (uint64)isr18, 0x8E00); // Machine check exception
125 | idt_set_entry(19, (uint64)isr19, 0x8E00); // Reserved
126 | idt_set_entry(20, (uint64)isr20, 0x8E00); // Reserved
127 | idt_set_entry(21, (uint64)isr21, 0x8E00); // Reserved
128 | idt_set_entry(22, (uint64)isr22, 0x8E00); // Reserved
129 | idt_set_entry(23, (uint64)isr23, 0x8E00); // Reserved
130 | idt_set_entry(24, (uint64)isr24, 0x8E00); // Reserved
131 | idt_set_entry(25, (uint64)isr25, 0x8E00); // Reserved
132 | idt_set_entry(26, (uint64)isr26, 0x8E00); // Reserved
133 | idt_set_entry(27, (uint64)isr27, 0x8E00); // Reserved
134 | idt_set_entry(28, (uint64)isr28, 0x8E00); // Reserved
135 | idt_set_entry(29, (uint64)isr29, 0x8E00); // Reserved
136 | idt_set_entry(30, (uint64)isr30, 0x8E00); // Reserved
137 | idt_set_entry(31, (uint64)isr31, 0x8E00); // Reserved
138 |
139 | idt_set_entry(32, (uint64)irq0 , 0x8E00); // IRQ0 - Programmable Interrupt Timer Interrupt
140 | idt_set_entry(33, (uint64)irq1 , 0x8E00); // IRQ1 - Keyboard Interrupt
141 | idt_set_entry(34, (uint64)irq2 , 0x8E00); // IRQ2 - Cascade (used internally by the two PICs. never raised)
142 | idt_set_entry(35, (uint64)irq3 , 0x8E00); // IRQ3 - COM2 (if enabled)
143 | idt_set_entry(36, (uint64)irq4 , 0x8E00); // IRQ4 - COM1 (if enabled)
144 | idt_set_entry(37, (uint64)irq5 , 0x8E00); // IRQ5 - LPT2 (if enabled)
145 | idt_set_entry(38, (uint64)irq6 , 0x8E00); // IRQ6 - Floppy Disk
146 | idt_set_entry(39, (uint64)irq7 , 0x8E00); // IRQ7 - LPT1 / Unreliable "spurious" interrupt (usually)
147 | idt_set_entry(40, (uint64)irq8 , 0x8E00); // IRQ8 - CMOS real-time clock (if enabled)
148 | idt_set_entry(41, (uint64)irq9 , 0x8E00); // IRQ9 - Free for peripherals / legacy SCSI / NIC
149 | idt_set_entry(42, (uint64)irq10, 0x8E00); // IRQ10 - Free for peripherals / SCSI / NIC
150 | idt_set_entry(43, (uint64)irq11, 0x8E00); // IRQ11 - Free for peripherals / SCSI / NIC
151 | idt_set_entry(44, (uint64)irq12, 0x8E00); // IRQ12 - PS2 Mouse
152 | idt_set_entry(45, (uint64)irq13, 0x8E00); // IRQ13 - FPU / Coprocessor / Inter-processor
153 | idt_set_entry(46, (uint64)irq14, 0x8E00); // IRQ14 - Primary ATA Hard Disk
154 | idt_set_entry(47, (uint64)irq15, 0x8E00); // IRQ15 - Secondary ATA Hard Disk
155 |
156 | idt_ptr.limit = (sizeof(idt_entry_t) * 256) - 1;
157 | idt_ptr.base = (uint64)&idt;
158 | idt_set(&idt_ptr);
159 | }
160 |
161 | void isr_handler(int_stack_t stack){
162 | #if DEBUG == 1
163 | if (stack.int_no < 19){
164 | debug_print(DC_WB, ints[stack.int_no]);
165 | } else {
166 | debug_print(DC_WB, "Interrupt: %x", stack.int_no);
167 | }
168 | #endif
169 | // Process some exceptions here
170 | uint64 cr2 = 0;
171 | switch (stack.int_no){
172 | case 0: // Division by zero
173 | //stack.rip++; // it's ok to divide by zero - move to next instruction :P
174 | break;
175 | case 13: // General protection fault
176 | #if DEBUG == 1
177 | debug_print(DC_WRD, "Error: %x", stack.err_code);
178 | #endif
179 | HANG();
180 | break;
181 | case 14: // Page fault
182 | asm volatile ("mov %%cr2, %0" : "=a"(cr2) :);
183 | // Map this page if it's not mapped yet, otherwise hang
184 | if (!page_resolve(cr2)){
185 | page_map(cr2);
186 | } else {
187 | #if DEBUG == 1
188 | debug_print(DC_WRD, "Error: %x", stack.err_code);
189 | debug_print(DC_WRD, "Addr: @%x", cr2);
190 | #endif
191 | HANG();
192 | }
193 | // Do something!
194 | break;
195 | }
196 | }
197 |
198 | void irq_handler(int_stack_t stack){
199 | #if DEBUG == 1
200 | debug_print(DC_WB, "IRQ %d", stack.err_code);
201 | #endif
202 | }
--------------------------------------------------------------------------------
/bbp/kernel/interrupts.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Helper functions for operations interrupts
4 | ==========================================
5 |
6 | This contains imports from ASM stub subroutines that catch all the neccessary
7 | exception interrupts and calls a C function interrupt_handler().
8 | It also contains LIDT wrapper function.
9 |
10 | License (BSD-3)
11 | ===============
12 |
13 | Copyright (c) 2012, Gusts 'gusC' Kaksis
14 | All rights reserved.
15 |
16 | Redistribution and use in source and binary forms, with or without
17 | modification, are permitted provided that the following conditions are met:
18 | * Redistributions of source code must retain the above copyright
19 | notice, this list of conditions and the following disclaimer.
20 | * Redistributions in binary form must reproduce the above copyright
21 | notice, this list of conditions and the following disclaimer in the
22 | documentation and/or other materials provided with the distribution.
23 | * Neither the name of the nor the
24 | names of its contributors may be used to endorse or promote products
25 | derived from this software without specific prior written permission.
26 |
27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
28 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
30 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
31 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
34 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 |
38 | */
39 |
40 | #ifndef __interrupts_h
41 | #define __interrupts_h
42 |
43 | #include "common.h"
44 |
45 | // Remaped IRQ numbers to interrupt numbers
46 | #define IRQ0 32
47 | #define IRQ1 33
48 | #define IRQ2 34
49 | #define IRQ3 35
50 | #define IRQ4 36
51 | #define IRQ5 37
52 | #define IRQ6 38
53 | #define IRQ7 39
54 | #define IRQ8 40
55 | #define IRQ9 41
56 | #define IRQ10 42
57 | #define IRQ11 43
58 | #define IRQ12 44
59 | #define IRQ13 45
60 | #define IRQ14 46
61 | #define IRQ15 47
62 |
63 | /**
64 | * Register stack passed from assembly
65 | */
66 | typedef struct {
67 | uint64 int_no; // Interrupt number
68 | uint64 err_code; // Error code (or IRQ number for IRQs)
69 | uint64 rip; // Return instruction pointer
70 | uint64 cs; // Code segment
71 | uint64 rflags; // RFLAGS
72 | uint64 rsp; // Previous stack pointer
73 | uint64 ss; // Stack segment
74 | } int_stack_t;
75 | /**
76 | * Interrupt Descriptor Table (IDT) entry structure
77 | */
78 | struct idt_entry_struct {
79 | uint16 offset_lo; // The lower 16 bits of 32bit address to jump to when this interrupt fires
80 | uint16 segment; // Kernel segment selector
81 | union {
82 | uint16 raw; // Raw value
83 | struct { // IDT flag structure
84 | uint16 ist :3; // Interrupt stack table
85 | uint16 res1 :5; // This must be zero
86 | uint16 type :4; // Interrupt gate, trap gate, task gate, etc.
87 | uint16 res2 :1; // This must be zero
88 | uint16 dpl :2; // Descriptor privilege level
89 | uint16 present :1; // Present flag
90 | } s;
91 | } flags;
92 | uint16 offset_hi; // The upper 16 bits of 32bit address to jump to
93 | uint32 offset_64; // The upper 32 bits of 64bit address
94 | uint32 reserved; // Reserved for 96bit systems :)
95 | } __PACKED;
96 | /**
97 | * Interrupt Descriptor Table (IDT) entry
98 | */
99 | typedef struct idt_entry_struct idt_entry_t;
100 | /**
101 | * Interrupt Descriptor Table (IDT) pointer structure
102 | */
103 | struct idt_ptr_struct {
104 | uint16 limit;
105 | uint64 base; // The address of the first element in our idt_entry_t array.
106 | } __PACKED;
107 | /**
108 | * Interrupt Descriptor Table (IDT) pointer
109 | */
110 | typedef struct idt_ptr_struct idt_ptr_t;
111 | /**
112 | * Initialize interrupt handlers
113 | */
114 | void interrupt_init();
115 | /**
116 | * Set IDT pointer
117 | * @see interrupts.asm
118 | * @param idt_ptr - an address of IDT pointer structure in memory
119 | * @return void
120 | */
121 | extern void idt_set(idt_ptr_t *idt_ptr);
122 | /**
123 | * Interrupt Service Routine (ISR) handler
124 | * This will be defined in kernel code
125 | * @param regs - registers pushed on the stack by assembly
126 | * @return void
127 | */
128 | void isr_handler(int_stack_t regs);
129 | /**
130 | * Interrupt Request (IRQ) handler
131 | * This will be defined in kernel code
132 | * @param regs - registers pushed on the stack by assembly
133 | * @return void
134 | */
135 | void irq_handler(int_stack_t regs);
136 |
137 | // Defined in interrupts.asm (with macros!)
138 | extern void isr0();
139 | extern void isr1();
140 | extern void isr2();
141 | extern void isr3();
142 | extern void isr4();
143 | extern void isr5();
144 | extern void isr6();
145 | extern void isr7();
146 | extern void isr8();
147 | extern void isr9();
148 | extern void isr10();
149 | extern void isr11();
150 | extern void isr12();
151 | extern void isr13();
152 | extern void isr14();
153 | extern void isr15();
154 | extern void isr16();
155 | extern void isr17();
156 | extern void isr18();
157 | extern void isr19();
158 | extern void isr20();
159 | extern void isr21();
160 | extern void isr22();
161 | extern void isr23();
162 | extern void isr24();
163 | extern void isr25();
164 | extern void isr26();
165 | extern void isr27();
166 | extern void isr28();
167 | extern void isr29();
168 | extern void isr30();
169 | extern void isr31();
170 | // Defined in interrupts.asm (with macros!)
171 | extern void irq0();
172 | extern void irq1();
173 | extern void irq2();
174 | extern void irq3();
175 | extern void irq4();
176 | extern void irq5();
177 | extern void irq6();
178 | extern void irq7();
179 | extern void irq8();
180 | extern void irq9();
181 | extern void irq10();
182 | extern void irq11();
183 | extern void irq12();
184 | extern void irq13();
185 | extern void irq14();
186 | extern void irq15();
187 |
188 |
189 | #endif
--------------------------------------------------------------------------------
/bbp/kernel/io.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Helper functions for legacy IO operations
4 | =========================================
5 |
6 | ASM wrappers
7 |
8 | License (BSD-3)
9 | ===============
10 |
11 | Copyright (c) 2012, Gusts 'gusC' Kaksis
12 | All rights reserved.
13 |
14 | Redistribution and use in source and binary forms, with or without
15 | modification, are permitted provided that the following conditions are met:
16 | * Redistributions of source code must retain the above copyright
17 | notice, this list of conditions and the following disclaimer.
18 | * Redistributions in binary form must reproduce the above copyright
19 | notice, this list of conditions and the following disclaimer in the
20 | documentation and/or other materials provided with the distribution.
21 | * Neither the name of the nor the
22 | names of its contributors may be used to endorse or promote products
23 | derived from this software without specific prior written permission.
24 |
25 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
26 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
29 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 |
36 | */
37 |
38 | #ifndef __io_h
39 | #define __io_h
40 |
41 | #include "common.h"
42 |
43 | /**
44 | * Write a byte out to the specified port.
45 | * @param port - IO port number
46 | * @param value - byte value
47 | * @return void
48 | */
49 | static void outb(uint16 port, uint8 value){
50 | asm volatile ("outb %1, %0" : : "d"(port), "a"(value));
51 | }
52 | /**
53 | * Write a word out to the specified port.
54 | * @param port - IO port number
55 | * @param value - word value
56 | * @return void
57 | */
58 | static void outw(uint16 port, uint16 value){
59 | asm volatile ("outw %1, %0" : : "d"(port), "a"(value));
60 | }
61 | /**
62 | * Write a dword out to the specified port.
63 | * @param port - IO port number
64 | * @param value - dword value
65 | * @return void
66 | */
67 | static void outd(uint16 port, uint32 value){
68 | asm volatile ("outl %1, %0" : : "d"(port), "a"(value));
69 | }
70 | /**
71 | * Read a byte from specified port.
72 | * @param port - IO port number
73 | * @return byte value
74 | */
75 | static uint8 inb(uint16 port){
76 | uint8 ret;
77 | asm volatile("inb %1, %0" : "=a"(ret) : "d"(port));
78 | return ret;
79 | }
80 | /**
81 | * Read a word from specified port.
82 | * @param port - IO port number
83 | * @return word value
84 | */
85 | static uint16 inw(uint16 port){
86 | uint16 ret;
87 | asm volatile("inw %1, %0" : "=a"(ret) : "d"(port));
88 | return ret;
89 | }
90 | /**
91 | * Read a dword from specified port.
92 | * @param port - IO port number
93 | * @return dword value
94 | */
95 | static uint32 ind(uint16 port){
96 | uint32 ret;
97 | asm volatile("inl %1, %0" : "=a"(ret) : "d"(port));
98 | return ret;
99 | }
100 |
101 | #endif
102 |
--------------------------------------------------------------------------------
/bbp/kernel/kernel.ld:
--------------------------------------------------------------------------------
1 | OUTPUT_FORMAT(elf64-x86-64)
2 | SECTIONS {
3 | .text : {
4 | *(.text);
5 | }
6 | .rodata : {
7 | *(.rodata);
8 | }
9 | .data : {
10 | *(.data);
11 | }
12 | .bss : {
13 | *(.bss);
14 | }
15 | . = ALIGN(4096);
16 | }
--------------------------------------------------------------------------------
/bbp/kernel/kmain.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Kernel entry point
4 | ==================
5 |
6 | This is where the fun part begins
7 |
8 | License (BSD-3)
9 | ===============
10 |
11 | Copyright (c) 2012, Gusts 'gusC' Kaksis
12 | All rights reserved.
13 |
14 | Redistribution and use in source and binary forms, with or without
15 | modification, are permitted provided that the following conditions are met:
16 | * Redistributions of source code must retain the above copyright
17 | notice, this list of conditions and the following disclaimer.
18 | * Redistributions in binary form must reproduce the above copyright
19 | notice, this list of conditions and the following disclaimer in the
20 | documentation and/or other materials provided with the distribution.
21 | * Neither the name of the nor the
22 | names of its contributors may be used to endorse or promote products
23 | derived from this software without specific prior written permission.
24 |
25 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
26 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
29 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 |
36 | */
37 |
38 | #include "../config.h"
39 | #include "kmain.h"
40 | #include "lib.h"
41 | #include "io.h"
42 | #include "interrupts.h"
43 | #include "paging.h"
44 | #include "acpi.h"
45 | #include "apic.h"
46 | #include "pci.h"
47 | #include "ahci.h"
48 | #if DEBUG == 1
49 | #include "debug_print.h"
50 | #endif
51 |
52 | /**
53 | * Kernel entry point
54 | */
55 | void kmain(){
56 |
57 | #if DEBUG == 1
58 | // Clear the screen
59 | debug_clear(DC_WB);
60 | // Show something on the screen
61 | debug_print(DC_WB, "Long mode");
62 | #endif
63 |
64 | // Initialize paging (well, actually re-initialize)
65 | page_init();
66 | // Initialize interrupts
67 | interrupt_init();
68 |
69 | #if DEBUG == 1
70 | // Show memory ammount
71 | debug_print(DC_WB, "RAM Total: %dMB", page_total_mem() / 1024 / 1024);
72 | debug_print(DC_WB, "RAM Avail: %dMB", page_available_mem() / 1024 / 1024);
73 | #endif
74 |
75 | // Initialize ACPI
76 | if (acpi_init()){
77 | #if DEBUG == 1
78 | //acpi_list();
79 | #endif
80 | // Initialize APIC
81 | apic_init();
82 | // Initialize PCI
83 | pci_init();
84 | #if DEBUG == 1
85 | //pci_list();
86 | debug_clear(DC_WB);
87 | #endif
88 | // Initialize AHCI
89 | if (ahci_init()){
90 |
91 | }
92 | }
93 |
94 | // Test interrupt exceptions
95 | // division by zero:
96 | //uint32 a = 1;
97 | //uint32 b = 0;
98 | //uint32 c = a / b;
99 | // page fault:
100 | //char *xyz = (char *)0xFFFFFFFF;
101 | //*xyz = 'A';
102 |
103 | // Infinite loop
104 | while(true){}
105 | }
106 |
--------------------------------------------------------------------------------
/bbp/kernel/kmain.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Kernel entry point
4 | ==================
5 |
6 | This is where the fun part begins
7 |
8 | License (BSD-3)
9 | ===============
10 |
11 | Copyright (c) 2012, Gusts 'gusC' Kaksis
12 | All rights reserved.
13 |
14 | Redistribution and use in source and binary forms, with or without
15 | modification, are permitted provided that the following conditions are met:
16 | * Redistributions of source code must retain the above copyright
17 | notice, this list of conditions and the following disclaimer.
18 | * Redistributions in binary form must reproduce the above copyright
19 | notice, this list of conditions and the following disclaimer in the
20 | documentation and/or other materials provided with the distribution.
21 | * Neither the name of the nor the
22 | names of its contributors may be used to endorse or promote products
23 | derived from this software without specific prior written permission.
24 |
25 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
26 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
29 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 |
36 | */
37 |
38 | #ifndef __kmain_h
39 | #define __kmain_h
40 |
41 | #include "common.h"
42 |
43 | #endif /* __kmain_h */
44 |
--------------------------------------------------------------------------------
/bbp/kernel/lib.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Tiny helper function library
4 | ============================
5 |
6 | TOC:
7 | * Memory manipulation functions
8 | * Character string functions
9 |
10 | License (BSD-3)
11 | ===============
12 |
13 | Copyright (c) 2012, Gusts 'gusC' Kaksis
14 | All rights reserved.
15 |
16 | Redistribution and use in source and binary forms, with or without
17 | modification, are permitted provided that the following conditions are met:
18 | * Redistributions of source code must retain the above copyright
19 | notice, this list of conditions and the following disclaimer.
20 | * Redistributions in binary form must reproduce the above copyright
21 | notice, this list of conditions and the following disclaimer in the
22 | documentation and/or other materials provided with the distribution.
23 | * Neither the name of the nor the
24 | names of its contributors may be used to endorse or promote products
25 | derived from this software without specific prior written permission.
26 |
27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
28 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
30 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
31 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
34 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 |
38 | */
39 |
40 | #include "lib.h"
41 | #include "common.h"
42 |
43 | //
44 | // Memory manipulation functions
45 | //
46 |
47 | void mem_copy(uint8 *dest, uint64 len, const uint8 *src){
48 | // Fast copy
49 | asm volatile ("rep\n\tmovsb" : : "c"(len), "S"(src), "D"(dest));
50 | }
51 | void mem_fill(uint8 *dest, uint64 len, uint8 val){
52 | // Fast fill
53 | asm volatile ("rep\n\tstosb" : : "c"(len), "a"(val), "D"(dest));
54 | }
55 | bool mem_compare(const uint8 *buff1, const uint8 *buff2, uint64 len){
56 | while (len--){
57 | if (*(buff1++) != *(buff2++)){
58 | return false;
59 | }
60 | }
61 | return true;
62 | }
63 |
64 | //
65 | // String functions
66 | //
67 |
68 | #define MAX_INT_STR 32
69 |
70 | uint64 str_copy(char *dest, uint64 len, const char *src){
71 | char *sp = (char *)src;
72 | char *dp = (char *)dest;
73 | uint64 s = 0;
74 | while (*sp != 0 && len != 0){
75 | // Copy till the end of source or destination has been reached
76 | *(dp++) = *(sp++);
77 | len --;
78 | s ++;
79 | }
80 | return s;
81 | }
82 | uint64 str_length(const char *str){
83 | uint64 len = 0;
84 | while (*(str++) != 0){
85 | // Increment till the end of string
86 | len ++;
87 | }
88 | return len;
89 | }
90 | int64 str_char_idx(const char *haystack, const char needle, uint64 offset){
91 | int64 idx = 0;
92 | // Move offset
93 | while (offset--){
94 | if (*(haystack++) == 0){
95 | // End of the string
96 | return -1;
97 | }
98 | }
99 | while (*haystack != 0){
100 | if (*haystack == needle){
101 | // Found an occurence
102 | return idx;
103 | }
104 | idx++;
105 | haystack++;
106 | }
107 | return -1;
108 | }
109 | uint64 int_to_str(char *dest, uint64 len, int64 val, int64 base){
110 | static char tmp[MAX_INT_STR + 1];
111 | mem_fill((uint8 *)tmp, MAX_INT_STR + 1, 0);
112 | char *b = (char *)tmp + MAX_INT_STR;
113 | char c = 0;
114 | if (val >= 0){
115 | // Process positive value
116 | do {
117 | c = (char)(val % base);
118 | if (c > 9){
119 | *--b = 'A' + (c - 10);
120 | } else {
121 | *--b = '0' + c;
122 | }
123 | val /= base;
124 | } while (val != 0);
125 | } else if (val < 0){
126 | // Process negative value
127 | do {
128 | c = (char)(val % base);
129 | if (c < -9){
130 | *--b = 'A' - (c + 10);
131 | } else {
132 | *--b = '0' - c;
133 | }
134 | val /= base;
135 | } while (val != 0);
136 | // Add minus sign only for decimals
137 | if (base == 10){
138 | *--b = '-';
139 | }
140 | }
141 | // Copy the result and return number of digits processed
142 | return str_copy(dest, len, b);
143 | }
144 | int64 str_to_int(const char *str, int64 base){
145 | char *b = (char *)str;
146 | int64 val = 0;
147 | uint8 negative = 0;
148 | // Trim leading spaces
149 | while (*b == 0x20 || *b == 0x09){ // space || tab
150 | b++;
151 | }
152 | // Check if a negative number
153 | if (*b == '-'){
154 | negative = 1;
155 | }
156 | // Calculate integer value
157 | while (*b >= 0x30 && *b <= 0x39){ // >= 0 && <= 9 (as in ascii 0, 1, ..., 9)
158 | val *= 10; // multiply upwwards
159 | val += (*b) - 0x30; // add current digit
160 | b ++;
161 | }
162 | // Set minus sign if necessary
163 | if (negative){
164 | return 0 - val;
165 | }
166 | return val;
167 | }
168 | uint64 str_write_f(char *dest, uint64 len, const char *format, ...){
169 | va_list args;
170 | va_start(args, format);
171 | uint64 ret = __write_f(dest, len, format, args);
172 | va_end(args);
173 | return ret;
174 | }
175 | uint64 str_read_f(const char *src, const char *format, ...){
176 | va_list args;
177 | va_start(args, format);
178 | uint64 ret = __read_f(src, format, args);
179 | va_end(args);
180 | return ret;
181 | }
182 |
183 |
184 | //
185 | // Private functions
186 | //
187 |
188 | uint64 __write_f(char *dest, uint64 len, const char *format, va_list args){
189 | char *f = (char *)format;
190 | char *d = (char *)dest;
191 | uint64 ret = 0;
192 |
193 | // Temporary value variables
194 | uint64 val_len;
195 | int64 val_int64;
196 | uint64 val_uint64;
197 | char val_char;
198 | char *val_str;
199 |
200 | while (*f && ret < len){
201 | if (*f == '%'){ // possible specifier
202 | switch (*(f + 1)){
203 | case 'd': // integer
204 | val_int64 = va_arg(args, int64);
205 | val_len = int_to_str(d, MAX_INT_STR, val_int64, 10);
206 | d += val_len;
207 | ret += val_len;
208 | f ++;
209 | break;
210 | case 'u': // unsigned integer
211 | val_uint64 = va_arg(args, uint64);
212 | val_len = int_to_str(d, MAX_INT_STR, val_uint64, 10);
213 | d += val_len;
214 | ret += val_len;
215 | f ++;
216 | break;
217 | case 'x': // unsigned integer in hex
218 | val_uint64 = va_arg(args, uint64);
219 | val_len = int_to_str(d, MAX_INT_STR, val_uint64, 16);
220 | d += val_len;
221 | ret += val_len;
222 | f ++;
223 | break;
224 | case 'b': // unsigned integer in binary
225 | val_uint64 = va_arg(args, uint64);
226 | val_len = int_to_str(d, MAX_INT_STR, val_uint64, 2);
227 | d += val_len;
228 | ret += val_len;
229 | f ++;
230 | break;
231 | case 'c': // char
232 | val_char = (char)va_arg(args, int64); // chars are promoted to int in va_list
233 | *(d++) = val_char;
234 | ret ++;
235 | f ++;
236 | break;
237 | case 's': // string
238 | val_str = (char *)va_arg(args, uint64);
239 | while (*val_str){
240 | *(d ++) = *(val_str ++);
241 | ret ++;
242 | }
243 | f ++;
244 | break;
245 | default: // not a specifier
246 | *(d ++) = *f;
247 | ret ++;
248 | break;
249 | }
250 | f ++;
251 | } else { // copy string
252 | *(d ++) = *(f ++);
253 | ret ++;
254 | }
255 | }
256 | return ret;
257 | }
258 | uint64 __read_f(const char *src, const char *format, va_list args){
259 |
260 | return 0;
261 | }
--------------------------------------------------------------------------------
/bbp/kernel/lib.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Tiny helper function library
4 | ============================
5 |
6 | TOC:
7 | * Memory manipulation functions
8 | * Character string functions
9 |
10 | Function argument order explanation. Basically it should sound like this:
11 | "Fill this bucket for that many items of that other bucket", thus it's like
12 | the Intel ASM syntax of "instruction destination, source" whith an extra size
13 | specifier, so to prevent buffer overflows etc.
14 |
15 | License (BSD-3)
16 | ===============
17 |
18 | Copyright (c) 2012, Gusts 'gusC' Kaksis
19 | All rights reserved.
20 |
21 | Redistribution and use in source and binary forms, with or without
22 | modification, are permitted provided that the following conditions are met:
23 | * Redistributions of source code must retain the above copyright
24 | notice, this list of conditions and the following disclaimer.
25 | * Redistributions in binary form must reproduce the above copyright
26 | notice, this list of conditions and the following disclaimer in the
27 | documentation and/or other materials provided with the distribution.
28 | * Neither the name of the nor the
29 | names of its contributors may be used to endorse or promote products
30 | derived from this software without specific prior written permission.
31 |
32 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
36 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 |
43 | */
44 |
45 | #ifndef __lib_h
46 | #define __lib_h
47 |
48 | #include "common.h"
49 |
50 | #define INT_BASE_BIN 2
51 | #define INT_BASE_OCT 8
52 | #define INT_BASE_DEC 10
53 | #define INT_BASE_HEX 16
54 |
55 | //
56 | // Memory manipulation functions
57 | //
58 |
59 | /**
60 | * Copy data from one memory location to another
61 | * @param [out] dest - destination memory
62 | * @param [in] src - source memory
63 | * @param len - number of bytes to copy
64 | * @return void
65 | */
66 | void mem_copy(uint8 *dest, uint64 len, const uint8 *src);
67 | /**
68 | * Fill a memory buffer with a single byte value
69 | * @param [out] dest - destination memory
70 | * @param [in] val - value to set
71 | * @param len - number of bytes to set
72 | * @return void
73 | */
74 | void mem_fill(uint8 *dest, uint64 len, uint8 val);
75 | /**
76 | * Compare two memory regions
77 | * @param [in] buff1
78 | * @param [in] buff2
79 | * @param len - comparison length
80 | * @return true if they are equal, false if not
81 | */
82 | bool mem_compare(const uint8 *buff1, const uint8 *buff2, uint64 len);
83 |
84 | //
85 | // String functions
86 | //
87 |
88 | /**
89 | * Copy a string from one buffer to another
90 | * @param [out] dest - destination buffer
91 | * @param len - destination buffer length
92 | * @param [in] src - source buffer
93 | * @return number of characters copied
94 | */
95 | uint64 str_copy(char *dest, uint64 len, const char *src);
96 | /**
97 | * Calculate the length of a string
98 | * @param [in] str - string
99 | * @return string length
100 | */
101 | uint64 str_length(const char *str);
102 | /**
103 | * Search for a character in a string
104 | * @param [in] haystack - source buffer
105 | * @param needle - character to find
106 | * @param offset - number of characters to offset from the beginning of haystack
107 | * @return character index (-1 if not found)
108 | */
109 | int64 str_char_idx(const char *haystack, const char needle, uint64 offset);
110 | /**
111 | * Convert integer to string
112 | * @param [out] dest - destination buffer
113 | * @param len - destination buffer length
114 | * @param in - input integer
115 | * @param base - the base of the integer represented by the string (8, 10 or 16)
116 | * @return number of characters in a string representation
117 | */
118 | uint64 int_to_str(char *dest, uint64 len, int64 val, int64 base);
119 | /**
120 | * Convert a string to integer
121 | * @param [in] str - integer string
122 | * @param base - the base of the integer represented by the string (8, 10 or 16)
123 | * @return output integer
124 | */
125 | int64 str_to_int(const char *str, int64 base);
126 | /**
127 | * Build a formated string from a format and additional parameters
128 | * @param [out] dest - destination string pointer
129 | * @param len - maximum length allowed to fill
130 | * @param [in] format - standard C printf format string
131 | * @param [in] ... - additional arguments
132 | * @return number of characters written
133 | */
134 | uint64 str_write_f(char *dest, uint64 len, const char *format, ...);
135 | /**
136 | * Parse a formated string using a format and store results in additional parameters
137 | * @param [in] src - source string pointer
138 | * @param [in] format - standard C printf format string
139 | * @param [out] ... - additional argument pointers
140 | * @return number of arguments parsed
141 | */
142 | uint64 str_read_f(const char *src, const char *format, ...);
143 |
144 | //
145 | // Private functions
146 | //
147 |
148 | uint64 __write_f(char *dest, uint64 len, const char *format, va_list args);
149 | uint64 __read_f(const char *src, const char *format, va_list args);
150 |
151 |
152 | #endif /* __lib_h */
--------------------------------------------------------------------------------
/bbp/kernel/makefile:
--------------------------------------------------------------------------------
1 | AS = nasm -felf64
2 | CC = x86_64-pc-elf-gcc -nostdlib -fno-builtin -nostartfiles -nodefaultlibs
3 | LD = x86_64-pc-elf-ld -i
4 | OBJECTS = lib.c.o interrupts.s.o interrupts.c.o apic.c.o acpi.c.o debug_print.c.o paging.c.o pci.c.o ahci.c.o kmain.c.o
5 |
6 | all: kernel.o
7 |
8 | kernel.o: $(OBJECTS)
9 | $(LD) -T kernel.ld $(OBJECTS) -o ../kernel.o
10 |
11 | %.s.o: %.asm
12 | $(AS) -o $@ $<
13 |
14 | %.c.o: %.c
15 | $(CC) -c $< -o $@
16 |
17 | clean:
18 | rm -f *.o
--------------------------------------------------------------------------------
/bbp/kernel/msr.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Helper functions for Model Specific Register (MSR) operations
4 | =============================================================
5 |
6 | This file also contains some notable MSR values defined as macros
7 |
8 | License (BSD-3)
9 | ===============
10 |
11 | Copyright (c) 2012, Gusts 'gusC' Kaksis
12 | All rights reserved.
13 |
14 | Redistribution and use in source and binary forms, with or without
15 | modification, are permitted provided that the following conditions are met:
16 | * Redistributions of source code must retain the above copyright
17 | notice, this list of conditions and the following disclaimer.
18 | * Redistributions in binary form must reproduce the above copyright
19 | notice, this list of conditions and the following disclaimer in the
20 | documentation and/or other materials provided with the distribution.
21 | * Neither the name of the nor the
22 | names of its contributors may be used to endorse or promote products
23 | derived from this software without specific prior written permission.
24 |
25 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
26 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
29 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 |
36 | */
37 |
38 | #ifndef __msr_h
39 | #define __msr_h
40 |
41 | #include "common.h"
42 |
43 | //
44 | // MSR macros (Core2+)
45 | //
46 |
47 | #define MSR_IA32_P5_MC_ADDR 0x0
48 | #define MSR_IA32_P5_MC_TYPE 0x1
49 | #define MSR_IA32_APIC_BASE 0x1B
50 | #define MSR_IA32_FEATURE_CONTROL 0x3A
51 | #define MSR_BBL_CR_CTL3 0x11E
52 | #define MSR_IA32_SYSENTER_CS 0x174
53 | #define MSR_IA32_SYSENTER_ESP 0x175
54 | #define MSR_IA32_SYSENTER_EIP 0x176
55 | #define MSR_IA32_MISC_ENABLE 0x1A0
56 | #define MSR_IA32_X2APIC_APICID 0x802
57 | #define MSR_IA32_X2APIC_VERSION 0x803
58 | #define MSR_IA32_X2APIC_TPR 0x808
59 | #define MSR_IA32_X2APIC_PPR 0x80A
60 | #define MSR_IA32_X2APIC_EOI 0x80B
61 | #define MSR_IA32_X2APIC_LDR 0x80D
62 | #define MSR_IA32_X2APIC_SIVR 0x80F
63 | #define MSR_IA32_X2APIC_ISR0 0x810
64 | #define MSR_IA32_X2APIC_ISR1 0x811
65 | #define MSR_IA32_X2APIC_ISR2 0x812
66 | #define MSR_IA32_X2APIC_ISR3 0x813
67 | #define MSR_IA32_X2APIC_ISR4 0x814
68 | #define MSR_IA32_X2APIC_ISR5 0x815
69 | #define MSR_IA32_X2APIC_ISR6 0x816
70 | #define MSR_IA32_X2APIC_ISR7 0x817
71 | #define MSR_IA32_X2APIC_TMR0 0x818
72 | #define MSR_IA32_X2APIC_TMR1 0x819
73 | #define MSR_IA32_X2APIC_TMR2 0x81A
74 | #define MSR_IA32_X2APIC_TMR3 0x81B
75 | #define MSR_IA32_X2APIC_TMR4 0x81C
76 | #define MSR_IA32_X2APIC_TMR5 0x81D
77 | #define MSR_IA32_X2APIC_TMR6 0x81E
78 | #define MSR_IA32_X2APIC_TMR7 0x81F
79 | #define MSR_IA32_X2APIC_IRR0 0x820
80 | #define MSR_IA32_X2APIC_IRR1 0x821
81 | #define MSR_IA32_X2APIC_IRR2 0x822
82 | #define MSR_IA32_X2APIC_IRR3 0x823
83 | #define MSR_IA32_X2APIC_IRR4 0x824
84 | #define MSR_IA32_X2APIC_IRR5 0x825
85 | #define MSR_IA32_X2APIC_IRR6 0x826
86 | #define MSR_IA32_X2APIC_IRR7 0x827
87 | #define MSR_IA32_X2APIC_ESR 0x828
88 | #define MSR_IA32_X2APIC_LVT_CMCI 0x82F
89 | #define MSR_IA32_X2APIC_ICR 0x830
90 | #define MSR_IA32_X2APIC_LVT_TIMER 0x832
91 | #define MSR_IA32_X2APIC_LVT_THERMAL 0x833
92 | #define MSR_IA32_X2APIC_LVT_PMI 0x834
93 | #define MSR_IA32_X2APIC_LVT_LINT0 0x835
94 | #define MSR_IA32_X2APIC_LVT_LINT1 0x836
95 | #define MSR_IA32_X2APIC_LVT_ERROR 0x837
96 | #define MSR_IA32_X2APIC_INIT_COUNT 0x838
97 | #define MSR_IA32_X2APIC_CUR_COUNT 0x839
98 | #define MSR_IA32_X2APIC_DIV_CONF 0x83E
99 | #define MSR_IA32_X2APIC_SELF_IPI 0x83F
100 | #define MSR_IA32_EFER 0xC0000080
101 | #define MSR_IA32_STAR 0xC0000081
102 | #define MSR_IA32_FMASK 0xC0000084
103 | #define MSR_IA32_FS_BASE 0xC0000100
104 | #define MSR_IA32_GS_BASE 0xC0000101
105 | #define MSR_IA32_KERNEL_GS_BASE 0xC0000102
106 |
107 | /**
108 | * Read MSR value
109 | * @param msr - Model Specific Register
110 | * @param [out] val - pointer to memory location where to write MSR value
111 | * @return void
112 | */
113 | static void msr_read(uint32 msr, uint64 *val){
114 | split_uint64_t *v = (split_uint64_t *)val;
115 | asm volatile("rdmsr" : "=a"(v->low), "=d"(v->high) : "c"(msr));
116 | }
117 | /**
118 | * Write MSR value
119 | * @param msr - Model Specific Register
120 | * @param [in] val - value to write into MSR
121 | * @return void
122 | */
123 | static void msr_write(uint32 msr, uint64 val){
124 | split_uint64_t *v = (split_uint64_t *)&val;
125 | asm volatile("wrmsr" : : "a"(v->low), "d"(v->high), "c"(msr));
126 | }
127 |
128 | #endif
129 |
--------------------------------------------------------------------------------
/bbp/kernel/paging.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Memory paging functions
4 | =======================
5 |
6 | License (BSD-3)
7 | ===============
8 |
9 | Copyright (c) 2012, Gusts 'gusC' Kaksis
10 | All rights reserved.
11 |
12 | Redistribution and use in source and binary forms, with or without
13 | modification, are permitted provided that the following conditions are met:
14 | * Redistributions of source code must retain the above copyright
15 | notice, this list of conditions and the following disclaimer.
16 | * Redistributions in binary form must reproduce the above copyright
17 | notice, this list of conditions and the following disclaimer in the
18 | documentation and/or other materials provided with the distribution.
19 | * Neither the name of the nor the
20 | names of its contributors may be used to endorse or promote products
21 | derived from this software without specific prior written permission.
22 |
23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
27 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 |
34 | */
35 |
36 | #include "../config.h"
37 | #include "paging.h"
38 | #include "lib.h"
39 | #if DEBUG == 1
40 | #include "debug_print.h"
41 | #endif
42 |
43 | /**
44 | * Memory type codes for E820
45 | */
46 | enum eMemType {
47 | kMemOk = 1, // Normal memory - usable
48 | kMemReserved, // Reserved memory - unusable
49 | kMemACPIReclaim, // ACPI reclaimable memory - might be usable after ACPI is taken care of
50 | kMemACPI, // ACPI NVS memory - unusable
51 | kMemBad // Bad memory - unsuable
52 | };
53 | /**
54 | * E820 memory map entry structure
55 | */
56 | struct e820entry_struct {
57 | uint16 entry_size; // if 24, then it has attributes
58 | uint64 base;
59 | uint64 length;
60 | uint32 type;
61 | uint32 attributes; // ACPI 3.0 only
62 | } __PACKED;
63 | typedef struct e820entry_struct e820entry_t;
64 | /**
65 | * E820 memory map structure
66 | */
67 | struct e820map_struct {
68 | uint16 size;
69 | e820entry_t entries[];
70 | } __PACKED;
71 | typedef struct e820map_struct e820map_t;
72 |
73 | /**
74 | * Page table structures
75 | */
76 | static pm_t *_pml4 = (pm_t *)PT_LOC;
77 | static uint64 _page_offset = PT_LOC;
78 |
79 | static uint64 _total_mem = 0;
80 | static uint64 _available_mem = 0;
81 |
82 | static uint64 *_page_frames;
83 | static uint64 _page_count = 0;
84 |
85 | // Get bitset index
86 | #define BIT_INDEX(b) (b / 64)
87 | // Get bit offset in bitset
88 | #define BIT_OFFSET(b) (b % 64)
89 |
90 | /**
91 | * Mark frame allocated
92 | * @param paddr - physical address to mark
93 | */
94 | static void page_set_frame(uint64 paddr){
95 | uint64 page = paddr / 4069;
96 | uint64 idx = BIT_INDEX(page);
97 | uint64 offset = BIT_OFFSET(page);
98 | _page_frames[idx] |= (0x1 << offset);
99 | }
100 | /**
101 | * Mark frame free
102 | * @param paddr - physical address to mark
103 | */
104 | static void page_clear_frame(uint64 paddr){
105 | uint64 page = paddr / 4069;
106 | uint64 idx = BIT_INDEX(page);
107 | uint64 offset = BIT_OFFSET(page);
108 | _page_frames[idx] &= ~(0x1 << offset);
109 | }
110 | /**
111 | * Check if frame is allocated or free
112 | * @param paddr - physical address to check
113 | * @return true if set false if not
114 | */
115 | static bool page_check_frame(uint64 paddr){
116 | uint64 page = paddr / 4069;
117 | uint64 idx = BIT_INDEX(page);
118 | uint64 offset = BIT_OFFSET(page);
119 | return (_page_frames[idx] & (0x1 << offset));
120 | }
121 |
122 | /**
123 | * Sort memory map in ascending order
124 | */
125 | static void sort_e820(e820map_t *mem_map){
126 | uint64 i = 0;
127 | // Do the bubble sort to make them in ascending order
128 | e820entry_t e;
129 | uint64 swapped = 1;
130 | uint64 count = mem_map->size;
131 | while (count > 0 && swapped ){
132 | i = 0;
133 | swapped = 0;
134 | while (i < count - 1){
135 | if (mem_map->entries[i].base > mem_map->entries[i + 1].base){
136 | e = mem_map->entries[i];
137 | mem_map->entries[i] = mem_map->entries[i + 1];
138 | mem_map->entries[i + 1] = e;
139 | swapped = 1;
140 | }
141 | i ++;
142 | }
143 | count --;
144 | }
145 | // Get total RAM
146 | for (i = 0; i < mem_map->size; i ++){
147 | #if DEBUG == 1
148 | //debug_print(DC_WB, "%x -> %x (%d)", mem_map->entries[i].base, mem_map->entries[i].base + mem_map->entries[i].length, mem_map->entries[i].type);
149 | #endif
150 | if (mem_map->entries[i].type != kMemReserved){
151 | if (mem_map->entries[i].base + mem_map->entries[i].length > _total_mem){
152 | _total_mem = mem_map->entries[i].base + mem_map->entries[i].length;
153 | }
154 | if (mem_map->entries[i].type == kMemOk){
155 | _available_mem += mem_map->entries[i].length;
156 | }
157 | }
158 | }
159 | }
160 |
161 | void page_init(){
162 | // Read E820 memory map and mark used regions
163 | e820map_t *mem_map = (e820map_t *)E820_LOC;
164 | // Sort memory map
165 | sort_e820(mem_map);
166 |
167 | // Single page (PML1 entry) holds 4KB of RAM
168 | uint64 page_count = INIT_MEM / PAGE_SIZE;
169 | if (INIT_MEM % PAGE_SIZE > 0){
170 | page_count ++;
171 | }
172 | // Single table (PML2 entry) holds 2MB of RAM
173 | uint64 table_count = page_count / 512;
174 | if (page_count % 512 > 0){
175 | table_count ++;
176 | }
177 | // Single directory (PML3 entry, directory table pointer) holds 1GB of RAM
178 | uint64 directory_count = table_count / 512;
179 | if (table_count % 512 > 0){
180 | directory_count ++;
181 | }
182 | // Single drawer (PML4 entry) holds 512GB of RAM
183 | uint64 drawer_count = directory_count / 512;
184 | if (directory_count % 512 > 0){
185 | drawer_count ++;
186 | }
187 |
188 | // Determine the end of PMLx structures to add new ones
189 | _page_offset += (sizeof(pm_t) * 512) * (1 + drawer_count + directory_count + table_count);
190 | // Calculate total frame count
191 | _page_count = _total_mem / PAGE_SIZE;
192 | // Allocate frame bitset at the next page boundary
193 | _page_frames = (uint64 *)_page_offset;
194 | // Clear bitset
195 | mem_fill((uint8 *)_page_count, _page_count / 8, 0);
196 | // Move offset further
197 | _page_offset += (_page_count / 8);
198 | // Align the offset
199 | if ((_page_offset & PAGE_MASK) != _page_offset){
200 | _page_offset &= PAGE_MASK;
201 | _page_offset += PAGE_SIZE;
202 | }
203 |
204 | #if DEBUG == 1
205 | debug_print(DC_WB, "Frames: %d", _page_count);
206 | #endif
207 |
208 | // Determine unsuable memory regions
209 | uint64 i;
210 | uint64 paddr_from;
211 | uint64 paddr_to;
212 | for (i = 0; i < mem_map->size; i ++){
213 | if (mem_map->entries[i].type != kMemOk){
214 | // Mark all unusable regions used
215 | paddr_from = (mem_map->entries[i].base & PAGE_MASK);
216 | paddr_to = ((mem_map->entries[i].base + mem_map->entries[i].length) & PAGE_MASK);
217 | while (paddr_from < paddr_to){
218 | page_set_frame(paddr_from);
219 | paddr_from += PAGE_SIZE;
220 | }
221 | }
222 | }
223 | }
224 | uint64 page_total_mem(){
225 | return _total_mem;
226 | }
227 | uint64 page_available_mem(){
228 | return _available_mem;
229 | }
230 | uint64 page_normalize_vaddr(uint64 vaddr){
231 | vaddr_t va;
232 | va.raw = vaddr;
233 | if ((va.s.drawer_idx & 0x100) != 0){
234 | va.s.canonical = 0xFFFF;
235 | } else {
236 | va.s.canonical = 0x0000;
237 | }
238 | return va.raw;
239 | }
240 | uint64 page_map(uint64 paddr){
241 | // Do the identity map
242 | vaddr_t va;
243 | pm_t *pml3;
244 | pm_t *pml2;
245 | pm_t *pml1;
246 | va.raw = page_normalize_vaddr(paddr);
247 | if (!_pml4[va.s.drawer_idx].s.present){
248 | page_set_frame(_page_offset);
249 | pml3 = (pm_t *)_page_offset;
250 | mem_fill((uint8 *)pml3, sizeof(pm_t) * 512, 0);
251 | _pml4[va.s.drawer_idx].raw = (uint64)pml3;
252 | _pml4[va.s.drawer_idx].s.present = 1;
253 | _pml4[va.s.drawer_idx].s.writable = 1;
254 | //_pml4[va.s.drawer_idx].s.write_through = 1;
255 | //_pml4[va.s.drawer_idx].s.cache_disable = 1;
256 | _page_offset += (sizeof(pm_t) * 512);
257 | }
258 | pml3 = (pm_t *)(_pml4[va.s.drawer_idx].raw & PAGE_MASK);
259 | if (!pml3[va.s.directory_idx].s.present){
260 | page_set_frame(_page_offset);
261 | pml2 = (pm_t *)_page_offset;
262 | mem_fill((uint8 *)pml2, sizeof(pm_t) * 512, 0);
263 | pml3[va.s.directory_idx].raw = (uint64)pml2;
264 | pml3[va.s.directory_idx].s.present = 1;
265 | pml3[va.s.directory_idx].s.writable = 1;
266 | //pml3[va.s.directory_idx].s.write_through = 1;
267 | //pml3[va.s.directory_idx].s.cache_disable = 1;
268 | _page_offset += (sizeof(pm_t) * 512);
269 | }
270 | pml2 = (pm_t *)(pml3[va.s.directory_idx].raw & PAGE_MASK);
271 | if (!pml2[va.s.table_idx].s.present){
272 | page_set_frame(_page_offset);
273 | pml1 = (pm_t *)_page_offset;
274 | mem_fill((uint8 *)pml1, sizeof(pm_t) * 512, 0);
275 | pml2[va.s.table_idx].raw = (uint64)pml1;
276 | pml2[va.s.table_idx].s.present = 1;
277 | pml2[va.s.table_idx].s.writable = 1;
278 | //pml2[va.s.table_idx].s.write_through = 1;
279 | //pml2[va.s.table_idx].s.cache_disable = 1;
280 | _page_offset += (sizeof(pm_t) * 512);
281 | }
282 | pml1 = (pm_t *)(pml2[va.s.table_idx].raw & PAGE_MASK);
283 | if (!pml1[va.s.page_idx].s.present){
284 | pml1[va.s.page_idx].raw = (paddr & PAGE_MASK);
285 | pml1[va.s.page_idx].s.present = 1;
286 | pml1[va.s.page_idx].s.writable = 1;
287 | //pml1[va.s.page_idx].s.write_through = 1;
288 | //pml1[va.s.page_idx].s.cache_disable = 1;
289 | }
290 | return va.raw;
291 | }
292 | uint64 page_map_mmio(uint64 paddr){
293 | // Do the identity map
294 | vaddr_t va;
295 | pm_t *pml3;
296 | pm_t *pml2;
297 | pm_t *pml1;
298 | va.raw = page_normalize_vaddr(paddr);
299 | if (!_pml4[va.s.drawer_idx].s.present){
300 | page_set_frame(_page_offset);
301 | pml3 = (pm_t *)_page_offset;
302 | mem_fill((uint8 *)pml3, sizeof(pm_t) * 512, 0);
303 | _pml4[va.s.drawer_idx].raw = (uint64)pml3;
304 | _pml4[va.s.drawer_idx].s.present = 1;
305 | _pml4[va.s.drawer_idx].s.writable = 1;
306 | _pml4[va.s.drawer_idx].s.write_through = 1;
307 | _pml4[va.s.drawer_idx].s.cache_disable = 1;
308 | _page_offset += (sizeof(pm_t) * 512);
309 | }
310 | pml3 = (pm_t *)(_pml4[va.s.drawer_idx].raw & PAGE_MASK);
311 | if (!pml3[va.s.directory_idx].s.present){
312 | page_set_frame(_page_offset);
313 | pml2 = (pm_t *)_page_offset;
314 | mem_fill((uint8 *)pml2, sizeof(pm_t) * 512, 0);
315 | pml3[va.s.directory_idx].raw = (uint64)pml2;
316 | pml3[va.s.directory_idx].s.present = 1;
317 | pml3[va.s.directory_idx].s.writable = 1;
318 | pml3[va.s.directory_idx].s.write_through = 1;
319 | pml3[va.s.directory_idx].s.cache_disable = 1;
320 | _page_offset += (sizeof(pm_t) * 512);
321 | }
322 | pml2 = (pm_t *)(pml3[va.s.directory_idx].raw & PAGE_MASK);
323 | if (!pml2[va.s.table_idx].s.present){
324 | page_set_frame(_page_offset);
325 | pml1 = (pm_t *)_page_offset;
326 | mem_fill((uint8 *)pml1, sizeof(pm_t) * 512, 0);
327 | pml2[va.s.table_idx].raw = (uint64)pml1;
328 | pml2[va.s.table_idx].s.present = 1;
329 | pml2[va.s.table_idx].s.writable = 1;
330 | pml2[va.s.table_idx].s.write_through = 1;
331 | pml2[va.s.table_idx].s.cache_disable = 1;
332 | _page_offset += (sizeof(pm_t) * 512);
333 | }
334 | pml1 = (pm_t *)(pml2[va.s.table_idx].raw & PAGE_MASK);
335 | if (!pml1[va.s.page_idx].s.present){
336 | pml1[va.s.page_idx].raw = (paddr & PAGE_MASK);
337 | pml1[va.s.page_idx].s.present = 1;
338 | pml1[va.s.page_idx].s.writable = 1;
339 | pml1[va.s.page_idx].s.write_through = 1;
340 | pml1[va.s.page_idx].s.cache_disable = 1;
341 | }
342 | return va.raw;
343 | }
344 | uint64 page_resolve(uint64 vaddr){
345 | vaddr_t va;
346 | uint64 paddr = 0;
347 | pm_t *table;
348 | va.raw = vaddr;
349 | if (_pml4[va.s.drawer_idx].s.present){
350 | table = (pm_t *)(_pml4[va.s.drawer_idx].raw & PAGE_MASK);
351 | if (table[va.s.directory_idx].s.present){
352 | table = (pm_t *)(table[va.s.directory_idx].raw & PAGE_MASK);
353 | if (table[va.s.table_idx].s.present){
354 | table = (pm_t *)(table[va.s.table_idx].raw & PAGE_MASK);
355 | if (table[va.s.page_idx].s.present){
356 | paddr = va.s.offset; // set offset
357 | paddr |= (table[va.s.page_idx].raw & PAGE_MASK); // merge page aligned address
358 | }
359 | }
360 | }
361 | }
362 | return paddr;
363 | }
364 |
365 | pm_t page_get_pml_entry(uint64 vaddr, uint8 level){
366 | vaddr_t va;
367 | va.raw = vaddr;
368 | pm_t *table = _pml4;
369 | if (level >= 3){
370 | return table[va.s.drawer_idx];
371 | }
372 | table = (pm_t *)(table[va.s.drawer_idx].raw & PAGE_MASK);
373 | if (level == 2){
374 | return table[va.s.directory_idx];
375 | }
376 | table = (pm_t *)(table[va.s.directory_idx].raw & PAGE_MASK);
377 | if (level == 1){
378 | return table[va.s.table_idx];
379 | }
380 | table = (pm_t *)(table[va.s.table_idx].raw & PAGE_MASK);
381 | return table[va.s.page_idx];
382 | }
383 |
384 | void page_set_pml_entry(uint64 vaddr, uint8 level, pm_t pe){
385 | vaddr_t va;
386 | va.raw = page_normalize_vaddr(vaddr);
387 | pm_t *table = _pml4;
388 | if (level >= 3){
389 | table[va.s.drawer_idx].raw = pe.raw;
390 | }
391 | table = (pm_t *)(table[va.s.drawer_idx].raw & PAGE_MASK);
392 | if (level == 2){
393 | table[va.s.directory_idx].raw = pe.raw;
394 | }
395 | table = (pm_t *)(table[va.s.directory_idx].raw & PAGE_MASK);
396 | if (level == 1){
397 | table[va.s.table_idx].raw = pe.raw;
398 | }
399 | table = (pm_t *)(table[va.s.table_idx].raw & PAGE_MASK);
400 | table[va.s.page_idx].raw = pe.raw;
401 | }
402 |
--------------------------------------------------------------------------------
/bbp/kernel/paging.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Memory paging functions
4 | =======================
5 |
6 | License (BSD-3)
7 | ===============
8 |
9 | Copyright (c) 2012, Gusts 'gusC' Kaksis
10 | All rights reserved.
11 |
12 | Redistribution and use in source and binary forms, with or without
13 | modification, are permitted provided that the following conditions are met:
14 | * Redistributions of source code must retain the above copyright
15 | notice, this list of conditions and the following disclaimer.
16 | * Redistributions in binary form must reproduce the above copyright
17 | notice, this list of conditions and the following disclaimer in the
18 | documentation and/or other materials provided with the distribution.
19 | * Neither the name of the nor the
20 | names of its contributors may be used to endorse or promote products
21 | derived from this software without specific prior written permission.
22 |
23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
27 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 |
34 | */
35 |
36 | #ifndef __paging_h
37 | #define __paging_h
38 |
39 | #include "common.h"
40 |
41 | typedef union {
42 | struct {
43 | uint64 present : 1; // Is the page present in memory?
44 | uint64 writable : 1; // Is the page writable?
45 | uint64 user : 1; // Is the page for userspace?
46 | uint64 write_through : 1; // Do we want write-trough? (when cached, this also writes to memory)
47 | uint64 cache_disable : 1; // Disable cache on this page?
48 | uint64 accessed : 1; // Has the page been accessed by software?
49 | uint64 dirty : 1; // Has the page been written to since last refresh?
50 | uint64 pat : 1; // Is the page a PAT? (dunno what it is)
51 | uint64 global : 1; // Is the page global? (dunno what it is)
52 | uint64 data : 3; // Available for kernel use (do what you want?)
53 | uint64 frame : 52; // Frame address (shifted right 12 bits)
54 | } s;
55 | uint64 raw; // Raw value
56 | } pm_t;
57 |
58 | typedef union {
59 | struct {
60 | uint64 offset : 12; // Offset from the begining of page
61 | uint64 page_idx : 9; // Page index (in pml1)
62 | uint64 table_idx : 9; // Table index (in pml2)
63 | uint64 directory_idx : 9; // Directory index (in pml3)
64 | uint64 drawer_idx : 9; // Drawer index (in pml4)
65 | uint64 canonical : 16; // Should be FFF... if drawer_idx 9th bit is 1 (see: canonical address)
66 | } s;
67 | uint64 raw;
68 | } vaddr_t;
69 |
70 | #define PAGE_MASK 0xFFFFFFFFFFFFF000
71 | #define PAGE_IMASK 0x0000000000000FFF // Inverse mask
72 |
73 | /**
74 | * Initialize paging
75 | */
76 | void page_init();
77 | /**
78 | * Get total installed RAM
79 | * @return RAM size in bytes
80 | */
81 | uint64 page_total_mem();
82 | /**
83 | * Get total available RAM
84 | * @return RAM size in bytes
85 | */
86 | uint64 page_available_mem();
87 | /**
88 | * Normalize virtual address to canonical form
89 | * Usefull when converting from 32bit addresses to 64bit
90 | * @param vaddr - virtual address to normalize
91 | * @return normalized virtual address
92 | */
93 | uint64 page_normalize_vaddr(uint64 vaddr);
94 | /**
95 | * Identity map a physical address
96 | * @param paddr - physical address to map
97 | * @return virtual address
98 | */
99 | uint64 page_map(uint64 paddr);
100 | /**
101 | * Identity map a physical address for memory maped IO (no cache!)
102 | * @param paddr - physical address to map
103 | * @return virtual address
104 | */
105 | uint64 page_map_mmio(uint64 paddr);
106 | /**
107 | * Resolve physical address from virtual addres
108 | * @param vaddr - virtual address to resolve
109 | * @return physical address
110 | */
111 | uint64 page_resolve(uint64 vaddr);
112 |
113 | /**
114 | * Get the PMLx entry from virtual address
115 | * @param vaddr - virtual address
116 | * @param level - zero based level (0-3 for PML4 paging)
117 | * @return PMLx entry
118 | */
119 | pm_t page_get_pml_entry(uint64 vaddr, uint8 level);
120 | /**
121 | * Set the PML4 entry for virtual address
122 | * @param vaddr - virtual address
123 | * @param level - zero based level (0-3 for PML4 paging)
124 | * @param pe - PML4 entry
125 | */
126 | void page_set_pml_entry(uint64 vaddr, uint8 level, pm_t pe);
127 |
128 | #endif /* __paging_h */
--------------------------------------------------------------------------------
/bbp/kernel/pci.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Helper functions for PCI operations
4 | ===================================
5 |
6 |
7 | License (BSD-3)
8 | ===============
9 |
10 | Copyright (c) 2012, Gusts 'gusC' Kaksis
11 | All rights reserved.
12 |
13 | Redistribution and use in source and binary forms, with or without
14 | modification, are permitted provided that the following conditions are met:
15 | * Redistributions of source code must retain the above copyright
16 | notice, this list of conditions and the following disclaimer.
17 | * Redistributions in binary form must reproduce the above copyright
18 | notice, this list of conditions and the following disclaimer in the
19 | documentation and/or other materials provided with the distribution.
20 | * Neither the name of the nor the
21 | names of its contributors may be used to endorse or promote products
22 | derived from this software without specific prior written permission.
23 |
24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 |
35 | */
36 |
37 | #include "../config.h"
38 | #include "lib.h"
39 | #include "io.h"
40 | #include "pci.h"
41 | #if DEBUG == 1
42 | #include "debug_print.h"
43 | #endif
44 |
45 | /**
46 | * Local PCI cache strucure
47 | * used to ease device lookup on run-time
48 | */
49 | typedef struct {
50 | pci_addr_t address;
51 | uint16 vendor_id;
52 | uint16 device_id;
53 | uint8 class_id;
54 | uint8 subclass_id;
55 | uint8 prog_if;
56 | uint8 type;
57 | } pci_cache_t;
58 |
59 | /*
60 | static uint32 pci_get_addr(uint16 bus, uint8 device, uint8 function, uint8 reg){
61 | uint32 addr = 0x80000000;
62 | addr |= ((uint32)bus) << 16;
63 | addr |= (((uint32)device) & 0x1F) << 11;
64 | addr |= (((uint32)function) & 0x7) << 8;
65 | addr |= (uint32)(reg & 0xfc);
66 | return addr;
67 | }
68 | */
69 |
70 | // Local PCI device cache
71 | static pci_cache_t _cache[256];
72 | static uint8 _cache_len = 0;
73 |
74 | /**
75 | * Enumerate a single PCI bus
76 | * @param bus - bus number
77 | */
78 | static void pci_enum_bus(uint16 bus);
79 | /**
80 | * Enumerate a single PCI device on a bus
81 | * @param bus - bus number
82 | * @param device - device number
83 | */
84 | static void pci_enum_device(uint16 bus, uint8 device);
85 | /**
86 | * Enumeration PCI device functions
87 | * @param bus - bus number
88 | * @param device - device number
89 | */
90 | static void pci_enum_function(uint16 bus, uint8 device, uint8 function);
91 | /**
92 | * Get secondary bus number from PCI-to-PCI bridge
93 | */
94 | static uint16 pci_get_secondary_bus(uint16 bus, uint8 device, uint8 function){
95 | uint32 secondary_bus = 0;
96 | pci_addr_t addr;
97 | if (bus < 256 && device < 32 && function < 8){
98 | addr.raw = 0;
99 | addr.s.enabled = 1;
100 | addr.s.bus = bus;
101 | addr.s.device = device;
102 | addr.s.function = function;
103 | addr.s.reg = 6;
104 | secondary_bus = pci_read(addr);
105 | return (uint16)((secondary_bus >> 8) & 0xFF);
106 | }
107 | return bus;
108 | }
109 |
110 | void pci_init(){
111 | uint16 bus = 0;
112 | pci_header_t header;
113 | pci_addr_t addr;
114 | addr.raw = 0x80000000;
115 | // Recursive scan - thanks OSDev Wiki
116 | pci_get_header(&header, addr);
117 | if ((header.type & 0x80) != 0){
118 | // Multiple PCI host controllers
119 | for (bus = 0; bus < 8; bus ++){
120 | addr.s.bus = bus;
121 | pci_get_header(&header, addr);
122 | if (header.vendor_id != 0xFFFF){
123 | // Valid PCI host controller
124 | pci_enum_bus(bus);
125 | }
126 | }
127 | } else {
128 | // Single PCI host controller
129 | pci_enum_bus(0);
130 | }
131 | }
132 |
133 | uint8 pci_num_device(uint8 class_id, uint8 subclass_id){
134 | uint16 i = 0;
135 | uint8 x = 0;
136 | for (i = 0; i < _cache_len; i ++){
137 | if (_cache[i].class_id == class_id && _cache[i].subclass_id == subclass_id){
138 | x ++;
139 | }
140 | }
141 | return x;
142 | }
143 |
144 | pci_addr_t pci_get_device(uint8 class_id, uint8 subclass_id, uint8 idx){
145 | uint16 i = 0;
146 | uint8 x = 0;
147 | pci_addr_t addr_none;
148 | addr_none.raw = 0;
149 | for (i = 0; i < _cache_len; i ++){
150 | if (_cache[i].class_id == class_id && _cache[i].subclass_id == subclass_id){
151 | if (x == idx){
152 | return _cache[i].address;
153 | }
154 | x ++;
155 | }
156 | }
157 | return addr_none;
158 | }
159 |
160 | void pci_get_header(pci_header_t *header,pci_addr_t addr){
161 | uint32 *rows = (uint32 *)header;
162 | uint8 row;
163 | for (row = 0; row < 4; row ++){
164 | addr.s.reg = row;
165 | rows[row] = pci_read(addr);
166 | }
167 | }
168 |
169 | void pci_get_config(pci_device_t *device, pci_addr_t addr){
170 | uint32 *rows = (uint32 *)device;
171 | uint8 row;
172 | for (row = 0; row < 16; row ++){
173 | addr.s.reg = row;
174 | rows[row] = pci_read(addr);
175 | }
176 | }
177 |
178 | uint32 pci_read(pci_addr_t addr){
179 | uint32 data;
180 | outd(PCI_CONFIG_ADDRESS, addr.raw);
181 | data = ind(PCI_CONFIG_DATA);
182 | return data;
183 | }
184 |
185 | void pci_write(pci_addr_t addr, uint32 data){
186 | outd(PCI_CONFIG_ADDRESS, addr.raw);
187 | outd(PCI_CONFIG_DATA, data);
188 | }
189 |
190 | /*uint32 pci_read(uint32 addr){
191 | uint32 data;
192 | asm volatile ("outl %%eax, %%dx" : : "d"(PCI_CONFIG_ADDRESS), "a"(addr));
193 | asm volatile("inl %%dx, %%eax" : "=a"(data) : "d"(PCI_CONFIG_DATA));
194 | return data;
195 | }
196 |
197 | void pci_write(uint32 addr, uint32 data){
198 | asm volatile ("outl %%eax, %%dx" : : "d"(PCI_CONFIG_ADDRESS), "a"(addr));
199 | asm volatile ("outl %%eax, %%dx" : : "d"(PCI_CONFIG_DATA), "a"(data));
200 | }*/
201 |
202 | static void pci_enum_bus(uint16 bus){
203 | uint8 device = 0;
204 | for (; device < 32; device ++){
205 | pci_enum_device(bus, device);
206 | }
207 | }
208 |
209 | static void pci_enum_device(uint16 bus, uint8 device){
210 | uint8 function = 0;
211 | pci_header_t header;
212 | pci_addr_t addr;
213 | addr.raw = 0x80000000;
214 | addr.s.bus = bus;
215 | addr.s.device = device;
216 | addr.s.function = 0;
217 | pci_get_header(&header, addr);
218 | if (header.vendor_id != 0xFFFF){
219 | if ((header.type & 0x80) != 0){
220 | // Multifunctional device
221 | for (function = 1; function < 8; function ++){
222 | pci_enum_function(bus, device, function);
223 | }
224 | } else {
225 | // Single function device
226 | pci_enum_function(bus, device, 0);
227 | }
228 | }
229 | }
230 |
231 | static void pci_enum_function(uint16 bus, uint8 device, uint8 function){
232 | uint16 secondary_bus = 0;
233 | pci_header_t header;
234 | pci_addr_t addr;
235 | addr.raw = 0x80000000;
236 | addr.s.bus = bus;
237 | addr.s.device = device;
238 | addr.s.function = function;
239 | pci_get_header(&header, addr);
240 | if (header.vendor_id != 0xFFFF){
241 | _cache[_cache_len].address.raw = addr.raw;
242 | _cache[_cache_len].class_id = header.class_id;
243 | _cache[_cache_len].subclass_id = header.subclass_id;
244 | _cache[_cache_len].prog_if = header.prog_if;
245 | _cache[_cache_len].type = header.type;
246 | _cache[_cache_len].vendor_id = header.vendor_id;
247 | _cache[_cache_len].device_id = header.device_id;
248 | _cache_len ++;
249 | if (header.class_id == 0x06 && header.subclass_id == 0x04){
250 | secondary_bus = pci_get_secondary_bus(bus, device, function);
251 | if (secondary_bus != bus){
252 | pci_enum_bus(secondary_bus);
253 | }
254 | }
255 | }
256 | }
257 |
258 | #if DEBUG == 1
259 | void pci_list(){
260 | uint16 i = 0;
261 | for (; i < _cache_len; i ++){
262 | debug_print(DC_BW, "pci:%u:%u:%u, class:0x%x:0x%x, vendor:0x%x:0x%x", (uint64)_cache[i].address.s.bus, (uint64)_cache[i].address.s.device, (uint64)_cache[i].address.s.function, (uint64)_cache[i].class_id, (uint64)_cache[i].subclass_id, (uint64)_cache[i].vendor_id, (uint64)_cache[i].device_id);
263 | }
264 | }
265 | #endif
--------------------------------------------------------------------------------
/bbp/kernel/pci.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Helper functions for PCI operations
4 | ===================================
5 |
6 |
7 | License (BSD-3)
8 | ===============
9 |
10 | Copyright (c) 2012, Gusts 'gusC' Kaksis
11 | All rights reserved.
12 |
13 | Redistribution and use in source and binary forms, with or without
14 | modification, are permitted provided that the following conditions are met:
15 | * Redistributions of source code must retain the above copyright
16 | notice, this list of conditions and the following disclaimer.
17 | * Redistributions in binary form must reproduce the above copyright
18 | notice, this list of conditions and the following disclaimer in the
19 | documentation and/or other materials provided with the distribution.
20 | * Neither the name of the nor the
21 | names of its contributors may be used to endorse or promote products
22 | derived from this software without specific prior written permission.
23 |
24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 |
35 | */
36 |
37 | #ifndef __pci_h
38 | #define __pci_h
39 |
40 | #include "common.h"
41 | #include "../config.h"
42 |
43 | #define PCI_CONFIG_ADDRESS 0x0CF8
44 | #define PCI_CONFIG_DATA 0x0CFC
45 |
46 | #define PCI_REG_DEVID_VNDID 0x0
47 | #define PCI_REG_STATUS_CMD 0x4
48 | #define PCI_REG_CLS_PRG_REV 0x8
49 | #define PCI_REG_BIST_TYPE 0xC
50 |
51 | /**
52 | * PCI address structure
53 | */
54 | typedef union {
55 | struct {
56 | uint32 empty : 2; // Always 0
57 | uint32 reg : 6; // Register number
58 | uint32 function : 3; // Function number
59 | uint32 device : 5; // Device number
60 | uint32 bus : 8; // Bus number
61 | uint32 reserved : 7; // Reserved
62 | uint32 enabled : 1; // Enabled bit
63 | } s;
64 | uint32 raw;
65 | } pci_addr_t;
66 | /**
67 | * PCI configuration space header structure
68 | */
69 | typedef volatile struct {
70 | uint16 vendor_id;
71 | uint16 device_id;
72 | uint16 command;
73 | uint16 status;
74 | uint8 revision_id;
75 | uint8 prog_if;
76 | uint8 subclass_id;
77 | uint8 class_id;
78 | uint8 cache_line_size;
79 | uint8 latency_timer;
80 | uint8 type;
81 | uint8 bist;
82 | } pci_header_t;
83 | /**
84 | * Standard PCI device configuration space structure
85 | */
86 | typedef volatile struct {
87 | pci_header_t header;
88 | uint32 bar[6];
89 | uint32 cis_ptr;
90 | uint16 sub_vendor_id;
91 | uint16 subsystem_id;
92 | uint32 exp_rom;
93 | uint8 compat;
94 | uint8 reserved[7];
95 | uint8 int_line;
96 | uint8 int_pin;
97 | uint8 min_grant;
98 | uint8 max_latency;
99 | } pci_device_t;
100 |
101 | /**
102 | * Enumerate PCI bus
103 | */
104 | void pci_init();
105 | /**
106 | * Get the number of devices represented by a class and subclass
107 | * @param class_id - class code
108 | * @param subclass_id - sub-class
109 | * @return number of devices found
110 | */
111 | uint8 pci_num_device(uint8 class_id, uint8 subclass_id);
112 | /**
113 | * Locate PCI device by class and subclass
114 | * @param class_id - class code
115 | * @param subclass_id - sub-class
116 | * @param idx - device index (@see pci_num_device)
117 | * @return PCI address (check if it's not 0!)
118 | */
119 | pci_addr_t pci_get_device(uint8 class_id, uint8 subclass_id, uint8 idx);
120 | /**
121 | * Read PCI device header
122 | * @param header - a pointer to header structure that needs to be filled
123 | * @param addr - PCI address
124 | */
125 | void pci_get_header(pci_header_t *header, pci_addr_t addr);
126 | /**
127 | * Read PCI device configuration structure
128 | * @param device - a pointer to configuration structure that needs to be filled
129 | * @param addr - PCI address
130 | */
131 | void pci_get_config(pci_device_t *device, pci_addr_t addr);
132 | /**
133 | * Read from PCI bus/device
134 | * @param addr - PCI address
135 | * @return register value
136 | */
137 | uint32 pci_read(pci_addr_t addr);
138 | /**
139 | * Write to PCI bus/device
140 | * @param addr - PCI address
141 | * @param data - data to write
142 | */
143 | void pci_write(pci_addr_t addr, uint32 data);
144 |
145 |
146 | #if DEBUG == 1
147 | /**
148 | * List available PCI devices on screen
149 | */
150 | void pci_list();
151 | #endif
152 |
153 |
154 | #endif /* __pci_h */
--------------------------------------------------------------------------------
/bbp/makefile:
--------------------------------------------------------------------------------
1 | AS = nasm -felf64 -O0
2 | LD = x86_64-pc-elf-ld -melf_x86_64
3 | OBJECTS = boot.o kernel.o
4 |
5 | all: $(OBJECTS)
6 | $(LD) -T bbp.ld $(OBJECTS) -o ../Release/bbp.img
7 |
8 | boot.o:
9 | make -C boot/
10 |
11 | kernel.o:
12 | make -C kernel/
13 |
14 | %.s.o: %.asm
15 | $(AS) -o $@ $<
16 |
17 | clean:
18 | rm -f *.o boot/*.o kernel/*.o ../Release/bbp.img ../Release/disk.img
--------------------------------------------------------------------------------
/bochsrc.bxrc:
--------------------------------------------------------------------------------
1 | #
2 | # MBR2GPT test environment
3 | #
4 |
5 | # CPU
6 | cpu: count=1:2:1, ips=9000000, quantum=16, model=core2_penryn_t9600, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0
7 |
8 | # RAM
9 | memory: host=256, guest=256
10 |
11 | # ROM images
12 | romimage: file="C:\Bochs-2.6\BIOS-bochs-latest"
13 | vgaromimage: file="C:\Bochs-2.6\VGABIOS-lgpl-latest"
14 |
15 | # Boot
16 | boot: disk
17 | floppy_bootsig_check: disabled=0
18 |
19 | # Storage
20 | ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
21 | ata0-master: type=disk, mode=flat, translation=auto, path="Release\disk.img", cylinders=10, heads=16, spt=63, biosdetect=auto, model="Generic 1234"
22 | ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
23 | ata2: enabled=0
24 | ata3: enabled=0
25 |
26 | # IO
27 | pci: enabled=1, chipset=i440fx
28 | parport1: enabled=1, file=""
29 | parport2: enabled=0
30 | com1: enabled=1, mode=null, dev=""
31 | com2: enabled=0
32 | com3: enabled=0
33 | com4: enabled=0
34 |
35 | # Video
36 | display_library: win32
37 | vga: extension=vbe, update_freq=5
38 | private_colormap: enabled=0
39 |
40 | # Bochs
41 | plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1, gameport=1
42 | config_interface: win32config
43 | print_timestamps: enabled=0
44 | port_e9_hack: enabled=0
45 | clock: sync=none, time0=local, rtc_sync=0
46 |
47 | # HID
48 | keyboard: type=mf, serial_delay=250, paste_delay=100000, keymap=
49 | user_shortcut: keys=none
50 | mouse: enabled=0, type=ps2, toggle=ctrl+mbutton
51 |
52 | # Logging
53 | log: bochsout.txt
54 | logprefix: %t%e%d
55 | panic: action=ask
56 | error: action=report
57 | info: action=report
58 | debug: action=ignore
59 |
--------------------------------------------------------------------------------
/bochsrc_debug.bxrc:
--------------------------------------------------------------------------------
1 | #
2 | # MBR2GPT debug environment
3 | #
4 |
5 | # CPU
6 | cpu: count=1:2:1, ips=9000000, quantum=16, model=core2_penryn_t9600, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0
7 |
8 | # RAM
9 | memory: host=256, guest=256
10 |
11 | # ROM images
12 | romimage: file="C:\Bochs-2.6\BIOS-bochs-latest"
13 | vgaromimage: file="C:\Bochs-2.6\VGABIOS-lgpl-latest"
14 |
15 | # Boot
16 | boot: disk
17 | floppy_bootsig_check: disabled=0
18 |
19 | # Storage
20 | ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
21 | ata0-master: type=disk, mode=flat, translation=auto, path="Release\disk.img", cylinders=10, heads=16, spt=63, biosdetect=auto, model="Generic 1234"
22 | ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
23 | ata2: enabled=0
24 | ata3: enabled=0
25 |
26 | # IO
27 | pci: enabled=1, chipset=i440fx
28 | parport1: enabled=1, file=""
29 | parport2: enabled=0
30 | com1: enabled=1, mode=null, dev=""
31 | com2: enabled=0
32 | com3: enabled=0
33 | com4: enabled=0
34 |
35 | # Video
36 | display_library: win32, options="gui_debug"
37 | vga: extension=vbe, update_freq=5
38 | private_colormap: enabled=0
39 |
40 | # Bochs
41 | magic_break: enabled=1
42 | plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1, gameport=1
43 | config_interface: win32config
44 | print_timestamps: enabled=0
45 | port_e9_hack: enabled=0
46 | clock: sync=none, time0=local, rtc_sync=0
47 |
48 | # HID
49 | keyboard: type=mf, serial_delay=250, paste_delay=100000, keymap=
50 | user_shortcut: keys=none
51 | mouse: enabled=0, type=ps2, toggle=ctrl+mbutton
52 |
53 | # Logging
54 | log: bochsout.txt
55 | logprefix: %t%e%d
56 | panic: action=ask
57 | error: action=report
58 | info: action=report
59 | debug: action=ignore
60 |
--------------------------------------------------------------------------------
/mbr/README.md:
--------------------------------------------------------------------------------
1 | Master Boot Record
2 | ==================
3 |
4 | This is the MBR bootcode that read GPT headers and partition array and loads first 512KiB of BIOS Boot Partition bootcode
5 |
6 | File list
7 | ---------
8 |
9 | * main.asm - main MBR code
10 | * main.inc - data structure definitions and memory location definitions
11 | * mbr.vcxproj - Visual Studio 2010 project file
12 |
13 | Requirements
14 | ------------
15 |
16 | * Netwide Assembler from: http://www.nasm.us/
17 | * Microsoft Visual Studio Express 2010
18 |
--------------------------------------------------------------------------------
/mbr/main.asm:
--------------------------------------------------------------------------------
1 | ; Program flow:
2 | ; 1. we are loaded at 0x7C00
3 | ; 2. init and store drive ID
4 | ; 3. do a check on MBR parition table for GPT protective record
5 | ; 4. do a check for LBA capabilities (extended read/write)
6 | ; 5. read GPT header
7 | ; 6. do a check on GPT signature
8 | ; 7. do a check on GPT partition count (should be more than or equal to 1)
9 | ; 8. read first 4 entries from GPT partition array
10 | ; 9. do a check on each partition entry for GUID of BBP
11 | ; 10. store BBP partition's start LBA
12 | ; 10. calculate and store BBP partition's lenght
13 | ; 11. relocate rest of the MBR (just the part that loads data from BBP) to 0x0700
14 | ; 12. read BBP from the disk and store in memory starting at 0x7C00
15 | ; 13. jump to BBP (0x7C00)
16 | ;
17 | ; memory map at the start:
18 | ; 0x0600 - 0x7BFF - free
19 | ; 0x7C00 - 0x7DFF - MBR loaded by BIOS
20 | ; 0x7E00 - 0x0007FFFF - free
21 | ;
22 | ; memory map before the jump to BBP:
23 | ; 0x0600 - Disk address packet (DAP) location (2x qword)
24 | ; 0x0660 - Local data (disk ID, bbp size, etc.) location (2x dword)
25 | ; 0x0700 - MBR bootstrap after relocation (curently it looks like just 16 bytes)
26 | ; 0x0800 - Read buffer location (512 bytes usually)
27 | ; 0x7C00 - Stack pointer
28 | ; 0x7C00 - ??? - Bootloader code loaded by MBR bootstrap (we need atleas 512KiB or 1024 sectors)
29 |
30 | %include "main.inc" ; Include data structures and memory location constants
31 |
32 | ; Remember in NASM it's:
33 | ; instruction destination, source
34 |
35 | [org ORG_LOC] ; set origin at 0x7C00
36 | [bits 16] ; tell NASM that we are working in 16bit environment
37 | jmp 0x0000:start
38 |
39 | start: ; Start MBR procedures
40 | xor eax, eax ; clear eax (is this some kind of asm developers way of seting value to 0? why can't we use
41 | ; mov ax, word 0x0000 instead? is this faster or cleaner?)
42 | mov ss, ax ; set stack segment to zero (is it, i'm dumb in assembly?)
43 | mov sp, ORG_LOC ; set stack pointer to the begining of MBR location in memory
44 | mov es, ax ; zero-out extra segment
45 | mov ds, ax ; zero-out data segment
46 | .setup_data:
47 | mov [DATA(drive_id)], dl ; store drive ID into memory
48 | .setup_dap:
49 | mov [DAP(size)], byte 0x10 ; set packet size
50 | mov [DAP(reserved)], byte 0x00 ; set reserved byte
51 | mov [DAP(lba_count)], word 0x0001 ; set number of blocks to transfer
52 | mov [DAP(dest_buff)], dword BUFF_LOC ; set read buffer position in memory
53 | mov [DAP(lba_start_l)], dword 0x0 ; clear start LBA low dword
54 | mov [DAP(lba_start_h)], dword 0x0 ; clear start LBA high dword
55 |
56 | test_mem: ; Get available lower memory ammount
57 | int 0x12 ; call memory interrupt
58 | jc $ ; hang if interrupt call failed
59 | test ax, ax ; check if memory is more than 0 (weird instruction - got to wrap my head around this)
60 | jz $ ; hang if ax is 0 (right?)
61 | sub ax, 0x001F ; 0x7C00 / 1024 = 0x001F
62 | ; we need to know if we have a region between 0x7C00 and 0xA0000 which is at least 512KiB
63 | cmp ax, 0x0200 ; test weather it's enough
64 | jl $ ; hang if not enough memory
65 |
66 | test_mbr_part: ; Test weather we are a protective MBR, we certanly don't want to be a hybrid MBR
67 | cmp [MBR(type)], byte 0xEE ; check weather we have GPT partitioning (0xEE - GPT protective partition)
68 | jne $ ; hang if not a protective partition
69 |
70 | test_ext: ; Check if drive supports extended read
71 | mov ah, 0x41 ; command - check for extensions
72 | mov bx, 0x55AA ; some magic test value
73 | mov dl, [DATA(drive_id)] ; set drive ID
74 | int 0x13 ; call disk interrupt
75 | jc $ ; hang if extensions are not supported
76 | cmp bx, 0xAA55 ; extra test for return value from extension test
77 | jne $ ; hang if the return value is not the one we expected
78 |
79 | reset_disk: ; Reset current disk
80 | mov ah, 0x00 ; command - reset disk
81 | mov dl, [DATA(drive_id)] ; set drive ID
82 | int 0x13 ; call disk interrupt
83 | jc $ ; hang if reset failed
84 |
85 | read_gpt: ; Read GPT header
86 | mov [DAP(lba_count)], word 0x0001 ; set number of blocks to transfer
87 | mov [DAP(lba_start_l)], dword 0x00000001 ; set start block address (low dword, 2nd block)
88 | mov ah, 0x42 ; command - extended read
89 | mov dl, [DATA(drive_id)] ; set drive ID
90 | mov si, DAP_LOC ; set DAP location
91 | int 0x13 ; call disk interrupt
92 | jc $ ; hang if disk read failed
93 |
94 | test_gpt: ; Parse GPT signature (should be "EFI PART" - look up ASCII yourself)
95 | cmp dword [GPT(signature)], 0x20494645 ; should be "EFI " (or " IFE" in little-endian order)
96 | jne $ ; hang - not even close
97 | cmp dword [GPT(signature) + 4], 0x54524150 ; should be "PART" (or "TRAP", pun intended?)
98 | jne $ ; hang - not quite there
99 |
100 | read_part_arr: ; Read Partition array
101 | mov [DAP(lba_start_l)], dword 0x00000002 ; set start block address (low dword, 3d block)
102 | mov ah, 0x42 ; command - extended read
103 | mov dl, [DATA(drive_id)] ; set drive ID
104 | mov si, DAP_LOC ; set DAP location
105 | int 0x13 ; call disk interrupt
106 | jc $ ; hang if disk read failed
107 | mov word cx, 0x0004 ; we only read first 4 partitions
108 |
109 | test_part: ; Read GPT partition entries to find if it's BBP (BIOS Boot Partition)
110 | ; we only accept first partition to be BIOS bootable
111 | mov ax, word 0x0004 ; set AX to 4 (we need it to calculate partition number)
112 | sub ax, cx ; subtract current step from AX (thus partition number is 4-4=0, 4-3=1, etc)
113 | mov dx, word 0x0080 ; set DX to 128 bytes (partition entry size)
114 | mul dx ; multiply our result in AX to get the offset
115 | mov bx, ax ; store offset in BX (I think it's base offset register, is it?)
116 | ; and we test it, and it's uggly (GUID and little-endianness I mean)
117 | cmp dword [PART(part_guid) + bx], 0x21686148
118 | jne test_next ; stop, you're no BBP
119 | cmp dword [PART(part_guid) + bx + 4], 0x6E6F6449
120 | jne test_next ; nice try
121 | cmp dword [PART(part_guid) + bx + 8], 0x65654E74
122 | jne test_next ; yeah, almost got me
123 | cmp dword [PART(part_guid) + bx + 12], 0x49464564
124 | jne test_next ; sooo close
125 | jmp prepare_copy ; found it!
126 |
127 | test_next:
128 | dec cx ; one step back means one step forward in partition entry array
129 | cmp cx, word 0x0000 ; check if we're not at the end of our 4 entry array
130 | jg test_part ; try our luck on the next one
131 | jmp $ ; hang - no BBPs found
132 |
133 | prepare_copy: ; Prepare our BBP copy
134 | mov [DAP(dest_buff)], dword BOOT_LOC ; set read buffer position in memory
135 | mov [DAP(lba_count)], word 0x0040 ; copy 64 sectors at a time
136 | .test_start_lba:
137 | cmp dword [PART(lba_start_h) + bx], 0x0 ; test if the start LBA is on the near side of disk
138 | jne $ ; hang if BBP is out of bounds
139 | .test_end_lba:
140 | cmp dword [PART(lba_end_h) + bx], 0x0 ; test if the end LBA is on the near side of disk
141 | jne $ ; hang if BBP is out of bounds
142 | .cont_prep:
143 | mov eax, dword [PART(lba_end_l) + bx] ; store low dword of end LBA
144 | sub eax, dword [PART(lba_start_l) + bx] ; subtract low dword of start LBA
145 | mov [DATA(bbp_size)], eax ; store sector count in memory
146 | mov eax, dword [PART(lba_start_l) + bx] ; get the low dword of start LBA
147 | mov [DAP(lba_start_l)], eax ; store it into DAP package
148 | mov eax, dword [PART(lba_start_h) + bx] ; get the high dword of start LBA
149 | mov [DAP(lba_start_h)], eax ; store it into DAP package
150 |
151 | mbr_relocate: ; Reallocate us in memory, so that we have more contiguous area where to put
152 | ; our bootloader
153 | mov si, bootstrap_start ; set source index (we only need the part from read_boot, rest is already a history)
154 | mov di, RELOC_LOC ; set destination index (where to put our MBR)
155 | mov cx, (bootstrap_end - bootstrap_start) ; how many blocks to copy (only from read_boot till padding)
156 |
157 | cld ; clear direction flag for copy
158 | rep ; repeat the copy cx times
159 | movsb ; move single byte
160 | jmp RELOC_LOC ; jump to relocated location
161 |
162 | bootstrap_start: ; Read bootable partition
163 | xor eax, eax ; clear eax
164 | xor ebx, ebx ; clear ebx
165 | xor ecx, ecx ; clear ecx
166 | mov eax, dword [DATA(bbp_size)] ; copy boot partition sector count
167 | cmp eax, 0x0400 ; test if not bigger than 1024 sectors (512 KiB)
168 | jle .prep_copy_loop ; continiue if less or equal
169 | mov eax, 0x0400 ; limit to 1024 sectors only
170 | .prep_copy_loop:
171 | mov bx, 0x0040 ; 64 sectors per iteration (32 KiB)
172 | div bx ; calculate iteration count
173 | mov cx, ax ; set iteration count
174 | .copy_block:
175 | mov ah, 0x42 ; command - extended read
176 | mov dl, [DATA(drive_id)] ; set drive ID
177 | mov si, DAP_LOC ; set DAP location
178 | int 0x13 ; call disk interrupt
179 | jc $ ; halt on error
180 | dec cx ; decrement cx for the next iteration
181 | cmp cx, 0x0 ; test if not the final iteration
182 | je .end ; last iteration - pass control over to BBP code
183 | mov eax, [DAP(dest_buff)] ; get current buffer position
184 | add eax, 0x8000000 ; move forward by 32 KiB (just increment the f*ing segments - ugly)
185 | mov [DAP(dest_buff)], eax ; set current buffer position
186 | jmp .copy_block ; next pass
187 | .end:
188 | jmp 0x0000:BOOT_LOC ; pass control over to BBP code
189 | bootstrap_end:
190 |
191 | padding: ; Zerofill up to 440 bytes
192 | times 0x01B8 - ($ - $$) db 0
193 |
194 | ; This is needed so we don't overwrite partition table with our assembly code
195 | part_table:
196 | times 0x0200 - 2 - ($ - $$) db 0
197 |
198 | magic: ; Add "magic number"
199 | dw 0xAA55 ; Magic number - boot sector signature
200 |
--------------------------------------------------------------------------------
/mbr/main.inc:
--------------------------------------------------------------------------------
1 | ; Code location constants
2 | %define ORG_LOC 0x7C00 ; Initial MBR position in memory (where BIOS loads it)
3 | %define RELOC_LOC 0x0800 ; Relocation position (where we will copy neccessary MBR code to chainload bootloader)
4 | %define BUFF_LOC 0x0800 ; Location of read buffer in memory
5 | %define BOOT_LOC 0x7C00 ; Location of BBP bootcode
6 |
7 | ; Local data structure
8 | struc tDATA
9 | .drive_id resb 1 ; drive ID
10 | ._pad resb 3 ; dummy padding
11 | .bbp_size resd 1 ; BBP sector count
12 | endstruc
13 | %define DATA_LOC 0x0660 ; Location of our global data structure in memory
14 | %define DATA(x) DATA_LOC + tDATA. %+ x ; Helper macro to clean up the code a bit
15 |
16 | ; MBR Partition entry structure
17 | struc tMBRPart
18 | .status resb 1 ; Partition status (0x80 if bootable, 0x00 otherwise)
19 | .chs_start resb 3 ; Start of partition as a CHS value (we're not going to use this)
20 | .type resb 1 ; Partition type (we're looking for 0xEE)
21 | .chs_end resb 3 ; End of partition as a CHS value
22 | .lba_start resd 1 ; Start of partition as a LBA value
23 | .lba_length resd 1 ; Size of partition - number of sectors
24 | endstruc
25 | %define MBR_LOC 0x7DBE ; Partition table start
26 | %define MBR(x) MBR_LOC + tMBRPart. %+ x ; Helper macro to clean up the code a bit
27 |
28 | ; DAP structure for extended read
29 | struc tDAP
30 | .size resb 1 ; Packet size
31 | .reserved resb 1 ; Reserved - should be 0
32 | .lba_count resw 1 ; Number of sectors to transfer
33 | .dest_buff resd 1 ; Desination buffer where to transfer data
34 | .lba_start_l resd 1 ; Low dword of start LBA
35 | .lba_start_h resd 1 ; High dword of start LBA
36 | endstruc
37 | %define DAP_LOC 0x0600 ; Location in memory
38 | %define DAP(x) DAP_LOC + tDAP. %+ x ; Helper macro to clean up the code a bit
39 |
40 | ; GPT Header
41 | struc tGPTHead
42 | .signature resd 2 ; EFI PART signature
43 | .version resd 1 ; Version number
44 | .header_size resd 1 ; Size of a header (should be 92)
45 | .header_crc32 resd 1 ; CRC32 of first 3 entries
46 | .reserved resd 1 ; Should be 0
47 | .lba_curr resd 2 ; Current address of GPT header
48 | .lba_backup resd 2 ; Address of backup GPT header
49 | .lba_first resd 2 ; First usable LBA
50 | .lba_last resd 2 ; Last usable LBA
51 | .disk_guid resd 4 ; Disk GUID
52 | .part_arr_lba resd 2 ; LBA adress of partition array
53 | .part_count resd 1 ; Number of entries in partition array
54 | .part_size resd 1 ; Size of partition entry
55 | .part_arr_crc32 resd 1 ; CRC32 of partition array
56 | ; There should be a definition of 420 reserved bytes, bet we don't need them
57 | endstruc
58 | %define GPT(x) BUFF_LOC + tGPTHead. %+ x ; Helper macro to clean up the code a bit
59 |
60 | ; GPT Partition
61 | struc tGPTPart
62 | .part_guid resd 4 ; Partition type GUID
63 | .unique_guid resd 4 ; Unique GUID of partition
64 | .lba_start_l resd 1 ; Start LBA low dword
65 | .lba_start_h resd 1 ; Start LBA high dword
66 | .lba_end_l resd 1 ; End LBA low dword
67 | .lba_end_h resd 1 ; End LBA high dword
68 | .attributes resd 2 ; Partition attributes
69 | .name resw 36 ; UTF-16 partition name
70 | endstruc
71 | %define PART(x) BUFF_LOC + tGPTPart. %+ x ; Helper macro to clean up the code a bit
72 |
--------------------------------------------------------------------------------
/mbr/makefile:
--------------------------------------------------------------------------------
1 | AS = nasm -fbin
2 |
3 | all: mbr.img
4 |
5 | mbr.img: main.asm
6 | $(AS) -o ../Release/mbr.img main.asm
7 |
8 | clean:
9 | rm -f ../Release/mbr.img
--------------------------------------------------------------------------------
/mbr/mbr.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Release
6 | Win32
7 |
8 |
9 |
10 | {FC061F2D-BC1C-4918-8FCD-CD6F0CBDBE36}
11 | mbr
12 | mbr
13 |
14 |
15 |
16 | Makefile
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | C:\MinGW\bin;C:\MinGW\msys\1.0\bin;C:\Program Files\Netwide Assembler
25 | make -C "$(ProjectDir)"
26 | $(NMakeBuildCommandLine)
27 | del "..\Release\mbr.img"
28 |
29 |
30 |
31 |
32 |
33 | mbr.img
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/mbr2gpt.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 11.00
3 | # Visual C++ Express 2010
4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bbp", "bbp\bbp.vcxproj", "{3D779CE6-A610-49F7-AC07-992AEEB4115D}"
5 | ProjectSection(ProjectDependencies) = postProject
6 | {FC061F2D-BC1C-4918-8FCD-CD6F0CBDBE36} = {FC061F2D-BC1C-4918-8FCD-CD6F0CBDBE36}
7 | EndProjectSection
8 | EndProject
9 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mbr", "mbr\mbr.vcxproj", "{FC061F2D-BC1C-4918-8FCD-CD6F0CBDBE36}"
10 | EndProject
11 | Global
12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
13 | Release|Win32 = Release|Win32
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {3D779CE6-A610-49F7-AC07-992AEEB4115D}.Release|Win32.ActiveCfg = Release|Win32
17 | {3D779CE6-A610-49F7-AC07-992AEEB4115D}.Release|Win32.Build.0 = Release|Win32
18 | {FC061F2D-BC1C-4918-8FCD-CD6F0CBDBE36}.Release|Win32.ActiveCfg = Release|Win32
19 | {FC061F2D-BC1C-4918-8FCD-CD6F0CBDBE36}.Release|Win32.Build.0 = Release|Win32
20 | EndGlobalSection
21 | GlobalSection(SolutionProperties) = preSolution
22 | HideSolutionNode = FALSE
23 | EndGlobalSection
24 | EndGlobal
25 |
--------------------------------------------------------------------------------
/run_bochs.bat:
--------------------------------------------------------------------------------
1 | ECHO Starting bochs...
2 | bochs-i7ivy-smp.exe -q -f "%CD%\bochsrc.bxrc"
3 |
--------------------------------------------------------------------------------
/run_bochs_debug.bat:
--------------------------------------------------------------------------------
1 | ECHO Starting bochs...
2 | bochsdbg-i7ivy-smp.exe -q -f "%CD%\bochsrc_debug.bxrc"
3 |
--------------------------------------------------------------------------------
/run_qemu.bat:
--------------------------------------------------------------------------------
1 | ECHO Starting QEmu...
2 |
3 | SET SDL_VIDEODRIVER=windib
4 | SET QEMU_AUDIO_DRV=sdl
5 | SET SDL_AUDIODRIVER=waveout
6 | SET QEMU_AUDIO_LOG_TO_MONITOR=0
7 |
8 | START qemu-system-x86_64w.exe -smp 2 -m 256M -L C:\Qemu\Bios -drive file=Release/disk.img,media=disk,if=none,id=mydisk -device ich9-ahci,id=ahci -device ide-drive,drive=mydisk,bus=ahci.0 -vga std -name MBR2GPT -rtc base=localtime,clock=host -no-reboot
--------------------------------------------------------------------------------