Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8ff6e4fdb8 | |||
| 8332af1370 | |||
|
|
14a9bdad7d | ||
|
|
756dc638e8 | ||
|
|
903188a543 | ||
|
|
8a68cf3b30 | ||
|
|
1085222d98 | ||
|
|
68a4be55ce | ||
|
|
cee509f6a1 | ||
|
|
c104657d52 | ||
|
|
1fa4b5c70a | ||
|
|
7071b4788b | ||
|
|
5ad32d3ee1 | ||
|
|
d02b3d62cb | ||
|
|
af716cb2ec | ||
|
|
e6f119236b | ||
|
|
c885e69be4 | ||
|
|
03b712ace0 | ||
|
|
87bb1d96fd | ||
|
|
8bac95890a |
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
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||

|

|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> The project is currently paused, after months of work around the subject. I've had enough for now, and I'll surely come back in some time to implement the more advanced stuff I had planned. For now, enjoy the latest alpha version.
|
> This is free and unencumbered software released into the public domain. Many things might be (are) broken.
|
||||||
> 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.
|
> 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
|
||||||
|
|
||||||
|
|||||||
BIN
blankos.png
Normal file
BIN
blankos.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 405 KiB |
@@ -42,9 +42,11 @@ sudo qemu-system-i386 -drive if=pflash,format=raw,readonly=on,file=/usr/share/OV
|
|||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
(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.
|
||||||
|
|
||||||
@@ -65,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:
|
||||||
|
|
||||||
@@ -87,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.
|
||||||
|
|
||||||
|
|||||||
@@ -143,3 +143,11 @@ Starts a simplified and buggy snake game. You can choose the speed by setting th
|
|||||||
Controls:
|
Controls:
|
||||||
- `q` to quit
|
- `q` to quit
|
||||||
- `wasd` to move
|
- `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.
|
||||||
|
|||||||
Binary file not shown.
BIN
include/fonts/viscii10-8x16.psfu
Normal file
BIN
include/fonts/viscii10-8x16.psfu
Normal file
Binary file not shown.
34
makefile
34
makefile
@@ -1,37 +1,49 @@
|
|||||||
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 -mno-sse -mno-mmx -mno-avx -march=i386 -c -I src/
|
CFLAGS = -ffreestanding -g -Wall -Wextra -mno-sse -mno-mmx -mno-avx -march=i386 -c -I src/
|
||||||
|
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
|
SRC_DIR = src
|
||||||
KERNEL_DIR = $(SRC_DIR)/kernel
|
KERNEL_DIR = $(SRC_DIR)/kernel
|
||||||
LIBC_DIR = $(SRC_DIR)/libc
|
LIBC_DIR = $(SRC_DIR)/libc
|
||||||
PROGRAMS_DIR = $(SRC_DIR)/programs
|
UTILS_DIR = $(SRC_DIR)/utils
|
||||||
DRIVERS_DIR = $(SRC_DIR)/drivers
|
DRIVERS_DIR = $(SRC_DIR)/drivers
|
||||||
|
PROGRAMS_DIR = $(SRC_DIR)/programs
|
||||||
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 $(LIBC_DIR)/*.c) $(wildcard $(UTILS_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 $(LIBC_DIR)/*.s) $(wildcard $(UTILS_DIR)/*.s) $(wildcard $(DRIVERS_DIR)/*.s)
|
||||||
|
PROGRAM_SOURCES = $(wildcard $(PROGRAMS_DIR)/*.c)
|
||||||
|
|
||||||
OBJECTS = $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(C_SOURCES:.c=.o) $(ASM_SOURCES:.s=.o))
|
OBJECTS = $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(C_SOURCES:.c=.o) $(ASM_SOURCES:.s=.o))
|
||||||
|
PROGRAM_OBJECTS = $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(PROGRAM_SOURCES:.c=.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 programs
|
||||||
|
|
||||||
$(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)/libc $(OBJ_DIR)/utils $(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
|
||||||
|
|
||||||
|
programs: $(PROGRAM_OBJECTS)
|
||||||
|
@mkdir -p $(SRC_DIR)/initrd
|
||||||
|
@for prog in $(PROGRAM_OBJECTS); do \
|
||||||
|
base=$$(basename $$prog .o); \
|
||||||
|
$(LD) -melf_i386 -T program.ld $$prog -o $(SRC_DIR)/initrd/$$base.bin; \
|
||||||
|
done
|
||||||
|
|
||||||
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
|
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
|
||||||
$(CC) $(CFLAGS) $< -o $@
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
@@ -66,5 +78,5 @@ debug:
|
|||||||
./debug.sh
|
./debug.sh
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(OBJ_DIR) kernel.elf blankos.iso $(TOOLCHAIN_FILE)
|
rm -rf $(OBJ_DIR) kernel.elf blankos.iso $(TOOLCHAIN_FILE) $(SRC_DIR)/initrd/*.bin
|
||||||
|
|
||||||
|
|||||||
10
program.ld
Normal file
10
program.ld
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
OUTPUT_FORMAT(binary)
|
||||||
|
ENTRY(main)
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x1000;
|
||||||
|
.text : { *(.text*) }
|
||||||
|
.data : { *(.data*) }
|
||||||
|
.bss : { *(.bss*) }
|
||||||
|
}
|
||||||
@@ -7,9 +7,51 @@
|
|||||||
#include "framebuffer.h"
|
#include "framebuffer.h"
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
#include "../kernel/system.h"
|
#include "../kernel/system.h"
|
||||||
|
#include "../kernel/kheap.h"
|
||||||
|
|
||||||
extern char* framebuffer;
|
extern char* framebuffer;
|
||||||
|
|
||||||
|
void psf_init()
|
||||||
|
{
|
||||||
|
uint16_t glyph = 0;
|
||||||
|
PSF_font *font = (PSF_font*)&FONT_START;
|
||||||
|
if (font->flags)
|
||||||
|
{
|
||||||
|
unicode = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* s = (char*)((unsigned char*)&FONT_START + font->headersize + font->numglyph * font->bytesperglyph);
|
||||||
|
unicode = calloc(USHRT_MAX, 2);
|
||||||
|
|
||||||
|
while((uintptr_t)s>(uintptr_t)FONT_END){
|
||||||
|
uint16_t uc = (uint16_t)((unsigned char)s[0]);
|
||||||
|
if(uc == 0xFF) {
|
||||||
|
glyph++;
|
||||||
|
s++;
|
||||||
|
continue;
|
||||||
|
} else if(uc & 128) {
|
||||||
|
/* UTF-8 to unicode */
|
||||||
|
if((uc & 32) == 0 ) {
|
||||||
|
uc = ((s[0] & 0x1F)<<6)+(s[1] & 0x3F);
|
||||||
|
s++;
|
||||||
|
} else
|
||||||
|
if((uc & 16) == 0 ) {
|
||||||
|
uc = ((((s[0] & 0xF)<<6)+(s[1] & 0x3F))<<6)+(s[2] & 0x3F);
|
||||||
|
s+=2;
|
||||||
|
} else
|
||||||
|
if((uc & 8) == 0 ) {
|
||||||
|
uc = ((((((s[0] & 0x7)<<6)+(s[1] & 0x3F))<<6)+(s[2] & 0x3F))<<6)+(s[3] & 0x3F);
|
||||||
|
s+=3;
|
||||||
|
} else
|
||||||
|
uc = 0;
|
||||||
|
}
|
||||||
|
/* save translation */
|
||||||
|
unicode[uc] = glyph;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
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));
|
||||||
@@ -18,13 +60,13 @@ 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)
|
||||||
{
|
{
|
||||||
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) +
|
||||||
@@ -54,7 +96,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
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "../libc/string.h"
|
#include "../libc/string.h"
|
||||||
#include "initrd.h"
|
#include "initrd.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
#include "kheap.h"
|
||||||
|
|
||||||
static unsigned int octal_to_int(const char* str, size_t size)
|
static unsigned int octal_to_int(const char* str, size_t size)
|
||||||
{
|
{
|
||||||
@@ -31,6 +32,18 @@ uint32_t tar_parse_size(const char* in)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t tar_get_size(tar_header_t* header)
|
||||||
|
{
|
||||||
|
uint32_t size = 0;
|
||||||
|
char* size_str = header->size;
|
||||||
|
|
||||||
|
for (int i=0; i<11 && size_str[i] != '\0'; i++)
|
||||||
|
{
|
||||||
|
size = size*8 + (size_str[i]-'0');
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
void tar_find_file(uint8_t *tar_start, const char* filename)
|
void tar_find_file(uint8_t *tar_start, const char* filename)
|
||||||
{
|
{
|
||||||
uint8_t *ptr = tar_start;
|
uint8_t *ptr = tar_start;
|
||||||
@@ -80,9 +93,21 @@ void ls_initrd(uint8_t* initrd, int verbose)
|
|||||||
{
|
{
|
||||||
if (!verbose)
|
if (!verbose)
|
||||||
{
|
{
|
||||||
printf("%s\n", header->filename);
|
if (header->typeflag == '5')
|
||||||
|
{
|
||||||
|
colorprintf(cyan, black, "%s\n", header->filename);
|
||||||
|
} else {
|
||||||
|
printf("%s\n", header->filename);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("%7d\t%c\t %s\n", (int)header->size, header->typeflag, header->filename);
|
if (header->typeflag == '5')
|
||||||
|
{
|
||||||
|
printf("%7d\t%c\t", (int)header->size, header->typeflag);
|
||||||
|
colorprintf(cyan, black, " %s\n", header->filename);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
printf("%7d\t%c\t %s\n", (int)header->size, header->typeflag, header->filename);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t size = tar_parse_size(header->size);
|
uint32_t size = tar_parse_size(header->size);
|
||||||
@@ -174,3 +199,52 @@ uint32_t tar_get_file_size(uint8_t* initrd, const char* filename)
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tar_header_t* tar_find(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)
|
||||||
|
{
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t file_size = tar_get_size(header);
|
||||||
|
uint32_t file_blocks = (file_size + 511)/512;
|
||||||
|
header = (tar_header_t*) ((uintptr_t)header+(file_blocks+1)*512);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* tar_get_file_content(tar_header_t* header)
|
||||||
|
{
|
||||||
|
return (void*) ((uintptr_t)header+512);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* load_file_from_initrd(uint8_t* initrd, const char* filename)
|
||||||
|
{
|
||||||
|
tar_header_t* file = tar_find(initrd, filename);
|
||||||
|
if (file == NULL)
|
||||||
|
{
|
||||||
|
printf("'%s' not found\n", filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t file_size = tar_get_size(file);
|
||||||
|
|
||||||
|
void* file_data = malloc(file_size);
|
||||||
|
if (file_data == NULL)
|
||||||
|
{
|
||||||
|
printf("Malloc error for file '%s'\n", filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* file_content = tar_get_file_content(file);
|
||||||
|
memcpy(file_data, file_content, file_size);
|
||||||
|
|
||||||
|
printf("[initrd] Loaded '%s' at 0x%x, size=%u\n", filename, (unsigned int)file_data, file_size);
|
||||||
|
|
||||||
|
return file_data;
|
||||||
|
}
|
||||||
|
|||||||
@@ -35,5 +35,6 @@ void ls_initrd(uint8_t* initrd, int verbose);
|
|||||||
void cat_initrd(uint8_t* initrd, const char* filename);
|
void cat_initrd(uint8_t* initrd, const char* filename);
|
||||||
int tar_file_to_buffer(uint8_t* initrd, const char* filename, char* buffer);
|
int tar_file_to_buffer(uint8_t* initrd, const char* filename, char* buffer);
|
||||||
uint32_t tar_get_file_size(uint8_t* initrd, const char* filename);
|
uint32_t tar_get_file_size(uint8_t* initrd, const char* filename);
|
||||||
|
void* load_file_from_initrd(uint8_t* initrd, const char* filename);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ extern void irq13();
|
|||||||
extern void irq14();
|
extern void irq14();
|
||||||
extern void irq15();
|
extern void irq15();
|
||||||
|
|
||||||
|
extern void syscall_common_stub();
|
||||||
|
|
||||||
void *irq_routines[16] =
|
void *irq_routines[16] =
|
||||||
{
|
{
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
@@ -76,6 +78,8 @@ void irq_install()
|
|||||||
idt_set_gate(46, (unsigned)irq14, 0x08, 0x8E);
|
idt_set_gate(46, (unsigned)irq14, 0x08, 0x8E);
|
||||||
idt_set_gate(47, (unsigned)irq15, 0x08, 0x8E);
|
idt_set_gate(47, (unsigned)irq15, 0x08, 0x8E);
|
||||||
printf("[kernel] installed irq 0-15\n");
|
printf("[kernel] installed irq 0-15\n");
|
||||||
|
|
||||||
|
idt_set_gate(0x80, (unsigned long)syscall_common_stub, 0x08, 0x8E);
|
||||||
}
|
}
|
||||||
|
|
||||||
void irq_handler(struct regs *r)
|
void irq_handler(struct regs *r)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "kheap.h"
|
#include "kheap.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
#include "../libc/stdio.h"
|
||||||
|
|
||||||
// Free list allocator
|
// Free list allocator
|
||||||
|
|
||||||
@@ -17,6 +18,7 @@ void init_alloc()
|
|||||||
free_list = (block_t*)heap;
|
free_list = (block_t*)heap;
|
||||||
free_list->size = HEAP_SIZE-sizeof(block_t);
|
free_list->size = HEAP_SIZE-sizeof(block_t);
|
||||||
free_list->next = NULL;
|
free_list->next = NULL;
|
||||||
|
printf("[kernel] initialized heap and allocator, start=0x%x\n", heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* malloc(size_t size)
|
void* malloc(size_t size)
|
||||||
@@ -54,6 +56,23 @@ void* malloc(size_t size)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* calloc(size_t num, size_t size)
|
||||||
|
{
|
||||||
|
size_t total_size = num*size;
|
||||||
|
void* ptr = malloc(total_size);
|
||||||
|
|
||||||
|
if (ptr != NULL)
|
||||||
|
{
|
||||||
|
uint8_t* byte_ptr = (uint8_t*)ptr;
|
||||||
|
for (size_t i=0; i<total_size; i++)
|
||||||
|
{
|
||||||
|
byte_ptr[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
void free(void* ptr)
|
void free(void* ptr)
|
||||||
{
|
{
|
||||||
if (ptr == NULL) return;
|
if (ptr == NULL) return;
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ typedef struct block
|
|||||||
|
|
||||||
#define HEAP_SIZE 1024*1024 // 1MB malloc-able
|
#define HEAP_SIZE 1024*1024 // 1MB malloc-able
|
||||||
|
|
||||||
|
|
||||||
void init_alloc();
|
void init_alloc();
|
||||||
void* malloc(size_t size);
|
void* malloc(size_t size);
|
||||||
void free(void* ptr);
|
void free(void* ptr);
|
||||||
|
void* calloc(size_t num, size_t size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#include "multiboot2.h"
|
#include "multiboot2.h"
|
||||||
#include "kheap.h"
|
#include "kheap.h"
|
||||||
#include "initrd.h"
|
#include "initrd.h"
|
||||||
#include "../programs/programs.h"
|
#include "../utils/utils.h"
|
||||||
#include "../libc/crypto.h"
|
#include "../libc/crypto.h"
|
||||||
|
|
||||||
void kmain(multiboot2_info *mb_info)
|
void kmain(multiboot2_info *mb_info)
|
||||||
@@ -63,7 +63,7 @@ void kmain(multiboot2_info *mb_info)
|
|||||||
serial_printf(3, "Framebuffer Pitch: %u", fb_info->framebuffer_pitch);
|
serial_printf(3, "Framebuffer Pitch: %u", fb_info->framebuffer_pitch);
|
||||||
serial_printf(3, "Framebuffer BPP: %u", fb_info->framebuffer_bpp);
|
serial_printf(3, "Framebuffer BPP: %u", fb_info->framebuffer_bpp);
|
||||||
}
|
}
|
||||||
|
psf_init();
|
||||||
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", (unsigned int)fb_info->framebuffer_addr);
|
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);
|
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);
|
||||||
@@ -78,14 +78,14 @@ void kmain(multiboot2_info *mb_info)
|
|||||||
|
|
||||||
if (mmap->addr != 0)
|
if (mmap->addr != 0)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
serial_printf(3, "base addr=0x%x%x, length=0x%x%x, type=%u",
|
serial_printf(3, "base addr=0x%x%x, length=0x%x%x, type=%u",
|
||||||
(uint32_t) (mmap->addr >> 32),
|
(uint32_t) (mmap->addr >> 32),
|
||||||
(uint32_t) (mmap->addr & 0xFFFFFFFF),
|
(uint32_t) (mmap->addr & 0xFFFFFFFF),
|
||||||
(uint32_t) (mmap->len >> 32),
|
(uint32_t) (mmap->len >> 32),
|
||||||
(uint32_t) (mmap->len & 0xFFFFFFFF),
|
(uint32_t) (mmap->len & 0xFFFFFFFF),
|
||||||
mmap->type);
|
mmap->type);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
mmap = (struct multiboot_mmap_entry*) ((uint8_t*)mmap + mmap_tag->entry_size);
|
mmap = (struct multiboot_mmap_entry*) ((uint8_t*)mmap + mmap_tag->entry_size);
|
||||||
@@ -118,6 +118,12 @@ void kmain(multiboot2_info *mb_info)
|
|||||||
printf("[debug] malloc test ptr1=0x%x, ptr2=0x%x\n", (unsigned int)ptr1, (unsigned int)ptr2);
|
printf("[debug] malloc test ptr1=0x%x, ptr2=0x%x\n", (unsigned int)ptr1, (unsigned int)ptr2);
|
||||||
free(ptr1); free(ptr2);
|
free(ptr1); free(ptr2);
|
||||||
|
|
||||||
|
void* ptr3 = calloc(1024, 2);
|
||||||
|
printf("[debug] calloc test ptr3=0x%x\n", (unsigned int)ptr3);
|
||||||
|
free (ptr3);
|
||||||
|
|
||||||
|
// usually the place where i do testing
|
||||||
|
|
||||||
timer_install();
|
timer_install();
|
||||||
keyboard_install();
|
keyboard_install();
|
||||||
printf("[kernel] spawning shell...\n");
|
printf("[kernel] spawning shell...\n");
|
||||||
|
|||||||
@@ -210,8 +210,39 @@ irq_common_stub:
|
|||||||
add esp, 8
|
add esp, 8
|
||||||
iret
|
iret
|
||||||
|
|
||||||
|
; we'll be placing the syscall_common_stub here.
|
||||||
|
; push everything, then call syscall_handler (be sure to define it extern)
|
||||||
|
; then pop back everything and iret
|
||||||
|
extern syscall_handler
|
||||||
|
|
||||||
|
global syscall_common_stub
|
||||||
|
syscall_common_stub:
|
||||||
|
pusha
|
||||||
|
push ds
|
||||||
|
push es
|
||||||
|
push fs
|
||||||
|
push gs
|
||||||
|
|
||||||
|
mov eax, ds
|
||||||
|
push eax ; save ds
|
||||||
|
mov ax, 0x01 ; kernel segment YES I CHEATED I KNOW THIS SUCKS
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
|
||||||
|
call syscall_handler
|
||||||
|
|
||||||
|
pop eax
|
||||||
|
mov ds, eax ; restore ds
|
||||||
|
|
||||||
|
pop gs
|
||||||
|
pop fs
|
||||||
|
pop es
|
||||||
|
pop ds
|
||||||
|
popa
|
||||||
|
iret
|
||||||
|
|
||||||
section .bss
|
section .bss
|
||||||
align 4
|
align 4
|
||||||
|
|
||||||
resb KERNEL_STACK_SIZE
|
|
||||||
kernel_stack:
|
kernel_stack:
|
||||||
|
resb KERNEL_STACK_SIZE
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "../libc/stdio.h"
|
#include "../libc/stdio.h"
|
||||||
#include "../libc/string.h"
|
#include "../libc/string.h"
|
||||||
#include "../programs/programs.h"
|
#include "../utils/utils.h"
|
||||||
#include "../libc/crypto.h"
|
#include "../libc/crypto.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "../drivers/rtc.h"
|
#include "../drivers/rtc.h"
|
||||||
@@ -146,6 +146,8 @@ void shell_install()
|
|||||||
register_command("lspci", program_lspci);
|
register_command("lspci", program_lspci);
|
||||||
register_command("naval", program_navalbattle);
|
register_command("naval", program_navalbattle);
|
||||||
register_command("snake", program_snake);
|
register_command("snake", program_snake);
|
||||||
|
register_command("exec", program_exec);
|
||||||
|
register_command("uhex", program_uhex);
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
|||||||
33
src/kernel/syscalls.c
Normal file
33
src/kernel/syscalls.c
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// System calls
|
||||||
|
// Author: xamidev
|
||||||
|
// Licensed under the Unlicense. See the repo below.
|
||||||
|
// https://github.com/xamidev/blankos
|
||||||
|
|
||||||
|
#include "../libc/stdio.h"
|
||||||
|
|
||||||
|
void handle_syscall(int syscall_number)
|
||||||
|
{
|
||||||
|
switch(syscall_number)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
puts("Here's the syscall 1\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("[error] Invalid syscall number '%d'!\n", syscall_number);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void syscall_handler()
|
||||||
|
{
|
||||||
|
int syscall_number;
|
||||||
|
void* arg;
|
||||||
|
// mov eax, syscall_number
|
||||||
|
// mov ebx, arg
|
||||||
|
asm volatile("mov %%eax, %0" : "=r"(syscall_number));
|
||||||
|
asm volatile("mov %%ebx, %0" : "=r"(arg));
|
||||||
|
|
||||||
|
printf("[syscall] syscall_number=%d, arg=%p\n", syscall_number, arg);
|
||||||
|
|
||||||
|
handle_syscall(syscall_number);
|
||||||
|
}
|
||||||
@@ -39,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
|
||||||
|
|
||||||
|
|||||||
10
src/programs/hello.c
Normal file
10
src/programs/hello.c
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
void user_syscall(int syscall_no) {
|
||||||
|
asm volatile ("mov %0, %%eax" : : "r"(syscall_no));
|
||||||
|
asm volatile ("int $0x80");
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
user_syscall(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
@@ -11,6 +11,8 @@
|
|||||||
#include "../drivers/rtc.h"
|
#include "../drivers/rtc.h"
|
||||||
#include "../kernel/io.h"
|
#include "../kernel/io.h"
|
||||||
#include "../drivers/pci.h"
|
#include "../drivers/pci.h"
|
||||||
|
#include "../kernel/initrd.h"
|
||||||
|
#include "../kernel/kmain.h"
|
||||||
|
|
||||||
// Print a rainbow colorful text for testing
|
// Print a rainbow colorful text for testing
|
||||||
|
|
||||||
@@ -74,7 +76,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\t ls\t cat\t bmp\t lspci\t naval\nsnake\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\t lspci\t naval\nsnake exec\t uhex\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Panic
|
// Panic
|
||||||
@@ -133,7 +135,7 @@ void program_read(int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reboots the machine (might just shutdown)
|
// Reboots the machine (might just shutdown) (or do nothing if youre lucky)
|
||||||
|
|
||||||
void program_reboot()
|
void program_reboot()
|
||||||
{
|
{
|
||||||
@@ -151,3 +153,24 @@ void program_lspci()
|
|||||||
{
|
{
|
||||||
scan_pci_bus();
|
scan_pci_bus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Executes binary file
|
||||||
|
|
||||||
|
void program_exec(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
puts("Usage: exec <binary>\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void* binary_file = load_file_from_initrd((uint8_t*)initrd_addr, argv[1]);
|
||||||
|
|
||||||
|
if (binary_file == NULL)
|
||||||
|
{
|
||||||
|
printf("[exec] Failed to load program '%s'.\n", argv[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void (*program_entry)() = (void (*)())binary_file;
|
||||||
|
program_entry();
|
||||||
|
}
|
||||||
82
src/utils/uhex.c
Normal file
82
src/utils/uhex.c
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
// uhex (microhex) port for BlankOS; read-only version
|
||||||
|
// Author: xamidev
|
||||||
|
// Licensed under the Unlicense. See the repo below.
|
||||||
|
// https://github.com/xamidev/blankos
|
||||||
|
|
||||||
|
// This version is the port of a hex viewer which already was not great,
|
||||||
|
// and now by being here it is even worse because it is RO and will have
|
||||||
|
// hardcoded stuff in it (no ioctl, STDOUT, or other stuff here...)
|
||||||
|
|
||||||
|
#define BYTES 1024
|
||||||
|
#define round(x) (int)(x < 0 ? (x -0.5) : x + 0.5)
|
||||||
|
|
||||||
|
#include "../libc/stdio.h"
|
||||||
|
#include "../kernel/kmain.h"
|
||||||
|
#include "../kernel/initrd.h"
|
||||||
|
#include "../libc/string.h"
|
||||||
|
#include "../kernel/kheap.h"
|
||||||
|
|
||||||
|
int isprint(int c)
|
||||||
|
{
|
||||||
|
return (c >= 32 && c <= 126);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_hex(unsigned char* buf, int byteno, int pos, int BYTES_PER_LINE)
|
||||||
|
{
|
||||||
|
for (int i=0; i<byteno; i++)
|
||||||
|
{
|
||||||
|
if (i%BYTES_PER_LINE == 0)
|
||||||
|
{
|
||||||
|
if (i != 0)
|
||||||
|
{
|
||||||
|
printf(" ");
|
||||||
|
for (int j=i-BYTES_PER_LINE; j<i; j++)
|
||||||
|
{
|
||||||
|
if (isprint(buf[j])) colorprintf(salmon, black, "%c", buf[j]);
|
||||||
|
else printf(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
puts("\n");
|
||||||
|
|
||||||
|
if (pos == 0) printf("%06d: ", i);
|
||||||
|
else printf("%06d: ", pos);
|
||||||
|
}
|
||||||
|
printf("%2x ", buf[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int padding = BYTES_PER_LINE - (byteno % BYTES_PER_LINE);
|
||||||
|
if (padding < BYTES_PER_LINE)
|
||||||
|
{
|
||||||
|
for (int i=0; i<padding; i++) printf(" ");
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
int start = byteno-(byteno%BYTES_PER_LINE);
|
||||||
|
for (int j=start; j<byteno; j++)
|
||||||
|
{
|
||||||
|
if (isprint(buf[j])) {
|
||||||
|
colorprintf(salmon, black, "%c", buf[j]);
|
||||||
|
} else {
|
||||||
|
printf(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
puts("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void program_uhex(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
puts("Usage: uhex <file>\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BYTES_PER_LINE = 20;
|
||||||
|
|
||||||
|
//unsigned char buf[BYTES]; // malloc with file_size next?
|
||||||
|
uint32_t file_size = tar_get_file_size((uint8_t*)initrd_addr, argv[1]);
|
||||||
|
unsigned char* buf = (unsigned char*)malloc(file_size);
|
||||||
|
tar_file_to_buffer((uint8_t*)initrd_addr, argv[1], (char*)buf);
|
||||||
|
print_hex(buf, file_size, 0, BYTES_PER_LINE);
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
@@ -3,8 +3,8 @@
|
|||||||
// 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
|
||||||
|
|
||||||
#ifndef PROGRAMS_H
|
#ifndef UTILS_H
|
||||||
#define PROGRAMS_H
|
#define UTILS_H
|
||||||
|
|
||||||
void program_words();
|
void program_words();
|
||||||
void program_primes();
|
void program_primes();
|
||||||
@@ -45,4 +45,9 @@ void program_navalbattle();
|
|||||||
void program_conway();
|
void program_conway();
|
||||||
void program_snake();
|
void program_snake();
|
||||||
|
|
||||||
|
// Binaries loading and execution
|
||||||
|
void program_exec();
|
||||||
|
|
||||||
|
void program_uhex();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Reference in New Issue
Block a user