Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8826a7d873 | ||
|
|
b0668b1fd7 | ||
|
|
cacc042a5c | ||
|
|
247558669e | ||
|
|
f55723c227 | ||
|
|
acbcc54e51 | ||
|
|
d2034cd68b | ||
|
|
b59af22897 | ||
|
|
4d05e0d620 | ||
|
|
3b39a0a1f4 |
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
# 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 (UEFI and BIOS).
|
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
|
||||||
@@ -65,7 +65,7 @@ Two other documents are available to help you understand the project better. One
|
|||||||
- [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
|
||||||
- [ ] Dynamic memory allocator (get memmap from GRUB?)
|
- [X] Dynamic memory allocator (get memmap from GRUB?)
|
||||||
- [ ] Paging/Page Frame Allocation
|
- [ ] Paging/Page Frame Allocation
|
||||||
- [ ] TCP/IP Network stack
|
- [ ] TCP/IP Network stack
|
||||||
- [ ] Getting to Ring-3 (userspace)
|
- [ ] Getting to Ring-3 (userspace)
|
||||||
|
|||||||
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
|
||||||
@@ -3,8 +3,11 @@
|
|||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
- Getting Started
|
- Getting Started
|
||||||
|
- Debugging the kernel
|
||||||
|
- Emulated booting in UEFI mode
|
||||||
- Writing programs for BlankOS
|
- Writing programs for BlankOS
|
||||||
- Changing the TTY font
|
- Changing the TTY font
|
||||||
|
- Changing the initial ramdisk content
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
@@ -33,6 +36,14 @@ gdb kernel.elf
|
|||||||
(gdb) target remote localhost:1234
|
(gdb) target remote localhost:1234
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 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:
|
||||||
|
|
||||||
|
```
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
## Writing programs for BlankOS
|
## 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.
|
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.
|
||||||
@@ -109,3 +120,10 @@ 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.
|
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.
|
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.
|
||||||
|
|||||||
@@ -69,9 +69,9 @@ 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`
|
||||||
|
|
||||||
@@ -113,3 +113,19 @@ Makes a cow speak!
|
|||||||
#### `pi <terms>`
|
#### `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.
|
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`.
|
||||||
|
|||||||
1
grub.cfg
1
grub.cfg
@@ -2,5 +2,6 @@ menuentry "Blank OS" {
|
|||||||
insmod all_video
|
insmod all_video
|
||||||
set gfxpayload=1024x768x32
|
set gfxpayload=1024x768x32
|
||||||
multiboot2 /boot/kernel.elf
|
multiboot2 /boot/kernel.elf
|
||||||
|
module2 /boot/initrd.tar
|
||||||
boot
|
boot
|
||||||
}
|
}
|
||||||
|
|||||||
10
makefile
10
makefile
@@ -49,17 +49,21 @@ toolchain:
|
|||||||
wget $(TOOLCHAIN_SRC)
|
wget $(TOOLCHAIN_SRC)
|
||||||
tar xf $(TOOLCHAIN_FILE)
|
tar xf $(TOOLCHAIN_FILE)
|
||||||
|
|
||||||
iso: kernel.elf
|
iso: kernel.elf initrd
|
||||||
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
|
||||||
|
|
||||||
|
initrd:
|
||||||
|
mkdir -p iso/boot/grub
|
||||||
|
tar -cf $(OBJ_DIR)/initrd.tar -C $(SRC_DIR)/initrd .
|
||||||
|
cp $(OBJ_DIR)/initrd.tar iso/boot
|
||||||
|
|
||||||
run: iso
|
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)
|
||||||
|
|||||||
BIN
src/initrd/flower.bmp
Normal file
BIN
src/initrd/flower.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
1
src/initrd/hello.bf
Normal file
1
src/initrd/hello.bf
Normal file
@@ -0,0 +1 @@
|
|||||||
|
-[------->+<]>-.-[->+++++<]>++.+++++++..+++.[--->+<]>-----.---[->+++<]>.-[--->+<]>---.+++.------.--------.
|
||||||
1
src/initrd/hello.txt
Normal file
1
src/initrd/hello.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
hello, ramdisk world!
|
||||||
BIN
src/initrd/hibou.bmp
Normal file
BIN
src/initrd/hibou.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 192 KiB |
BIN
src/initrd/red.bmp
Normal file
BIN
src/initrd/red.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
BIN
src/initrd/smiley.bmp
Normal file
BIN
src/initrd/smiley.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
37
src/initrd/welcome.txt
Normal file
37
src/initrd/welcome.txt
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
***********************
|
||||||
|
* Welcome to BlankOS! *
|
||||||
|
***********************
|
||||||
|
|
||||||
|
Congratulations, you've entered my small world!
|
||||||
|
|
||||||
|
You can try all the commands, try tweaking stuff like explained
|
||||||
|
in the DEVELOPERS.md file, and even contribute if you got the
|
||||||
|
guts. lol.
|
||||||
|
|
||||||
|
Don't look too much at the code, it's badly designed, but hey,
|
||||||
|
that's my first OS project so I find it kinda cool.
|
||||||
|
|
||||||
|
There's no paging, ring 3, processes... I am not smart enough
|
||||||
|
for all this modern stuff. Let's keep it simple and stay in
|
||||||
|
ring0, without processes, maybe one day there'll be more
|
||||||
|
advanced features, but not today.
|
||||||
|
|
||||||
|
** Why am I doing this?
|
||||||
|
|
||||||
|
I wanted to explore the world of low-level programing.
|
||||||
|
As I had only 1 year of experience in C, it was super challenging
|
||||||
|
especially at the beginning, and I needed much time to understand
|
||||||
|
even the most basic things around OSDev.
|
||||||
|
|
||||||
|
I'll backup the project on archival media once it'll be at a good
|
||||||
|
enough point; I think it's cool to leave a trace of my passage on
|
||||||
|
Earth.
|
||||||
|
|
||||||
|
** Easter eggs
|
||||||
|
|
||||||
|
To make the exploration a bit funnier, I hid some easter eggs
|
||||||
|
around. You can try to find them if you have time to lose.
|
||||||
|
|
||||||
|
** Ravtzn
|
||||||
|
|
||||||
|
Jub xabjf? Znlor fbzrguvat'f uvqqra va gurer...
|
||||||
144
src/kernel/initrd.c
Normal file
144
src/kernel/initrd.c
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
// Initial TAR ramdisk kernel module
|
||||||
|
// Author: xamidev
|
||||||
|
// Licensed under the Unlicense. See the repo below.
|
||||||
|
// https://github.com/xamidev/blankos
|
||||||
|
|
||||||
|
#include "../libc/stdio.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../libc/string.h"
|
||||||
|
#include "initrd.h"
|
||||||
|
#include "system.h"
|
||||||
|
|
||||||
|
static unsigned int octal_to_int(const char* str, size_t size)
|
||||||
|
{
|
||||||
|
unsigned int result = 0;
|
||||||
|
while (*str && size-- > 0)
|
||||||
|
{
|
||||||
|
result = (result << 3) | (*str - '0');
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t tar_parse_size(const char* in)
|
||||||
|
{
|
||||||
|
uint32_t size = 0;
|
||||||
|
while (*in >= '0' && *in <= '7')
|
||||||
|
{
|
||||||
|
size = (size*8) + (*in - '0');
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tar_find_file(uint8_t *tar_start, const char* filename)
|
||||||
|
{
|
||||||
|
uint8_t *ptr = tar_start;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
tar_header_t *header = (tar_header_t*)ptr;
|
||||||
|
|
||||||
|
if (header->filename[0] == '\0')
|
||||||
|
{
|
||||||
|
puts("[tar] EOF\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int filesize = octal_to_int(header->size, 11);
|
||||||
|
|
||||||
|
if (strcmp(header->filename, filename) == 0)
|
||||||
|
{
|
||||||
|
printf("[tar] found file '%s', size=%u bytes\n", header->filename, filesize);
|
||||||
|
|
||||||
|
uint8_t *file_data = ptr+TAR_BLOCK_SIZE;
|
||||||
|
printf("[tar] content of '%s':\n", filename);
|
||||||
|
for (unsigned int i=0; i<filesize; i++)
|
||||||
|
{
|
||||||
|
putc(file_data[i]);
|
||||||
|
}
|
||||||
|
puts("\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr += TAR_BLOCK_SIZE + ((filesize + TAR_BLOCK_SIZE-1) / TAR_BLOCK_SIZE) * TAR_BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("[tar] file '%s' not found\n", filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ls_initrd(uint8_t* initrd, int verbose)
|
||||||
|
{
|
||||||
|
tar_header_t *header = (tar_header_t*)initrd;
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
{
|
||||||
|
puts("Size Type Filename\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
while (header->filename[0] != '\0')
|
||||||
|
{
|
||||||
|
if (!verbose)
|
||||||
|
{
|
||||||
|
printf("%s\n", header->filename);
|
||||||
|
} else {
|
||||||
|
printf("%7d\t%c\t %s\n", header->size, header->typeflag, header->filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t size = tar_parse_size(header->size);
|
||||||
|
uint32_t next_file_offset = ((size+TAR_BLOCK_SIZE-1)/TAR_BLOCK_SIZE)*TAR_BLOCK_SIZE;
|
||||||
|
header = (tar_header_t*)((uint8_t*)header + next_file_offset + TAR_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cat_initrd(uint8_t* initrd, const char* filename)
|
||||||
|
{
|
||||||
|
tar_header_t *header = (tar_header_t*)initrd;
|
||||||
|
|
||||||
|
while (header->filename[0] != '\0')
|
||||||
|
{
|
||||||
|
if (strcmp(header->filename, filename) == 0)
|
||||||
|
{
|
||||||
|
uint32_t size = tar_parse_size(header->size);
|
||||||
|
uint8_t* file_content = (uint8_t*)header + 512;
|
||||||
|
|
||||||
|
for (uint32_t i=0; i<size; i++) putc(file_content[i]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t next_file_offset = ((tar_parse_size(header->size)+TAR_BLOCK_SIZE-1)/TAR_BLOCK_SIZE)*TAR_BLOCK_SIZE;
|
||||||
|
header = (tar_header_t*)((uint8_t*)header + next_file_offset + TAR_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("File '%s' not found\n", filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tar_file_to_buffer(uint8_t* initrd, const char* filename, char* buffer)
|
||||||
|
{
|
||||||
|
uint8_t* current_block = initrd;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (current_block[0] == '\0')
|
||||||
|
{
|
||||||
|
//puts("[tar] EOF\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* file_name = (const char*)current_block;
|
||||||
|
uint32_t file_size = tar_parse_size((const char*)(current_block+124));
|
||||||
|
|
||||||
|
if (strcmp(file_name, filename) == 0)
|
||||||
|
{
|
||||||
|
uint8_t* file_data = current_block + TAR_BLOCK_SIZE;
|
||||||
|
memcpy(buffer, file_data, file_size);
|
||||||
|
buffer[file_size] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t total_size = ((file_size + TAR_BLOCK_SIZE - 1) / TAR_BLOCK_SIZE) * TAR_BLOCK_SIZE;
|
||||||
|
current_block += TAR_BLOCK_SIZE + total_size;
|
||||||
|
}
|
||||||
|
printf("[tar] file '%s' not found\n", filename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
38
src/kernel/initrd.h
Normal file
38
src/kernel/initrd.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
// Initial TAR ramdisk kernel module header
|
||||||
|
// Author: xamidev
|
||||||
|
// Licensed under the Unlicense. See the repo below.
|
||||||
|
// https://github.com/xamidev/blankos
|
||||||
|
|
||||||
|
#ifndef INITRD_H
|
||||||
|
#define INITRD_H
|
||||||
|
|
||||||
|
#define TAR_BLOCK_SIZE 512
|
||||||
|
|
||||||
|
#include "system.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char filename[100];
|
||||||
|
char mode[8];
|
||||||
|
char owner[8];
|
||||||
|
char group[8];
|
||||||
|
char size[12];
|
||||||
|
char mtime[12];
|
||||||
|
char checksum[8];
|
||||||
|
char typeflag;
|
||||||
|
char linkname[100];
|
||||||
|
char magic[6];
|
||||||
|
char version[2];
|
||||||
|
char uname[32];
|
||||||
|
char gname[32];
|
||||||
|
char devmajor[8];
|
||||||
|
char devminor[8];
|
||||||
|
char prefix[155];
|
||||||
|
} tar_header_t;
|
||||||
|
|
||||||
|
void tar_find_file(uint8_t *tar_start, const char* filename);
|
||||||
|
void ls_initrd(uint8_t* initrd, int verbose);
|
||||||
|
void cat_initrd(uint8_t* initrd, const char* filename);
|
||||||
|
int tar_file_to_buffer(uint8_t* initrd, const char* filename, char* buffer);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -5,42 +5,60 @@
|
|||||||
|
|
||||||
#include "kheap.h"
|
#include "kheap.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "system.h"
|
||||||
|
|
||||||
extern uint32_t end;
|
// Free list allocator
|
||||||
uint32_t placement_address = (uint32_t)&end;
|
|
||||||
|
|
||||||
uint32_t kmalloc_int(uint32_t sz, int align, uint32_t *phys)
|
static uint8_t heap[HEAP_SIZE];
|
||||||
|
static block_t* free_list = NULL;
|
||||||
|
|
||||||
|
void init_alloc()
|
||||||
{
|
{
|
||||||
if (align == 1 && (placement_address & 0x00000FFF))
|
free_list = (block_t*)heap;
|
||||||
{
|
free_list->size = HEAP_SIZE-sizeof(block_t);
|
||||||
placement_address &= 0xFFFFF000;
|
free_list->next = NULL;
|
||||||
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)
|
void* malloc(size_t size)
|
||||||
{
|
{
|
||||||
return kmalloc_int(sz, 1, 0);
|
block_t* prev = NULL;
|
||||||
|
block_t* curr = free_list;
|
||||||
|
|
||||||
|
while (curr != NULL)
|
||||||
|
{
|
||||||
|
if (curr->size >= size)
|
||||||
|
{
|
||||||
|
if (curr->size > (size_t)(size + sizeof(block_t)))
|
||||||
|
{
|
||||||
|
block_t* new_block = (block_t*)((uint8_t*)curr + sizeof(block_t) + size);
|
||||||
|
new_block->size = curr->size - size - sizeof(block_t);
|
||||||
|
new_block->next = curr->next;
|
||||||
|
curr->size = size;
|
||||||
|
curr->next = new_block;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t kmalloc_p(uint32_t sz, uint32_t *phys)
|
if (prev == NULL)
|
||||||
{
|
{
|
||||||
return kmalloc_int(sz, 0, phys);
|
free_list = curr->next;
|
||||||
|
} else {
|
||||||
|
prev->next = curr->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t kmalloc_ap(uint32_t sz, uint32_t *phys)
|
return (void*)((uint8_t*)curr + sizeof(block_t));
|
||||||
{
|
|
||||||
return kmalloc_int(sz, 1, phys);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t kmalloc(uint32_t sz)
|
prev = curr;
|
||||||
{
|
curr = curr->next;
|
||||||
return kmalloc_int(sz, 0, 0);
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free(void* ptr)
|
||||||
|
{
|
||||||
|
if (ptr == NULL) return;
|
||||||
|
|
||||||
|
block_t* block_to_free = (block_t*)((uint8_t*)ptr - sizeof(block_t));
|
||||||
|
block_to_free->next = free_list;
|
||||||
|
free_list = block_to_free;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,19 @@
|
|||||||
#define KHEAP_H
|
#define KHEAP_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "system.h"
|
||||||
|
|
||||||
uint32_t kmalloc_a(uint32_t sz);
|
typedef struct block
|
||||||
uint32_t kmalloc_p(uint32_t sz, uint32_t *phys);
|
{
|
||||||
uint32_t kmalloc_ap(uint32_t sz, uint32_t *phys);
|
size_t size;
|
||||||
uint32_t kmalloc(uint32_t sz);
|
struct block* next;
|
||||||
|
} block_t;
|
||||||
|
|
||||||
|
#define HEAP_SIZE 1024*1024 // 1MB malloc-able
|
||||||
|
|
||||||
|
|
||||||
|
void init_alloc();
|
||||||
|
void* malloc(size_t size);
|
||||||
|
void free(void* ptr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -12,10 +12,16 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "../drivers/framebuffer.h"
|
#include "../drivers/framebuffer.h"
|
||||||
#include "kmain.h"
|
#include "kmain.h"
|
||||||
|
#include "multiboot2.h"
|
||||||
|
#include "kheap.h"
|
||||||
|
#include "initrd.h"
|
||||||
|
#include "../programs/programs.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) {
|
||||||
@@ -23,37 +29,81 @@ 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] multiboot2 info at 0x%x, size=%u\n", mb_info, mb_info->total_size);
|
||||||
printf("[kernel] framebuffer discovered at 0x%x\n", fb_info->framebuffer_addr);
|
printf("[kernel] framebuffer discovered at 0x%x\n", 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);
|
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
|
||||||
|
{
|
||||||
|
printf("[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\n",
|
||||||
|
(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initrd_module) {
|
||||||
|
initrd_addr = initrd_module->mod_start;
|
||||||
|
|
||||||
|
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();
|
||||||
idt_install();
|
idt_install();
|
||||||
@@ -61,7 +111,11 @@ void kmain(multiboot2_info *mb_info)
|
|||||||
irq_install();
|
irq_install();
|
||||||
__asm__ __volatile__("sti");
|
__asm__ __volatile__("sti");
|
||||||
|
|
||||||
//test_read_sector();
|
init_alloc();
|
||||||
|
void* ptr1 = malloc(256);
|
||||||
|
void* ptr2 = malloc(512);
|
||||||
|
printf("[debug] malloc test ptr1=0x%x, ptr2=0x%x\n", ptr1, ptr2);
|
||||||
|
free(ptr1); free(ptr2);
|
||||||
|
|
||||||
timer_install();
|
timer_install();
|
||||||
keyboard_install();
|
keyboard_install();
|
||||||
|
|||||||
@@ -6,6 +6,10 @@
|
|||||||
#ifndef KMAIN_H
|
#ifndef KMAIN_H
|
||||||
#define KMAIN_H
|
#define KMAIN_H
|
||||||
|
|
||||||
|
#define BLANK_VERSION "0.3.107-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
|
||||||
417
src/kernel/multiboot2.h
Normal file
417
src/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 */
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "../libc/crypto.h"
|
#include "../libc/crypto.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "../drivers/rtc.h"
|
#include "../drivers/rtc.h"
|
||||||
|
#include "kmain.h"
|
||||||
|
|
||||||
#define BUFFER_SIZE 256
|
#define BUFFER_SIZE 256
|
||||||
#define MAX_COMMANDS 64
|
#define MAX_COMMANDS 64
|
||||||
@@ -54,7 +55,10 @@ void splash()
|
|||||||
int random = randint(time_seed());
|
int random = randint(time_seed());
|
||||||
char* motd_pick = motd[random%motd_size];
|
char* motd_pick = motd[random%motd_size];
|
||||||
cowsay(motd_pick, red, black);
|
cowsay(motd_pick, red, black);
|
||||||
colorputs(" blankOS 0.3.97-alpha", red, black);
|
puts(" ");
|
||||||
|
colorputs("blankOS", black, white);
|
||||||
|
puts(" ");
|
||||||
|
colorputs(BLANK_VERSION, red, black);
|
||||||
puts("\n");
|
puts("\n");
|
||||||
|
|
||||||
|
|
||||||
@@ -136,6 +140,9 @@ void shell_install()
|
|||||||
register_command("read", program_read);
|
register_command("read", program_read);
|
||||||
register_command("reboot", program_reboot);
|
register_command("reboot", program_reboot);
|
||||||
register_command("pi", program_pi);
|
register_command("pi", program_pi);
|
||||||
|
register_command("ls", program_ls);
|
||||||
|
register_command("cat", program_cat);
|
||||||
|
register_command("bmp", program_bmp);
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -34,6 +34,18 @@ 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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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++)
|
||||||
|
|||||||
@@ -87,4 +87,7 @@ enum Colors
|
|||||||
beige = 0x00F5F5DC
|
beige = 0x00F5F5DC
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int get_cursor_x();
|
||||||
|
int get_cursor_y();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include "../kernel/system.h"
|
#include "../kernel/system.h"
|
||||||
#include "../libc/stdio.h"
|
#include "../libc/stdio.h"
|
||||||
|
#include "../kernel/kmain.h"
|
||||||
|
#include "../kernel/initrd.h"
|
||||||
|
|
||||||
#define BUF_SIZE 256
|
#define BUF_SIZE 256
|
||||||
|
|
||||||
@@ -48,12 +50,25 @@ void brainfuck(char* input)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void program_bf()
|
void program_bf(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
if (argc == 1)
|
||||||
{
|
{
|
||||||
char input_buffer[BUF_SIZE];
|
char input_buffer[BUF_SIZE];
|
||||||
puts("Brainfuck code? ");
|
puts("Brainfuck code? ");
|
||||||
get_input(input_buffer, BUF_SIZE);
|
get_input(input_buffer, BUF_SIZE);
|
||||||
brainfuck(input_buffer);
|
brainfuck(input_buffer);
|
||||||
//brainfuck(",[.[-],]");
|
|
||||||
puts("\n");
|
puts("\n");
|
||||||
|
} else if (argc == 2) {
|
||||||
|
// Read file content into buffer, then interpret it
|
||||||
|
char input_buffer[BUF_SIZE];
|
||||||
|
int read = tar_file_to_buffer((uint8_t*)initrd_addr, argv[1], input_buffer);
|
||||||
|
if (read == 0)
|
||||||
|
{
|
||||||
|
brainfuck(input_buffer);
|
||||||
|
puts("\n");
|
||||||
|
} else {
|
||||||
|
printf("Could not find file '%s'\n", argv[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
100
src/programs/bmp.c
Normal file
100
src/programs/bmp.c
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
// Bitmap image renderer
|
||||||
|
// Author: xamidev
|
||||||
|
// Licensed under the Unlicense. See the repo below.
|
||||||
|
// https://github.com/xamidev/blankos
|
||||||
|
|
||||||
|
#include "../kernel/kmain.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../kernel/initrd.h"
|
||||||
|
#include "../drivers/framebuffer.h"
|
||||||
|
#include "../libc/stdio.h"
|
||||||
|
#include "../drivers/serial.h"
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint16_t bfType;
|
||||||
|
uint32_t bfSize;
|
||||||
|
uint16_t bfReserved1;
|
||||||
|
uint16_t bfReserved2;
|
||||||
|
uint32_t bfOffBits;
|
||||||
|
} BMPHeader;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t biSize;
|
||||||
|
int32_t biWidth;
|
||||||
|
int32_t biHeight;
|
||||||
|
uint16_t biPlanes;
|
||||||
|
uint16_t biBitCount;
|
||||||
|
uint32_t biCompression;
|
||||||
|
uint32_t biSizeImage;
|
||||||
|
int32_t biXPelsPerMeter;
|
||||||
|
int32_t biYPelsPerMeter;
|
||||||
|
uint32_t biClrUsed;
|
||||||
|
uint32_t biClrImportant;
|
||||||
|
} BMPInfoHeader;
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
void display_bmp(uint32_t* fb, int pitch, int bpp, uint8_t* initrd, const char* filename)
|
||||||
|
{
|
||||||
|
// Should use dynamic allocation when heap works
|
||||||
|
// Cannot go more than ~500k size for buffer
|
||||||
|
// Fail zone 450k->470k
|
||||||
|
// So right now the max should be 400kb img size
|
||||||
|
char buffer[400*1000];
|
||||||
|
int file_status = tar_file_to_buffer(initrd, filename, buffer);
|
||||||
|
|
||||||
|
if (file_status != 0)
|
||||||
|
{
|
||||||
|
printf("Error loading file '%s'\n", filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BMPHeader* bmp_header = (BMPHeader*)buffer;
|
||||||
|
BMPInfoHeader* bmp_info = (BMPInfoHeader*) (buffer+sizeof(BMPHeader));
|
||||||
|
|
||||||
|
if (bmp_header->bfType != 0x4D42)
|
||||||
|
{
|
||||||
|
printf("'%s' is not a valid BMP file\n", filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int width = bmp_info->biWidth;
|
||||||
|
int height = bmp_info->biHeight;
|
||||||
|
int pixel_offset = bmp_header->bfOffBits;
|
||||||
|
|
||||||
|
printf("%d-bit BMP, width: %d, height: %d, pixel offset: %d\n", bmp_info->biBitCount, bmp_info->biWidth, bmp_info->biHeight, bmp_header->bfOffBits);
|
||||||
|
erase_cursor();
|
||||||
|
uint8_t* pixel_data = (uint8_t*)(buffer + pixel_offset);
|
||||||
|
|
||||||
|
int cursor_y = (get_cursor_y()+1)*16;
|
||||||
|
serial_printf(3, "cursor_y=%d\n", cursor_y);
|
||||||
|
|
||||||
|
for (int y=cursor_y; y<height+cursor_y; y++)
|
||||||
|
{
|
||||||
|
for (int x=0; x<width; x++)
|
||||||
|
{
|
||||||
|
int index = (x+(height-y-1+cursor_y)*width)*3;
|
||||||
|
uint8_t blue = pixel_data[index];
|
||||||
|
uint8_t green = pixel_data[index+1];
|
||||||
|
uint8_t red = pixel_data[index+2];
|
||||||
|
|
||||||
|
uint32_t color = (0xFF << 24) | (red << 16) | (green << 8) | blue;
|
||||||
|
putpixel(fb, pitch, bpp, x, y, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update cursor pos after image drawing
|
||||||
|
move_cursor(get_cursor_x(), get_cursor_y()+(height/16)+2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void program_bmp(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
puts("Usage: bmp <file>\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
display_bmp(framebuffer, pitch, bpp, (uint8_t*)initrd_addr, argv[1]);
|
||||||
|
}
|
||||||
30
src/programs/fs.c
Normal file
30
src/programs/fs.c
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// Filesystem utilities (for initrd)
|
||||||
|
// Author: xamidev
|
||||||
|
// Licensed under the Unlicense. See the repo below.
|
||||||
|
// https://github.com/xamidev/blankos
|
||||||
|
|
||||||
|
#include "../kernel/initrd.h"
|
||||||
|
#include "../kernel/kmain.h"
|
||||||
|
#include "../libc/stdio.h"
|
||||||
|
#include "../libc/string.h"
|
||||||
|
|
||||||
|
void program_ls(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
if (argc == 1)
|
||||||
|
{
|
||||||
|
ls_initrd((uint8_t*)initrd_addr, 0);
|
||||||
|
} else if (argc == 2 && strcmp(argv[1], "-l") == 0) {
|
||||||
|
ls_initrd((uint8_t*)initrd_addr, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic cat just to read, no concatenation here
|
||||||
|
void program_cat(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
if (argc != 2)
|
||||||
|
{
|
||||||
|
puts("Usage: cat <file>\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cat_initrd((uint8_t*)initrd_addr, argv[1]);
|
||||||
|
}
|
||||||
@@ -73,7 +73,7 @@ void program_uptime()
|
|||||||
|
|
||||||
void program_help()
|
void program_help()
|
||||||
{
|
{
|
||||||
printf("help\tpanic\twords\tprimes\trainbow\tclear\nmath\tbf\t uptime echo\t sysinfo\tconway\nrot13 morse\tcowsay time\t read\t reboot\npi\n");
|
printf("help\tpanic\twords\tprimes\trainbow\tclear\nmath\tbf\t uptime echo\t sysinfo\tconway\nrot13 morse\tcowsay time\t read\t reboot\npi\t ls\t cat\t bmp\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Panic
|
// Panic
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ void program_bf();
|
|||||||
void program_sysinfo();
|
void program_sysinfo();
|
||||||
|
|
||||||
void get_cpuid();
|
void get_cpuid();
|
||||||
void get_meminfo(unsigned int multiboot_info_address);
|
void get_meminfo(unsigned int multiboot_info_address); // to be fixed: cannot get full memory map (sysinfo -v)
|
||||||
void program_conway();
|
void program_conway();
|
||||||
void program_cowsay();
|
void program_cowsay();
|
||||||
void cowsay(); // Splash screen
|
void cowsay(); // Splash screen
|
||||||
@@ -34,4 +34,10 @@ void program_time();
|
|||||||
void program_read();
|
void program_read();
|
||||||
void program_reboot();
|
void program_reboot();
|
||||||
|
|
||||||
|
// Filesystem (initrd)
|
||||||
|
void program_ls();
|
||||||
|
void program_cat();
|
||||||
|
|
||||||
|
void program_bmp();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user