Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
abeb22eaab
|
|||
|
a8582ba343
|
|||
|
b3687d20ee
|
|||
|
27569fd5d8
|
|||
|
|
14a9bdad7d | ||
|
|
756dc638e8 | ||
|
|
903188a543 | ||
|
|
8a68cf3b30 | ||
|
|
1085222d98 | ||
|
|
68a4be55ce | ||
|
|
cee509f6a1 | ||
|
|
c104657d52 | ||
|
|
1fa4b5c70a | ||
|
|
7071b4788b | ||
|
|
5ad32d3ee1 | ||
|
|
d02b3d62cb | ||
|
|
af716cb2ec | ||
|
|
e6f119236b | ||
|
|
c885e69be4 | ||
|
|
03b712ace0 | ||
|
|
87bb1d96fd | ||
|
|
8bac95890a | ||
|
|
d89a1c4071 | ||
|
|
becfc2bc3b | ||
|
|
9d665c9648 | ||
|
|
6f3c23e088 | ||
|
|
ef2de556e3 | ||
|
|
40561a6537 | ||
|
|
8093880eaa | ||
|
|
64ccec0866 | ||
|
|
bf0228d3ac | ||
|
|
5e4e6d2db8 | ||
|
|
fa879acd8a | ||
|
|
e14e5db15a | ||
|
|
d90682c40e | ||
|
|
a9a4b89c85 | ||
|
|
841e72b431 | ||
|
|
2fa918bc87 | ||
|
|
df7187ca75 | ||
|
|
8826a7d873 | ||
|
|
b0668b1fd7 | ||
|
|
cacc042a5c | ||
|
|
247558669e | ||
|
|
f55723c227 | ||
|
|
acbcc54e51 | ||
|
|
d2034cd68b | ||
|
|
b59af22897 | ||
|
|
4d05e0d620 | ||
|
|
3b39a0a1f4 | ||
|
|
f1f45fbeb6 | ||
|
|
6f5c05e0d9 | ||
|
|
a4b036dfbd | ||
|
|
a316367236 | ||
|
|
93f5feff85 | ||
|
|
7c80cc8af9 | ||
|
|
88debf5085 | ||
|
|
449873f55d | ||
|
|
adcfdc8231 | ||
|
|
deafe2439b | ||
|
|
b1e4ef8ad2 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,3 +5,4 @@ blankos.iso
|
|||||||
iso/
|
iso/
|
||||||
i386-elf-7.5.0-Linux-x86_64/
|
i386-elf-7.5.0-Linux-x86_64/
|
||||||
i386-elf-7.5.0-Linux-x86_64.tar.xz
|
i386-elf-7.5.0-Linux-x86_64.tar.xz
|
||||||
|
src/initrd/*.bin
|
||||||
|
|||||||
19
README.md
19
README.md
@@ -1,8 +1,12 @@
|
|||||||

|

|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> This is free and unencumbered software released into the public domain. Many things might be (are) broken.
|
||||||
|
> The project is a hobbyist operating system, and it comes without any warranty whatsoever! See the license for more info. Feedback and contributions are highly appreciated.
|
||||||
|
|
||||||
# BlankOS
|
# BlankOS
|
||||||
|
|
||||||
Rewritten monolithic, ring 0, lower-half, singletasking kernel for the x86 processor architecture, using GRUB 2 as bootloader. Emulation was tested on QEMU using Arch Linux 6.9.7-arch1-1, and on real hardware too.
|
Rewritten megalithic, ring 0, lower-half, singletasking kernel for the x86 processor architecture (using 32-bit protected mode), with GRUB 2 as bootloader. Emulation was tested on QEMU using Arch Linux 6.9.7-arch1-1, and on real hardware (UEFI and BIOS).
|
||||||
The long-term goal of this OS is to be capable of running user programs and having its own complete kernel C library so that users can write their own C programs and expand the system!
|
The long-term goal of this OS is to be capable of running user programs and having its own complete kernel C library so that users can write their own C programs and expand the system!
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -36,10 +40,11 @@ sudo dd bs=4M if=blankos.iso of=/dev/sdX status=progress oflag=sync
|
|||||||
|
|
||||||
Replace `sdX` with your USB drive name (you can find it by doing `sudo fdisk -l`).
|
Replace `sdX` with your USB drive name (you can find it by doing `sudo fdisk -l`).
|
||||||
Tada! You now have a working BlankOS USB stick. Go ahead and try it out!
|
Tada! You now have a working BlankOS USB stick. Go ahead and try it out!
|
||||||
|
(*Might not work properly on monitors that aren't Full HD*)
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
Two other documents are available to help you understand the project better. One is the User's Manual, labelled [USERS.md](docs/USERS.md), and the other one is the Developer's Manual, labelled [DEVELOPERS.md](docs/DEVELOPERS.md). They are full of useful resources around Blank OS. You'll learn how to use the system and how to contribute to it. *(The docs might not always be up-to-date)*
|
Two other documents are available to help you understand the project better. One is the User's Manual, labelled [USERS.md](docs/USERS.md), and the other one is the Developer's Manual, labelled [DEVELOPERS.md](docs/DEVELOPERS.md). They are full of useful resources: you'll learn how to use the system and how to contribute to it. *(The docs might not always be up-to-date)*
|
||||||
|
|
||||||
### Resources
|
### Resources
|
||||||
|
|
||||||
@@ -56,11 +61,12 @@ Two other documents are available to help you understand the project better. One
|
|||||||
|
|
||||||
- [X] Booting with GRUB
|
- [X] Booting with GRUB
|
||||||
- [X] Common basic structures (IDT, GDT, ISRs, IRQs)
|
- [X] Common basic structures (IDT, GDT, ISRs, IRQs)
|
||||||
- [X] Common drivers (framebuffer, keyboard, serial, timer)
|
- [X] Common drivers (framebuffer, keyboard, serial, timer, RTC, ATA PIO)
|
||||||
- [X] Kernel-space utilities (shell, simple programs)
|
- [X] Kernel-space utilities (shell, simple programs)
|
||||||
- [ ] Filesystem (FAT32 or VFS ramdisk)
|
- [ ] Filesystem (FAT32 or VFS ramdisk)
|
||||||
- [ ] Changing the default VGA font
|
- [ ] Changing the default VGA font
|
||||||
- [X] Paging/Page Frame Allocation
|
- [X] Dynamic memory allocator (get memmap from GRUB?)
|
||||||
|
- [ ] Paging/Page Frame Allocation
|
||||||
- [ ] TCP/IP Network stack
|
- [ ] TCP/IP Network stack
|
||||||
- [ ] Getting to Ring-3 (userspace)
|
- [ ] Getting to Ring-3 (userspace)
|
||||||
- [ ] Multitasking (via round robin scheduling)
|
- [ ] Multitasking (via round robin scheduling)
|
||||||
@@ -70,6 +76,3 @@ Two other documents are available to help you understand the project better. One
|
|||||||
- [ ] System calls
|
- [ ] System calls
|
||||||
- [ ] GUI
|
- [ ] GUI
|
||||||
- [ ] POSIX and ANSI specification compatibility
|
- [ ] POSIX and ANSI specification compatibility
|
||||||
|
|
||||||
> [!WARNING]
|
|
||||||
> This is a hobbyist operating system, and it comes without any warranty whatsoever! See the license for more info. Feedback and contributions are highly appreciated.
|
|
||||||
|
|||||||
5
debug.sh
Executable file
5
debug.sh
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
qemu-system-i386 -s -S -drive file=blankos.iso,format=raw &
|
||||||
|
sleep 1
|
||||||
|
gdb -x gdbinit
|
||||||
@@ -1,14 +1,24 @@
|
|||||||
# Blank OS Developer's Manual
|
# Blank OS Developer's Manual
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- Getting Started
|
||||||
|
- Debugging the kernel
|
||||||
|
- Emulated booting in UEFI mode
|
||||||
|
- Writing programs for BlankOS
|
||||||
|
- Changing the TTY font
|
||||||
|
- Changing the initial ramdisk content
|
||||||
|
- Changing the framebuffer resolution
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
### System description
|
### System description
|
||||||
|
|
||||||
Blank OS runs on a monolithic kernel booted by a 3rd party bootloader; GRUB (whose executable is named `stage2_eltorito`). The kernel is compiled in ELF format. The target processor architecture is 32-bit x86. Blank OS is BIOS-independent which means it does not use Real mode BIOS functions as its routines. It rather uses in and out port communication to communicate with hardware directly (such as the keyboard) and it uses specific memory locations (for example the framebuffer to manage the screen in text mode).
|
Blank OS is a megalithic kernel booted by a 3rd party bootloader, GRUB2, using the Multiboot2 specification. The kernel is compiled in ELF format. The target processor architecture is 32-bit x86. Blank OS is BIOS-independent which means it does not use Real mode BIOS functions as its routines. It rather uses in and out port communication to communicate with hardware directly (such as the keyboard) and it uses specific memory locations (for example the framebuffer to manage the screen in text mode). A linear framebuffer is requested in 1920x1080x32 mode via Multiboot and GRUB. It cannot run on other screen resolutions for now. The keyboard layout is QWERTY.
|
||||||
|
|
||||||
### Code structure
|
### Code structure
|
||||||
|
|
||||||
The source code is available in folder `src`. You will find subfolders corresponding to appropriate system parts, such as the kernel, the C library (including drivers) and programs.
|
The source code is available in folder `src`. You will find subfolders corresponding to appropriate system parts, such as the kernel, the C library (including drivers) and "programs", which are really just functions embedded in the kernel.
|
||||||
|
|
||||||
### System calls
|
### System calls
|
||||||
|
|
||||||
@@ -20,18 +30,23 @@ No system calls are available, as the OS runs in kernel-space.
|
|||||||
make debug
|
make debug
|
||||||
```
|
```
|
||||||
|
|
||||||
In another shell:
|
## Emulated booting in UEFI mode (QEMU w/ OVMF)
|
||||||
|
|
||||||
|
Install the OVMF firmware package by doing `sudo pacman -S ovmf` or the equivalent for your distro. Then, you can emulate the OS as if it was ran using an UEFI machine:
|
||||||
|
|
||||||
```
|
```
|
||||||
gdb kernel.elf
|
sudo qemu-system-i386 -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/ia32/OVMF_CODE.fd -drive if=pflash,format=raw,file=/usr/share/OVMF/ia32/OVMF_VARS.fd -drive file=blankos.iso,format=raw -m 4098
|
||||||
(gdb) target remote localhost:1234
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Making programs for the OS
|
## Writing programs for BlankOS
|
||||||
|
|
||||||
|
Be warned, these are not actual programs in the sense you'd expect. These are indeed functions that are called from the shell, and embedded in the kernel ELF binary. Real programs apart from the kernel are not yet a thing here, but might be one day.
|
||||||
|
|
||||||
|
(Now, there is a 'beginning' of something that we could call real programs, but I still suck at making the syscalls work. One day, one day...)
|
||||||
|
|
||||||
### Step 1 - Making the program and the entry point
|
### Step 1 - Making the program and the entry point
|
||||||
|
|
||||||
To make a program for the OS, first create the appropriate C source file and header file in the `src/programs` subfolder. Name it appropriately, for example `myprogram.c`.
|
To make a program for the OS, first create the appropriate C source file and header file in the `src/utils` subfolder. Name it appropriately, for example `myprogram.c`.
|
||||||
|
|
||||||
In this file, you will put the functions your program will use. The entry point for the program should be a void function named `program_<PROGRAM_NAME>`. The entry point can either take no arguments, or use the classic argc/argv structure.
|
In this file, you will put the functions your program will use. The entry point for the program should be a void function named `program_<PROGRAM_NAME>`. The entry point can either take no arguments, or use the classic argc/argv structure.
|
||||||
|
|
||||||
@@ -44,7 +59,7 @@ void program_myprogram(int argc, char* argv[])
|
|||||||
```
|
```
|
||||||
|
|
||||||
Then, code your stuff freely. The entry point function will basically be the "main" function of your program, like in a regular C file. You can make your own header file too, for example `myprogram.h`.
|
Then, code your stuff freely. The entry point function will basically be the "main" function of your program, like in a regular C file. You can make your own header file too, for example `myprogram.h`.
|
||||||
Keep in mind that the standard C library is not available here, so you'll have to use functions from the BlankOS C library, which is located in `src/libc`. Also feel free to look at the header files in `src/drivers` and `src/kernel`, there might be interesting functions in there too (managing input/output devices, the timer, etc..)
|
Keep in mind that the standard C library is not available here, so you'll have to use functions from the BlankOS C library, which is located in `src/libk`. Also feel free to look at the header files in `src/drivers` and `src/kernel`, there might be interesting functions in there too (managing input/output devices, the timer, etc..)
|
||||||
|
|
||||||
### Step 2 - Registering the program
|
### Step 2 - Registering the program
|
||||||
|
|
||||||
@@ -52,7 +67,7 @@ Now that your program is done, you will need to make it a part of the OS.
|
|||||||
|
|
||||||
#### General program header file registering
|
#### General program header file registering
|
||||||
|
|
||||||
To make the entry point function reachable from the shell, you first have to include it in the general programs header file located in `src/programs/programs.h`.
|
To make the entry point function reachable from the shell, you first have to include it in the general programs header file located in `src/utils/programs.h`.
|
||||||
|
|
||||||
Put the entry point function prototype in that file. A valid example might be:
|
Put the entry point function prototype in that file. A valid example might be:
|
||||||
|
|
||||||
@@ -74,7 +89,7 @@ Don't make your command name too long, preferably a few characters, like the oth
|
|||||||
|
|
||||||
#### Help utility registering (optional)
|
#### Help utility registering (optional)
|
||||||
|
|
||||||
Finally, you can add your command to the list of available commands by adding it to the `printf` call in the `src/programs/misc.c` source file, in the function `program_help()`.
|
Finally, you can add your command to the list of available commands by adding it to the `printf` call in the `src/utils/misc.c` source file, in the function `program_help()`.
|
||||||
|
|
||||||
If possible make sure that the new command name is aligned with the other ones.
|
If possible make sure that the new command name is aligned with the other ones.
|
||||||
|
|
||||||
@@ -86,4 +101,41 @@ The linking process should be taken care of by the appropriate Linker script `li
|
|||||||
|
|
||||||
If you're proud of what you've made, you can clone the repo, make your changes, open a pull request and maybe your program will be added to the main BlankOS repo, and later distributed in the new ISOs!
|
If you're proud of what you've made, you can clone the repo, make your changes, open a pull request and maybe your program will be added to the main BlankOS repo, and later distributed in the new ISOs!
|
||||||
|
|
||||||
|
## Changing the TTY font
|
||||||
|
|
||||||
|
In order to change the default font, first get your hands on a 8x16 `.psf` (PC Screen Font 2) formatted font. Then, put it in `include/fonts` and remove the default one (`UniCyr_8x16.psf`).
|
||||||
|
|
||||||
|
Go ahead and run `make` one time. The compilation/linking will fail because of unresolved symbols, but an object file should have been created in `build/fonts` with your custom font's name.
|
||||||
|
|
||||||
|
Read the symbols in that object file:
|
||||||
|
|
||||||
|
```
|
||||||
|
readelf -s -W build/fonts/YOUR_FONT_8x16.o
|
||||||
|
```
|
||||||
|
|
||||||
|
Get the symbol name that ends with `_start` and replace all occurences of it in the `src/drivers/framebuffer.c` file.
|
||||||
|
|
||||||
|
Then, run `make` again and the font should have changed properly.
|
||||||
|
|
||||||
|
## Changing the initial ramdisk content
|
||||||
|
|
||||||
|
The system loads an initial ramdisk as a simple TAR file located in `iso/boot/initrd.tar`.
|
||||||
|
You can add, delete, or modify this file's contents by doing that in the `src/initrd` folder. Anything in that folder will be added to the initial ramdisk and will therefore be loaded into the system.
|
||||||
|
|
||||||
|
The ramdisk gets loaded as a GRUB2 module.
|
||||||
|
|
||||||
|
## Changing the framebuffer resolution
|
||||||
|
|
||||||
|
Locate the framebuffer request tag from the Multiboot2 header in `src/kernel/loader.s`. It should look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
align 8
|
||||||
|
dw 5 ; 2
|
||||||
|
dw 0 ; 2
|
||||||
|
dd 20 ; 4
|
||||||
|
dd 1920 ; 4
|
||||||
|
dd 1080 ; 4
|
||||||
|
dd 32 ; 4
|
||||||
|
```
|
||||||
|
|
||||||
|
Change the `1920` and `1080` values with the resolution you want, according to your screen. Be aware that this might break some programs that rely on the hardcoded Full HD framebuffer value (1920x1080x32). You can also try switching the value under that,`32`, but it will break the display because the kernel is made for 32bpp.
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ Shows all of the available commands, which are explained here.
|
|||||||
|
|
||||||
#### `panic`
|
#### `panic`
|
||||||
|
|
||||||
Triggers a kernel panic by trying to divide four by zero.
|
Triggers a kernel panic by reserved exception.
|
||||||
|
|
||||||
#### `words`
|
#### `words`
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ Options:
|
|||||||
- `<nothing>` will default to `PRIMES_MAX` (a million)
|
- `<nothing>` will default to `PRIMES_MAX` (a million)
|
||||||
- `<integer>` will compute primes up to that number
|
- `<integer>` will compute primes up to that number
|
||||||
|
|
||||||
#### `rainbow`
|
#### `rainbow <string>`
|
||||||
|
|
||||||
Asks for text and then outputs it with different vibrant colors.
|
Asks for text and then outputs it with different vibrant colors.
|
||||||
|
|
||||||
@@ -69,19 +69,19 @@ Clears the screen by scrolling (screen height) times.
|
|||||||
|
|
||||||
A math lexer & parser that can calculate simple arithmetic operations. Adding, subtracting, multiplying, dividing, and factoring are supported. (I plan to get support for trigonometric functions maybe)
|
A math lexer & parser that can calculate simple arithmetic operations. Adding, subtracting, multiplying, dividing, and factoring are supported. (I plan to get support for trigonometric functions maybe)
|
||||||
|
|
||||||
#### `bf`
|
#### `bf <optional: file>`
|
||||||
|
|
||||||
A brainfuck interpreter with every instruction and default tape size (30k cells).
|
A brainfuck interpreter with every instruction and default tape size (30k cells). Takes an optional argument, the filename for a Brainfuck source file.
|
||||||
|
|
||||||
#### `uptime`
|
#### `uptime`
|
||||||
|
|
||||||
Gets system uptime from the timer in ticks. Ticks are incremented at a rate of 18.222Hz (18.222 ticks per second).
|
Gets system uptime from the timer in ticks. Ticks are incremented at a rate of 18.222Hz (18.222 ticks per second).
|
||||||
|
|
||||||
#### `echo`
|
#### `echo <string>`
|
||||||
|
|
||||||
The classic echo command, that outputs your input.
|
The classic echo command, that outputs your input.
|
||||||
|
|
||||||
#### `sysinfo`
|
#### `sysinfo [option]`
|
||||||
|
|
||||||
Outputs information about the current system (CPU and RAM).
|
Outputs information about the current system (CPU and RAM).
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ Options:
|
|||||||
- `<nothing>` will show basic info about the CPUid and lower/upper memory.
|
- `<nothing>` will show basic info about the CPUid and lower/upper memory.
|
||||||
- `-v` will output the CPUID, lower/upper memory, and the memory map.
|
- `-v` will output the CPUID, lower/upper memory, and the memory map.
|
||||||
|
|
||||||
#### `conway`
|
#### `conway [option]`
|
||||||
|
|
||||||
A classic Game of Life implementation with standard rules and 100 generations.
|
A classic Game of Life implementation with standard rules and 100 generations.
|
||||||
|
|
||||||
@@ -98,14 +98,56 @@ Options:
|
|||||||
- `-g` will spawn a classic glider
|
- `-g` will spawn a classic glider
|
||||||
- `-l` will spawn a lightweight spaceship
|
- `-l` will spawn a lightweight spaceship
|
||||||
|
|
||||||
#### `rot13`
|
#### `rot13 <string>`
|
||||||
|
|
||||||
Encode a string using the rot13 cipher.
|
Encode a string using the rot13 cipher.
|
||||||
|
|
||||||
#### `morse`
|
#### `morse <string>`
|
||||||
|
|
||||||
Convert a string to its morse equivalent.
|
Convert a string to its morse equivalent.
|
||||||
|
|
||||||
#### `cowsay`
|
#### `cowsay <string>`
|
||||||
|
|
||||||
Makes a cow speak!
|
Makes a cow speak!
|
||||||
|
|
||||||
|
#### `pi <terms>`
|
||||||
|
|
||||||
|
Computes Pi up to a couple of digits using the Leibniz series; takes one integer argument, the number of terms of the series to compute.
|
||||||
|
|
||||||
|
#### `bmp <file>`
|
||||||
|
|
||||||
|
Shows information about a 24-bit BMP image and renders it in the terminal.
|
||||||
|
|
||||||
|
### Initrd utilities
|
||||||
|
|
||||||
|
You can browse the (really) simple TAR filesystem with the following commands:
|
||||||
|
|
||||||
|
#### `ls`
|
||||||
|
|
||||||
|
Lists all files present in `initrd.tar`.
|
||||||
|
|
||||||
|
#### `cat <file>`
|
||||||
|
|
||||||
|
Prints file content to terminal. Filename must be specified the same way as it is outputted when using `ls`.
|
||||||
|
|
||||||
|
### Games
|
||||||
|
|
||||||
|
#### `naval`
|
||||||
|
|
||||||
|
Starts a simplified naval battle game with 5 ships, one position each.
|
||||||
|
|
||||||
|
#### `snake <ticks>`
|
||||||
|
|
||||||
|
Starts a simplified and buggy snake game. You can choose the speed by setting the `ticks` argument, or let it default to a normal speed.
|
||||||
|
|
||||||
|
Controls:
|
||||||
|
- `q` to quit
|
||||||
|
- `wasd` to move
|
||||||
|
|
||||||
|
#### `exec <binary>`
|
||||||
|
|
||||||
|
Executes a binary file. Warning: this is highly broken and syscalls aren't working. It's written in a childish manner. Help is always appreciated (lol).
|
||||||
|
|
||||||
|
#### `uhex <file>`
|
||||||
|
|
||||||
|
Prints the hex and ASCII contents of a file.
|
||||||
|
|||||||
@@ -12,21 +12,19 @@ extern char* framebuffer;
|
|||||||
|
|
||||||
void putpixel(uint32_t* fb, int pitch, int bpp, int x, int y, uint32_t color)
|
void putpixel(uint32_t* fb, int pitch, int bpp, int x, int y, uint32_t color)
|
||||||
{
|
{
|
||||||
if (bpp == 32) {
|
uint32_t* pixel_addr = (uint32_t*)((uint8_t*)fb + y * pitch + x *(bpp / 8));
|
||||||
uint32_t* pixel_addr = (uint32_t*)((uint8_t*)fb + y * pitch + x *(bpp / 8));
|
*pixel_addr = color;
|
||||||
*pixel_addr = color;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_char(unsigned short int c, int cx, int cy, uint32_t fg, uint32_t bg)
|
void draw_char(unsigned short int c, int cx, int cy, uint32_t fg, uint32_t bg)
|
||||||
{
|
{
|
||||||
PSF_font *font = (PSF_font*)&_binary_include_fonts_UniCyr_8x16_psf_start;
|
PSF_font *font = (PSF_font*)&FONT_START;
|
||||||
int bytesperline=(font->width+7)/8;
|
int bytesperline=(font->width+7)/8;
|
||||||
if (unicode != NULL) {
|
if (unicode != NULL) {
|
||||||
c = unicode[c];
|
c = unicode[c];
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char* glyph = (unsigned char*)&_binary_include_fonts_UniCyr_8x16_psf_start + font->headersize + (c>0&&c<font->numglyph?c:0)*font->bytesperglyph;
|
unsigned char* glyph = (unsigned char*)&FONT_START + font->headersize + (c>0&&c<font->numglyph?c:0)*font->bytesperglyph;
|
||||||
|
|
||||||
int offs =
|
int offs =
|
||||||
(cy * font->height * scanline) +
|
(cy * font->height * scanline) +
|
||||||
@@ -56,7 +54,7 @@ void scroll()
|
|||||||
{
|
{
|
||||||
serial_printf(3, "Scrolling...\r");
|
serial_printf(3, "Scrolling...\r");
|
||||||
uint32_t bg_color = 0x00000000;
|
uint32_t bg_color = 0x00000000;
|
||||||
PSF_font *font = (PSF_font*)&_binary_include_fonts_UniCyr_8x16_psf_start;
|
PSF_font *font = (PSF_font*)&FONT_START;
|
||||||
|
|
||||||
int line_size = font->height * scanline;
|
int line_size = font->height * scanline;
|
||||||
int framebuffer_size = scanline * font->height * (1080/font->height);
|
int framebuffer_size = scanline * font->height * (1080/font->height);
|
||||||
@@ -9,11 +9,16 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
extern int scanline;
|
extern int scanline;
|
||||||
extern char _binary_include_fonts_UniCyr_8x16_psf_start;
|
|
||||||
uint16_t* unicode;
|
|
||||||
|
|
||||||
|
#define FONT_START _binary_include_fonts_viscii10_8x16_psfu_start
|
||||||
|
#define FONT_END _binary_include_fonts_viscii10_8x16_psfu_start
|
||||||
|
|
||||||
|
extern char FONT_START;
|
||||||
|
extern char FONT_END;
|
||||||
|
uint16_t* unicode;
|
||||||
#define PIXEL uint32_t
|
#define PIXEL uint32_t
|
||||||
|
|
||||||
|
#define USHRT_MAX 10000
|
||||||
#define PSF1_FONT_MAGIC 0x0436
|
#define PSF1_FONT_MAGIC 0x0436
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -38,5 +43,6 @@ typedef struct {
|
|||||||
void putpixel(uint32_t* fb, int pitch, int bpp, int x, int y, uint32_t color);
|
void putpixel(uint32_t* fb, int pitch, int bpp, int x, int y, uint32_t color);
|
||||||
void draw_char(unsigned short int c, int cx, int cy, uint32_t fg, uint32_t bg);
|
void draw_char(unsigned short int c, int cx, int cy, uint32_t fg, uint32_t bg);
|
||||||
void scroll();
|
void scroll();
|
||||||
|
void psf_init();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include "../kernel/io.h"
|
#include "../kernel/io.h"
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
#include "../libc/stdio.h"
|
#include "../libk/stdio.h"
|
||||||
|
|
||||||
int init_serial()
|
int init_serial()
|
||||||
{
|
{
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
// https://github.com/xamidev/blankos
|
// https://github.com/xamidev/blankos
|
||||||
|
|
||||||
#include "../kernel/system.h"
|
#include "../kernel/system.h"
|
||||||
#include "../libc/stdio.h"
|
#include "../libk/stdio.h"
|
||||||
|
|
||||||
volatile unsigned long global_ticks = 0;
|
volatile unsigned long global_ticks = 0;
|
||||||
|
|
||||||
2
grub.cfg
2
grub.cfg
@@ -1,6 +1,6 @@
|
|||||||
menuentry "Blank OS" {
|
menuentry "Blank OS" {
|
||||||
insmod all_video
|
insmod all_video
|
||||||
set gfxpayload=1024x768x32
|
|
||||||
multiboot2 /boot/kernel.elf
|
multiboot2 /boot/kernel.elf
|
||||||
|
module2 /boot/initrd.tar
|
||||||
boot
|
boot
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
BIN
include/fonts/viscii10-8x16.psfu
Normal file
BIN
include/fonts/viscii10-8x16.psfu
Normal file
Binary file not shown.
@@ -4,7 +4,7 @@
|
|||||||
// https://github.com/xamidev/blankos
|
// https://github.com/xamidev/blankos
|
||||||
|
|
||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
#include "../libc/stdio.h"
|
#include "../libk/stdio.h"
|
||||||
|
|
||||||
struct gdt_entry gdt[3];
|
struct gdt_entry gdt[3];
|
||||||
struct gdt_ptr gp;
|
struct gdt_ptr gp;
|
||||||
@@ -36,9 +36,9 @@ void gdt_install()
|
|||||||
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
|
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
|
||||||
|
|
||||||
// Ring 3
|
// Ring 3
|
||||||
gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF);
|
//gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF);
|
||||||
gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF);
|
//gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF);
|
||||||
|
|
||||||
gdt_flush();
|
gdt_flush();
|
||||||
printf("[kernel] GDT gates set (ring 0 and 3), gdt=0x%x\n", &gdt);
|
printf("[kernel] GDT gates set (ring 0), gdt=0x%x\n", (unsigned int)&gdt);
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "../libc/stdio.h"
|
#include "../libk/stdio.h"
|
||||||
|
|
||||||
struct idt_entry idt[256];
|
struct idt_entry idt[256];
|
||||||
struct idt_ptr idtp;
|
struct idt_ptr idtp;
|
||||||
@@ -30,5 +30,5 @@ void idt_install()
|
|||||||
memset(&idt, 0, sizeof(struct idt_entry)*256);
|
memset(&idt, 0, sizeof(struct idt_entry)*256);
|
||||||
|
|
||||||
idt_load();
|
idt_load();
|
||||||
printf("[kernel] loaded IDT at idt=0x%x\n", &idt);
|
printf("[kernel] loaded IDT at idt=0x%x\n", (unsigned int)&idt);
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
#include "../libc/stdio.h"
|
#include "../libk/stdio.h"
|
||||||
|
|
||||||
extern void irq0();
|
extern void irq0();
|
||||||
extern void irq1();
|
extern void irq1();
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
// https://github.com/xamidev/blankos
|
// https://github.com/xamidev/blankos
|
||||||
|
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "../libc/stdio.h"
|
#include "../libk/stdio.h"
|
||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
|
|
||||||
extern void isr0();
|
extern void isr0();
|
||||||
@@ -116,7 +116,7 @@ void fault_handler(struct regs *r)
|
|||||||
{
|
{
|
||||||
if (r->int_no < 32)
|
if (r->int_no < 32)
|
||||||
{
|
{
|
||||||
printf("\n\n*** [Kernel panic - %s Exception] ***\nInterrupt error code %u\nedi: %x esi: %u ebp: %u esp: %u\nebx: %u edx: %u ecx: %u eax: %u\neip: %x cs:%x eflags: %x ss: %x\ngs: %x fs: %x es: %x ds: %x\nHalting!\n", exception_messages[r->int_no], r->err_code, r->edi, r->esi, r->ebp, r->esp, r->ebx, r->edx, r->ecx, r->eax, r->eip, r->cs, r->eflags, r->ss, r->gs, r->fs, r->es, r->ds);
|
colorprintf(white, red, "\n\n*** [Kernel panic - %s Exception] ***\nInterrupt error code %u\nedi: 0x%x\nesi: 0x%x\nebp: 0x%x\nesp: 0x%x\neip: 0x%x\neax: 0x%x\nebx: 0x%x\necx: 0x%x\nedx: 0x%x\ncs: 0x%x\neflags: 0x%x\nss: 0x%x\ngs: 0x%x\nfs: 0x%x\nes: 0x%x\nds: 0x%x\nHalting!\n", exception_messages[r->int_no], r->err_code, r->edi, r->esi, r->ebp, r->esp, r->eip, r->eax, r->ebx, r->ecx, r->edx, r->cs, r->eflags, r->ss, r->gs, r->fs, r->es, r->ds);
|
||||||
for (;;);
|
for (;;);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,20 +3,21 @@
|
|||||||
// Licensed under the Unlicense. See the repo below.
|
// Licensed under the Unlicense. See the repo below.
|
||||||
// https://github.com/xamidev/blankos
|
// https://github.com/xamidev/blankos
|
||||||
|
|
||||||
#include "../libc/stdio.h"
|
#include "../libk/stdio.h"
|
||||||
#include "../drivers/serial.h"
|
#include "../drivers/serial.h"
|
||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "paging.h"
|
|
||||||
#include "../drivers/ata.h"
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "../drivers/framebuffer.h"
|
#include "../drivers/framebuffer.h"
|
||||||
#include "kmain.h"
|
#include "kmain.h"
|
||||||
|
#include "multiboot2.h"
|
||||||
|
|
||||||
void kmain(multiboot2_info *mb_info)
|
void kmain(multiboot2_info *mb_info)
|
||||||
{
|
{
|
||||||
multiboot2_tag_framebuffer *fb_info = NULL;
|
multiboot2_tag_framebuffer *fb_info = NULL;
|
||||||
|
struct multiboot_tag_mmap *mmap_tag = NULL;
|
||||||
|
struct multiboot_tag_module *initrd_module = NULL;
|
||||||
|
|
||||||
uint8_t *tags = mb_info->tags;
|
uint8_t *tags = mb_info->tags;
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -24,36 +25,79 @@ void kmain(multiboot2_info *mb_info)
|
|||||||
uint32_t tag_size = *((uint32_t*) (tags + 4));
|
uint32_t tag_size = *((uint32_t*) (tags + 4));
|
||||||
|
|
||||||
if (tag_type == 0) break;
|
if (tag_type == 0) break;
|
||||||
if (tag_type == 8) {
|
if (tag_type == MULTIBOOT_TAG_TYPE_FRAMEBUFFER) {
|
||||||
fb_info = (multiboot2_tag_framebuffer*) tags;
|
fb_info = (multiboot2_tag_framebuffer*) tags;
|
||||||
}
|
}
|
||||||
|
if (tag_type == MULTIBOOT_TAG_TYPE_MMAP) {
|
||||||
|
mmap_tag = (struct multiboot_tag_mmap*) tags;
|
||||||
|
}
|
||||||
|
if (tag_type == MULTIBOOT_TAG_TYPE_MODULE) {
|
||||||
|
initrd_module = (struct multiboot_tag_module*) tags;
|
||||||
|
}
|
||||||
|
|
||||||
tags += ((tag_size + 7) & ~7);
|
tags += ((tag_size + 7) & ~7);
|
||||||
}
|
}
|
||||||
|
|
||||||
serial_printf(3, "Framebuffer Address: 0x%x", fb_info->framebuffer_addr);
|
if (fb_info) { // fb setup
|
||||||
serial_printf(3, "Framebuffer Width: %u", fb_info->framebuffer_width);
|
|
||||||
serial_printf(3, "Framebuffer Height: %u", fb_info->framebuffer_height);
|
|
||||||
serial_printf(3, "Framebuffer Pitch: %u", fb_info->framebuffer_pitch);
|
|
||||||
serial_printf(3, "Framebuffer BPP: %u", fb_info->framebuffer_bpp);
|
|
||||||
|
|
||||||
if (fb_info) {
|
|
||||||
framebuffer = (uint32_t *)(uintptr_t) fb_info->framebuffer_addr;
|
framebuffer = (uint32_t *)(uintptr_t) fb_info->framebuffer_addr;
|
||||||
|
|
||||||
uint32_t width = fb_info->framebuffer_width;
|
uint32_t width = fb_info->framebuffer_width;
|
||||||
uint32_t height = fb_info->framebuffer_height;
|
uint32_t height = fb_info->framebuffer_height;
|
||||||
uint32_t bpp = fb_info->framebuffer_bpp;
|
bpp = fb_info->framebuffer_bpp;
|
||||||
|
pitch = fb_info->framebuffer_pitch;
|
||||||
|
|
||||||
//8x16 font, not padded
|
//8x16 font, not padded
|
||||||
VGA_WIDTH = width/8;
|
VGA_WIDTH = width/8;
|
||||||
VGA_HEIGHT = height/16;
|
VGA_HEIGHT = height/16;
|
||||||
serial_printf(3, "VGA_WIDTH=%d, VGA_HEIGHT=%d", VGA_WIDTH, VGA_HEIGHT);
|
serial_printf(3, "VGA_WIDTH=%d, VGA_HEIGHT=%d", VGA_WIDTH, VGA_HEIGHT);
|
||||||
scanline = width * (bpp/8);
|
scanline = width * (bpp/8);
|
||||||
|
|
||||||
|
serial_printf(3, "Framebuffer Address: 0x%x", fb_info->framebuffer_addr);
|
||||||
|
serial_printf(3, "Framebuffer Width: %u", fb_info->framebuffer_width);
|
||||||
|
serial_printf(3, "Framebuffer Height: %u", fb_info->framebuffer_height);
|
||||||
|
serial_printf(3, "Framebuffer Pitch: %u", fb_info->framebuffer_pitch);
|
||||||
|
serial_printf(3, "Framebuffer BPP: %u", fb_info->framebuffer_bpp);
|
||||||
|
}
|
||||||
|
printf("[kernel] multiboot2 info at 0x%x, size=%u\n", mb_info, mb_info->total_size);
|
||||||
|
printf("[kernel] framebuffer discovered at 0x%x\n", (unsigned int)fb_info->framebuffer_addr);
|
||||||
|
printf("[kernel] fb0: width=%u, height=%u, pitch=%u, bpp=%u\n", fb_info->framebuffer_width, fb_info->framebuffer_height, fb_info->framebuffer_pitch, fb_info->framebuffer_bpp);
|
||||||
|
|
||||||
|
if (mmap_tag) // memmap debug print
|
||||||
|
{
|
||||||
|
puts("[kernel] found memory map tag by multiboot2\n");
|
||||||
|
struct multiboot_mmap_entry *mmap = mmap_tag->entries;
|
||||||
|
|
||||||
|
while ((uint8_t*) mmap < tags + mmap_tag->size)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (mmap->addr != 0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
serial_printf(3, "base addr=0x%x%x, length=0x%x%x, type=%u",
|
||||||
|
(uint32_t) (mmap->addr >> 32),
|
||||||
|
(uint32_t) (mmap->addr & 0xFFFFFFFF),
|
||||||
|
(uint32_t) (mmap->len >> 32),
|
||||||
|
(uint32_t) (mmap->len & 0xFFFFFFFF),
|
||||||
|
mmap->type);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
mmap = (struct multiboot_mmap_entry*) ((uint8_t*)mmap + mmap_tag->entry_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("[kernel] multiboot2 info at 0x%x, size=%u\n", mb_info, mb_info->total_size);
|
if (initrd_module) {
|
||||||
printf("[kernel] framebuffer discovered at 0x%x\n", fb_info->framebuffer_addr);
|
initrd_addr = initrd_module->mod_start;
|
||||||
printf("[kernel] fb0: width=%u, height=%u, pitch=%u, bpp=%u\n", fb_info->framebuffer_width, fb_info->framebuffer_height, fb_info->framebuffer_pitch, fb_info->framebuffer_bpp);
|
|
||||||
|
uint32_t initrd_start = initrd_module->mod_start;
|
||||||
|
uint32_t initrd_end = initrd_module->mod_end;
|
||||||
|
uint32_t initrd_size = initrd_end - initrd_start;
|
||||||
|
|
||||||
|
printf("[kernel] TAR initrd module found at 0x%x, size=%u bytes\n", initrd_start, initrd_size);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
puts("[kernel] TAR initrd module not found\n");
|
||||||
|
}
|
||||||
|
|
||||||
init_serial();
|
init_serial();
|
||||||
gdt_install();
|
gdt_install();
|
||||||
@@ -62,13 +106,7 @@ void kmain(multiboot2_info *mb_info)
|
|||||||
irq_install();
|
irq_install();
|
||||||
__asm__ __volatile__("sti");
|
__asm__ __volatile__("sti");
|
||||||
|
|
||||||
//init_paging();
|
|
||||||
//test_read_sector();
|
|
||||||
//uint32_t *ptr = (uint32_t*)0xA0000000;
|
|
||||||
//uint32_t do_page_fault = *ptr;
|
|
||||||
|
|
||||||
timer_install();
|
timer_install();
|
||||||
keyboard_install();
|
printf("Nothing to do, halting...");
|
||||||
printf("[kernel] spawning shell...\n");
|
asm("hlt");
|
||||||
shell_install();
|
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,10 @@
|
|||||||
#ifndef KMAIN_H
|
#ifndef KMAIN_H
|
||||||
#define KMAIN_H
|
#define KMAIN_H
|
||||||
|
|
||||||
|
#define BLANK_VERSION "0.3.123-alpha"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
@@ -28,9 +32,13 @@ unsigned int g_multiboot_info_address;
|
|||||||
|
|
||||||
uint32_t* framebuffer;
|
uint32_t* framebuffer;
|
||||||
int scanline;
|
int scanline;
|
||||||
|
uint32_t initrd_addr;
|
||||||
|
|
||||||
// in characters, not pixels
|
// in characters, not pixels
|
||||||
uint32_t VGA_WIDTH;
|
uint32_t VGA_WIDTH;
|
||||||
uint32_t VGA_HEIGHT;
|
uint32_t VGA_HEIGHT;
|
||||||
|
|
||||||
|
uint32_t bpp;
|
||||||
|
uint32_t pitch;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -7,13 +7,14 @@ global loader
|
|||||||
|
|
||||||
section .multiboot_header
|
section .multiboot_header
|
||||||
|
|
||||||
|
mb_start:
|
||||||
align 8
|
align 8
|
||||||
|
|
||||||
; ASM macros
|
; ASM macros
|
||||||
|
|
||||||
MAGIC_NUMBER equ 0xe85250d6 ; multiboot2 magic
|
MAGIC_NUMBER equ 0xe85250d6 ; multiboot2 magic
|
||||||
FLAGS equ 0x0 ; 32-bit protected mode for i386
|
FLAGS equ 0x0 ; 32-bit protected mode for i386
|
||||||
HEADER_LEN equ 44 ; Tags=2+2+4+4+4+4+2+2+4=28
|
HEADER_LEN equ mb_end-mb_start
|
||||||
CHECKSUM equ -(MAGIC_NUMBER + FLAGS + HEADER_LEN)
|
CHECKSUM equ -(MAGIC_NUMBER + FLAGS + HEADER_LEN)
|
||||||
|
|
||||||
; Multiboot 2 header, according to specification (16bytes)
|
; Multiboot 2 header, according to specification (16bytes)
|
||||||
@@ -26,7 +27,7 @@ CHECKSUM equ -(MAGIC_NUMBER + FLAGS + HEADER_LEN)
|
|||||||
; Tags? (28bytes)
|
; Tags? (28bytes)
|
||||||
|
|
||||||
; Tag 1 : set graphics mode (only recommended, can be overriden by GRUB)
|
; Tag 1 : set graphics mode (only recommended, can be overriden by GRUB)
|
||||||
|
align 8
|
||||||
dw 5 ; 2
|
dw 5 ; 2
|
||||||
dw 0 ; 2
|
dw 0 ; 2
|
||||||
dd 20 ; 4
|
dd 20 ; 4
|
||||||
@@ -36,11 +37,13 @@ CHECKSUM equ -(MAGIC_NUMBER + FLAGS + HEADER_LEN)
|
|||||||
|
|
||||||
; End of tags
|
; End of tags
|
||||||
|
|
||||||
|
align 8
|
||||||
|
dw 0 ; 2
|
||||||
dw 0 ; 2
|
dw 0 ; 2
|
||||||
;dw 0 ; 2
|
|
||||||
dd 8 ; 4
|
dd 8 ; 4
|
||||||
|
|
||||||
; End of Multiboot 2 header
|
; End of Multiboot 2 header
|
||||||
|
mb_end:
|
||||||
|
|
||||||
section .text:
|
section .text:
|
||||||
|
|
||||||
@@ -48,6 +51,7 @@ KERNEL_STACK_SIZE equ 4096
|
|||||||
extern kmain
|
extern kmain
|
||||||
|
|
||||||
loader:
|
loader:
|
||||||
|
mov esp, kernel_stack + KERNEL_STACK_SIZE
|
||||||
cli
|
cli
|
||||||
push ebx
|
push ebx
|
||||||
call kmain
|
call kmain
|
||||||
@@ -208,6 +212,6 @@ irq_common_stub:
|
|||||||
|
|
||||||
section .bss
|
section .bss
|
||||||
align 4
|
align 4
|
||||||
|
|
||||||
kernel_stack:
|
kernel_stack:
|
||||||
resb KERNEL_STACK_SIZE
|
resb KERNEL_STACK_SIZE
|
||||||
mov esp, kernel_stack + KERNEL_STACK_SIZE
|
|
||||||
417
kernel/multiboot2.h
Normal file
417
kernel/multiboot2.h
Normal file
@@ -0,0 +1,417 @@
|
|||||||
|
/* multiboot2.h - Multiboot 2 header file. */
|
||||||
|
/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
|
||||||
|
* DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||||
|
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MULTIBOOT_HEADER
|
||||||
|
#define MULTIBOOT_HEADER 1
|
||||||
|
|
||||||
|
/* How many bytes from the start of the file we search for the header. */
|
||||||
|
#define MULTIBOOT_SEARCH 32768
|
||||||
|
#define MULTIBOOT_HEADER_ALIGN 8
|
||||||
|
|
||||||
|
/* The magic field should contain this. */
|
||||||
|
#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
|
||||||
|
|
||||||
|
/* This should be in %eax. */
|
||||||
|
#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
|
||||||
|
|
||||||
|
/* Alignment of multiboot modules. */
|
||||||
|
#define MULTIBOOT_MOD_ALIGN 0x00001000
|
||||||
|
|
||||||
|
/* Alignment of the multiboot info structure. */
|
||||||
|
#define MULTIBOOT_INFO_ALIGN 0x00000008
|
||||||
|
|
||||||
|
/* Flags set in the ’flags’ member of the multiboot header. */
|
||||||
|
|
||||||
|
#define MULTIBOOT_TAG_ALIGN 8
|
||||||
|
#define MULTIBOOT_TAG_TYPE_END 0
|
||||||
|
#define MULTIBOOT_TAG_TYPE_CMDLINE 1
|
||||||
|
#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
|
||||||
|
#define MULTIBOOT_TAG_TYPE_MODULE 3
|
||||||
|
#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
|
||||||
|
#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
|
||||||
|
#define MULTIBOOT_TAG_TYPE_MMAP 6
|
||||||
|
#define MULTIBOOT_TAG_TYPE_VBE 7
|
||||||
|
#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
|
||||||
|
#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
|
||||||
|
#define MULTIBOOT_TAG_TYPE_APM 10
|
||||||
|
#define MULTIBOOT_TAG_TYPE_EFI32 11
|
||||||
|
#define MULTIBOOT_TAG_TYPE_EFI64 12
|
||||||
|
#define MULTIBOOT_TAG_TYPE_SMBIOS 13
|
||||||
|
#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
|
||||||
|
#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
|
||||||
|
#define MULTIBOOT_TAG_TYPE_NETWORK 16
|
||||||
|
#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
|
||||||
|
#define MULTIBOOT_TAG_TYPE_EFI_BS 18
|
||||||
|
#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
|
||||||
|
#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
|
||||||
|
#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
|
||||||
|
|
||||||
|
#define MULTIBOOT_HEADER_TAG_END 0
|
||||||
|
#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
|
||||||
|
#define MULTIBOOT_HEADER_TAG_ADDRESS 2
|
||||||
|
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
|
||||||
|
#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
|
||||||
|
#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
|
||||||
|
#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
|
||||||
|
#define MULTIBOOT_HEADER_TAG_EFI_BS 7
|
||||||
|
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
|
||||||
|
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
|
||||||
|
#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
|
||||||
|
|
||||||
|
#define MULTIBOOT_ARCHITECTURE_I386 0
|
||||||
|
#define MULTIBOOT_ARCHITECTURE_MIPS32 4
|
||||||
|
#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
|
||||||
|
|
||||||
|
#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
|
||||||
|
#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
|
||||||
|
#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
|
||||||
|
|
||||||
|
#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
|
||||||
|
#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
|
||||||
|
|
||||||
|
#ifndef ASM_FILE
|
||||||
|
|
||||||
|
typedef unsigned char multiboot_uint8_t;
|
||||||
|
typedef unsigned short multiboot_uint16_t;
|
||||||
|
typedef unsigned int multiboot_uint32_t;
|
||||||
|
typedef unsigned long long multiboot_uint64_t;
|
||||||
|
|
||||||
|
struct multiboot_header
|
||||||
|
{
|
||||||
|
/* Must be MULTIBOOT_MAGIC - see above. */
|
||||||
|
multiboot_uint32_t magic;
|
||||||
|
|
||||||
|
/* ISA */
|
||||||
|
multiboot_uint32_t architecture;
|
||||||
|
|
||||||
|
/* Total header length. */
|
||||||
|
multiboot_uint32_t header_length;
|
||||||
|
|
||||||
|
/* The above fields plus this one must equal 0 mod 2^32. */
|
||||||
|
multiboot_uint32_t checksum;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_header_tag
|
||||||
|
{
|
||||||
|
multiboot_uint16_t type;
|
||||||
|
multiboot_uint16_t flags;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_header_tag_information_request
|
||||||
|
{
|
||||||
|
multiboot_uint16_t type;
|
||||||
|
multiboot_uint16_t flags;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t requests[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_header_tag_address
|
||||||
|
{
|
||||||
|
multiboot_uint16_t type;
|
||||||
|
multiboot_uint16_t flags;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t header_addr;
|
||||||
|
multiboot_uint32_t load_addr;
|
||||||
|
multiboot_uint32_t load_end_addr;
|
||||||
|
multiboot_uint32_t bss_end_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_header_tag_entry_address
|
||||||
|
{
|
||||||
|
multiboot_uint16_t type;
|
||||||
|
multiboot_uint16_t flags;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t entry_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_header_tag_console_flags
|
||||||
|
{
|
||||||
|
multiboot_uint16_t type;
|
||||||
|
multiboot_uint16_t flags;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t console_flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_header_tag_framebuffer
|
||||||
|
{
|
||||||
|
multiboot_uint16_t type;
|
||||||
|
multiboot_uint16_t flags;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t width;
|
||||||
|
multiboot_uint32_t height;
|
||||||
|
multiboot_uint32_t depth;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_header_tag_module_align
|
||||||
|
{
|
||||||
|
multiboot_uint16_t type;
|
||||||
|
multiboot_uint16_t flags;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_header_tag_relocatable
|
||||||
|
{
|
||||||
|
multiboot_uint16_t type;
|
||||||
|
multiboot_uint16_t flags;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t min_addr;
|
||||||
|
multiboot_uint32_t max_addr;
|
||||||
|
multiboot_uint32_t align;
|
||||||
|
multiboot_uint32_t preference;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_color
|
||||||
|
{
|
||||||
|
multiboot_uint8_t red;
|
||||||
|
multiboot_uint8_t green;
|
||||||
|
multiboot_uint8_t blue;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_mmap_entry
|
||||||
|
{
|
||||||
|
multiboot_uint64_t addr;
|
||||||
|
multiboot_uint64_t len;
|
||||||
|
#define MULTIBOOT_MEMORY_AVAILABLE 1
|
||||||
|
#define MULTIBOOT_MEMORY_RESERVED 2
|
||||||
|
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
|
||||||
|
#define MULTIBOOT_MEMORY_NVS 4
|
||||||
|
#define MULTIBOOT_MEMORY_BADRAM 5
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t zero;
|
||||||
|
};
|
||||||
|
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
|
||||||
|
|
||||||
|
struct multiboot_tag
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_string
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
char string[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_module
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t mod_start;
|
||||||
|
multiboot_uint32_t mod_end;
|
||||||
|
char cmdline[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_basic_meminfo
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t mem_lower;
|
||||||
|
multiboot_uint32_t mem_upper;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_bootdev
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t biosdev;
|
||||||
|
multiboot_uint32_t slice;
|
||||||
|
multiboot_uint32_t part;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_mmap
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t entry_size;
|
||||||
|
multiboot_uint32_t entry_version;
|
||||||
|
struct multiboot_mmap_entry entries[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_vbe_info_block
|
||||||
|
{
|
||||||
|
multiboot_uint8_t external_specification[512];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_vbe_mode_info_block
|
||||||
|
{
|
||||||
|
multiboot_uint8_t external_specification[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_vbe
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
|
||||||
|
multiboot_uint16_t vbe_mode;
|
||||||
|
multiboot_uint16_t vbe_interface_seg;
|
||||||
|
multiboot_uint16_t vbe_interface_off;
|
||||||
|
multiboot_uint16_t vbe_interface_len;
|
||||||
|
|
||||||
|
struct multiboot_vbe_info_block vbe_control_info;
|
||||||
|
struct multiboot_vbe_mode_info_block vbe_mode_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_framebuffer_common
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
|
||||||
|
multiboot_uint64_t framebuffer_addr;
|
||||||
|
multiboot_uint32_t framebuffer_pitch;
|
||||||
|
multiboot_uint32_t framebuffer_width;
|
||||||
|
multiboot_uint32_t framebuffer_height;
|
||||||
|
multiboot_uint8_t framebuffer_bpp;
|
||||||
|
#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
|
||||||
|
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
|
||||||
|
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
|
||||||
|
multiboot_uint8_t framebuffer_type;
|
||||||
|
multiboot_uint16_t reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_framebuffer
|
||||||
|
{
|
||||||
|
struct multiboot_tag_framebuffer_common common;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
multiboot_uint16_t framebuffer_palette_num_colors;
|
||||||
|
struct multiboot_color framebuffer_palette[0];
|
||||||
|
};
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
multiboot_uint8_t framebuffer_red_field_position;
|
||||||
|
multiboot_uint8_t framebuffer_red_mask_size;
|
||||||
|
multiboot_uint8_t framebuffer_green_field_position;
|
||||||
|
multiboot_uint8_t framebuffer_green_mask_size;
|
||||||
|
multiboot_uint8_t framebuffer_blue_field_position;
|
||||||
|
multiboot_uint8_t framebuffer_blue_mask_size;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_elf_sections
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t num;
|
||||||
|
multiboot_uint32_t entsize;
|
||||||
|
multiboot_uint32_t shndx;
|
||||||
|
char sections[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_apm
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint16_t version;
|
||||||
|
multiboot_uint16_t cseg;
|
||||||
|
multiboot_uint32_t offset;
|
||||||
|
multiboot_uint16_t cseg_16;
|
||||||
|
multiboot_uint16_t dseg;
|
||||||
|
multiboot_uint16_t flags;
|
||||||
|
multiboot_uint16_t cseg_len;
|
||||||
|
multiboot_uint16_t cseg_16_len;
|
||||||
|
multiboot_uint16_t dseg_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_efi32
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t pointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_efi64
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint64_t pointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_smbios
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint8_t major;
|
||||||
|
multiboot_uint8_t minor;
|
||||||
|
multiboot_uint8_t reserved[6];
|
||||||
|
multiboot_uint8_t tables[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_old_acpi
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint8_t rsdp[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_new_acpi
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint8_t rsdp[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_network
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint8_t dhcpack[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_efi_mmap
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t descr_size;
|
||||||
|
multiboot_uint32_t descr_vers;
|
||||||
|
multiboot_uint8_t efi_mmap[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_efi32_ih
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t pointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_efi64_ih
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint64_t pointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_load_base_addr
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t load_base_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* ! ASM_FILE */
|
||||||
|
|
||||||
|
#endif /* ! MULTIBOOT_HEADER */
|
||||||
@@ -34,7 +34,20 @@ void *memmove(void* dest, const void* src, size_t n)
|
|||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *memcpy(void* dest, const void* src, uint32_t n)
|
||||||
|
{
|
||||||
|
uint8_t* d = (uint8_t*)dest;
|
||||||
|
const uint8_t* s = (const uint8_t*)src;
|
||||||
|
|
||||||
|
for (uint32_t i=0; i<n; i++)
|
||||||
|
{
|
||||||
|
d[i] = s[i];
|
||||||
|
}
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
void panic()
|
void panic()
|
||||||
{
|
{
|
||||||
for (;;);
|
for (;;);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13,6 +13,7 @@ typedef int size_t;
|
|||||||
|
|
||||||
void *memset(void *dest, char val, size_t count);
|
void *memset(void *dest, char val, size_t count);
|
||||||
void *memmove(void* dest, const void* src, size_t n);
|
void *memmove(void* dest, const void* src, size_t n);
|
||||||
|
void *memcpy(void* dest, const void* src, uint32_t n);
|
||||||
|
|
||||||
struct regs
|
struct regs
|
||||||
{
|
{
|
||||||
@@ -38,5 +39,7 @@ extern volatile unsigned long global_ticks;
|
|||||||
|
|
||||||
extern unsigned int g_multiboot_info_address;
|
extern unsigned int g_multiboot_info_address;
|
||||||
|
|
||||||
|
void syscall_handler();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Ctype implementation for blankos/libc
|
// Ctype implementation for blankos/libk
|
||||||
// Author: xamidev
|
// Author: xamidev
|
||||||
// Licensed under the Unlicense. See the repo below.
|
// Licensed under the Unlicense. See the repo below.
|
||||||
// https://github.com/xamidev/blankos
|
// https://github.com/xamidev/blankos
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Ctype implementation for blankos/libc header
|
// Ctype implementation for blankos/libk header
|
||||||
// Author: xamidev
|
// Author: xamidev
|
||||||
// Licensed under the Unlicense. See the repo below.
|
// Licensed under the Unlicense. See the repo below.
|
||||||
// https://github.com/xamidev/blankos
|
// https://github.com/xamidev/blankos
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Standard input/output implementation for blankos/libc
|
// Standard input/output implementation for blankos/libk
|
||||||
// Author: xamidev
|
// Author: xamidev
|
||||||
// Licensed under the Unlicense. See the repo below.
|
// Licensed under the Unlicense. See the repo below.
|
||||||
// https://github.com/xamidev/blankos
|
// https://github.com/xamidev/blankos
|
||||||
@@ -15,8 +15,19 @@ extern uint32_t* framebuffer;
|
|||||||
extern uint32_t VGA_WIDTH;
|
extern uint32_t VGA_WIDTH;
|
||||||
extern uint32_t VGA_HEIGHT;
|
extern uint32_t VGA_HEIGHT;
|
||||||
unsigned int VGA_X = 0, VGA_Y = 0;
|
unsigned int VGA_X = 0, VGA_Y = 0;
|
||||||
|
|
||||||
extern int scanline;
|
extern int scanline;
|
||||||
|
|
||||||
|
int get_cursor_x()
|
||||||
|
{
|
||||||
|
return VGA_X;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_cursor_y()
|
||||||
|
{
|
||||||
|
return VGA_Y;
|
||||||
|
}
|
||||||
|
|
||||||
void draw_cursor(uint32_t color)
|
void draw_cursor(uint32_t color)
|
||||||
{
|
{
|
||||||
for (int y=12; y<CURSOR_HEIGHT; y++)
|
for (int y=12; y<CURSOR_HEIGHT; y++)
|
||||||
@@ -28,6 +39,25 @@ void draw_cursor(uint32_t color)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void draw_pixel(int x, int y, uint32_t color) //high level wrapper for putpixel
|
||||||
|
{
|
||||||
|
putpixel(framebuffer, scanline, 32, x, y, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_square(int x, int y, uint32_t color, int size)
|
||||||
|
{
|
||||||
|
int startx = x*size;
|
||||||
|
int starty = y*size;
|
||||||
|
|
||||||
|
for (int i=0; i<size; i++)
|
||||||
|
{
|
||||||
|
for (int j=0; j<size; j++)
|
||||||
|
{
|
||||||
|
draw_pixel(startx+i, starty+j, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void erase_cursor()
|
void erase_cursor()
|
||||||
{
|
{
|
||||||
draw_cursor(black);
|
draw_cursor(black);
|
||||||
@@ -452,7 +482,7 @@ int* printf_number(int* argp, int length, bool sign, int radix, int width, char
|
|||||||
|
|
||||||
return argp;
|
return argp;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
int getch()
|
int getch()
|
||||||
{
|
{
|
||||||
return keyboard_getchar();
|
return keyboard_getchar();
|
||||||
@@ -481,3 +511,247 @@ void get_input(char *buffer, int size) {
|
|||||||
}
|
}
|
||||||
buffer[index] = '\0';
|
buffer[index] = '\0';
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void colorprintf(uint32_t fg, uint32_t bg, const char* fmt, ...)
|
||||||
|
{
|
||||||
|
int* argp = (int*)&fmt;
|
||||||
|
int state = PRINTF_STATE_START;
|
||||||
|
int length = PRINTF_LENGTH_START;
|
||||||
|
int radix = 10;
|
||||||
|
bool sign = false;
|
||||||
|
int width = 0;
|
||||||
|
char pad_char = ' ';
|
||||||
|
|
||||||
|
argp++;
|
||||||
|
while (*fmt)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case PRINTF_STATE_START:
|
||||||
|
if (*fmt == '%')
|
||||||
|
{
|
||||||
|
state = PRINTF_STATE_LENGTH;
|
||||||
|
width = 0;
|
||||||
|
pad_char = ' ';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
colorputc(*fmt, fg, bg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRINTF_STATE_LENGTH:
|
||||||
|
if (*fmt == '0')
|
||||||
|
{
|
||||||
|
pad_char = '0';
|
||||||
|
state = PRINTF_STATE_WIDTH;
|
||||||
|
}
|
||||||
|
else if (*fmt >= '1' && *fmt <= '9')
|
||||||
|
{
|
||||||
|
width = *fmt - '0';
|
||||||
|
state = PRINTF_STATE_WIDTH;
|
||||||
|
}
|
||||||
|
else if (*fmt == 'h')
|
||||||
|
{
|
||||||
|
length = PRINTF_LENGTH_SHORT;
|
||||||
|
state = PRINTF_STATE_SHORT;
|
||||||
|
}
|
||||||
|
else if (*fmt == 'l')
|
||||||
|
{
|
||||||
|
length = PRINTF_LENGTH_LONG;
|
||||||
|
state = PRINTF_STATE_LONG;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
goto PRINTF_STATE_SPEC_;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRINTF_STATE_WIDTH:
|
||||||
|
if (*fmt >= '0' && *fmt <= '9')
|
||||||
|
{
|
||||||
|
width = width * 10 + (*fmt - '0');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
goto PRINTF_STATE_SPEC_;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRINTF_STATE_SHORT:
|
||||||
|
if (*fmt == 'h')
|
||||||
|
{
|
||||||
|
length = PRINTF_LENGTH_SHORT_SHORT;
|
||||||
|
state = PRINTF_STATE_SPEC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
goto PRINTF_STATE_SPEC_;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRINTF_STATE_LONG:
|
||||||
|
if (*fmt == 'l')
|
||||||
|
{
|
||||||
|
length = PRINTF_LENGTH_LONG_LONG;
|
||||||
|
state = PRINTF_STATE_SPEC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
goto PRINTF_STATE_SPEC_;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRINTF_STATE_SPEC:
|
||||||
|
PRINTF_STATE_SPEC_:
|
||||||
|
switch (*fmt)
|
||||||
|
{
|
||||||
|
case 'c':
|
||||||
|
colorputc((char)*argp, fg, bg);
|
||||||
|
argp++;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
colorputs(*(const char**)argp, fg, bg);
|
||||||
|
argp++;
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
putc('%');
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
case 'i':
|
||||||
|
radix = 10;
|
||||||
|
sign = true;
|
||||||
|
argp = colorprintf_number(argp, length, sign, radix, width, pad_char, fg, bg);
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
radix = 10;
|
||||||
|
sign = false;
|
||||||
|
argp = colorprintf_number(argp, length, sign, radix, width, pad_char, fg, bg);
|
||||||
|
break;
|
||||||
|
case 'X':
|
||||||
|
case 'x':
|
||||||
|
case 'p':
|
||||||
|
radix = 16;
|
||||||
|
sign = false;
|
||||||
|
argp = colorprintf_number(argp, length, sign, radix, width, pad_char, fg, bg);
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
radix = 8;
|
||||||
|
sign = false;
|
||||||
|
argp = colorprintf_number(argp, length, sign, radix, width, pad_char, fg, bg);
|
||||||
|
break;
|
||||||
|
case 'f': {
|
||||||
|
double* dargp = (double*)argp;
|
||||||
|
double d = *(double*)dargp;
|
||||||
|
char buffer[64];
|
||||||
|
dtostrf(d, buffer, 6);
|
||||||
|
colorputs(buffer, fg, bg);
|
||||||
|
argp += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
state = PRINTF_STATE_START;
|
||||||
|
length = PRINTF_LENGTH_START;
|
||||||
|
radix = 10;
|
||||||
|
sign = false;
|
||||||
|
width = 0;
|
||||||
|
pad_char = ' ';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fmt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int* colorprintf_number(int* argp, int length, bool sign, int radix, int width, char pad_char, uint32_t fg, uint32_t bg)
|
||||||
|
{
|
||||||
|
char buffer[32];
|
||||||
|
unsigned long long number;
|
||||||
|
int number_sign = 1;
|
||||||
|
int pos = 0;
|
||||||
|
|
||||||
|
switch (length)
|
||||||
|
{
|
||||||
|
case PRINTF_LENGTH_SHORT_SHORT:
|
||||||
|
case PRINTF_LENGTH_SHORT:
|
||||||
|
case PRINTF_LENGTH_START:
|
||||||
|
if (sign)
|
||||||
|
{
|
||||||
|
int n = *argp;
|
||||||
|
if (n < 0)
|
||||||
|
{
|
||||||
|
n = -n;
|
||||||
|
number_sign = -1;
|
||||||
|
}
|
||||||
|
number = (unsigned long long)n;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
number = *(unsigned int*)argp;
|
||||||
|
}
|
||||||
|
argp++;
|
||||||
|
break;
|
||||||
|
case PRINTF_LENGTH_LONG:
|
||||||
|
if (sign)
|
||||||
|
{
|
||||||
|
long int n = *(long int*)argp;
|
||||||
|
if (n < 0)
|
||||||
|
{
|
||||||
|
n = -n;
|
||||||
|
number_sign = -1;
|
||||||
|
}
|
||||||
|
number = (unsigned long long)n;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
number = *(unsigned long int*)argp;
|
||||||
|
}
|
||||||
|
argp += 2;
|
||||||
|
break;
|
||||||
|
case PRINTF_LENGTH_LONG_LONG:
|
||||||
|
if (sign)
|
||||||
|
{
|
||||||
|
long long int n = *(long long int*)argp;
|
||||||
|
if (n < 0)
|
||||||
|
{
|
||||||
|
n = -n;
|
||||||
|
number_sign = -1;
|
||||||
|
}
|
||||||
|
number = (unsigned long long)n;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
number = *(unsigned long long int*)argp;
|
||||||
|
}
|
||||||
|
argp += 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
uint32_t rem;
|
||||||
|
x86_div64_32(number, radix, &number, &rem);
|
||||||
|
buffer[pos++] = charset[rem];
|
||||||
|
} while (number > 0);
|
||||||
|
|
||||||
|
if (sign && number_sign < 0)
|
||||||
|
{
|
||||||
|
buffer[pos++] = '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
int padding = width - pos;
|
||||||
|
|
||||||
|
while (padding-- > 0)
|
||||||
|
{
|
||||||
|
colorputc(pad_char, fg, bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (--pos >= 0)
|
||||||
|
{
|
||||||
|
colorputc(buffer[pos], fg, bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return argp;
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Standard input/output implementation for blankos/libc header
|
// Standard input/output implementation for blankos/libk header
|
||||||
// Author: xamidev
|
// Author: xamidev
|
||||||
// Licensed under the Unlicense. See the repo below.
|
// Licensed under the Unlicense. See the repo below.
|
||||||
// https://github.com/xamidev/blankos
|
// https://github.com/xamidev/blankos
|
||||||
@@ -22,8 +22,10 @@
|
|||||||
|
|
||||||
void draw_cursor(uint32_t color);
|
void draw_cursor(uint32_t color);
|
||||||
void erase_cursor();
|
void erase_cursor();
|
||||||
|
|
||||||
void move_cursor(int x, int y);
|
void move_cursor(int x, int y);
|
||||||
|
|
||||||
|
void draw_pixel(int x, int y, uint32_t color);
|
||||||
|
void draw_square(int x, int y, uint32_t color, int size);
|
||||||
void putchar(unsigned short int c, int x, int y, uint32_t fg, uint32_t bg);
|
void putchar(unsigned short int c, int x, int y, uint32_t fg, uint32_t bg);
|
||||||
void puts(const char* str);
|
void puts(const char* str);
|
||||||
void clear(void);
|
void clear(void);
|
||||||
@@ -33,6 +35,8 @@ char getchar(int x, int y);
|
|||||||
unsigned int getcolor(int x, int y);
|
unsigned int getcolor(int x, int y);
|
||||||
void putc(char c);
|
void putc(char c);
|
||||||
void colorputc(char c, uint32_t fg, uint32_t bg);
|
void colorputc(char c, uint32_t fg, uint32_t bg);
|
||||||
|
void colorprintf(uint32_t fg, uint32_t bg, const char* fmt, ...);
|
||||||
|
int* colorprintf_number(int* argp, int length, bool sign, int radix, int width, char pad_char, uint32_t fg, uint32_t bg);
|
||||||
|
|
||||||
#define PRINTF_STATE_START 0
|
#define PRINTF_STATE_START 0
|
||||||
#define PRINTF_STATE_LENGTH 1
|
#define PRINTF_STATE_LENGTH 1
|
||||||
@@ -56,12 +60,38 @@ void dtostrf(double val, char *buffer, int precision);
|
|||||||
enum Colors
|
enum Colors
|
||||||
{
|
{
|
||||||
// AARRGGBB?
|
// AARRGGBB?
|
||||||
white = 0xFFFFFFFF,
|
white = 0xFFFFFFFF,
|
||||||
black = 0x00000000,
|
black = 0x00000000,
|
||||||
red = 0x00FF0000,
|
red = 0x00FF0000,
|
||||||
green = 0x0000FF00,
|
green = 0x0000FF00,
|
||||||
blue = 0x000000FF,
|
blue = 0x000000FF,
|
||||||
yellow = 0x00FFFF00,
|
yellow = 0x00FFFF00,
|
||||||
|
cyan = 0x0000FFFF,
|
||||||
|
magenta = 0x00FF00FF,
|
||||||
|
orange = 0x00FFA500,
|
||||||
|
purple = 0x00800080,
|
||||||
|
brown = 0x00A52A2A,
|
||||||
|
gray = 0x00808080,
|
||||||
|
pink = 0x00FFC0CB,
|
||||||
|
lime = 0x00BFFF00,
|
||||||
|
navy = 0x00000080,
|
||||||
|
teal = 0x00008080,
|
||||||
|
maroon = 0x00800000,
|
||||||
|
olive = 0x00808000,
|
||||||
|
silver = 0x00C0C0C0,
|
||||||
|
gold = 0x00FFD700,
|
||||||
|
indigo = 0x004B0082,
|
||||||
|
violet = 0x00EE82EE,
|
||||||
|
coral = 0x00FF7F50,
|
||||||
|
turquoise = 0x0040E0D0,
|
||||||
|
salmon = 0x00FA8072,
|
||||||
|
chocolate = 0x00D2691E,
|
||||||
|
khaki = 0x00F0E68C,
|
||||||
|
lavender = 0x00E6E6FA,
|
||||||
|
beige = 0x00F5F5DC
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int get_cursor_x();
|
||||||
|
int get_cursor_y();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// String operations implementation for blankos/libc
|
// String operations implementation for blankos/libk
|
||||||
// Author: xamidev
|
// Author: xamidev
|
||||||
// Licensed under the Unlicense. See the repo below.
|
// Licensed under the Unlicense. See the repo below.
|
||||||
// https://github.com/xamidev/blankos
|
// https://github.com/xamidev/blankos
|
||||||
@@ -103,3 +103,32 @@ void strcat(char* dest, const char* src)
|
|||||||
|
|
||||||
*dest = '\0';
|
*dest = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t strnlen(const char* str, size_t max_len)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
while (*str && len < max_len)
|
||||||
|
{
|
||||||
|
len++;
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void strncat(char* dest, const char* src, size_t n)
|
||||||
|
{
|
||||||
|
while (*dest)
|
||||||
|
{
|
||||||
|
dest++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*src && n > 0)
|
||||||
|
{
|
||||||
|
*dest = *src;
|
||||||
|
dest++;
|
||||||
|
src++;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dest = '\0';
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// String operations implementation for blankos/libc header
|
// String operations implementation for blankos/libk header
|
||||||
// Author: xamidev
|
// Author: xamidev
|
||||||
// Licensed under the Unlicense. See the repo below.
|
// Licensed under the Unlicense. See the repo below.
|
||||||
// https://github.com/xamidev/blankos
|
// https://github.com/xamidev/blankos
|
||||||
@@ -6,11 +6,16 @@
|
|||||||
#ifndef STRING_H
|
#ifndef STRING_H
|
||||||
#define STRING_H
|
#define STRING_H
|
||||||
|
|
||||||
|
#include "../kernel/system.h"
|
||||||
|
|
||||||
int strlen(const char* str);
|
int strlen(const char* str);
|
||||||
int strcmp(const char* str1, const char* str2);
|
int strcmp(const char* str1, const char* str2);
|
||||||
char* strtok(char* str, const char* delimiter);
|
char* strtok(char* str, const char* delimiter);
|
||||||
int atoi(char* str);
|
int atoi(char* str);
|
||||||
void strcat(char* dest, const char* src);
|
void strcat(char* dest, const char* src);
|
||||||
|
|
||||||
|
// Safer functions
|
||||||
|
size_t strnlen(const char* str, size_t max_len);
|
||||||
|
void strncat(char* dest, const char* src, size_t n);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
2
link.ld
2
link.ld
@@ -3,7 +3,7 @@ ENTRY(loader)
|
|||||||
SECTIONS {
|
SECTIONS {
|
||||||
/* Address to load at; 2MB */
|
/* Address to load at; 2MB */
|
||||||
|
|
||||||
/*. = 2M;*/
|
. = 2M;
|
||||||
|
|
||||||
.multiboot_header ALIGN(4K) : {
|
.multiboot_header ALIGN(4K) : {
|
||||||
*(.multiboot_header)
|
*(.multiboot_header)
|
||||||
|
|||||||
36
makefile
36
makefile
@@ -1,42 +1,42 @@
|
|||||||
CC = i386-elf-7.5.0-Linux-x86_64/bin/i386-elf-gcc
|
CC = i386-elf-7.5.0-Linux-x86_64/bin/i386-elf-gcc
|
||||||
CFLAGS = -ffreestanding -g -Wall -Wextra -Wno-builtin-declaration-mismatch -c -I src/
|
CFLAGS = -ffreestanding -g -Wall -Wextra -mno-sse -mno-mmx -mno-avx -march=i386 -c -I .
|
||||||
|
LD = ld
|
||||||
LDFLAGS = -T link.ld -melf_i386
|
LDFLAGS = -T link.ld -melf_i386
|
||||||
AS = nasm
|
AS = nasm
|
||||||
ASFLAGS = -f elf
|
ASFLAGS = -f elf
|
||||||
|
AR = i386-elf-7.5.0-Linux-x86_64/bin/i386-elf-ar
|
||||||
|
|
||||||
SRC_DIR = src
|
KERNEL_DIR = kernel
|
||||||
KERNEL_DIR = $(SRC_DIR)/kernel
|
libk_DIR = libk
|
||||||
LIBC_DIR = $(SRC_DIR)/libc
|
DRIVERS_DIR = drivers
|
||||||
PROGRAMS_DIR = $(SRC_DIR)/programs
|
|
||||||
DRIVERS_DIR = $(SRC_DIR)/drivers
|
|
||||||
INCLUDE_DIR = include
|
INCLUDE_DIR = include
|
||||||
FONTS_DIR = $(INCLUDE_DIR)/fonts
|
FONTS_DIR = $(INCLUDE_DIR)/fonts
|
||||||
OBJ_DIR = build
|
OBJ_DIR = build
|
||||||
|
|
||||||
C_SOURCES = $(wildcard $(KERNEL_DIR)/*.c) $(wildcard $(LIBC_DIR)/*.c) $(wildcard $(PROGRAMS_DIR)/*.c) $(wildcard $(DRIVERS_DIR)/*.c)
|
C_SOURCES = $(wildcard $(KERNEL_DIR)/*.c) $(wildcard $(libk_DIR)/*.c) $(wildcard $(DRIVERS_DIR)/*.c)
|
||||||
ASM_SOURCES = $(wildcard $(KERNEL_DIR)/*.s) $(wildcard $(LIBC_DIR)/*.s) $(wildcard $(PROGRAMS_DIR)/*.s) $(wildcard $(DRIVERS_DIR)/*.s)
|
ASM_SOURCES = $(wildcard $(KERNEL_DIR)/*.s) $(wildcard $(libk_DIR)/*.s) $(wildcard $(DRIVERS_DIR)/*.s)
|
||||||
|
|
||||||
OBJECTS = $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(C_SOURCES:.c=.o) $(ASM_SOURCES:.s=.o))
|
OBJECTS = $(patsubst %, $(OBJ_DIR)/%, $(C_SOURCES:.c=.o) $(ASM_SOURCES:.s=.o))
|
||||||
|
|
||||||
TOOLCHAIN_SRC = https://newos.org/toolchains/i386-elf-7.5.0-Linux-x86_64.tar.xz
|
TOOLCHAIN_SRC = https://newos.org/toolchains/i386-elf-7.5.0-Linux-x86_64.tar.xz
|
||||||
TOOLCHAIN_FILE = i386-elf-7.5.0-Linux-x86_64.tar.xz
|
TOOLCHAIN_FILE = i386-elf-7.5.0-Linux-x86_64.tar.xz
|
||||||
|
|
||||||
FONT_OBJ = $(OBJ_DIR)/fonts/UniCyr_8x16.o
|
FONT_OBJ = $(OBJ_DIR)/fonts/viscii10-8x16.o
|
||||||
FONT_SRC = $(FONTS_DIR)/UniCyr_8x16.psf
|
FONT_SRC = $(FONTS_DIR)/viscii10-8x16.psfu
|
||||||
|
|
||||||
all: $(OBJ_DIR) kernel.elf
|
all: $(OBJ_DIR) kernel.elf
|
||||||
|
|
||||||
$(OBJ_DIR):
|
$(OBJ_DIR):
|
||||||
mkdir -p $(OBJ_DIR)
|
mkdir -p $(OBJ_DIR)
|
||||||
mkdir -p $(OBJ_DIR)/kernel $(OBJ_DIR)/libc $(OBJ_DIR)/programs $(OBJ_DIR)/drivers $(OBJ_DIR)/fonts
|
mkdir -p $(OBJ_DIR)/kernel $(OBJ_DIR)/libk $(OBJ_DIR)/drivers $(OBJ_DIR)/fonts $(OBJ_DIR)/programs
|
||||||
|
|
||||||
kernel.elf: $(OBJECTS) $(FONT_OBJ)
|
kernel.elf: $(OBJECTS) $(FONT_OBJ)
|
||||||
ld $(LDFLAGS) $(OBJECTS) $(FONT_OBJ) -o kernel.elf
|
$(LD) $(LDFLAGS) $(OBJECTS) $(FONT_OBJ) -o kernel.elf
|
||||||
|
|
||||||
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
|
$(OBJ_DIR)/%.o: %.c
|
||||||
$(CC) $(CFLAGS) $< -o $@
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
|
||||||
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.s
|
$(OBJ_DIR)/%.o: %.s
|
||||||
$(AS) $(ASFLAGS) $< -o $@
|
$(AS) $(ASFLAGS) $< -o $@
|
||||||
|
|
||||||
$(FONT_OBJ): $(FONT_SRC) | $(OBJ_DIR)/fonts
|
$(FONT_OBJ): $(FONT_SRC) | $(OBJ_DIR)/fonts
|
||||||
@@ -50,7 +50,6 @@ toolchain:
|
|||||||
tar xf $(TOOLCHAIN_FILE)
|
tar xf $(TOOLCHAIN_FILE)
|
||||||
|
|
||||||
iso: kernel.elf
|
iso: kernel.elf
|
||||||
mkdir -p iso/boot/grub
|
|
||||||
cp kernel.elf iso/boot/kernel.elf
|
cp kernel.elf iso/boot/kernel.elf
|
||||||
cp grub.cfg iso/boot/grub/grub.cfg
|
cp grub.cfg iso/boot/grub/grub.cfg
|
||||||
grub-mkrescue iso -o blankos.iso
|
grub-mkrescue iso -o blankos.iso
|
||||||
@@ -59,8 +58,7 @@ run: iso
|
|||||||
qemu-system-i386 -drive file=blankos.iso,format=raw
|
qemu-system-i386 -drive file=blankos.iso,format=raw
|
||||||
|
|
||||||
debug:
|
debug:
|
||||||
qemu-system-i386 -s -S -drive file=blankos.iso,format=raw
|
./debug.sh
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(OBJ_DIR) kernel.elf blankos.iso $(TOOLCHAIN_FILE)
|
rm -rf $(OBJ_DIR) kernel.elf blankos.iso $(TOOLCHAIN_FILE) initrd/*.bin
|
||||||
|
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
// ATA PIO driver implementation
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "../kernel/io.h"
|
|
||||||
#include "../libc/stdio.h"
|
|
||||||
#include "ata.h"
|
|
||||||
|
|
||||||
static inline uint16_t inw(uint16_t port) {
|
|
||||||
uint16_t result;
|
|
||||||
asm volatile("inw %1, %0" : "=a"(result) : "dN"(port));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void outw(uint16_t port, uint16_t data) {
|
|
||||||
asm volatile("outw %1, %0" : : "dN"(port), "a"(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ata_wait_bsy() {
|
|
||||||
while (inb(ATA_PRIMARY_IO + ATA_REG_STATUS) & ATA_SR_BSY);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ata_wait_drq() {
|
|
||||||
while (!(inb(ATA_PRIMARY_IO + ATA_REG_STATUS) & ATA_SR_DRQ));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ata_select_drive(uint8_t drive) {
|
|
||||||
outb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xE0 | (drive << 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ata_read_sector(uint32_t lba, uint8_t* buffer) {
|
|
||||||
ata_wait_bsy();
|
|
||||||
ata_select_drive(0);
|
|
||||||
|
|
||||||
outb(ATA_PRIMARY_IO + ATA_REG_SECCOUNT0, 1);
|
|
||||||
outb(ATA_PRIMARY_IO + ATA_REG_LBA0, (uint8_t)lba);
|
|
||||||
outb(ATA_PRIMARY_IO + ATA_REG_LBA1, (uint8_t)(lba >> 8));
|
|
||||||
outb(ATA_PRIMARY_IO + ATA_REG_LBA2, (uint8_t)(lba >> 16));
|
|
||||||
outb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xE0 | ((lba >> 24) & 0x0F));
|
|
||||||
|
|
||||||
outb(ATA_PRIMARY_IO + ATA_REG_COMMAND, ATA_CMD_READ_PIO);
|
|
||||||
|
|
||||||
ata_wait_bsy();
|
|
||||||
ata_wait_drq();
|
|
||||||
|
|
||||||
for (int i = 0; i < 256; i++) {
|
|
||||||
((uint16_t*)buffer)[i] = inw(ATA_PRIMARY_IO + ATA_REG_DATA);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Works only w/o paging
|
|
||||||
void test_read_sector() {
|
|
||||||
uint8_t buffer[512];
|
|
||||||
ata_read_sector(0, buffer);
|
|
||||||
|
|
||||||
for (int i = 0; i < 512; i++) {
|
|
||||||
if (i%25==0) puts("\n");
|
|
||||||
printf("%02x ", buffer[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
// ATA PIO driver implementation header
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#ifndef ATA_H
|
|
||||||
#define ATA_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define ATA_PRIMARY_IO 0x1F0
|
|
||||||
#define ATA_PRIMARY_CTRL 0x3F6
|
|
||||||
#define ATA_CMD_READ_PIO 0x20
|
|
||||||
#define ATA_CMD_WRITE_PIO 0x30
|
|
||||||
#define ATA_IDENTIFY 0xEC
|
|
||||||
|
|
||||||
#define ATA_REG_DATA 0x00
|
|
||||||
#define ATA_REG_ERROR 0x01
|
|
||||||
#define ATA_REG_SECCOUNT0 0x02
|
|
||||||
#define ATA_REG_LBA0 0x03
|
|
||||||
#define ATA_REG_LBA1 0x04
|
|
||||||
#define ATA_REG_LBA2 0x05
|
|
||||||
#define ATA_REG_HDDEVSEL 0x06
|
|
||||||
#define ATA_REG_COMMAND 0x07
|
|
||||||
#define ATA_REG_STATUS 0x07
|
|
||||||
|
|
||||||
#define ATA_SR_BSY 0x80
|
|
||||||
#define ATA_SR_DRDY 0x40
|
|
||||||
#define ATA_SR_DRQ 0x08
|
|
||||||
#define ATA_SR_ERR 0x01
|
|
||||||
|
|
||||||
void ata_read_sector(uint32_t lba, uint8_t* buffer);
|
|
||||||
void test_read_sector();
|
|
||||||
|
|
||||||
#endif
|
|
||||||
142
src/drivers/kb.c
142
src/drivers/kb.c
@@ -1,142 +0,0 @@
|
|||||||
// Keyboard driver
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#include "../kernel/io.h"
|
|
||||||
#include "../libc/stdio.h"
|
|
||||||
#include "../kernel/system.h"
|
|
||||||
#include "kb.h"
|
|
||||||
|
|
||||||
unsigned char kbdus[128] =
|
|
||||||
{
|
|
||||||
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */
|
|
||||||
'9', '0', '-', '=', '\b', /* Backspace */
|
|
||||||
'\t', /* Tab */
|
|
||||||
'q', 'w', 'e', 'r', /* 19 */
|
|
||||||
't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */
|
|
||||||
0, /* 29 - Control */
|
|
||||||
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */
|
|
||||||
'\'', '`', 0, /* Left shift */
|
|
||||||
'\\', 'z', 'x', 'c', 'v', 'b', 'n', /* 49 */
|
|
||||||
'm', ',', '.', '/', 0, /* Right shift */
|
|
||||||
'*',
|
|
||||||
0, /* Alt */
|
|
||||||
' ', /* Space bar */
|
|
||||||
0, /* Caps lock */
|
|
||||||
0, /* 59 - F1 key ... > */
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, /* < ... F10 */
|
|
||||||
0, /* 69 - Num lock*/
|
|
||||||
0, /* Scroll Lock */
|
|
||||||
0, /* Home key */
|
|
||||||
0, /* Up Arrow */
|
|
||||||
0, /* Page Up */
|
|
||||||
'-',
|
|
||||||
0, /* Left Arrow */
|
|
||||||
0,
|
|
||||||
0, /* Right Arrow */
|
|
||||||
'+',
|
|
||||||
0, /* 79 - End key*/
|
|
||||||
0, /* Down Arrow */
|
|
||||||
0, /* Page Down */
|
|
||||||
0, /* Insert Key */
|
|
||||||
0, /* Delete Key */
|
|
||||||
0, 0, 0,
|
|
||||||
0, /* F11 Key */
|
|
||||||
0, /* F12 Key */
|
|
||||||
0, /* All other keys are undefined */
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned char kbdus_shift[128] =
|
|
||||||
{
|
|
||||||
0, 27, '!', '@', '#', '$', '%', '^', '&', '*', /* 9 */
|
|
||||||
'(', ')', '_', '+', '\b', /* Backspace */
|
|
||||||
'\t', /* Tab */
|
|
||||||
'Q', 'W', 'E', 'R', /* 19 */
|
|
||||||
'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', /* Enter key */
|
|
||||||
0, /* 29 - Control */
|
|
||||||
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* 39 */
|
|
||||||
'"', '~', 0, /* Left shift */
|
|
||||||
'|', 'Z', 'X', 'C', 'V', 'B', 'N', /* 49 */
|
|
||||||
'M', '<', '>', '?', 0, /* Right shift */
|
|
||||||
'*',
|
|
||||||
0, /* Alt */
|
|
||||||
' ', /* Space bar */
|
|
||||||
0, /* Caps lock */
|
|
||||||
0, /* 59 - F1 key ... > */
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, /* < ... F10 */
|
|
||||||
0, /* 69 - Num lock*/
|
|
||||||
0, /* Scroll Lock */
|
|
||||||
0, /* Home key */
|
|
||||||
0, /* Up Arrow */
|
|
||||||
0, /* Page Up */
|
|
||||||
'-',
|
|
||||||
0, /* Left Arrow */
|
|
||||||
0,
|
|
||||||
0, /* Right Arrow */
|
|
||||||
'+',
|
|
||||||
0, /* 79 - End key*/
|
|
||||||
0, /* Down Arrow */
|
|
||||||
0, /* Page Down */
|
|
||||||
0, /* Insert Key */
|
|
||||||
0, /* Delete Key */
|
|
||||||
0, 0, 0,
|
|
||||||
0, /* F11 Key */
|
|
||||||
0, /* F12 Key */
|
|
||||||
0, /* All other keys are undefined */
|
|
||||||
};
|
|
||||||
|
|
||||||
static char keyboard_buffer[KEYBOARD_BUFFER_SIZE];
|
|
||||||
static unsigned int keyboard_buffer_start = 0;
|
|
||||||
static unsigned int keyboard_buffer_end = 0;
|
|
||||||
static int shift_pressed = 0;
|
|
||||||
|
|
||||||
void keyboard_handler()
|
|
||||||
{
|
|
||||||
unsigned char scancode;
|
|
||||||
|
|
||||||
scancode = inb(0x60);
|
|
||||||
|
|
||||||
if (scancode & 0x80)
|
|
||||||
{
|
|
||||||
if (scancode == LEFT_SHIFT_RELEASED || scancode == RIGHT_SHIFT_RELEASED) {
|
|
||||||
shift_pressed = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (scancode == LEFT_SHIFT_PRESSED || scancode == RIGHT_SHIFT_PRESSED) {
|
|
||||||
shift_pressed = 1;
|
|
||||||
} else {
|
|
||||||
char c;
|
|
||||||
if (shift_pressed) {
|
|
||||||
c = kbdus_shift[scancode];
|
|
||||||
} else {
|
|
||||||
c = kbdus[scancode];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c)
|
|
||||||
{
|
|
||||||
keyboard_buffer[keyboard_buffer_end] = c;
|
|
||||||
keyboard_buffer_end = (keyboard_buffer_end+1) % KEYBOARD_BUFFER_SIZE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void keyboard_install()
|
|
||||||
{
|
|
||||||
irq_install_handler(1, keyboard_handler);
|
|
||||||
printf("[keyboard] installed irq handler\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
char keyboard_getchar()
|
|
||||||
{
|
|
||||||
while (keyboard_buffer_start == keyboard_buffer_end);
|
|
||||||
|
|
||||||
char c = keyboard_buffer[keyboard_buffer_start];
|
|
||||||
keyboard_buffer_start = (keyboard_buffer_start+1) % KEYBOARD_BUFFER_SIZE;
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
// Keyboard driver header
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#ifndef KB_H
|
|
||||||
#define KB_H
|
|
||||||
|
|
||||||
#define KEYBOARD_BUFFER_SIZE 256
|
|
||||||
|
|
||||||
#define LEFT_SHIFT_PRESSED 0x2A
|
|
||||||
#define RIGHT_SHIFT_PRESSED 0x36
|
|
||||||
#define LEFT_SHIFT_RELEASED 0xAA
|
|
||||||
#define RIGHT_SHIFT_RELEASED 0xB6
|
|
||||||
|
|
||||||
char keyboard_getchar();
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
// Real-time clock driver implementation for better PRNG
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "rtc.h"
|
|
||||||
#include "../kernel/io.h"
|
|
||||||
#include "../libc/stdio.h"
|
|
||||||
|
|
||||||
uint8_t rtc_read_register(uint8_t reg)
|
|
||||||
{
|
|
||||||
outb(0x70, reg);
|
|
||||||
return inb(0x71);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t bcd_to_bin(uint8_t bcd)
|
|
||||||
{
|
|
||||||
return ((bcd/16)*10) + (bcd%16);
|
|
||||||
}
|
|
||||||
|
|
||||||
int rtc_is_updating()
|
|
||||||
{
|
|
||||||
outb(0x70, 0x0A);
|
|
||||||
return (inb(0x71) & 0x80);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rtc_read_time(rtc_time_t *time)
|
|
||||||
{
|
|
||||||
while (rtc_is_updating());
|
|
||||||
|
|
||||||
time->seconds = rtc_read_register(0x00);
|
|
||||||
time->minutes = rtc_read_register(0x02);
|
|
||||||
time->hours = rtc_read_register(0x04);
|
|
||||||
time->day = rtc_read_register(0x06);
|
|
||||||
time->month = rtc_read_register(0x07);
|
|
||||||
time->year = rtc_read_register(0x08);
|
|
||||||
|
|
||||||
outb(0x70, 0x0B);
|
|
||||||
uint8_t registerB = inb(0x71);
|
|
||||||
|
|
||||||
if (!(registerB & 0x04))
|
|
||||||
{
|
|
||||||
time->seconds = bcd_to_bin(time->seconds);
|
|
||||||
time->minutes = bcd_to_bin(time->minutes);
|
|
||||||
time->hours = bcd_to_bin(time->hours);
|
|
||||||
time->day = bcd_to_bin(time->day);
|
|
||||||
time->month = bcd_to_bin(time->month);
|
|
||||||
time->year = bcd_to_bin(time->year);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_time(const rtc_time_t *time)
|
|
||||||
{
|
|
||||||
printf("%02d/%02d/%02d %02d:%02d:%02d\n", time->day, time->month, time->year, time->hours, time->minutes, time->seconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
long time_seed()
|
|
||||||
{
|
|
||||||
rtc_time_t* time = {0};
|
|
||||||
rtc_read_time(time);
|
|
||||||
|
|
||||||
return time->day + time->month + time->year + time->hours + time->minutes + time->seconds;
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
// Real-time clock driver implementation header for better PRNG
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#ifndef RTC_H
|
|
||||||
#define RTC_H
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint8_t seconds;
|
|
||||||
uint8_t minutes;
|
|
||||||
uint8_t hours;
|
|
||||||
uint8_t day;
|
|
||||||
uint8_t month;
|
|
||||||
uint8_t year;
|
|
||||||
} rtc_time_t;
|
|
||||||
|
|
||||||
void rtc_read_time(rtc_time_t *time);
|
|
||||||
long time_seed();
|
|
||||||
void print_time(const rtc_time_t *time);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
// Kernel heap management
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#include "kheap.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
extern uint32_t end;
|
|
||||||
uint32_t placement_address = (uint32_t)&end;
|
|
||||||
|
|
||||||
uint32_t kmalloc_int(uint32_t sz, int align, uint32_t *phys)
|
|
||||||
{
|
|
||||||
if (align == 1 && (placement_address & 0x00000FFF))
|
|
||||||
{
|
|
||||||
placement_address &= 0xFFFFF000;
|
|
||||||
placement_address += 0x1000;
|
|
||||||
}
|
|
||||||
if (phys)
|
|
||||||
{
|
|
||||||
*phys = placement_address;
|
|
||||||
}
|
|
||||||
uint32_t tmp = placement_address;
|
|
||||||
placement_address += sz;
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t kmalloc_a(uint32_t sz)
|
|
||||||
{
|
|
||||||
return kmalloc_int(sz, 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t kmalloc_p(uint32_t sz, uint32_t *phys)
|
|
||||||
{
|
|
||||||
return kmalloc_int(sz, 0, phys);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t kmalloc_ap(uint32_t sz, uint32_t *phys)
|
|
||||||
{
|
|
||||||
return kmalloc_int(sz, 1, phys);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t kmalloc(uint32_t sz)
|
|
||||||
{
|
|
||||||
return kmalloc_int(sz, 0, 0);
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
// Kernel heap management header
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#ifndef KHEAP_H
|
|
||||||
#define KHEAP_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
uint32_t kmalloc_a(uint32_t sz);
|
|
||||||
uint32_t kmalloc_p(uint32_t sz, uint32_t *phys);
|
|
||||||
uint32_t kmalloc_ap(uint32_t sz, uint32_t *phys);
|
|
||||||
uint32_t kmalloc(uint32_t sz);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
// Paging kernel module
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "paging.h"
|
|
||||||
#include "../libc/stdio.h"
|
|
||||||
#include "system.h"
|
|
||||||
#include "kheap.h"
|
|
||||||
|
|
||||||
uint32_t *frames;
|
|
||||||
uint32_t nframes;
|
|
||||||
|
|
||||||
extern uint32_t placement_address;
|
|
||||||
|
|
||||||
static void set_frame(uint32_t frame_addr)
|
|
||||||
{
|
|
||||||
uint32_t frame = frame_addr/0x1000;
|
|
||||||
uint32_t idx = INDEX_FROM_BIT(frame);
|
|
||||||
uint32_t off = OFFSET_FROM_BIT(frame);
|
|
||||||
frames[idx] |= (0x1 << off);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void clear_frame(uint32_t frame_addr)
|
|
||||||
{
|
|
||||||
uint32_t frame = frame_addr/0x1000;
|
|
||||||
uint32_t idx = INDEX_FROM_BIT(frame);
|
|
||||||
uint32_t off = OFFSET_FROM_BIT(frame);
|
|
||||||
frames[idx] &= ~(0x1 << off);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
static uint32_t test_frame(uint32_t frame_addr)
|
|
||||||
{
|
|
||||||
uint32_t frame = frame_addr/0x1000;
|
|
||||||
uint32_t idx = INDEX_FROM_BIT(frame);
|
|
||||||
uint32_t off = OFFSET_FROM_BIT(frame);
|
|
||||||
return (frames[idx] & (0x1 << off));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static uint32_t first_frame()
|
|
||||||
{
|
|
||||||
uint32_t i, j;
|
|
||||||
for (i=0; i<INDEX_FROM_BIT(nframes); i++)
|
|
||||||
{
|
|
||||||
if (frames[i] != 0xFFFFFFFF)
|
|
||||||
{
|
|
||||||
for (j=0; j<32; j++)
|
|
||||||
{
|
|
||||||
uint32_t toTest = 0x1 << j;
|
|
||||||
if (!(frames[i]&toTest))
|
|
||||||
{
|
|
||||||
return i*4*8+j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void alloc_frame(page_t *page, int is_kernel, int is_writeable)
|
|
||||||
{
|
|
||||||
if (page->frame != 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
uint32_t idx = first_frame();
|
|
||||||
if (idx == (uint32_t)-1)
|
|
||||||
{
|
|
||||||
panic();
|
|
||||||
}
|
|
||||||
set_frame(idx*0x1000);
|
|
||||||
page->present = 1;
|
|
||||||
page->rw = (is_writeable)?1:0;
|
|
||||||
page->user = (is_kernel)?0:1;
|
|
||||||
page->frame = idx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void free_frame(page_t *page)
|
|
||||||
{
|
|
||||||
uint32_t frame;
|
|
||||||
if (!(frame=page->frame))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
clear_frame(frame);
|
|
||||||
page->frame = 0x0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_paging()
|
|
||||||
{
|
|
||||||
uint32_t mem_end_page = 0x10000000;
|
|
||||||
nframes = mem_end_page / 0x1000;
|
|
||||||
frames = (uint32_t*)kmalloc(INDEX_FROM_BIT(nframes));
|
|
||||||
memset(frames, 0, INDEX_FROM_BIT(nframes));
|
|
||||||
|
|
||||||
page_directory_t* kernel_directory = (page_directory_t*)kmalloc_a(sizeof(page_directory_t));
|
|
||||||
memset(kernel_directory, 0, sizeof(page_directory_t));
|
|
||||||
//page_directory_t* current_directory = kernel_directory;
|
|
||||||
|
|
||||||
unsigned int i = 0;
|
|
||||||
while (i < placement_address)
|
|
||||||
{
|
|
||||||
alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
|
|
||||||
i += 0x1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
irq_install_handler(14, page_fault);
|
|
||||||
|
|
||||||
switch_page_directory(kernel_directory);
|
|
||||||
}
|
|
||||||
|
|
||||||
void switch_page_directory(page_directory_t *dir)
|
|
||||||
{
|
|
||||||
//page_directory_t* current_directory = dir;
|
|
||||||
asm volatile("mov %0, %%cr3":: "r"(&dir->tablesPhysical));
|
|
||||||
uint32_t cr0;
|
|
||||||
asm volatile("mov %%cr0, %0": "=r"(cr0));
|
|
||||||
cr0 |= 0x80000000;
|
|
||||||
asm volatile("mov %0, %%cr0":: "r"(cr0));
|
|
||||||
}
|
|
||||||
|
|
||||||
page_t *get_page(uint32_t address, int make, page_directory_t *dir)
|
|
||||||
{
|
|
||||||
address /= 0x1000;
|
|
||||||
uint32_t table_idx = address / 1024;
|
|
||||||
if (dir->tables[table_idx])
|
|
||||||
{
|
|
||||||
return &dir->tables[table_idx]->pages[address%1024];
|
|
||||||
} else if (make)
|
|
||||||
{
|
|
||||||
uint32_t tmp;
|
|
||||||
dir->tables[table_idx] = (page_table_t*)kmalloc_ap(sizeof(page_table_t), &tmp);
|
|
||||||
memset(dir->tables[table_idx], 0, 0x1000);
|
|
||||||
dir->tablesPhysical[table_idx] = tmp | 0x7;
|
|
||||||
return &dir->tables[table_idx]->pages[address%1024];
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void page_fault()
|
|
||||||
{
|
|
||||||
puts("Page fault");
|
|
||||||
panic();
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
// Paging kernel module header
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#ifndef PAGING_H
|
|
||||||
#define PAGING_H
|
|
||||||
|
|
||||||
#include "system.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define INDEX_FROM_BIT(a) (a/(8*4))
|
|
||||||
#define OFFSET_FROM_BIT(a) (a%(8*4))
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint32_t present : 1;
|
|
||||||
uint32_t rw : 1;
|
|
||||||
uint32_t user : 1;
|
|
||||||
uint32_t accessed : 1;
|
|
||||||
uint32_t dirty : 1;
|
|
||||||
uint32_t unused : 7;
|
|
||||||
uint32_t frame : 20;
|
|
||||||
} page_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
page_t pages[1024];
|
|
||||||
} page_table_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
page_table_t *tables[1024];
|
|
||||||
uint32_t tablesPhysical[1024];
|
|
||||||
uint32_t physicalAsddr;
|
|
||||||
} page_directory_t;
|
|
||||||
|
|
||||||
void init_paging();
|
|
||||||
void switch_page_directory(page_directory_t *new);
|
|
||||||
page_t *get_page(uint32_t address, int make, page_directory_t *dir);
|
|
||||||
void page_fault();
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
// Basic shell and commands kernel module
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#include "system.h"
|
|
||||||
#include "../libc/stdio.h"
|
|
||||||
#include "../libc/string.h"
|
|
||||||
#include "../programs/programs.h"
|
|
||||||
#include "../libc/crypto.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "../drivers/rtc.h"
|
|
||||||
|
|
||||||
#define BUFFER_SIZE 256
|
|
||||||
#define MAX_COMMANDS 16
|
|
||||||
#define MAX_ARGS 64
|
|
||||||
|
|
||||||
// Splash screen: esthetic stuff.
|
|
||||||
|
|
||||||
char* motd[] =
|
|
||||||
{
|
|
||||||
"Now in 2D!",
|
|
||||||
"Supercalifragilisticexpialidocious!",
|
|
||||||
"Tylko jedno w glowie mam!",
|
|
||||||
};
|
|
||||||
int motd_size = sizeof(motd)/sizeof(motd[0]);
|
|
||||||
|
|
||||||
void splash()
|
|
||||||
{
|
|
||||||
int random = randint(time_seed());
|
|
||||||
char* motd_pick = motd[random%motd_size];
|
|
||||||
cowsay(motd_pick, red, black);
|
|
||||||
colorputs(" blankOS 0.3.86-alpha", red, black);
|
|
||||||
puts("\n");
|
|
||||||
|
|
||||||
|
|
||||||
puts(" Time: ");
|
|
||||||
rtc_time_t time;
|
|
||||||
rtc_read_time(&time);
|
|
||||||
print_time(&time);
|
|
||||||
puts("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef void (*command_func_t)(int argc, char *argv[]);
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
const char* name;
|
|
||||||
command_func_t function;
|
|
||||||
} shell_command_t;
|
|
||||||
|
|
||||||
shell_command_t shell_commands[MAX_COMMANDS];
|
|
||||||
int command_count = 0;
|
|
||||||
|
|
||||||
void register_command(const char* name, command_func_t function)
|
|
||||||
{
|
|
||||||
if (command_count < MAX_COMMANDS)
|
|
||||||
{
|
|
||||||
shell_commands[command_count].name = name;
|
|
||||||
shell_commands[command_count].function = function;
|
|
||||||
command_count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
command_func_t find_command(const char* name)
|
|
||||||
{
|
|
||||||
for (int i=0; i < command_count; i++)
|
|
||||||
{
|
|
||||||
if (strcmp(name, shell_commands[i].name) == 0)
|
|
||||||
return shell_commands[i].function;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int parse_input(char* input, char* argv[], int max_args)
|
|
||||||
{
|
|
||||||
int argc = 0;
|
|
||||||
char* token = strtok(input, " ");
|
|
||||||
while (token != NULL && argc < max_args - 1)
|
|
||||||
{
|
|
||||||
argv[argc++] = token;
|
|
||||||
token = strtok(NULL, " ");
|
|
||||||
}
|
|
||||||
argv[argc] = NULL;
|
|
||||||
return argc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void shell_install()
|
|
||||||
{
|
|
||||||
splash();
|
|
||||||
|
|
||||||
register_command("help", program_help);
|
|
||||||
register_command("panic", program_panic);
|
|
||||||
register_command("words", program_words);
|
|
||||||
register_command("primes", program_primes);
|
|
||||||
register_command("rainbow", program_rainbow);
|
|
||||||
register_command("clear", program_clear);
|
|
||||||
register_command("math", program_math);
|
|
||||||
register_command("bf", program_bf);
|
|
||||||
register_command("uptime", program_uptime);
|
|
||||||
register_command("echo", program_echo);
|
|
||||||
register_command("sysinfo", program_sysinfo);
|
|
||||||
register_command("conway", program_conway);
|
|
||||||
register_command("rot13", program_rot13);
|
|
||||||
register_command("morse", program_morse);
|
|
||||||
register_command("cowsay", program_cowsay);
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
char input_buffer[BUFFER_SIZE];
|
|
||||||
char* argv[MAX_ARGS];
|
|
||||||
|
|
||||||
// Prompt
|
|
||||||
colorputs("root", blue, black);
|
|
||||||
colorputs("@", white, black);
|
|
||||||
colorputs("blankos", green, black);
|
|
||||||
colorputs("~$ ", white, black);
|
|
||||||
|
|
||||||
get_input(input_buffer, BUFFER_SIZE);
|
|
||||||
puts("\n");
|
|
||||||
|
|
||||||
int argc = parse_input(input_buffer, argv, MAX_ARGS);
|
|
||||||
|
|
||||||
if (argc == 0) continue;
|
|
||||||
|
|
||||||
command_func_t command = find_command(argv[0]);
|
|
||||||
if (command)
|
|
||||||
{
|
|
||||||
command(argc, argv);
|
|
||||||
} else {
|
|
||||||
printf("Unknown command %s\n", argv[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
// System information kernel module
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#include "../libc/stdio.h"
|
|
||||||
#include "../libc/string.h"
|
|
||||||
|
|
||||||
void cpuid(int code, unsigned int* a, unsigned int* d)
|
|
||||||
{
|
|
||||||
asm volatile("cpuid"
|
|
||||||
: "=a"(*a), "=d"(*d)
|
|
||||||
: "a"(code)
|
|
||||||
: "ecx", "ebx");
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
// System information kernel module header
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#ifndef SYSINFO_H
|
|
||||||
#define SYSINFO_H
|
|
||||||
|
|
||||||
void cpuid(int code, unsigned int* a, unsigned int* d);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
// Cryptography routines for blankos/libc
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#include "crypto.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
int lcg(int seed)
|
|
||||||
{
|
|
||||||
int x = seed;
|
|
||||||
|
|
||||||
// Constants (ZX81 LCG)
|
|
||||||
int a = 75;
|
|
||||||
int c = 74;
|
|
||||||
long m = 65537;
|
|
||||||
|
|
||||||
for (int i=0; i<10; i++)
|
|
||||||
{
|
|
||||||
x = (a*x + c) % m;
|
|
||||||
}
|
|
||||||
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
int randint(int seed)
|
|
||||||
{
|
|
||||||
int x = lcg(seed);
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t next = 1;
|
|
||||||
|
|
||||||
uint32_t rand()
|
|
||||||
{
|
|
||||||
next = next * 1103515245 + 12345;
|
|
||||||
return (next/65536) % 32768;
|
|
||||||
}
|
|
||||||
|
|
||||||
float rand_float()
|
|
||||||
{
|
|
||||||
return rand() / 32767.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void srand(uint32_t seed)
|
|
||||||
{
|
|
||||||
next = seed;
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
// Cryptography routines for blankos/libc header
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#ifndef CRYPTO_H
|
|
||||||
#define CRYPTO_H
|
|
||||||
|
|
||||||
#define RAND_MAX 1024
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
int lcg(int seed);
|
|
||||||
int randint(int seed);
|
|
||||||
uint32_t rand();
|
|
||||||
float rand_float();
|
|
||||||
void srand(uint32_t seed);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
// Simple brainfuck interpreter program
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#include "../kernel/system.h"
|
|
||||||
#include "../libc/stdio.h"
|
|
||||||
|
|
||||||
#define BUF_SIZE 256
|
|
||||||
|
|
||||||
void brainfuck(char* input)
|
|
||||||
{
|
|
||||||
unsigned char tape[30000] = {0};
|
|
||||||
unsigned char* ptr = tape;
|
|
||||||
char current_char;
|
|
||||||
size_t i;
|
|
||||||
size_t loop;
|
|
||||||
|
|
||||||
for (i=0; input[i] != 0; i++)
|
|
||||||
{
|
|
||||||
current_char = input[i];
|
|
||||||
if (current_char == '>') {
|
|
||||||
++ptr;
|
|
||||||
} else if (current_char == '<') {
|
|
||||||
--ptr;
|
|
||||||
} else if (current_char == '+') {
|
|
||||||
++*ptr;
|
|
||||||
} else if (current_char == '-') {
|
|
||||||
--*ptr;
|
|
||||||
} else if (current_char == '.') {
|
|
||||||
putc(*ptr);
|
|
||||||
} else if (current_char == ',') {
|
|
||||||
*ptr = keyboard_getchar();
|
|
||||||
} else if (current_char == '[') {
|
|
||||||
continue;
|
|
||||||
} else if (current_char == ']' && *ptr) {
|
|
||||||
loop = 1;
|
|
||||||
while (loop > 0)
|
|
||||||
{
|
|
||||||
current_char = input[--i];
|
|
||||||
if (current_char == '[') {
|
|
||||||
loop--;
|
|
||||||
} else if (current_char == ']') {
|
|
||||||
loop++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void program_bf()
|
|
||||||
{
|
|
||||||
char input_buffer[BUF_SIZE];
|
|
||||||
puts("Brainfuck code? ");
|
|
||||||
get_input(input_buffer, BUF_SIZE);
|
|
||||||
brainfuck(input_buffer);
|
|
||||||
//brainfuck(",[.[-],]");
|
|
||||||
puts("\n");
|
|
||||||
}
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
// Cipher programs
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#include "../libc/stdio.h"
|
|
||||||
#include "ciphers.h"
|
|
||||||
#include "../libc/string.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
void rot13(char* input, char* output)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
while (input[i] != '\0')
|
|
||||||
{
|
|
||||||
char c = input[i];
|
|
||||||
|
|
||||||
if (c >= 'a' && c <= 'z') {
|
|
||||||
output[i] = ((c - 'a' + 13) % 26) + 'a';
|
|
||||||
} else if (c >= 'A' && c <= 'Z') {
|
|
||||||
output[i] = ((c - 'A' + 13) % 26) + 'A';
|
|
||||||
} else {
|
|
||||||
output[i] = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
output[i] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
void program_rot13()
|
|
||||||
{
|
|
||||||
char input_buffer[BUFFER_SIZE];
|
|
||||||
char output[BUFFER_SIZE];
|
|
||||||
puts("String? ");
|
|
||||||
get_input(input_buffer, BUFFER_SIZE);
|
|
||||||
rot13(input_buffer, output);
|
|
||||||
printf("\n%s\n", output);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* morse_alphabet[] = {
|
|
||||||
".-", // A
|
|
||||||
"-...", // B
|
|
||||||
"-.-.", // C
|
|
||||||
"-..", // D
|
|
||||||
".", // E
|
|
||||||
"..-.", // F
|
|
||||||
"--.", // G
|
|
||||||
"....", // H
|
|
||||||
"..", // I
|
|
||||||
".---", // J
|
|
||||||
"-.-", // K
|
|
||||||
".-..", // L
|
|
||||||
"--", // M
|
|
||||||
"-.", // N
|
|
||||||
"---", // O
|
|
||||||
".--.", // P
|
|
||||||
"--.-", // Q
|
|
||||||
".-.", // R
|
|
||||||
"...", // S
|
|
||||||
"-", // T
|
|
||||||
"..-", // U
|
|
||||||
"...-", // V
|
|
||||||
".--", // W
|
|
||||||
"-..-", // X
|
|
||||||
"-.--", // Y
|
|
||||||
"--.." // Z
|
|
||||||
};
|
|
||||||
|
|
||||||
const char* morse_digits[] = {
|
|
||||||
"-----", // 0
|
|
||||||
".----", // 1
|
|
||||||
"..---", // 2
|
|
||||||
"...--", // 3
|
|
||||||
"....-", // 4
|
|
||||||
".....", // 5
|
|
||||||
"-....", // 6
|
|
||||||
"--...", // 7
|
|
||||||
"---..", // 8
|
|
||||||
"----." // 9
|
|
||||||
};
|
|
||||||
|
|
||||||
void to_morse(const char* input, char* output) {
|
|
||||||
int i = 0;
|
|
||||||
int pos = 0;
|
|
||||||
|
|
||||||
while (input[i] != '\0') {
|
|
||||||
char c = input[i];
|
|
||||||
|
|
||||||
if (c >= 'a' && c <= 'z') {
|
|
||||||
const char* morse_code = morse_alphabet[c - 'a'];
|
|
||||||
int j = 0;
|
|
||||||
while (morse_code[j] != '\0') {
|
|
||||||
output[pos++] = morse_code[j++];
|
|
||||||
}
|
|
||||||
} else if (c >= 'A' && c <= 'Z') {
|
|
||||||
const char* morse_code = morse_alphabet[c - 'A'];
|
|
||||||
int j = 0;
|
|
||||||
while (morse_code[j] != '\0') {
|
|
||||||
output[pos++] = morse_code[j++];
|
|
||||||
}
|
|
||||||
} else if (c >= '0' && c <= '9') {
|
|
||||||
const char* morse_code = morse_digits[c - '0'];
|
|
||||||
int j = 0;
|
|
||||||
while (morse_code[j] != '\0') {
|
|
||||||
output[pos++] = morse_code[j++];
|
|
||||||
}
|
|
||||||
} else if (c == ' ') {
|
|
||||||
output[pos++] = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
output[pos++] = ' ';
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos > 0) {
|
|
||||||
output[pos - 1] = '\0';
|
|
||||||
} else {
|
|
||||||
output[pos] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void program_morse() {
|
|
||||||
char output[512];
|
|
||||||
char input_buffer[BUFFER_SIZE];
|
|
||||||
puts("String? ");
|
|
||||||
get_input(input_buffer, BUFFER_SIZE);
|
|
||||||
to_morse(input_buffer, output);
|
|
||||||
printf("\n%s\n", output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
// Cipher programs header
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#ifndef CIPHERS_H
|
|
||||||
#define CIPHERS_H
|
|
||||||
|
|
||||||
#define BUFFER_SIZE 256
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
// Conway's Game of Life program
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#include "conway.h"
|
|
||||||
#include "../libc/stdio.h"
|
|
||||||
#include "../kernel/system.h"
|
|
||||||
#include "../libc/crypto.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "../drivers/serial.h"
|
|
||||||
#include "../libc/string.h"
|
|
||||||
|
|
||||||
void print_grid(const unsigned char grid[X][Y])
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
for (int i=0; i<X; i++)
|
|
||||||
{
|
|
||||||
for (int j=0; j<Y; j++)
|
|
||||||
{
|
|
||||||
if (grid[i][j] == LIVE) {
|
|
||||||
putc(35);
|
|
||||||
} else {
|
|
||||||
putc(32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int count_live_neighbors(const unsigned char grid[X][Y], int i, int j)
|
|
||||||
{
|
|
||||||
int live_neighbors = 0;
|
|
||||||
|
|
||||||
for (int x=-1; x<=1; x++)
|
|
||||||
{
|
|
||||||
for (int y=-1; y<=1; y++)
|
|
||||||
{
|
|
||||||
if (x==0 && y==0) continue;
|
|
||||||
|
|
||||||
int ni = i+x;
|
|
||||||
int nj = j+y;
|
|
||||||
|
|
||||||
if (ni >= 0 && ni < X && nj >= 0)
|
|
||||||
{
|
|
||||||
if (grid[ni][nj] == LIVE) live_neighbors++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return live_neighbors;
|
|
||||||
}
|
|
||||||
|
|
||||||
void grid_new_generation(unsigned char grid[X][Y], unsigned char temp[X][Y])
|
|
||||||
{
|
|
||||||
for (int i=0; i<X; i++)
|
|
||||||
{
|
|
||||||
for (int j=0; j<Y; j++)
|
|
||||||
{
|
|
||||||
int cell = grid[i][j];
|
|
||||||
int live_neighbors = count_live_neighbors(grid, i, j);
|
|
||||||
|
|
||||||
if (cell == LIVE)
|
|
||||||
{
|
|
||||||
switch(live_neighbors)
|
|
||||||
{
|
|
||||||
case 2:
|
|
||||||
case 3:
|
|
||||||
temp[i][j] = LIVE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
temp[i][j] = DEAD;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (cell == DEAD && live_neighbors == 3)
|
|
||||||
{
|
|
||||||
temp[i][j] = LIVE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i=0; i<X; i++)
|
|
||||||
{
|
|
||||||
for (int j=0; j<Y; j++)
|
|
||||||
{
|
|
||||||
grid[i][j] = temp[i][j];
|
|
||||||
temp[i][j] = DEAD;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void soup(unsigned char grid[X][Y])
|
|
||||||
{
|
|
||||||
srand(global_ticks);
|
|
||||||
for (int i=0; i<X; i++)
|
|
||||||
{
|
|
||||||
for (int j=0; j<Y; j++)
|
|
||||||
{
|
|
||||||
grid[i][j] = rand_float() > SOUP_PROB ? LIVE : DEAD;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void program_conway(int argc, char* argv[])
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
unsigned char grid[X][Y] = {0};
|
|
||||||
unsigned char temp[X][Y] = {0};
|
|
||||||
|
|
||||||
if (argc == 1)
|
|
||||||
{
|
|
||||||
soup(grid);
|
|
||||||
} else if (argc == 2 && strcmp(argv[1], "-g") == 0) {
|
|
||||||
grid[1][2] = LIVE;
|
|
||||||
grid[2][3] = LIVE;
|
|
||||||
grid[3][1] = LIVE;
|
|
||||||
grid[3][2] = LIVE;
|
|
||||||
grid[3][3] = LIVE;
|
|
||||||
} else if (argc == 2 && strcmp(argv[1], "-l") == 0) {
|
|
||||||
grid[10][3] = LIVE; grid[10][4] = LIVE; grid[10][5] = LIVE; grid[10][6] = LIVE;
|
|
||||||
grid[11][2] = LIVE; grid[11][6] = LIVE;
|
|
||||||
grid[12][6] = LIVE;
|
|
||||||
grid[13][2] = LIVE; grid[13][5] = LIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
print_grid(grid);
|
|
||||||
puts("generation 0");
|
|
||||||
for (int i=1; i<GENERATIONS; i++)
|
|
||||||
{
|
|
||||||
grid_new_generation(grid, temp);
|
|
||||||
delay(DELAY);
|
|
||||||
clear();
|
|
||||||
print_grid(grid);
|
|
||||||
printf("generation %d", i);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
// Conway's Game of Life program header
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#ifndef CONWAY_H
|
|
||||||
#define CONWAY_H
|
|
||||||
|
|
||||||
#define X 66
|
|
||||||
#define Y 240
|
|
||||||
|
|
||||||
#define GENERATIONS 100
|
|
||||||
#define DEAD 0
|
|
||||||
#define LIVE 1
|
|
||||||
#define SOUP_PROB 0.7
|
|
||||||
#define DELAY 10
|
|
||||||
|
|
||||||
void print_grid(const unsigned char grid[X][Y]);
|
|
||||||
int count_live_neighbors(const unsigned char grid[X][Y], int i, int j);
|
|
||||||
void grid_new_generation(unsigned char grid[X][Y], unsigned char temp[X][Y]);
|
|
||||||
void soup(unsigned char grid[X][Y]);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
// Cowsay-like program
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#include "../libc/stdio.h"
|
|
||||||
#include "../libc/string.h"
|
|
||||||
|
|
||||||
#define MAX_MSG_LEN 128
|
|
||||||
|
|
||||||
const char* cow =
|
|
||||||
" \\ ^__^\n"
|
|
||||||
" \\ (oo)\\_______\n"
|
|
||||||
" (__)\\ )\\/\\\n"
|
|
||||||
" ||----w |\n"
|
|
||||||
" || ||\n";
|
|
||||||
|
|
||||||
void print_bubble(const char* message)
|
|
||||||
{
|
|
||||||
int len = strlen(message);
|
|
||||||
puts(" ");
|
|
||||||
for (int i=0; i<len+2; i++)
|
|
||||||
{
|
|
||||||
puts("_");
|
|
||||||
}
|
|
||||||
puts("\n");
|
|
||||||
|
|
||||||
printf("< %s >\n", message);
|
|
||||||
|
|
||||||
puts(" ");
|
|
||||||
for (int i=0; i<len+2; i++)
|
|
||||||
{
|
|
||||||
puts("-");
|
|
||||||
}
|
|
||||||
puts("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void cowsay(char* msg, uint32_t fg, uint32_t bg)
|
|
||||||
{
|
|
||||||
print_bubble(msg);
|
|
||||||
colorputs(cow, fg, bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void program_cowsay(int argc, char* argv[])
|
|
||||||
{
|
|
||||||
if (argc < 2)
|
|
||||||
{
|
|
||||||
printf("Usage: %s <message>\n", argv[0]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char message[MAX_MSG_LEN];
|
|
||||||
message[0] = '\0';
|
|
||||||
|
|
||||||
for (int i=1; i<argc; i++)
|
|
||||||
{
|
|
||||||
if (strlen(message) + strlen(argv[i]) + 1 < MAX_MSG_LEN)
|
|
||||||
{
|
|
||||||
strcat(message, argv[i]);
|
|
||||||
if (i < argc-1)
|
|
||||||
{
|
|
||||||
strcat(message, " ");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
puts("Too long message.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
print_bubble(message);
|
|
||||||
printf("%s", cow);
|
|
||||||
}
|
|
||||||
@@ -1,245 +0,0 @@
|
|||||||
// Basic math expression lexer and parser program
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "../kernel/system.h"
|
|
||||||
#include "../libc/stdio.h"
|
|
||||||
#include "../libc/ctype.h"
|
|
||||||
|
|
||||||
#define BUFFER_SIZE 256
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
TOKEN_NUMBER,
|
|
||||||
TOKEN_PLUS,
|
|
||||||
TOKEN_MINUS,
|
|
||||||
TOKEN_MULTIPLY,
|
|
||||||
TOKEN_DIVIDE,
|
|
||||||
TOKEN_LPAREN,
|
|
||||||
TOKEN_RPAREN,
|
|
||||||
TOKEN_END
|
|
||||||
} TokenType;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
TokenType type;
|
|
||||||
double value;
|
|
||||||
} Token;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
const char *text;
|
|
||||||
size_t pos;
|
|
||||||
Token current_token;
|
|
||||||
} Lexer;
|
|
||||||
|
|
||||||
void lexer_init(Lexer *lexer, const char *text)
|
|
||||||
{
|
|
||||||
lexer->text = text;
|
|
||||||
lexer->pos = 0;
|
|
||||||
lexer->current_token.type = TOKEN_END;
|
|
||||||
lexer->current_token.value = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void lexer_advance(Lexer *lexer)
|
|
||||||
{
|
|
||||||
lexer->pos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
char lexer_peek(const Lexer *lexer)
|
|
||||||
{
|
|
||||||
return lexer->text[lexer->pos];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lexer_is_at_end(const Lexer *lexer)
|
|
||||||
{
|
|
||||||
return lexer->text[lexer->pos] == '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
Token lexer_get_next_token(Lexer *lexer)
|
|
||||||
{
|
|
||||||
while (!lexer_is_at_end(lexer))
|
|
||||||
{
|
|
||||||
char current_char = lexer_peek(lexer);
|
|
||||||
|
|
||||||
if (isspace(current_char)) {
|
|
||||||
lexer_advance(lexer);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isdigit(current_char)) {
|
|
||||||
double value = 0;
|
|
||||||
while (isdigit(current_char))
|
|
||||||
{
|
|
||||||
value = value * 10 + (current_char - '0');
|
|
||||||
lexer_advance(lexer);
|
|
||||||
current_char = lexer_peek(lexer);
|
|
||||||
}
|
|
||||||
if (current_char == '.')
|
|
||||||
{
|
|
||||||
lexer_advance(lexer);
|
|
||||||
double decimal_place = 0.1;
|
|
||||||
while (isdigit(lexer_peek(lexer)))
|
|
||||||
{
|
|
||||||
value += decimal_place * (lexer_peek(lexer)-'0');
|
|
||||||
decimal_place *= 0.1;
|
|
||||||
lexer_advance(lexer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lexer->current_token.type = TOKEN_NUMBER;
|
|
||||||
lexer->current_token.value = value;
|
|
||||||
return lexer->current_token;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_char == '+')
|
|
||||||
{
|
|
||||||
lexer_advance(lexer);
|
|
||||||
lexer->current_token.type = TOKEN_PLUS;
|
|
||||||
return lexer->current_token;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_char == '-')
|
|
||||||
{
|
|
||||||
lexer_advance(lexer);
|
|
||||||
lexer->current_token.type = TOKEN_MINUS;
|
|
||||||
return lexer->current_token;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_char == '*')
|
|
||||||
{
|
|
||||||
lexer_advance(lexer);
|
|
||||||
lexer->current_token.type = TOKEN_MULTIPLY;
|
|
||||||
return lexer->current_token;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_char == '/')
|
|
||||||
{
|
|
||||||
lexer_advance(lexer);
|
|
||||||
lexer->current_token.type = TOKEN_DIVIDE;
|
|
||||||
return lexer->current_token;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_char == '(')
|
|
||||||
{
|
|
||||||
lexer_advance(lexer);
|
|
||||||
lexer->current_token.type = TOKEN_LPAREN;
|
|
||||||
return lexer->current_token;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_char == ')')
|
|
||||||
{
|
|
||||||
lexer_advance(lexer);
|
|
||||||
lexer->current_token.type = TOKEN_RPAREN;
|
|
||||||
return lexer->current_token;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\nUnknown character %c\n", current_char);
|
|
||||||
shell_install();
|
|
||||||
}
|
|
||||||
|
|
||||||
lexer->current_token.type = TOKEN_END;
|
|
||||||
return lexer->current_token;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
Lexer lexer;
|
|
||||||
Token current_token;
|
|
||||||
} Parser;
|
|
||||||
|
|
||||||
void parser_init(Parser *parser, const char *text)
|
|
||||||
{
|
|
||||||
lexer_init(&parser->lexer, text);
|
|
||||||
parser->current_token = lexer_get_next_token(&parser->lexer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void parser_eat(Parser *parser, TokenType type)
|
|
||||||
{
|
|
||||||
if (parser->current_token.type == type)
|
|
||||||
{
|
|
||||||
parser->current_token = lexer_get_next_token(&parser->lexer);
|
|
||||||
} else {
|
|
||||||
printf("\nUnexpected token %d\n", parser->current_token.type);
|
|
||||||
shell_install();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double parser_factor(Parser *parser);
|
|
||||||
double parser_term(Parser *parser);
|
|
||||||
double parser_expression(Parser *parser);
|
|
||||||
|
|
||||||
double parser_factor(Parser *parser)
|
|
||||||
{
|
|
||||||
Token token = parser->current_token;
|
|
||||||
if (token.type == TOKEN_NUMBER)
|
|
||||||
{
|
|
||||||
parser_eat(parser, TOKEN_NUMBER);
|
|
||||||
return token.value;
|
|
||||||
} else if (token.type == TOKEN_LPAREN) {
|
|
||||||
parser_eat(parser, TOKEN_LPAREN);
|
|
||||||
double result = parser_expression(parser);
|
|
||||||
parser_eat(parser, TOKEN_RPAREN);
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
printf("\nUnexpected token in factor %d\n", token.type);
|
|
||||||
shell_install();
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
double parser_term(Parser *parser)
|
|
||||||
{
|
|
||||||
double result = parser_factor(parser);
|
|
||||||
|
|
||||||
while (parser->current_token.type == TOKEN_MULTIPLY || parser->current_token.type == TOKEN_DIVIDE)
|
|
||||||
{
|
|
||||||
Token token = parser->current_token;
|
|
||||||
if (token.type == TOKEN_MULTIPLY)
|
|
||||||
{
|
|
||||||
parser_eat(parser, TOKEN_MULTIPLY);
|
|
||||||
result *= parser_factor(parser);
|
|
||||||
} else if (token.type == TOKEN_DIVIDE) {
|
|
||||||
parser_eat(parser, TOKEN_DIVIDE);
|
|
||||||
result /= parser_factor(parser);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
double parser_expression(Parser *parser)
|
|
||||||
{
|
|
||||||
double result = parser_term(parser);
|
|
||||||
|
|
||||||
while (parser->current_token.type == TOKEN_PLUS || parser->current_token.type == TOKEN_MINUS)
|
|
||||||
{
|
|
||||||
Token token = parser->current_token;
|
|
||||||
if (token.type == TOKEN_PLUS)
|
|
||||||
{
|
|
||||||
parser_eat(parser, TOKEN_PLUS);
|
|
||||||
result += parser_term(parser);
|
|
||||||
} else if (token.type == TOKEN_MINUS) {
|
|
||||||
parser_eat(parser, TOKEN_MINUS);
|
|
||||||
result -= parser_term(parser);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
double parse(const char* text)
|
|
||||||
{
|
|
||||||
Parser parser;
|
|
||||||
parser_init(&parser, text);
|
|
||||||
double result = parser_expression(&parser);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void program_math()
|
|
||||||
{
|
|
||||||
char input_buffer[BUFFER_SIZE];
|
|
||||||
puts("Expression? ");
|
|
||||||
get_input(input_buffer, BUFFER_SIZE);
|
|
||||||
double result = parse(input_buffer);
|
|
||||||
printf("\n%f\n", result);
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
// Miscellaneous small programs
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#include "../libc/stdio.h"
|
|
||||||
#include "../kernel/system.h"
|
|
||||||
#include "../libc/string.h"
|
|
||||||
#include "../drivers/framebuffer.h"
|
|
||||||
|
|
||||||
// Print a rainbow colorful text for testing
|
|
||||||
|
|
||||||
#define BUF_SIZE 256
|
|
||||||
#define COLORS 20
|
|
||||||
|
|
||||||
void program_rainbow()
|
|
||||||
{
|
|
||||||
char input_buffer[BUF_SIZE];
|
|
||||||
puts("What to print? ");
|
|
||||||
get_input(input_buffer, BUF_SIZE);
|
|
||||||
puts("\n");
|
|
||||||
|
|
||||||
for (int i=0; i<COLORS; i++)
|
|
||||||
{
|
|
||||||
//colorputs(input_buffer, i);
|
|
||||||
puts("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear the terminal
|
|
||||||
|
|
||||||
#define ROWS 25
|
|
||||||
|
|
||||||
void program_clear()
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get uptime in ticks
|
|
||||||
|
|
||||||
void program_uptime()
|
|
||||||
{
|
|
||||||
int ticks = uptime();
|
|
||||||
double seconds = ticks/18.2065; // PIT channel 0 freq
|
|
||||||
printf("%d ticks\t%f seconds\n", ticks, seconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get help
|
|
||||||
|
|
||||||
void program_help()
|
|
||||||
{
|
|
||||||
printf("help\tpanic\twords\tprimes\trainbow\tclear\nmath\tbf\t uptime echo\t sysinfo\tconway\nrot13 morse\tcowsay\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Panic
|
|
||||||
|
|
||||||
void program_panic()
|
|
||||||
{
|
|
||||||
asm volatile("int $0x13");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Output input
|
|
||||||
|
|
||||||
void program_echo(int argc, char* argv[])
|
|
||||||
{
|
|
||||||
for (int i=1; i<argc; i++)
|
|
||||||
{
|
|
||||||
puts(argv[i]);
|
|
||||||
if (i < argc-1) {
|
|
||||||
putc(' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
puts("\n");
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
// Prime number computation program
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "../libc/stdio.h"
|
|
||||||
#include "../kernel/system.h"
|
|
||||||
#include "../libc/string.h"
|
|
||||||
|
|
||||||
#define PRIMES_MAX 1000000
|
|
||||||
|
|
||||||
bool isPrime(int n)
|
|
||||||
{
|
|
||||||
if (n == 1 || n == 0) return false;
|
|
||||||
for (int i=2; i<= n/2; i++) if (n%i == 0) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void program_primes(int argc, char* argv[])
|
|
||||||
{
|
|
||||||
int primes_max;
|
|
||||||
|
|
||||||
if (argc == 1)
|
|
||||||
{
|
|
||||||
primes_max = PRIMES_MAX;
|
|
||||||
} else if (argc == 2)
|
|
||||||
{
|
|
||||||
primes_max = atoi(argv[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (long long x=0; x<primes_max; x++)
|
|
||||||
{
|
|
||||||
if (isPrime(x))
|
|
||||||
{
|
|
||||||
printf("%d ", x);
|
|
||||||
}
|
|
||||||
delay(1);
|
|
||||||
}
|
|
||||||
puts("\n");
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
// Global program entry points header
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#ifndef PROGRAMS_H
|
|
||||||
#define PROGRAMS_H
|
|
||||||
|
|
||||||
void program_words();
|
|
||||||
void program_primes();
|
|
||||||
void program_math();
|
|
||||||
void program_bf();
|
|
||||||
void program_sysinfo();
|
|
||||||
|
|
||||||
void get_cpuid();
|
|
||||||
void get_meminfo(unsigned int multiboot_info_address);
|
|
||||||
void program_conway();
|
|
||||||
void program_cowsay();
|
|
||||||
void cowsay(); // Splash screen
|
|
||||||
|
|
||||||
// Ciphers
|
|
||||||
void program_rot13();
|
|
||||||
void program_morse();
|
|
||||||
|
|
||||||
// Misc
|
|
||||||
void program_rainbow();
|
|
||||||
void program_clear();
|
|
||||||
void program_uptime();
|
|
||||||
void program_panic();
|
|
||||||
void program_help();
|
|
||||||
void program_echo();
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
// System information program
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#include "../kernel/sysinfo.h"
|
|
||||||
#include "../libc/stdio.h"
|
|
||||||
#include "../kernel/system.h"
|
|
||||||
#include "../libc/string.h"
|
|
||||||
|
|
||||||
extern unsigned int multiboot_info_address;
|
|
||||||
|
|
||||||
typedef struct multiboot_memory_map
|
|
||||||
{
|
|
||||||
unsigned int size;
|
|
||||||
unsigned int base_addr_low;
|
|
||||||
unsigned int base_addr_high;
|
|
||||||
unsigned int length_low;
|
|
||||||
unsigned int length_high;
|
|
||||||
unsigned int type;
|
|
||||||
} multiboot_memory_map_t;
|
|
||||||
|
|
||||||
void get_cpuid()
|
|
||||||
{
|
|
||||||
// CPUid
|
|
||||||
|
|
||||||
unsigned int eax, edx;
|
|
||||||
char vendor[13];
|
|
||||||
unsigned int* v = (unsigned int*)vendor;
|
|
||||||
|
|
||||||
asm volatile("cpuid"
|
|
||||||
: "=b"(v[0]), "=d"(v[1]), "=c"(v[2])
|
|
||||||
: "a"(0));
|
|
||||||
vendor[12] = '\0';
|
|
||||||
|
|
||||||
cpuid(1, &eax, &edx);
|
|
||||||
unsigned int model = (eax >> 4) & 0xF;
|
|
||||||
unsigned int family = (eax >> 8) & 0xF;
|
|
||||||
|
|
||||||
printf("CPU information\n\tvendor: %s\n\tfamily: %u\n\tmodel: %u\n\tfeatures: 0x%x\n", vendor, family, model, edx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void get_meminfo(unsigned int multiboot_info_address, int verbose)
|
|
||||||
{
|
|
||||||
// RAM
|
|
||||||
|
|
||||||
unsigned int mem_lower = *((unsigned int*)(multiboot_info_address + 4));
|
|
||||||
unsigned int mem_upper = *((unsigned int*)(multiboot_info_address + 8));
|
|
||||||
|
|
||||||
printf("RAM information\n\tLower memory: %u KB\n\tUpper memory: %u KB\n", mem_lower, mem_upper);
|
|
||||||
|
|
||||||
if (verbose)
|
|
||||||
{
|
|
||||||
multiboot_memory_map_t* mmap = (multiboot_memory_map_t*)*((unsigned int*)(multiboot_info_address + 44));
|
|
||||||
printf("Memory map:\nBase addr | Length | Type\n----------------------------------------------------\n");
|
|
||||||
|
|
||||||
while ((unsigned int)mmap < multiboot_info_address + *((unsigned int*)(multiboot_info_address + 40)))
|
|
||||||
{
|
|
||||||
if (mmap->length_high != 0 && mmap->length_low != 0)
|
|
||||||
{
|
|
||||||
printf("0x%x%x | 0x%x%x | %u\n",
|
|
||||||
mmap->base_addr_high, mmap->base_addr_low,
|
|
||||||
mmap->length_high, mmap->length_low,
|
|
||||||
mmap->type);
|
|
||||||
}
|
|
||||||
mmap = (multiboot_memory_map_t*)((unsigned int)mmap + mmap->size + sizeof(unsigned int));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void program_sysinfo(int argc, char* argv[])
|
|
||||||
{
|
|
||||||
if (argc == 1)
|
|
||||||
{
|
|
||||||
get_cpuid();
|
|
||||||
get_meminfo(g_multiboot_info_address, 0);
|
|
||||||
} else if (argc == 2 && strcmp(argv[1], "-v") == 0)
|
|
||||||
{
|
|
||||||
get_cpuid();
|
|
||||||
get_meminfo(g_multiboot_info_address, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,217 +0,0 @@
|
|||||||
// Pseudo-random word generation program
|
|
||||||
// Author: xamidev
|
|
||||||
// Licensed under the Unlicense. See the repo below.
|
|
||||||
// https://github.com/xamidev/blankos
|
|
||||||
|
|
||||||
#include "../libc/stdio.h"
|
|
||||||
#include "../libc/crypto.h"
|
|
||||||
#include "../kernel/system.h"
|
|
||||||
#include "../libc/string.h"
|
|
||||||
|
|
||||||
// Small dictionary
|
|
||||||
|
|
||||||
char* words[] =
|
|
||||||
{
|
|
||||||
// A
|
|
||||||
"I", "us", "they", "my",
|
|
||||||
"a", "an", "is", "are", "for", "while", "not", "none", "yes", "no",
|
|
||||||
"absolutely", "addition", "additive", "afternoon", "architect", "ask",
|
|
||||||
"ability", "above", "absence", "academy", "account", "achieve", "acquire",
|
|
||||||
"adapt", "admit", "adventure", "affection", "agenda", "agreement", "airport",
|
|
||||||
"alert", "alibi", "alive", "allow", "almond", "alphabet", "always",
|
|
||||||
|
|
||||||
// B
|
|
||||||
"be", "blindfold", "brilliant", "boy", "bring", "buddy",
|
|
||||||
"balance", "bamboo", "band", "banjo", "bank", "banner", "barrel",
|
|
||||||
"basic", "battery", "beach", "beacon", "beard", "behavior", "believe",
|
|
||||||
"belt", "benefit", "berry", "bicycle", "bingo", "biology", "birthday",
|
|
||||||
"biscuit", "bitter", "blanket", "blizzard", "blossom", "blueprint", "board",
|
|
||||||
|
|
||||||
// C
|
|
||||||
"career", "caterpillar", "change", "cheeky", "chop",
|
|
||||||
"cabin", "cactus", "camera", "candle", "candy", "canoe", "canvas",
|
|
||||||
"capital", "captain", "caravan", "carbon", "carpet", "cartoon", "castle",
|
|
||||||
"casual", "catalog", "catch", "category", "celebrate", "ceremony", "certain",
|
|
||||||
"chain", "chair", "chamber", "charge", "charity", "cheese", "chef",
|
|
||||||
|
|
||||||
// D
|
|
||||||
"decide", "demonstrate", "draw", "druggist",
|
|
||||||
"daisy", "dance", "danger", "daring", "database", "debate", "decade",
|
|
||||||
"decline", "decorate", "decrease", "dedicate", "defeat", "defend", "define",
|
|
||||||
"degree", "delight", "delivery", "demand", "dentist", "deny", "depart",
|
|
||||||
"depth", "describe", "deserve", "desire", "destroy", "develop", "device",
|
|
||||||
|
|
||||||
// E
|
|
||||||
"eagle", "ear", "effort", "evening",
|
|
||||||
"early", "earn", "earth", "ease", "east", "easy", "echo",
|
|
||||||
"eclipse", "economy", "edge", "edit", "educate", "effect", "effort",
|
|
||||||
"egg", "eight", "either", "elder", "elect", "elegant", "element",
|
|
||||||
"elephant", "elevator", "elite", "embark", "embrace", "emerge", "emotion",
|
|
||||||
|
|
||||||
// F
|
|
||||||
"fabric", "famous", "fuse",
|
|
||||||
"face", "factor", "fail", "fair", "fall", "false", "fame",
|
|
||||||
"family", "fancy", "fantasy", "farewell", "farm", "fashion", "fast",
|
|
||||||
"fault", "favor", "feather", "feature", "federal", "feedback", "feeling",
|
|
||||||
"female", "fence", "festival", "fever", "fiber", "fiction", "field",
|
|
||||||
|
|
||||||
// G
|
|
||||||
"generation", "generous", "girl", "gypsy", "grip",
|
|
||||||
"gallery", "game", "garage", "garden", "garlic", "gas", "gate",
|
|
||||||
"gather", "general", "genius", "gentle", "genuine", "geography", "gesture",
|
|
||||||
"ghost", "giant", "gift", "giggle", "ginger", "giraffe", "glance",
|
|
||||||
"glass", "globe", "glory", "glove", "glue", "goal", "gold",
|
|
||||||
|
|
||||||
// H
|
|
||||||
"habit", "handsome", "helmet", "help", "horror",
|
|
||||||
"hair", "half", "hammer", "hand", "handle", "hang", "happen",
|
|
||||||
"harbor", "hard", "harm", "harvest", "hat", "hate", "have",
|
|
||||||
"head", "health", "heart", "heat", "heaven", "heavy", "hedge",
|
|
||||||
"height", "hello", "heritage", "hero", "hesitate", "hidden", "high",
|
|
||||||
|
|
||||||
// I
|
|
||||||
"insist", "inventor", "itself", "ivory",
|
|
||||||
"ice", "idea", "ideal", "identify", "ignore", "ill", "image",
|
|
||||||
"imagine", "impact", "import", "impress", "improve", "impulse", "inch",
|
|
||||||
"include", "income", "increase", "index", "industry", "infant", "inform",
|
|
||||||
"insect", "inside", "inspire", "install", "instead", "insult", "intact",
|
|
||||||
|
|
||||||
// J
|
|
||||||
"jog", "joint", "joke", "judge",
|
|
||||||
"jacket", "jaguar", "jail", "jam", "january", "jar", "jazz",
|
|
||||||
"jealous", "jeans", "jelly", "jewel", "job", "join", "journey",
|
|
||||||
"joy", "judge", "juice", "jump", "jungle", "junior", "justice",
|
|
||||||
"just", "justify", "juggle", "juice", "jumper", "junction", "jury",
|
|
||||||
|
|
||||||
// K
|
|
||||||
"karate", "kebab", "kitchen",
|
|
||||||
"kangaroo", "keen", "keep", "kettle", "key", "keyboard", "kick",
|
|
||||||
"kid", "kidney", "king", "kiss", "kite", "knee", "knife",
|
|
||||||
"knit", "knock", "knot", "know", "knowledge", "koala", "kudos",
|
|
||||||
"keen", "kernel", "kit", "kitten", "knack", "knight", "knock",
|
|
||||||
|
|
||||||
// L
|
|
||||||
"lamb", "lawnmower", "left", "lock",
|
|
||||||
"label", "labor", "lace", "ladder", "lady", "lake", "lamp",
|
|
||||||
"land", "language", "large", "laser", "last", "later", "laugh",
|
|
||||||
"launch", "law", "layer", "lead", "leaf", "learn", "least",
|
|
||||||
"leather", "leave", "lecture", "legal", "legend", "lemon", "length",
|
|
||||||
|
|
||||||
// M
|
|
||||||
"math", "medicine", "most",
|
|
||||||
"machine", "magnet", "mail", "main", "major", "make", "male",
|
|
||||||
"manage", "mango", "manner", "manual", "map", "marble", "march",
|
|
||||||
"mark", "market", "marriage", "master", "match", "material", "matter",
|
|
||||||
"maximum", "mayor", "meal", "mean", "measure", "media", "memory",
|
|
||||||
|
|
||||||
// N
|
|
||||||
"noodles", "nowadays", "nowhere",
|
|
||||||
"nail", "name", "narrow", "nation", "native", "nature", "navy",
|
|
||||||
"near", "neat", "necessary", "neck", "need", "negative", "neglect",
|
|
||||||
"neither", "nerve", "nest", "net", "network", "neutral", "never",
|
|
||||||
"new", "news", "next", "nice", "night", "noble", "noise",
|
|
||||||
|
|
||||||
// O
|
|
||||||
"ocean", "older", "ounce",
|
|
||||||
"object", "observe", "obtain", "occasion", "occupy", "occur", "ocean",
|
|
||||||
"offer", "office", "often", "oil", "old", "olive", "olympic",
|
|
||||||
"omit", "once", "one", "onion", "online", "only", "open",
|
|
||||||
"opera", "opinion", "oppose", "option", "orange", "orbit", "order",
|
|
||||||
|
|
||||||
// P
|
|
||||||
"part", "pathetic", "pastime",
|
|
||||||
"pace", "package", "page", "pain", "paint", "pair", "palm",
|
|
||||||
"panel", "panic", "paper", "parent", "park", "part", "party",
|
|
||||||
"pass", "path", "patient", "pattern", "pause", "peace", "peak",
|
|
||||||
"pen", "pencil", "people", "pepper", "perfect", "perform", "permit",
|
|
||||||
|
|
||||||
// Q
|
|
||||||
"quite", "quits", "quotation",
|
|
||||||
"quality", "quantity", "quarter", "queen", "query", "quest", "quick",
|
|
||||||
"quiet", "quilt", "quit", "quote", "quiz", "quota", "quiver",
|
|
||||||
"quirky", "quaint", "quake", "qualification", "qualify", "quark", "quartz",
|
|
||||||
"queue", "quench", "question", "quote", "quiver", "quorum", "quote",
|
|
||||||
|
|
||||||
// R
|
|
||||||
"race", "raise", "reality",
|
|
||||||
"rabbit", "race", "radio", "rain", "raise", "random", "range",
|
|
||||||
"rapid", "rare", "rate", "rather", "ratio", "reach", "react",
|
|
||||||
"read", "ready", "real", "reason", "rebel", "recall", "receive",
|
|
||||||
"recipe", "record", "recover", "reduce", "refer", "reflect", "reform",
|
|
||||||
|
|
||||||
// S
|
|
||||||
"safe", "scare", "screen",
|
|
||||||
"sack", "sail", "salad", "salt", "same", "sample", "sand",
|
|
||||||
"save", "scale", "scan", "scar", "scene", "school", "science",
|
|
||||||
"score", "scratch", "scream", "screen", "script", "search", "season",
|
|
||||||
"seat", "second", "secret", "section", "secure", "see", "seed",
|
|
||||||
|
|
||||||
// T
|
|
||||||
"taught", "temple", "that", "this",
|
|
||||||
"table", "tackle", "tail", "take", "tale", "talent", "talk",
|
|
||||||
"tank", "tape", "target", "task", "taste", "tax", "teach",
|
|
||||||
"team", "tear", "technology", "telephone", "television", "temperature", "tend",
|
|
||||||
"tennis", "tent", "term", "test", "text", "thank", "theory",
|
|
||||||
|
|
||||||
// U
|
|
||||||
"unable", "unkind", "usual",
|
|
||||||
"umbrella", "unable", "uncle", "under", "undo", "unfair", "unfold",
|
|
||||||
"union", "unique", "unit", "universe", "unknown", "unless", "unlike",
|
|
||||||
"unlock", "until", "unusual", "update", "upgrade", "upon", "upper",
|
|
||||||
"upset", "urban", "urge", "use", "usual", "utility", "utter",
|
|
||||||
|
|
||||||
// V
|
|
||||||
"velvet", "vivid", "vote",
|
|
||||||
"vacuum", "valid", "valley", "value", "vampire", "van", "vase",
|
|
||||||
"vast", "vault", "vector", "vehicle", "velvet", "vendor", "venture",
|
|
||||||
"verb", "verify", "version", "vessel", "veteran", "veto", "vibrate",
|
|
||||||
"victory", "video", "view", "village", "violin", "virtue", "virus",
|
|
||||||
|
|
||||||
// W
|
|
||||||
"we", "warm", "watch",
|
|
||||||
"wage", "wait", "walk", "wall", "wander", "want", "war",
|
|
||||||
"wash", "waste", "watch", "water", "wave", "way", "wealth",
|
|
||||||
"weapon", "wear", "weather", "weave", "wedding", "week", "weight",
|
|
||||||
"welcome", "well", "west", "wheel", "when", "whisper", "white",
|
|
||||||
|
|
||||||
// X
|
|
||||||
"xylophone",
|
|
||||||
"xenon", "xenophobia", "xerox", "xmas", "x-ray", "xylophone", "xylem",
|
|
||||||
|
|
||||||
// Y
|
|
||||||
"yolk", "young", "your",
|
|
||||||
"yard", "yarn", "year", "yell", "yellow", "yes", "yesterday",
|
|
||||||
"yet", "yield", "yogurt", "yoke", "youth", "yawn", "yearn",
|
|
||||||
"yacht", "yummy", "yogurt", "yoga", "yardstick", "yonder", "yummy",
|
|
||||||
|
|
||||||
// Z
|
|
||||||
"zebra", "zodiac", "zucchini",
|
|
||||||
"zero", "zone", "zoo", "zoom", "zeal", "zip", "zigzag",
|
|
||||||
"zenith", "zest", "zipper", "zombie", "zonal", "zinc", "zephyr"
|
|
||||||
};
|
|
||||||
|
|
||||||
int words_size = sizeof(words)/sizeof(words[0]);
|
|
||||||
|
|
||||||
// Generates random words
|
|
||||||
void program_words(int argc, char* argv[])
|
|
||||||
{
|
|
||||||
int amount;
|
|
||||||
|
|
||||||
if (argc == 1)
|
|
||||||
{
|
|
||||||
amount = 10;
|
|
||||||
} else if (argc == 2)
|
|
||||||
{
|
|
||||||
amount = atoi(argv[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i=0; i<amount; i++)
|
|
||||||
{
|
|
||||||
int random = randint(global_ticks);
|
|
||||||
char* word = words[random%words_size];
|
|
||||||
//printf("Global ticks: %d\nRandom integer: %d\nWord: %s\n", global_ticks, random, word);
|
|
||||||
printf("%s ", word);
|
|
||||||
delay(10);
|
|
||||||
}
|
|
||||||
puts("\n");
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user