├── .gitignore
├── Makefile
├── README.md
├── core
├── hal
│ ├── Makefile
│ ├── include
│ │ ├── cpu.h
│ │ ├── gdt.h
│ │ ├── idt.h
│ │ └── reg.h
│ ├── libhal.a
│ └── source
│ │ ├── cpu.c
│ │ ├── gdt.c
│ │ ├── hal.c
│ │ └── idt.c
├── include
│ ├── ctype
│ ├── ctype.h
│ ├── hal.h
│ ├── null.h
│ ├── size.h
│ ├── stdarg
│ ├── stdarg.h
│ ├── stdint
│ ├── stdint.h
│ ├── stdio.h
│ ├── string.h
│ └── va_list.h
├── kernel
│ ├── Makefile
│ ├── include
│ │ └── console.h
│ ├── linker.ld
│ ├── loader.s
│ └── source
│ │ ├── console.c
│ │ └── kernel.c
└── lib
│ ├── Makefile
│ ├── libhal.a
│ ├── libstd.a
│ └── source
│ ├── stdio.c
│ └── string.c
├── grub
└── stage2_eltorito
├── initialise.sh
└── screenshots
└── home.png
/.gitignore:
--------------------------------------------------------------------------------
1 | bochs/
2 | compiler/
3 | core/hal/obj
4 | core/kernel/bin
5 | core/kernel/obj
6 | core/lib/obj
7 | experiment/
8 | iso/
9 | theory/
10 | *.iso
11 | *.depend
12 | core/lib/*.a
13 | core/lib/*.so
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # Usefull directories
2 | LIB_DIR = ./core/lib
3 | KER_DIR = ./core/kernel
4 | HAL_DIR = ./core/hal
5 |
6 |
7 | # Output files
8 | KNAME = kernel.bin
9 | KERNEL = $(KER_DIR)/bin/$(KNAME)
10 | ISO = os32.iso
11 |
12 |
13 | # Tools for building
14 | CCOM = compiler/bin/i686-elf-gcc
15 | CPPCOM = compiler/bin/i686-elf-g++
16 | AS = compiler/bin/i686-elf-as
17 |
18 |
19 | # Flags for building tools
20 | CFLAG = -c -std=gnu99 -ffreestanding -O2 -Wall -Wextra -L$(LIB_DIR)
21 | CPPFLAG = -c -ffreestanding -O2 -Wall -Wextra -fno-exceptions -fno-rtti -L$(LIB_DIR)
22 |
23 |
24 | # Libraries used
25 | LIB = -lhal -lstd
26 |
27 |
28 | # Object files
29 | _OBJ = console.o kernel.o loader.o
30 | OBJ = $(_OBJ:%.o=$(KER_DIR)/obj/debug/%.o)
31 |
32 |
33 | # Linker file
34 | LD_FILE = ./core/kernel/linker.ld
35 |
36 |
37 | # Bochs emulator
38 | BOCHS = bochs
39 | BCONFIG = bochsconfig.txt
40 |
41 |
42 | #--------------------------------------------------------------------------
43 | # Linking all object to kernel
44 | $(KERNEL): $(OBJ) $(LIB_DIR)/libhal.a $(LIB_DIR)/libstd.a
45 | $(CCOM) -T $(LD_FILE) -o $(KERNEL) -ffreestanding -O2 -nostdlib $(OBJ) -lgcc -L$(LIB_DIR) $(LIB)
46 |
47 | $(LIB_DIR)/libhal.a: $(HAL_DIR)/libhal.a
48 | cp $(HAL_DIR)/libhal.a $(LIB_DIR)/libhal.a
49 |
50 | #--------------------------------------------------------------------------
51 |
52 | all: hal stdlib kernel $(KERNEL)
53 |
54 | #--------------------------------------------------------------------------
55 | # Building all modules
56 |
57 | # Building kernel
58 | kernel:
59 | cd $(KER_DIR); make depend; make;
60 |
61 |
62 | # Building HAL
63 | hal:
64 | cd $(HAL_DIR); make depend; make;
65 |
66 |
67 | # Building stdlib
68 | stdlib:
69 | cd $(LIB_DIR); make depend; make;
70 |
71 | # Setup directory and dependencies file for first run
72 | configure:
73 | chmod +x initialise.sh
74 | ./initialise.sh
75 | #-------------------------------------------------------------------------
76 |
77 |
78 | # Generating iso image of OS
79 | iso: $(ISO)
80 |
81 |
82 | $(ISO): $(KERNEL)
83 | cp $(KERNEL) iso/boot/$(KNAME)
84 | genisoimage -R -b boot/grub/stage2_eltorito -no-emul-boot -input-charset utf8 -boot-load-size 4 -boot-info-table -o $(ISO) iso
85 |
86 |
87 | # Running OS in bochs emulator
88 | run: $(ISO)
89 | bochs -f $(BOCHS)/$(BCONFIG) -q
90 |
91 | # Delete all object files in Binary folder
92 | clean:
93 | rm $(KERNEL) $(ISO)
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Basic Hybrid Kernel
2 | > Hybrid Kernel with minimal features like interrupt handling, command line interface
3 |
4 | GNU GRUB(GRand Unified Bootloader) legacy is used as bootloader
5 |
6 | ## Requirement
7 | * `gcc` cross Compiler [get prebuild binaries here](http://wiki.osdev.org/GCC_Cross-Compiler).
8 |
9 | * bochs x86 Emulator for running kernel in virtual environment.
10 | ```
11 | [sudo] apt-get install bochs
12 | [sudo] apt-get install bochs-sdl (for GUI support)
13 | ```
14 | * `genisoimage` to generate ISO image of kernel.
15 | ```
16 | [sudo] apt-get install genisoimage
17 | ```
18 | * `makedepend` for generating dependencies
19 | ```
20 | [sudo] apt-get install xutils-dev
21 | ```
22 |
23 | ## Installation
24 | * Clone the repository
25 | ```
26 | git clone https://github.com/Kapilks/Basic-Kernel.git
27 | ```
28 | * Setup the directory
29 | ```
30 | [sudo] make configure
31 | ```
32 | * Build `hal` (Hardware Abstraction Layer) library, `stdlib` for C and kernel binaries
33 | (Can be done separately)
34 | ```
35 | [sudo] make all
36 | ```
37 | * Generate the bootable iso image of kernel
38 | ```
39 | [sudo] make iso
40 | ```
41 | * Run kernel in `bochs`
42 | ```
43 | [sudo] make run
44 | ```
45 |
46 | ## Directory Structure of ISO image
47 | - iso
48 | - boot
49 | - grub
50 | - menu.lst
51 | - stage2_eltorito
52 | - kernel.bin
53 |
54 | ## Screenshot
55 | 
56 |
--------------------------------------------------------------------------------
/core/hal/Makefile:
--------------------------------------------------------------------------------
1 | # Output librabry file
2 | LIB_ARCH = libhal.a
3 |
4 |
5 | # Usefull directories
6 | INC_DIR = ../include
7 | INC_HAL_DIR = ./include
8 | SRC_DIR = ./source
9 | D_OBJ_DIR = ./obj/debug
10 | R_OBJ_DIR = ./obj/release
11 |
12 |
13 | # Tools for building
14 | CCOM = ../../compiler/bin/i686-elf-gcc
15 | CPPCOM = ../../compiler/bin/i686-elf-g++
16 | ASM = ../../compiler/bin/i686-elf-as
17 | ARCH = ../../compiler/bin/i686-elf-ar
18 | MAKEDEPEND = makedepend
19 |
20 |
21 | # Flags for building tools
22 | CFLAG = -c -std=gnu99 -ffreestanding -O2 -Wall -Wextra -I$(INC_DIR) -I$(INC_HAL_DIR)
23 | CPPFLAG = -c -ffreestanding -O2 -Wall -Wextra -fno-exceptions -fno-rtti -I$(INC_DIR) -I$(INC_HAL_DIR)
24 | ARFLAG = -vrcs
25 |
26 |
27 | _SOURCE = hal.c gdt.c idt.c cpu.c
28 |
29 | # Contain path to source files
30 | SRC_FILE = $(_SOURCE:%.c=$(SRC_DIR)/%.c)
31 |
32 | # Output debug object file
33 | D_OBJ = $(_SOURCE:%.c=$(D_OBJ_DIR)/%.o)
34 |
35 | # Output release object file
36 | R_OBJ = $(_SOURCE:%.c=$(R_OBJ_DIR)/%.o)
37 |
38 | # Output dependency file
39 | DEP = .depend
40 |
41 | #-------------------------------------------------------------------------
42 |
43 | lib: $(LIB_ARCH)
44 |
45 | $(LIB_ARCH): $(D_OBJ)
46 | $(ARCH) $(ARFLAG) $(LIB_ARCH) $(D_OBJ)
47 |
48 | $(D_OBJ_DIR)/%.o: $(SRC_DIR)/%.c
49 | $(CCOM) $< -o $@ $(CFLAG)
50 |
51 |
52 | # Include dependency files for object files
53 | include $(DEP)
54 |
55 | # Clean object files
56 | clean:
57 | rm $(D_OBJ_DIR)/*
58 | rm $(LIB_ARCH)
59 |
60 | # Generate dependency for course and output to DEP file
61 | depend:
62 | $(MAKEDEPEND) -v -f$(DEP) -Y$(INC_DIR) -I$(INC_HAL_DIR) $(SRC_FILE)
63 | rm $(DEP).bak
--------------------------------------------------------------------------------
/core/hal/include/cpu.h:
--------------------------------------------------------------------------------
1 | #ifndef CPU_H
2 | #define CPU_H
3 |
4 |
5 | //************************
6 | // Processor interface for managing processors,
7 | // processor cores, data structure
8 | // File: cpu.h
9 | //************************
10 | //
11 |
12 |
13 | #ifndef ARCH_x86
14 | #error "[cpu.h] platform not implimented. Define ARCH_X86 for HAL"
15 | #endif /* ARCH_x86 */
16 |
17 |
18 | #include
19 | #include
20 |
21 |
22 | /* Setup the processor idt, gdt */
23 | int32 initializeProcessor();
24 |
25 | /* Shutdown processor */
26 | void shutdownProcessor();
27 |
28 |
29 | #endif /* CPU_H */
--------------------------------------------------------------------------------
/core/hal/include/gdt.h:
--------------------------------------------------------------------------------
1 | #ifndef GDT_H
2 | #define GDT_H
3 |
4 |
5 | //************************
6 | /* GDT: Global Descripter Table */
7 | //
8 | // Contain function to setup Global Descriptor Table(GDT)
9 | // This handles memory map for system and permission level
10 | // File: gdt.h
11 | //************************
12 |
13 |
14 | #ifndef ARCH_x86
15 | #error "[gdt.h] platform not implimented. Define ARCH_X86 for HAL"
16 | #endif /* ARCH_x86 */
17 |
18 |
19 | #include
20 |
21 |
22 | // Maximum number of descriptor allowed
23 | #define I86_MAX_GDT_DESCRIPTOR 3
24 |
25 |
26 |
27 | /* GDTDescripter bit flags */
28 |
29 | /* Access bit */
30 | // Set this to 0
31 | // CPU set it 1 when segment is accessed
32 | #define I86_GDT_DESC_ACCESS 0x0001 //0000000000000001
33 |
34 | /* Readable/Writable bit */
35 | // Readable bit for Code selector
36 | // Writable bit for Data selector
37 | #define I86_GDT_DESC_READWRITE 0x0002 //0000000000000010
38 |
39 | /* Direction/Conforming bit */
40 | // Direction bit for Data selector
41 | // Conforming bit for Code selector
42 | #define I86_GDT_DESC_EXPANSION 0x0004 //0000000000000100
43 |
44 | /* Executable bit */
45 | // Code/Data Segement
46 | // Default Data Segment(0)
47 | #define I86_GDT_DESC_EXEC_CODE 0x0008 //0000000000001000
48 |
49 | /* Descripter bit */
50 | // System/Code-Data Descripter
51 | // Default System Descripter
52 | #define I86_GDT_DESC_CODEDATA 0x0010 //0000000000010000
53 |
54 | /* DPL(Descripter Priviledge Level) bits */
55 | #define I86_GDT_DESC_DPL 0x0060 //0000000001100000
56 |
57 | /* In memory bit (Virtual Memory) */
58 | #define I86_GDT_DESC_MEMORY 0x0080 //0000000010000000
59 |
60 | /* Masks out limitHigh (High 4 bits of limit) */
61 | #define I86_GDT_DESC_LIMITHI_MASK 0x0f00 //0000111100000000
62 |
63 | /* OS Reserve bit (Next reserve bit always 0)*/
64 | #define I86_GDT_DESC_RESERVE_OS 0x1000 //0001000000000000
65 |
66 | /* Segment type 32bit/16bit */
67 | // Default 16bit(0)
68 | #define I86_GDT_DESC_SEG_TYPE 0x4000 //0100000000000000
69 |
70 | /* 4KB Page size */
71 | // Default 1byte
72 | #define I86_GDT_DESC_PAGE_4KB 0x8000 //1000000000000000
73 |
74 |
75 | /* Descripter for GDT */
76 | // GDT is array of GDTDescripter
77 | // limit - 20 bits
78 | // base - 32 bits
79 | struct GDTDescriptor
80 | {
81 | uint16 limit; // 0-15 bits of Segment limit
82 | uint16 baseLow; // 0-15 bits of Segment base address
83 | uint8 baseMid; // 16-23 bits of Segment base address
84 | uint16 flags; // Bit mask for different bit flags
85 | uint8 baseHigh; // 24-31 bits of Segment base address
86 | }__attribute__((__packed__));
87 |
88 |
89 | /* Public Function */
90 |
91 | /* Put the given formed descripter at position index from the parameter passed */
92 | void gdtPutDescriptor(uint32 index, uint32 base, uint32 limit /* 20 bits only */, uint16 flags);
93 |
94 | /* Return pointer to the descripter */
95 | struct GDTDescriptor* gdtGetDesciptor(uint32 index);
96 |
97 | /* Setup GDT */
98 | int32 initializeGdt();
99 |
100 |
101 | #endif /* GDT_H */
--------------------------------------------------------------------------------
/core/hal/include/idt.h:
--------------------------------------------------------------------------------
1 | #ifndef IDT_H
2 | #define IDT_H
3 |
4 |
5 | //************************
6 | /* IDT: Interrupt Descripter Table */
7 | //
8 | // IDT is responsible for managing interrupt related functionality
9 | // File: idt.h
10 | //************************
11 |
12 |
13 | #ifndef ARCH_x86
14 | #error "[idt.h] platform not implimented. Define ARCH_X86 for HAL"
15 | #endif /* ARCH_x86 */
16 |
17 |
18 | #include
19 |
20 |
21 | /* I86 Has 256 interrupts (0-255) */
22 | #define I86_MAX_INTERRUPTS 256
23 |
24 | /* Descripter flags bits */
25 |
26 | /* Type of interrupt gate 32bit/16bit */
27 | #define I86_IDT_DESC_BIT16 0x06 // 00000110
28 | #define I86_IDT_DESC_BIT32 0x0E // 00001110
29 |
30 | /* Priviledge level */
31 | #define I86_IDT_DESC_RING1 0x40 // 01000000
32 | #define I86_IDT_DESC_RING2 0x20 // 00100000
33 | #define I86_IDT_DESC_RING3 0x60 // 01100000
34 |
35 | /* Present bit (Virtual Memory) */
36 | #define I86_IDT_DESC_PRESENT 0x80 // 10000000
37 |
38 |
39 | /* Descripter for IDT */
40 | // IDT is array of GDTDescripter
41 | // selector - 16 bits
42 | // base - 32 bits
43 | struct IDTDescripter
44 | {
45 | uint16 baseLow; // 0-15 bits of Interrupt Routine address
46 | uint16 selector; // Code selector in GDT (index of GDT array)
47 | uint8 reserve; // Reserved (0)
48 | uint8 flags; // Bit mask for flags
49 | uint16 baseHigh; // 16-32 bits of Interrupt Routine address
50 | }__attribute__((__packed__));
51 |
52 |
53 | /* Interrupt handler function type */
54 | typedef void (*InterruptHandler)(void);
55 |
56 |
57 | /* Public function */
58 |
59 | /* Return pointer to the IDTDescripter indexed by given index */
60 | struct IDTDescripter* idtGetDescripter(uint32 index);
61 |
62 | /* Register own interrupt handler for specific interrupts */
63 | // If not registered default handler will be called
64 | int32 putInterruptHandler(uint32 index, uint16 flags, uint16 selector, InterruptHandler handler);
65 |
66 | /* Setup IDT */
67 | // called from cpu initialization function
68 | int32 initializeIdt(uint16 selector);
69 |
70 |
71 | #endif /* IDT_H */
--------------------------------------------------------------------------------
/core/hal/include/reg.h:
--------------------------------------------------------------------------------
1 | #ifndef REG_H
2 | #define REG_H
3 |
4 |
5 | #ifndef ARCH_x86
6 | #error "[reg.h] platform not implimented. Define ARCH_X86 for HAL"
7 | #endif /* ARCH_x86 */
8 |
9 |
10 | #include
11 |
12 |
13 | // 32 bit Registers
14 | struct R32Bit
15 | {
16 | uint32 eax;
17 | uint32 ebx;
18 | uint32 ecx;
19 | uint32 edx;
20 | uint32 esi;
21 | uint32 edi;
22 | uint32 ebp;
23 | uint32 esp;
24 | uint32 eflags;
25 | uint8 cflags;
26 | };
27 |
28 |
29 | // 16 bit Registers
30 | struct R16Bit
31 | {
32 | uint16 ax;
33 | uint16 bx;
34 | uint16 cx;
35 | uint16 dx;
36 | uint16 si;
37 | uint16 di;
38 | uint16 bp;
39 | uint16 sp;
40 | uint16 es;
41 | uint16 cs;
42 | uint16 ss;
43 | uint16 ds;
44 | uint16 flags;
45 | uint8 cflags;
46 | };
47 |
48 |
49 | // 16 bit Registers expressed as 32 bit Registers
50 | struct R16Bit32
51 | {
52 | uint16 ax;
53 | uint16 axh;
54 | uint16 bx;
55 | uint16 bxh;
56 | uint16 cx;
57 | uint16 cxh;
58 | uint16 dx;
59 | uint16 dxh;
60 |
61 | uint16 si;
62 | uint16 di;
63 | uint16 bp;
64 | uint16 sp;
65 | uint16 es;
66 | uint16 cs;
67 | uint16 ss;
68 | uint16 ds;
69 | uint16 flags;
70 | uint8 cflags;
71 | };
72 |
73 |
74 | // 8 bit Registers
75 | struct R8Bit
76 | {
77 | uint8 al;
78 | uint8 ah;
79 | uint8 bl;
80 | uint8 bh;
81 | uint8 cl;
82 | uint8 ch;
83 | uint8 dl;
84 | uint8 dh;
85 | };
86 |
87 |
88 | // 8 bit Registers expressed as 32 bit Registers
89 | struct R8Bit32
90 | {
91 | uint8 al, ah;
92 | uint16 axh;
93 | uint8 bl, bh;
94 | uint16 bxh;
95 | uint8 cl, ch;
96 | uint16 cxh;
97 | uint8 dl, dh;
98 | uint16 dxh;
99 | };
100 |
101 |
102 | union IntR16
103 | {
104 | struct R16Bit x;
105 | struct R8Bit h;
106 | };
107 |
108 | union IntR32
109 | {
110 | struct R32Bit x;
111 | struct R16Bit32 l;
112 | struct R8Bit32 h;
113 | };
114 | #endif /* REG_H */
--------------------------------------------------------------------------------
/core/hal/libhal.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kapilks/Basic-Kernel/e672cfcaa81df053856f7ace7399bb8ce21a3eba/core/hal/libhal.a
--------------------------------------------------------------------------------
/core/hal/source/cpu.c:
--------------------------------------------------------------------------------
1 | #define ARCH_x86
2 |
3 |
4 | #include
5 | #include
6 | #include
7 |
8 |
9 | int32 initializeProcessor()
10 | {
11 | initializeGdt();
12 | initializeIdt(0x8); // selector of gdt 1 index (code selector)
13 |
14 | return 0;
15 | }
16 |
17 |
18 | void shutdownProcessor()
19 | {
20 |
21 | }
--------------------------------------------------------------------------------
/core/hal/source/gdt.c:
--------------------------------------------------------------------------------
1 | #define ARCH_x86
2 |
3 | #include
4 |
5 | #include
6 | #include
7 |
8 | /* Extracting bit (All 1) */
9 | #define LEAST_32_BITS 0xffffffff
10 | #define LEAST_16_BITS 0xffff
11 | #define LEAST_8_BITS 0xff
12 |
13 | /* Content of GDTR register */
14 | struct GDTR
15 | {
16 | uint16 limit; // Size of GDT - 1 bytes
17 | uint32 base; // Linear address of first entry of GDT
18 | }__attribute__((__packed__));
19 |
20 |
21 |
22 | //====================================================================================
23 |
24 |
25 | /* Private */
26 |
27 | // Global Destriptor Table as array of descriptor entries
28 | static struct GDTDescriptor gdt[I86_MAX_GDT_DESCRIPTOR];
29 |
30 | // GDT Register value
31 | static struct GDTR gdtr;
32 |
33 |
34 | /* Load GDTR register */
35 | static void loadGdt()
36 | {
37 | asm
38 | (
39 | "lgdt %0"
40 | :
41 | : [input] "g" (gdtr)
42 | :
43 | );
44 | }
45 |
46 |
47 |
48 | //=====================================================================================
49 |
50 |
51 |
52 | void gdtPutDescriptor(uint32 index, uint32 base, uint32 limit, uint16 flags)
53 | {
54 | if(index >= I86_MAX_GDT_DESCRIPTOR)
55 | {
56 | return;
57 | }
58 |
59 | memset((void*)&gdt[index], 0, sizeof(struct GDTDescriptor));
60 |
61 | // Set limit and base address
62 | gdt[index].baseLow = (uint16)(base & LEAST_16_BITS);
63 | gdt[index].baseMid = (uint8)((base >> 16) & LEAST_8_BITS);
64 | gdt[index].baseHigh = (uint8)((base >> 24) & LEAST_8_BITS);
65 | gdt[index].limit = (uint16)(limit & LEAST_16_BITS);
66 |
67 | // Add limit first 4 bits to flag starting at 5th bit
68 | flags |= (uint16)((limit >> 16) << 8);
69 |
70 | // Set flag
71 | gdt[index].flags = flags;
72 | }
73 |
74 |
75 | struct GDTDescriptor* gdtGetDesciptor(uint32 index)
76 | {
77 | if(index >= I86_MAX_GDT_DESCRIPTOR)
78 | {
79 | return NULL;
80 | }
81 |
82 | return &gdt[index];
83 | }
84 |
85 |
86 | int32 initializeGdt()
87 | {
88 | // Set up gdtr
89 | gdtr.limit = sizeof(struct GDTDescriptor) * I86_MAX_GDT_DESCRIPTOR - 1;
90 | gdtr.base = (uint32)(&gdt[0]);
91 |
92 | // Set null descriptor
93 | gdtPutDescriptor(0, 0, 0, 0);
94 |
95 | // Set default code descriptor
96 | gdtPutDescriptor(1, 0, LEAST_32_BITS,
97 | I86_GDT_DESC_READWRITE |
98 | I86_GDT_DESC_EXEC_CODE |
99 | I86_GDT_DESC_CODEDATA |
100 | I86_GDT_DESC_MEMORY |
101 | I86_GDT_DESC_PAGE_4KB |
102 | I86_GDT_DESC_SEG_TYPE |
103 | I86_GDT_DESC_LIMITHI_MASK);
104 |
105 | // Set default data descriptor
106 | gdtPutDescriptor(2, 0, LEAST_32_BITS,
107 | I86_GDT_DESC_READWRITE |
108 | I86_GDT_DESC_CODEDATA |
109 | I86_GDT_DESC_MEMORY |
110 | I86_GDT_DESC_PAGE_4KB |
111 | I86_GDT_DESC_SEG_TYPE |
112 | I86_GDT_DESC_LIMITHI_MASK);
113 |
114 | loadGdt();
115 |
116 | return 0;
117 | }
--------------------------------------------------------------------------------
/core/hal/source/hal.c:
--------------------------------------------------------------------------------
1 | #define ARCH_x86
2 |
3 | #ifndef ARCH_x86
4 | #error "[hal.c] platform not implimented. Define ARCH_X86 for HAL"
5 | #endif /* ARCH_x86 */
6 |
7 |
8 | #include
9 | #include
10 | #include
11 |
12 | #include
13 |
14 | void zero_int()
15 | {
16 | //__asm__("pushad");
17 |
18 | perror("Error: divide by zero\n");
19 |
20 | //__asm__("popad; leave; iret;");
21 | }
22 |
23 | int initializeHal()
24 | {
25 | initializeProcessor();
26 |
27 | putInterruptHandler(0, I86_IDT_DESC_PRESENT | I86_IDT_DESC_BIT32, 0x8, (InterruptHandler)zero_int);
28 | return 0;
29 | }
30 |
31 |
32 | int shutdownHal()
33 | {
34 | shutdownProcessor();
35 | return 0;
36 | }
37 |
38 |
39 | void genInterrupt(uint32 interrupt)
40 | {
41 | uint16 opcode = 0;
42 | asm
43 | (
44 | "movb %0, %%al\n\t"
45 | "movb %%al, genInt + 1\n\t"
46 | "jmp genInt\n\t"
47 | "genInt:\n\t"
48 | "int $0\n\t"
49 | :
50 | : [input] "g" (interrupt)
51 | : "%al"
52 | );
53 | }
--------------------------------------------------------------------------------
/core/hal/source/idt.c:
--------------------------------------------------------------------------------
1 | #define ARCH_x86
2 |
3 | #include
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | /* Content of IDTR register */
11 | struct IDTR
12 | {
13 | uint16 limit;
14 | uint32 base;
15 | }__attribute__((__packed__));
16 |
17 |
18 | //====================================================================================
19 |
20 |
21 |
22 | /* Private */
23 |
24 | /* Interrupt Descripter Table as array of IDTDescripter */
25 | static struct IDTDescripter idt[I86_MAX_INTERRUPTS];
26 |
27 | /* IDT Register value */
28 | static struct IDTR idtr;
29 |
30 |
31 | /* Load IDTR register */
32 | static void loadIdtr()
33 | {
34 | asm
35 | (
36 | "lidt %0"
37 | :
38 | : [input] "g" (idtr)
39 | :
40 | );
41 | }
42 |
43 |
44 | /* Default interrupt handler */
45 | // This handler is used for interrupts whose handler is
46 | // not defined
47 | static void defaultInterruptHandler()
48 | {
49 | perror("I86 Default interrupt handler\n");
50 |
51 | for(;;);
52 | }
53 |
54 |
55 |
56 | //====================================================================================
57 |
58 |
59 |
60 | struct IDTDescripter* idtGetDescripter(uint32 index)
61 | {
62 | if(index >= I86_MAX_INTERRUPTS)
63 | {
64 | return NULL;
65 | }
66 |
67 | return &idt[index];
68 | }
69 |
70 |
71 | int32 putInterruptHandler(uint32 index, uint16 flags, uint16 selector, InterruptHandler handler)
72 | {
73 | if(index >= I86_MAX_INTERRUPTS)
74 | {
75 | return 0;
76 | }
77 |
78 | if(!handler)
79 | {
80 | return 0;
81 | }
82 |
83 | uint32 ibase = (uint32)(&(*handler));
84 |
85 | idt[index].baseLow = (uint16)(ibase & 0xffff);
86 | idt[index].baseHigh = (uint16)((ibase >> 16) & 0xffff);
87 | idt[index].reserve = 0;
88 | idt[index].flags = (uint8)(flags);
89 | idt[index].selector = selector;
90 |
91 | return 0;
92 | }
93 |
94 |
95 | int32 initializeIdt(uint16 selector)
96 | {
97 | // Setup idtr
98 | idtr.limit = sizeof(struct IDTDescripter) * I86_MAX_INTERRUPTS -1;
99 | idtr.base = (uint32)&idt[0];
100 |
101 | // Null idtdescripter
102 | memset((void*)&idt[0], 0, sizeof(struct IDTDescripter) * I86_MAX_INTERRUPTS - 1);
103 |
104 | // Register default handler
105 | for(int i = 0; i < I86_MAX_INTERRUPTS; ++i)
106 | {
107 | putInterruptHandler(i, I86_IDT_DESC_PRESENT | I86_IDT_DESC_BIT32, selector, (InterruptHandler)defaultInterruptHandler);
108 | }
109 |
110 | loadIdtr();
111 |
112 | return 0;
113 | }
--------------------------------------------------------------------------------
/core/include/ctype:
--------------------------------------------------------------------------------
1 | #ifndef CTYPE_CPP_H
2 | #define CTYPE_CPP_H
3 |
4 | /* Will be used in C++ include */
5 | #include
6 |
7 |
8 | #endif /* CTYPE_CPP_H */
--------------------------------------------------------------------------------
/core/include/ctype.h:
--------------------------------------------------------------------------------
1 | #ifndef CTYPE_H
2 | #define CTYPE_H
3 |
4 |
5 | //************************
6 | // Header for determining type and their details
7 | // of the character of string
8 | // File: ctype.h
9 | //************************
10 |
11 |
12 | #ifdef __cplusplus
13 | extern "C"
14 | {
15 | #endif
16 |
17 | extern char _ctype[];
18 |
19 | /* Character type Constants */
20 |
21 | #define CTYPE_UP 0x01 /* upper case */
22 | #define CTYPE_LOW 0x02 /* lower case */
23 | #define CTYPE_DIG 0x04 /* digit */
24 | #define CTYPE_CTL 0x08 /* control */
25 | #define CTYPE_PUN 0x10 /* punctuation */
26 | #define CTYPE_WHT 0x20 /* white space (space/cr/lf/tab) */
27 | #define CTYPE_HEX 0x40 /* hex digit */
28 | #define CTYPE_SP 0x80 /* hard space (0x20) */
29 |
30 | /* Basic macros for getting details of character */
31 |
32 | #define isAlnum(c) ((_ctype + 1)[(unsigned int)(c)] & (CTYPE_UP | CTYPE_LOW | CTYPE_DIG))
33 | #define isAlpha(c) ((_ctype + 1)[(unsigned int)(c)] & (CTYPE_UP | CTYPE_LOW))
34 | #define isCntrl(c) ((_ctype + 1)[(unsigned int)(c)] & (CTYPE_CTL))
35 | #define isDigit(c) ((_ctype + 1)[(unsigned int)(c)] & (CTYPE_DIG))
36 | #define isGraph(c) ((_ctype + 1)[(unsigned int)(c)] & (CTYPE_PUN | CTYPE_UP | CTYPE_LOW | CTYPE_DIG))
37 | #define isLower(c) ((_ctype + 1)[(unsigned int)(c)] & (CTYPE_LOW))
38 | #define isPrint(c) ((_ctype + 1)[(unsigned int)(c)] & (CTYPE_PUN | CTYPE_UP | CTYPE_LOW | CTYPE_DIG | CTYPE_SP))
39 | #define isPunct(c) ((_ctype + 1)[(unsigned int)(c)] & (CTYPE_PUN))
40 | #define isSpace(c) ((_ctype + 1)[(unsigned int)(c)] & (CTYPE_WHT))
41 | #define isUpper(c) ((_ctype + 1)[(unsigned int)(c)] & (CTYPE_UP))
42 | #define isXdigit(c) ((_ctype + 1)[(unsigned int)(c)] & (CTYPE_DIG | CTYPE_HEX))
43 | #define isAscii(c) ((unsigned int)(c) <= 0x7F)
44 |
45 | #define toAscii(c) ((unsigned int)(c) & 0x7F)
46 | #define toLower(c) (isupper(c) ? c + 'a' - 'A' : c)
47 | #define toUpper(c) (islower(c) ? c + 'A' - 'a' : c)
48 |
49 | #ifdef __cplusplus
50 | }
51 | #endif
52 |
53 |
54 | #endif /* CTYPE_H */
--------------------------------------------------------------------------------
/core/include/hal.h:
--------------------------------------------------------------------------------
1 | #ifndef HAL_H
2 | #define HAL_H
3 |
4 |
5 | //************************
6 | /* HAL: Hardware Abstraction Layer */
7 | //
8 | // The Hardware Abstraction Layer provide interface for controlling
9 | // motherboard hardware device
10 | // Specific HAL inplimentation is provided in for of library for
11 | // specific hardware
12 | // File: hal.h
13 | //************************
14 |
15 |
16 | #ifndef ARCH_x86
17 | #error "HAL is not implimented"
18 | #endif /* ARCH_x86 */
19 |
20 |
21 | #include
22 |
23 |
24 | /* Public Function */
25 |
26 | /* Initialize HAL specific implimentation */
27 | int initializeHal();
28 |
29 | /* Shutdown HAL */
30 | int shutdownHal();
31 |
32 | /* Generate Software interrupt */
33 | // interrupt is index in IDT
34 | void genInterrupt(uint32 interrupt);
35 |
36 |
37 | #endif /* HAL_H */
--------------------------------------------------------------------------------
/core/include/null.h:
--------------------------------------------------------------------------------
1 | #ifndef NULL_H
2 | #define NULL_H
3 |
4 |
5 | //************************
6 | // Standard NULL declaration
7 | // File: null.h
8 | //************************
9 |
10 |
11 | /* Undefine NULL if it is already defined by stdlib */
12 | #ifdef NULL
13 | #undef NULL
14 | #endif
15 |
16 |
17 | #ifdef __cplusplus
18 | extern "C"
19 | {
20 | /* Standard NULL declaraton for C++*/
21 | #define NULL 0
22 | /* Written #endif so that redefinition does not occur */
23 | #endif
24 |
25 | #ifdef __cplusplus
26 | }
27 | #else
28 | /* Standard NULL declaration for C*/
29 | #define NULL (void*)0
30 | #endif
31 |
32 |
33 | #endif /* NULL_H */
--------------------------------------------------------------------------------
/core/include/size.h:
--------------------------------------------------------------------------------
1 | #ifndef SIZE_H
2 | #define SIZE_H
3 |
4 |
5 | //************************
6 | // Standard size declaration
7 | // File: size.h
8 | //************************
9 |
10 |
11 | #include
12 |
13 | #ifdef __cplusplus
14 | extern "C"
15 | {
16 | #endif
17 |
18 | /* size declaration 32-bit*/
19 | typedef uint32 size;
20 |
21 | #ifdef __cplusplus
22 | }
23 | #endif
24 |
25 |
26 | #endif /* SIZE_H */
--------------------------------------------------------------------------------
/core/include/stdarg:
--------------------------------------------------------------------------------
1 | #ifndef STDARG_CPP_H
2 | #define STDARG_CPP_H
3 |
4 | /* Will be used in C++ include */
5 | #include
6 |
7 |
8 | #endif /* STDARG_CPP_H */
--------------------------------------------------------------------------------
/core/include/stdarg.h:
--------------------------------------------------------------------------------
1 | #ifndef STDARG_H
2 | #define STDARG_H
3 |
4 |
5 | //************************
6 | // Defines macros for using in variable lenght arguments
7 | // File: stdarg.h
8 | //************************
9 |
10 |
11 | #include
12 |
13 | #ifdef __cplusplus
14 | extern "C"
15 | {
16 | #endif
17 |
18 | /* Stack width = Int width */
19 | #define STACKITEM int
20 |
21 | /* Round up width of objects pushed on stack. The expression before the &
22 | * ensures that we get 0 for objects of size 0.
23 | */
24 | #define VA_SIZE(TYPE) ((sizeof(TYPE) + sizeof(STACKITEM) - 1) & ~(sizeof(STACKITEM) - 1))
25 |
26 | /* &(LASTARG) Points to the LEFTMOST argument of the function call (before the ...) */
27 | /* AP - argument pointer */
28 | /* LASTARG - last argument */
29 | #define va_start(AP, LASTARG) (AP=((va_list) &(LASTARG) + VA_SIZE(LASTARG)))
30 |
31 | /* nothing for vaEnd */
32 | #define va_end(AP)
33 |
34 | #define va_arg(AP, TYPE) (AP += VA_SIZE(TYPE), *((TYPE *)(AP - VA_SIZE(TYPE))))
35 |
36 |
37 | #ifdef __cplusplus
38 | }
39 | #endif
40 |
41 |
42 | #endif /* STDARG_H */
--------------------------------------------------------------------------------
/core/include/stdint:
--------------------------------------------------------------------------------
1 | #ifndef STDINT_CPP_H
2 | #define STDINT_CPP_H
3 |
4 | /* Will be used in C++ include */
5 | #include
6 |
7 |
8 | #endif /* STDINT_CPP_H */
--------------------------------------------------------------------------------
/core/include/stdint.h:
--------------------------------------------------------------------------------
1 | #ifndef STDINT_H
2 | #define STDINT_H
3 |
4 |
5 | //************************
6 | // Standard integer data-type
7 | // File: stdint.h
8 | //************************
9 |
10 |
11 | /* Exact width integer type */
12 | typedef signed char int8;
13 | typedef unsigned char uint8;
14 | typedef signed short int16;
15 | typedef unsigned short uint16;
16 | typedef signed int int32;
17 | typedef unsigned int uint32;
18 | typedef signed long long int64;
19 | typedef unsigned long long uint64;
20 |
21 |
22 | /* Integer capable of holding pointers */
23 | typedef signed int intp;
24 | typedef unsigned int uintp;
25 |
26 |
27 | /* Min and Max values for integer data-type */
28 | #define INT8_MIN (-128)
29 | #define INT16_MIN (-32768)
30 | #define INT32_MIN (-2147483647 - 1)
31 | #define INT64_MIN (-9223372036854775807LL - 1)
32 |
33 | #define INT8_MAX 127
34 | #define INT16_MAX 32767
35 | #define INT32_MAX 2147483647
36 | #define INT64_MAX 9223372036854775807LL
37 |
38 | // Unsigned integer Min all 0
39 | #define UINT8_MAX 0xff /* 255U */
40 | #define UINT16_MAX 0xffff /* 65535U */
41 | #define UINT32_MAX 0xffffffff /* 4294967295U */
42 | #define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */
43 |
44 | /* Min and Max values for integer pointer data-type */
45 | #define INTP_MIN INT32_MIN
46 | #define INTP_MAX INT32_MAX
47 | #define UINTP_MAX UINT32_MAX
48 |
49 |
50 | #endif /* STDINT_H */
--------------------------------------------------------------------------------
/core/include/stdio.h:
--------------------------------------------------------------------------------
1 | #ifndef STDIO_H
2 | #define STDIO_H
3 |
4 |
5 |
6 | //************************
7 | // Constain function related to input and output to console
8 | // File: stdio.h
9 | //************************
10 |
11 |
12 |
13 | /* String of this size can be printed on console at a time */
14 | #define BUFFER_SIZE 255
15 |
16 |
17 | //////////////////////
18 | /* Public Function */
19 | //////////////////////
20 |
21 |
22 | /* Print formatted output to console */
23 | void printf(const char* format, ...);
24 |
25 | /* Print formatted error on console with red color */
26 | void perror(const char* format, ...);
27 |
28 |
29 | #endif /* STDIO_H */
--------------------------------------------------------------------------------
/core/include/string.h:
--------------------------------------------------------------------------------
1 | #ifndef STRING_H
2 | #define STRING_H
3 |
4 |
5 |
6 | //************************
7 | // Conatain function related to string - character array
8 | // File: string.h
9 | //************************
10 |
11 |
12 |
13 | #include
14 |
15 |
16 | /* Conversion base for integers */
17 | enum BASE
18 | {
19 | BASE_HEX = 16,
20 | BASE_DEC = 10,
21 | BASE_OCT = 8,
22 | BASE_BIN = 2,
23 | };
24 |
25 |
26 | //////////////////////
27 | /* Public Function */
28 | //////////////////////
29 |
30 |
31 | /* Return the length of the string (excluding NULL character) */
32 | size strlen(const char*);
33 |
34 | /* Copy source to destination */
35 | // Return pointer to destination string
36 | char* strcpy(char* destination, const char* source);
37 |
38 | /* Copy value to each byte of destination till count */
39 | void* memset(void* destination, char value, size count);
40 |
41 | /* Copy source to destination till count */
42 | void* memcpy(void* destination, const void* source, size count);
43 |
44 | /* Convert positive integer to string */
45 | // base is for string(output value)
46 | void inttostr(uint32 value, enum BASE base, char* destination);
47 |
48 | /* Convert string to positive integer */
49 | // base is for string(source value)
50 | void strtoint(char* source, enum BASE base, uint32* destination);
51 |
52 | /* Reverse the string inplace */
53 | void strrev(char* source);
54 |
55 |
56 | #endif /* STRING_H */
--------------------------------------------------------------------------------
/core/include/va_list.h:
--------------------------------------------------------------------------------
1 | #ifndef VA_LIST_H
2 | #define VA_LIST_H
3 |
4 |
5 | //************************
6 | // Define the data-type used for variable list argument in function
7 | // File: va_list.h
8 | //************************
9 |
10 |
11 | #include
12 |
13 | #ifdef __cplusplus
14 | extern "C"
15 | {
16 | #endif
17 |
18 | typedef uint8* va_list;
19 |
20 | #ifdef __cplusplus
21 | }
22 | #endif
23 |
24 |
25 | #endif /* VA_LIST_H */
--------------------------------------------------------------------------------
/core/kernel/Makefile:
--------------------------------------------------------------------------------
1 | # Usefull directories
2 | INC_DIR = ../include
3 | INC_KER_DIR = ./include
4 | SRC_DIR = ./source
5 | D_OBJ_DIR = ./obj/debug
6 | R_OBJ_DIR = ./obj/release
7 |
8 |
9 | # Tools for building
10 | CCOM = ../../compiler/bin/i686-elf-gcc
11 | CPPCOM = ../../compiler/bin/i686-elf-g++
12 | ASM = ../../compiler/bin/i686-elf-as
13 | ARCH = ../../compiler/bin/i686-elf-ar
14 | MAKEDEPEND = makedepend
15 |
16 |
17 | # Flags for building tools
18 | CFLAG = -c -std=gnu99 -ffreestanding -O2 -Wall -Wextra -I$(INC_DIR) -I$(INC_KER_DIR)
19 | CPPFLAG = -c -ffreestanding -O2 -Wall -Wextra -fno-exceptions -fno-rtti -I$(INC_DIR) -I$(INC_KER_DIR)
20 | ARFLAG = -vrcs
21 |
22 |
23 | _SOURCE = console.c kernel.c
24 |
25 | # Contain path to source files
26 | SRC_FILE = $(_SOURCE:%.c=$(SRC_DIR)/%.c)
27 |
28 | # Output debug object file
29 | D_OBJ = $(_SOURCE:%.c=$(D_OBJ_DIR)/%.o)
30 |
31 | # Output release object file
32 | R_OBJ = $(_SOURCE:%.c=$(R_OBJ_DIR)/%.o)
33 |
34 | # Output dependency file
35 | DEP = .depend
36 |
37 | #-------------------------------------------------------------------------
38 |
39 | all: $(D_OBJ) loader.o
40 |
41 |
42 | $(D_OBJ_DIR)/%.o: $(SRC_DIR)/%.c
43 | $(CCOM) $< -o $@ $(CFLAG)
44 |
45 | %.o: %.s
46 | $(ASM) $< -o $(D_OBJ_DIR)/$@
47 |
48 | # Include dependency files for object files
49 | include $(DEP)
50 |
51 | # Clean object files
52 | clean:
53 | rm $(D_OBJ_DIR)/*
54 |
55 | # Generate dependency for course and output to DEP file
56 | depend:
57 | $(MAKEDEPEND) -v -f$(DEP) -Y$(INC_DIR) -I$(INC_KER_DIR) $(SRC_FILE)
58 | rm $(DEP).bak
--------------------------------------------------------------------------------
/core/kernel/include/console.h:
--------------------------------------------------------------------------------
1 | #ifndef CONSOLE_H
2 | #define CONSOLE_H
3 |
4 |
5 |
6 | //************************
7 | // Initialize console for inputing and outputing
8 | // data on screen
9 | // File: console.h
10 | //************************
11 |
12 |
13 |
14 | #include
15 | #include
16 |
17 |
18 | /* color data-type, include Foreground and background color */
19 | // first 4-bit are background color
20 | // last 4-bit are foreground color
21 | typedef uint8 color;
22 |
23 |
24 | /* vga_entry data-type, for using in VGA buffer */
25 | // first 8-bit are color data-type
26 | // last 8-bit are character
27 | typedef uint16 vga_entry;
28 |
29 |
30 | /* Hardware text mode color constants. */
31 | enum VGA_COLOR
32 | {
33 | COLOR_BLACK = 0,
34 | COLOR_BLUE = 1,
35 | COLOR_GREEN = 2,
36 | COLOR_CYAN = 3,
37 | COLOR_RED = 4,
38 | COLOR_MAGENTA = 5,
39 | COLOR_BROWN = 6,
40 | COLOR_LIGHT_GREY = 7,
41 | COLOR_DARK_GREY = 8,
42 | COLOR_LIGHT_BLUE = 9,
43 | COLOR_LIGHT_GREEN = 10,
44 | COLOR_LIGHT_CYAN = 11,
45 | COLOR_LIGHT_RED = 12,
46 | COLOR_LIGHT_MAGENTA = 13,
47 | COLOR_LIGHT_BROWN = 14,
48 | COLOR_WHITE = 15,
49 | };
50 |
51 |
52 | /* VGA console dimension - 80 * 25 characters */
53 | #define VGA_WIDTH 80
54 | #define VGA_HEIGHT 25
55 |
56 |
57 | /* Color bits */
58 | #define FOREGROUND_COLOR 0x0F // 00001111
59 | #define BACKGROUND_COLOR 0xF0 // 11110000
60 |
61 |
62 | //////////////////////
63 | /* Public function */
64 | //////////////////////
65 |
66 |
67 | /* Print the string to console */
68 | void printConsole(const char*);
69 |
70 | /* Clear VGA memory and move cursor to starting position*/
71 | void clearConsole();
72 |
73 | /* Initialize console for printing data */
74 | void initializeConsole(color defaultColor);
75 |
76 | /* Set color used to display in console */
77 | void consoleSetColor(color c);
78 |
79 | /* Return the current color used in console */
80 | color consoleGetColor();
81 |
82 | /* Make color from foreground and background colors */
83 | color makeColor(enum VGA_COLOR fg, enum VGA_COLOR bg);
84 |
85 |
86 | #endif /* CONSOLE_H */
--------------------------------------------------------------------------------
/core/kernel/linker.ld:
--------------------------------------------------------------------------------
1 | /* The bootloader will look at this image and start execution at the symbol
2 | designated as the entry point. */
3 | ENTRY(_start)
4 |
5 | /* Tell where the various sections of the object files will be put in the final
6 | kernel image. */
7 | SECTIONS
8 | {
9 | /* Begin putting sections at 1 MiB, a conventional place for kernels to be
10 | loaded at by the bootloader. */
11 | . = 1M;
12 |
13 | /* First put the multiboot header, as it is required to be put very early
14 | early in the image or the bootloader won't recognize the file format.
15 | Next we'll put the .text section. */
16 | .text BLOCK(4K) : ALIGN(4K)
17 | {
18 | *(.multiboot)
19 | *(.text)
20 | }
21 |
22 | /* Read-only data. */
23 | .rodata BLOCK(4K) : ALIGN(4K)
24 | {
25 | *(.rodata)
26 | }
27 |
28 | /* Read-write data (initialized) */
29 | .data BLOCK(4K) : ALIGN(4K)
30 | {
31 | *(.data)
32 | }
33 |
34 | /* Read-write data (uninitialized) and stack */
35 | .bss BLOCK(4K) : ALIGN(4K)
36 | {
37 | *(COMMON)
38 | *(.bss)
39 | *(.bootstrap_stack)
40 | }
41 |
42 | /* The compiler may produce other sections, by default it will put them in
43 | a segment with the same name. Simply add stuff here as needed. */
44 | }
--------------------------------------------------------------------------------
/core/kernel/loader.s:
--------------------------------------------------------------------------------
1 | # Declare constants used for creating a multiboot header.
2 | .set ALIGN, 1<<0 # align loaded modules on page boundaries
3 | .set MEMINFO, 1<<1 # provide memory map
4 | .set FLAGS, ALIGN | MEMINFO # this is the Multiboot 'flag' field
5 | .set MAGIC, 0x1BADB002 # 'magic number' lets bootloader find the header
6 | .set CHECKSUM, -(MAGIC + FLAGS) # checksum of above, to prove we are multiboot
7 |
8 | # Declare a header as in the Multiboot Standard. We put this into a special
9 | # section so we can force the header to be in the start of the final program.
10 | # You don't need to understand all these details as it is just magic values that
11 | # is documented in the multiboot standard. The bootloader will search for this
12 | # magic sequence and recognize us as a multiboot kernel.
13 | .section .multiboot
14 | .align 4
15 | .long MAGIC
16 | .long FLAGS
17 | .long CHECKSUM
18 |
19 | # Currently the stack pointer register (esp) points at anything and using it may
20 | # cause massive harm. Instead, we'll provide our own stack. We will allocate
21 | # room for a small temporary stack by creating a symbol at the bottom of it,
22 | # then allocating 16384 bytes for it, and finally creating a symbol at the top.
23 | .section .bootstrap_stack, "aw", @nobits
24 | stack_bottom:
25 | .skip 16384 # 16 KiB
26 | stack_top:
27 |
28 | # The linker script specifies _start as the entry point to the kernel and the
29 | # bootloader will jump to this position once the kernel has been loaded. It
30 | # doesn't make sense to return from this function as the bootloader is gone.
31 | .section .text
32 | .global _start
33 | .type _start, @function
34 | _start:
35 | # Welcome to kernel mode! We now have sufficient code for the bootloader to
36 | # load and run our operating system. It doesn't do anything interesting yet.
37 | # Perhaps we would like to call printf("Hello, World\n"). You should now
38 | # realize one of the profound truths about kernel mode: There is nothing
39 | # there unless you provide it yourself. There is no printf function. There
40 | # is no header. If you want a function, you will have to code it
41 | # yourself. And that is one of the best things about kernel development:
42 | # you get to make the entire system yourself. You have absolute and complete
43 | # power over the machine, there are no security restrictions, no safe
44 | # guards, no debugging mechanisms, there is nothing but what you build.
45 |
46 | # By now, you are perhaps tired of assembly language. You realize some
47 | # things simply cannot be done in C, such as making the multiboot header in
48 | # the right section and setting up the stack. However, you would like to
49 | # write the operating system in a higher level language, such as C or C++.
50 | # To that end, the next task is preparing the processor for execution of
51 | # such code. C doesn't expect much at this point and we only need to set up
52 | # a stack. Note that the processor is not fully initialized yet and stuff
53 | # such as floating point instructions are not available yet.
54 |
55 | # To set up a stack, we simply set the esp register to point to the top of
56 | # our stack (as it grows downwards).
57 | movl $stack_top, %esp
58 |
59 | # We are now ready to actually execute C code. We cannot embed that in an
60 | # assembly file, so we'll create a kernel.c file in a moment. In that file,
61 | # we'll create a C entry point called kernel and call it here.
62 | call kernel
63 |
64 | # In case the function returns, we'll want to put the computer into an
65 | # infinite loop. To do that, we use the clear interrupt ('cli') instruction
66 | # to disable interrupts, the halt instruction ('hlt') to stop the CPU until
67 | # the next interrupt arrives, and jumping to the halt instruction if it ever
68 | # continues execution, just to be safe. We will create a local label rather
69 | # than real symbol and jump to there endlessly.
70 | cli
71 | hlt
72 | .Lhang:
73 | jmp .Lhang
74 |
75 | # Set the size of the _start symbol to the current location '.' minus its start.
76 | # This is useful when debugging or when you implement call tracing.
77 | .size _start, . - _start
78 |
--------------------------------------------------------------------------------
/core/kernel/source/console.c:
--------------------------------------------------------------------------------
1 | #include "console.h"
2 | #include
3 |
4 |
5 | //////////////
6 | /* Private */
7 | //////////////
8 |
9 |
10 | static size consoleRow;
11 | static size consoleColumn;
12 | static color consoleColor;
13 | static vga_entry* consoleBuffer;
14 |
15 |
16 | /* Make single vga_entry for given chracter and color */
17 | static vga_entry makeVGAEntry(char ch, color c);
18 |
19 | /* Put a character in VGA text memory at specific location */
20 | static void consolePutVGAEntryAt(char ch, color c, size x, size y);
21 |
22 | /* Put a character in VGA text moemory at current cursor location */
23 | static void consolePutChar(char ch);
24 |
25 | /* Change the cursor position in console as character are printed*/
26 | static void moveCursor();
27 |
28 |
29 | //////////////////////
30 | /* Private funtion */
31 | //////////////////////
32 |
33 |
34 | vga_entry makeVGAEntry(char ch, color c)
35 | {
36 | uint16 ch16 = ch;
37 | uint16 color16 = c;
38 |
39 | return ch16 | color16 << 8;
40 | }
41 |
42 | void consolePutVGAEntryAt(char ch, color c, size x, size y)
43 | {
44 | const size index = y * VGA_WIDTH + x;
45 | consoleBuffer[index] = makeVGAEntry(ch, c);
46 | }
47 |
48 | void consolePutChar(char ch)
49 | {
50 | if(consoleRow == VGA_HEIGHT - 1)
51 | {
52 | // Scroll
53 | size limit = VGA_WIDTH * VGA_HEIGHT - VGA_WIDTH;
54 | for(size i = 0; i < limit; ++i)
55 | {
56 | consoleBuffer[i] = consoleBuffer[i + VGA_WIDTH];
57 | }
58 |
59 | consoleRow--;
60 | }
61 |
62 |
63 | if(ch == '\n')
64 | {
65 | consoleColumn = 0;
66 | consoleRow++;
67 |
68 | return;
69 | }
70 |
71 | consolePutVGAEntryAt(ch, consoleColor, consoleColumn, consoleRow);
72 |
73 | if ( ++consoleColumn == VGA_WIDTH )
74 | {
75 | consoleColumn = 0;
76 | consoleRow++;
77 | }
78 | }
79 |
80 | void moveCursor()
81 | {
82 | uint16 location = consoleRow * VGA_WIDTH + consoleColumn;
83 |
84 | /* out ins. write second operand to port in first operand */
85 | asm
86 | (
87 | "mov %0, %%bx\n\t" /*Copy location to bx register*/
88 |
89 | /*Setting Low byte of cursor position*/
90 |
91 | "mov $0x0f, %%al\n\t" /*Cursor location low byte index*/
92 | "mov $0x03D4, %%dx\n\t" /*Write it to the CRT index register*/
93 | "out %%al, %%dx\n\t"
94 |
95 | "mov %%bl, %%al\n\t" /*The current location is in EBX. BL contains the low byte, BH high byte*/
96 | "mov $0x03D5, %%dx\n\t" /*Write it to the data register*/
97 | "out %%al, %%dx\n\t" /*low byte*/
98 |
99 |
100 | /*Setting High byte of cursor position*/
101 |
102 | "mov $0x0e, %%al\n\t" /*Cursor location high byte index*/
103 | "mov $0x03D4, %%dx\n\t" /*Write to the CRT index register*/
104 | "out %%al, %%dx\n\t"
105 |
106 | "mov %%bh, %%al\n\t" /*the current location is in EBX. BL contains low byte, BH high byte*/
107 | "mov $0x03D5, %%dx\n\t" /*Write it to the data register*/
108 | "out %%al, %%dx\n\t"
109 | :
110 | : [input] "g" (location)
111 | : "%bx"
112 | );
113 | }
114 |
115 |
116 | //////////////////////
117 | /* Public Function */
118 | //////////////////////
119 |
120 |
121 | color makeColor(enum VGA_COLOR fg, enum VGA_COLOR bg)
122 | {
123 | return fg | bg << 4;
124 | }
125 |
126 | void initializeConsole(color defaultColor)
127 | {
128 | consoleColor = defaultColor;
129 | consoleBuffer = (uint16*) 0xB8000;
130 |
131 | clearConsole();
132 | }
133 |
134 | void printConsole(const char* data)
135 | {
136 | size datalen = strlen(data);
137 | for (size i = 0; i < datalen; i++)
138 | {
139 | consolePutChar(data[i]);
140 | }
141 |
142 | moveCursor();
143 | }
144 |
145 | void consoleSetColor(color c)
146 | {
147 | consoleColor = c;
148 | }
149 |
150 | color consoleGetColor()
151 | {
152 | return consoleColor;
153 | }
154 |
155 | void clearConsole()
156 | {
157 | for ( size y = 0; y < VGA_HEIGHT; y++ )
158 | {
159 | for ( size x = 0; x < VGA_WIDTH; x++ )
160 | {
161 | const size index = y * VGA_WIDTH + x;
162 | consoleBuffer[index] = makeVGAEntry(' ', consoleColor);
163 | }
164 | }
165 |
166 | consoleRow = 0;
167 | consoleColumn = 0;
168 |
169 | moveCursor();
170 | }
--------------------------------------------------------------------------------
/core/kernel/source/kernel.c:
--------------------------------------------------------------------------------
1 | /* Check if the compiler thinks if we are targeting the wrong operating system. */
2 | #if defined(__linux__)
3 | #error "You are not using a cross-compiler, you will most certainly run into trouble"
4 | #endif
5 |
6 | /* This tutorial will only work for the 32-bit ix86 targets. */
7 | #if !defined(__i386__)
8 | #error "This tutorial needs to be compiled with a ix86-elf compiler"
9 | #endif
10 |
11 | #define ARCH_x86
12 |
13 | #include "console.h" /* Included here so no other file include it, directly use print */
14 | #include
15 | #include
16 | #include // For generating interrupts
17 |
18 | void usefullStuff()
19 | {
20 | initializeHal();
21 |
22 | //genInterrupt(0);
23 | //genInterrupt(7);
24 |
25 | initializeHal();
26 |
27 | printf("Hello World\n");
28 | }
29 |
30 |
31 | #if defined(__cplusplus)
32 | extern "C" /* Use C linkage for kernel. */
33 | #endif
34 | void kernel()
35 | {
36 | /* Initialize console so that print start working */
37 | initializeConsole(makeColor(COLOR_WHITE, COLOR_BLUE));
38 |
39 | usefullStuff();
40 | }
--------------------------------------------------------------------------------
/core/lib/Makefile:
--------------------------------------------------------------------------------
1 | # Output librabry file
2 | LIB_ARCH = libstd.a
3 |
4 |
5 | # Usefull directories
6 | INC_DIR = ../include
7 | SRC_DIR = ./source
8 | D_OBJ_DIR = ./obj/debug
9 | R_OBJ_DIR = ./obj/release
10 |
11 |
12 | # Tools for building
13 | CCOM = ../../compiler/bin/i686-elf-gcc
14 | CPPCOM = ../../compiler/bin/i686-elf-g++
15 | ASM = ../../compiler/bin/i686-elf-as
16 | ARCH = ../../compiler/bin/i686-elf-ar
17 | MAKEDEPEND = makedepend
18 |
19 |
20 | # Flags for building tools
21 | CFLAG = -c -std=gnu99 -ffreestanding -O2 -Wall -Wextra -I$(INC_DIR)
22 | CPPFLAG = -c -ffreestanding -O2 -Wall -Wextra -fno-exceptions -fno-rtti -I$(INC_DIR)
23 | ARFLAG = -vrcs
24 |
25 |
26 | _SOURCE = string.c stdio.c
27 |
28 | # Contain path to source files
29 | SRC_FILE = $(_SOURCE:%.c=$(SRC_DIR)/%.c)
30 |
31 | # Output debug object file
32 | D_OBJ = $(_SOURCE:%.c=$(D_OBJ_DIR)/%.o)
33 |
34 | # Output release object file
35 | R_OBJ = $(_SOURCE:%.c=$(R_OBJ_DIR)/%.o)
36 |
37 | # Output dependency file
38 | DEP = .depend
39 |
40 | #-------------------------------------------------------------------------
41 |
42 | lib: $(LIB_ARCH)
43 |
44 | $(LIB_ARCH): $(D_OBJ)
45 | $(ARCH) $(ARFLAG) $(LIB_ARCH) $(D_OBJ)
46 |
47 | $(D_OBJ_DIR)/%.o: $(SRC_DIR)/%.c
48 | $(CCOM) $< -o $@ $(CFLAG)
49 |
50 | # Include dependency files for object files
51 | include $(DEP)
52 |
53 | # Clean object file
54 | clean:
55 | rm $(D_OBJ_DIR)/*
56 | rm $(LIB_ARCH)
57 |
58 | # Generate dependency for course and output to DEP file
59 | depend:
60 | $(MAKEDEPEND) -v -f$(DEP) -Y$(INC_DIR) $(SRC_FILE)
61 | rm $(DEP).bak
--------------------------------------------------------------------------------
/core/lib/libhal.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kapilks/Basic-Kernel/e672cfcaa81df053856f7ace7399bb8ce21a3eba/core/lib/libhal.a
--------------------------------------------------------------------------------
/core/lib/libstd.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kapilks/Basic-Kernel/e672cfcaa81df053856f7ace7399bb8ce21a3eba/core/lib/libstd.a
--------------------------------------------------------------------------------
/core/lib/source/stdio.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include <../kernel/include/console.h>
8 |
9 |
10 | /////////////
11 | /* Private */
12 | /////////////
13 |
14 |
15 | static size bprintf(char* buffer, const char* format, va_list arguments);
16 |
17 |
18 | //////////////////////
19 | /* Private Function */
20 | //////////////////////
21 |
22 |
23 | static size bprintf(char* buffer, const char* format, va_list arguments)
24 | {
25 | if(!format || !arguments)
26 | {
27 | return 0;
28 | }
29 |
30 | size formatLength = strlen(format);
31 | size index = 0;
32 |
33 | for(size i = 0; i < formatLength; ++i)
34 | {
35 | if(format[i] == '%')
36 | {
37 | i++;
38 |
39 | switch(format[i])
40 | {
41 | case 'c': // Characters
42 | {
43 | buffer[index] = va_arg(arguments, char);
44 | index++;
45 |
46 | break;
47 | }
48 | case 's': // String
49 | {
50 | const char* str = va_arg(arguments, char*);
51 | strcpy(&buffer[index], str);
52 | index += strlen(str);
53 |
54 | break;
55 | }
56 | default:
57 | {
58 | // Default decimal base
59 | enum BASE base = BASE_DEC;
60 |
61 | switch(format[i])
62 | {
63 | case 'x': // Hex
64 | {
65 | base = BASE_HEX; break;
66 | }
67 | case 'b': // Binary
68 | {
69 | base = BASE_BIN; break;
70 | }
71 | case 'o': // Octal
72 | {
73 | base = BASE_OCT; break;
74 | }
75 | case 'd': // Integers
76 | {
77 | base = BASE_DEC; break;
78 | }
79 | }
80 |
81 | uint32 num = va_arg(arguments, uint32);
82 |
83 | // 32 bits integer
84 | char str[32] = {0};
85 |
86 | inttostr(num, base, str);
87 | strcpy(&buffer[index], str);
88 | index += strlen(str);
89 | }
90 | }
91 | }
92 | else
93 | {
94 | buffer[index++] = format[i];
95 | }
96 | }
97 |
98 | buffer[index] = (char)0;
99 |
100 | // index id the length of buffer string
101 | return index;
102 | }
103 |
104 |
105 | //////////////////////
106 | /* Public Function */
107 | //////////////////////
108 |
109 |
110 | void printf(const char* format, ...)
111 | {
112 | char buffer[BUFFER_SIZE];
113 |
114 | va_list arguments;
115 | va_start(arguments, format);
116 |
117 | bprintf(buffer, format, arguments);
118 |
119 | va_end(arguments);
120 |
121 | printConsole(buffer);
122 | }
123 |
124 | void perror(const char* format, ...)
125 | {
126 | color consoleColor = consoleGetColor();
127 | // Using bg of consoleColor and fg as red
128 |
129 | consoleSetColor(makeColor(COLOR_LIGHT_RED, (consoleColor & BACKGROUND_COLOR) >> 4));
130 |
131 | // Same as printf
132 | char buffer[BUFFER_SIZE];
133 |
134 | va_list arguments;
135 | va_start(arguments, format);
136 |
137 | bprintf(buffer, format, arguments);
138 |
139 | va_end(arguments);
140 |
141 | printConsole(buffer);
142 |
143 |
144 | consoleSetColor(consoleColor);
145 | }
--------------------------------------------------------------------------------
/core/lib/source/string.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 |
4 | //////////////
5 | /* Private */
6 | //////////////
7 |
8 |
9 | // Integers characters in different base
10 | static char characters[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
11 |
12 |
13 | //////////////////////
14 | /* Public Function */
15 | //////////////////////
16 |
17 |
18 | size strlen(const char* str)
19 | {
20 | size length = 0;
21 |
22 | while(str[length] != 0)
23 | {
24 | length++;
25 | }
26 |
27 | /* This length exclude NULL character */
28 | return length;
29 | }
30 |
31 | char* strcpy(char* destination, const char* source)
32 | {
33 | char* destinationTmp = destination;
34 |
35 | while(*source)
36 | {
37 | *destination = *source;
38 | destination++;
39 | source++;
40 | }
41 |
42 | // Copy null character
43 | *destination = *source;
44 |
45 | return destinationTmp;
46 | }
47 |
48 | void* memset(void* destination, char value, size count)
49 | {
50 | // Converting for valid pointer ++
51 | uint8* destinationTmp = (uint8*)destination;
52 |
53 | for(; count > 0; --count, ++destinationTmp)
54 | {
55 | *destinationTmp = value;
56 | }
57 |
58 | return destination;
59 | }
60 |
61 | void* memcpy(void* destination, const void* source, size count)
62 | {
63 | uint8* destinationTmp = (uint8*)destination;
64 | const uint8* sourceTmp = (const uint8*)source;
65 |
66 | for(; count > 0; --count, ++destinationTmp, ++sourceTmp)
67 | {
68 | *destinationTmp = *sourceTmp;
69 | }
70 |
71 | return destination;
72 | }
73 |
74 | void inttostr(uint32 value, enum BASE base, char* destination)
75 | {
76 | char* destinationTmp = destination;
77 | uint8 ch;
78 |
79 | if(value == 0)
80 | {
81 | *destination++ = '0';
82 | *destination = '\0';
83 |
84 | return;
85 | }
86 |
87 | while(value > 0)
88 | {
89 | ch = (uint8)(value % base);
90 |
91 | *destination++ = characters[ch];
92 |
93 | value /= base;
94 | }
95 |
96 | // NULL character
97 | *destination = '\0';
98 |
99 | strrev(destinationTmp);
100 | }
101 |
102 | void strtoint(char* source, enum BASE base, uint32* destination)
103 | {
104 | uint32 output = 0;
105 |
106 | size length = strlen(source);
107 |
108 | for(; length > 0; --length, source++)
109 | {
110 | uint8 ch = (uint8)*source;
111 |
112 | if(ch >= 'a' && ch <= 'f')
113 | {
114 | ch = ch - (uint8)'a' + 10;
115 | }
116 | else if(ch >= 'A' && ch <= 'F')
117 | {
118 | ch = ch - (uint8)'A' + 10;
119 | }
120 | else
121 | {
122 | ch -= (uint8)'0';
123 | }
124 |
125 | output = output * base + ch;
126 | }
127 |
128 | *destination = output;
129 | }
130 |
131 | void strrev(char* source)
132 | {
133 | size length = strlen(source);
134 | uint8 tmp;
135 |
136 | size high = length - 1;
137 | size low = 0;
138 |
139 | while(low < high)
140 | {
141 | tmp = source[low];
142 | source[low] = source[high];
143 | source[high] = tmp;
144 |
145 | low++;
146 | high--;
147 | }
148 | }
149 |
150 | uint8 strcmp(const char* str1, const char* str2)
151 | {
152 | size len1 = strlen(str1);
153 | size len2 = strlen(str2);
154 |
155 | if(len1 != len2)
156 | {
157 | return 0;
158 | }
159 |
160 | for(size i = 0; i < len1; ++i)
161 | {
162 | if(*str1++ != *str2++)
163 | {
164 | return 0;
165 | }
166 | }
167 |
168 | return 1;
169 | }
--------------------------------------------------------------------------------
/grub/stage2_eltorito:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kapilks/Basic-Kernel/e672cfcaa81df053856f7ace7399bb8ce21a3eba/grub/stage2_eltorito
--------------------------------------------------------------------------------
/initialise.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Create diretories structure for binaries
4 | mkdir -p core/hal/obj/debug
5 | mkdir -p core/kernel/bin
6 | mkdir -p core/kernel/obj
7 | mkdir -p core/lib/obj
8 |
9 | # Dependencies files
10 | touch core/hal/.depend
11 | touch core/kernel/.depend
12 | touch core/lib/.depend
--------------------------------------------------------------------------------
/screenshots/home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kapilks/Basic-Kernel/e672cfcaa81df053856f7ace7399bb8ce21a3eba/screenshots/home.png
--------------------------------------------------------------------------------