first commit
This commit is contained in:
commit
a42aab7667
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
obj/*
|
||||
radix.iso
|
34
Makefile
Normal file
34
Makefile
Normal file
|
@ -0,0 +1,34 @@
|
|||
KERNEL=obj/radix.bin
|
||||
ISO=radix.iso
|
||||
|
||||
CC=gcc
|
||||
LD=ld
|
||||
CFLAGS=-ffreestanding -fno-stack-protector -fno-stack-check -O3 -Wall -Wextra -Werror -m32 -Isrc
|
||||
LDFLAGS=-T linker.ld -m elf_i386
|
||||
NASMFLAGS=-f elf32
|
||||
|
||||
CFILES=$(shell cd src && find -L * -type f -name '*.c')
|
||||
ASMFILES=$(shell cd src && find -L * -type f -name '*.asm')
|
||||
OBJ=$(addprefix obj/,$(CFILES:.c=.c.o) $(ASMFILES:.asm=.asm.o))
|
||||
|
||||
$(ISO): $(KERNEL) isolinux.cfg
|
||||
cp isolinux.cfg cdroot/isolinux/
|
||||
cp $(KERNEL) cdroot/
|
||||
mkisofs -o $(ISO) -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table cdroot/
|
||||
|
||||
$(KERNEL): makedir linker.ld $(OBJ)
|
||||
$(LD) $(LDFLAGS) $(OBJ) -o $@
|
||||
|
||||
obj/%.c.o: src/%.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
obj/%.asm.o: src/%.asm
|
||||
nasm $(NASMFLAGS) $< -o $@
|
||||
|
||||
makedir:
|
||||
mkdir -p obj
|
||||
|
||||
run: $(ISO)
|
||||
qemu-system-i386 -boot d -cdrom $(ISO) -m 1G -enable-kvm -cpu host -serial stdio
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJ) $(KERNEL)
|
BIN
cdroot/isolinux/isolinux.bin
Normal file
BIN
cdroot/isolinux/isolinux.bin
Normal file
Binary file not shown.
4
cdroot/isolinux/isolinux.cfg
Normal file
4
cdroot/isolinux/isolinux.cfg
Normal file
|
@ -0,0 +1,4 @@
|
|||
DEFAULT radix
|
||||
LABEL radix
|
||||
KERNEL mboot.c32
|
||||
APPEND /radix.bin
|
BIN
cdroot/isolinux/ldlinux.c32
Normal file
BIN
cdroot/isolinux/ldlinux.c32
Normal file
Binary file not shown.
BIN
cdroot/isolinux/libcom32.c32
Normal file
BIN
cdroot/isolinux/libcom32.c32
Normal file
Binary file not shown.
BIN
cdroot/isolinux/mboot.c32
Normal file
BIN
cdroot/isolinux/mboot.c32
Normal file
Binary file not shown.
BIN
cdroot/radix.bin
Executable file
BIN
cdroot/radix.bin
Executable file
Binary file not shown.
4
isolinux.cfg
Normal file
4
isolinux.cfg
Normal file
|
@ -0,0 +1,4 @@
|
|||
DEFAULT radix
|
||||
LABEL radix
|
||||
KERNEL mboot.c32
|
||||
APPEND /radix.bin
|
28
linker.ld
Normal file
28
linker.ld
Normal file
|
@ -0,0 +1,28 @@
|
|||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 1M;
|
||||
|
||||
.text BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.multiboot)
|
||||
*(.text)
|
||||
}
|
||||
|
||||
.rodata BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.rodata)
|
||||
}
|
||||
|
||||
.data BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.data)
|
||||
}
|
||||
|
||||
.bss BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(COMMON)
|
||||
*(.bss)
|
||||
}
|
||||
}
|
36
src/boot.asm
Normal file
36
src/boot.asm
Normal file
|
@ -0,0 +1,36 @@
|
|||
extern kernel_main
|
||||
|
||||
MBALIGN equ 1 << 0
|
||||
MEMINFO equ 1 << 1
|
||||
VIDINFO equ 1 << 2
|
||||
MBFLAGS equ MBALIGN | MEMINFO | VIDINFO
|
||||
MAGIC equ 0x1BADB002
|
||||
CHECKSUM equ -(MAGIC + MBFLAGS)
|
||||
|
||||
section .multiboot
|
||||
align 4
|
||||
dd MAGIC
|
||||
dd MBFLAGS
|
||||
dd CHECKSUM
|
||||
dd 0, 0, 0, 0, 0
|
||||
dd 0
|
||||
dd 320, 200, 8
|
||||
|
||||
section .bss
|
||||
align 16
|
||||
stack_bottom:
|
||||
resb 16384
|
||||
stack_top:
|
||||
|
||||
section .text
|
||||
global _start:function (_start.end - _start)
|
||||
_start:
|
||||
mov esp, stack_top
|
||||
push ebx
|
||||
push eax
|
||||
|
||||
call kernel_main
|
||||
cli
|
||||
.hang:
|
||||
jmp .hang
|
||||
.end:
|
5
src/ctype.c
Normal file
5
src/ctype.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
#include <ctype.h>
|
||||
|
||||
int isdigit(char c) {
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
6
src/ctype.h
Normal file
6
src/ctype.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
#ifndef __CTYPE_H__
|
||||
#define __CTYPE_H__
|
||||
|
||||
int isdigit(char arg);
|
||||
|
||||
#endif
|
7
src/hcf.asm
Normal file
7
src/hcf.asm
Normal file
|
@ -0,0 +1,7 @@
|
|||
global hcf
|
||||
|
||||
hcf:
|
||||
cli
|
||||
.loop:
|
||||
hlt
|
||||
jmp .loop
|
6
src/hcf.h
Normal file
6
src/hcf.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
#ifndef __HCF_H__
|
||||
#define __HCF_H__
|
||||
|
||||
void hcf();
|
||||
|
||||
#endif
|
241
src/kernel.c
Normal file
241
src/kernel.c
Normal file
|
@ -0,0 +1,241 @@
|
|||
#include <multiboot.h>
|
||||
#include <stdio.h>
|
||||
#include <hcf.h>
|
||||
#include <vga.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
void putpixel(unsigned char* addr, int pos_x, int pos_y, unsigned char VGA_COLOR)
|
||||
{
|
||||
unsigned char* location = addr + 320 * pos_y + pos_x;
|
||||
*location = VGA_COLOR;
|
||||
}
|
||||
|
||||
static inline void outb(uint16_t port, uint8_t val)
|
||||
{
|
||||
__asm__ volatile ( "outb %b0, %w1" : : "a"(val), "Nd"(port) : "memory");
|
||||
/* There's an outb %al, $imm8 encoding, for compile-time constant port numbers that fit in 8b. (N constraint).
|
||||
* Wider immediate constants would be truncated at assemble-time (e.g. "i" constraint).
|
||||
* The outb %al, %dx encoding is the only option for all other cases.
|
||||
* %1 expands to %dx because port is a uint16_t. %w1 could be used if we had the port number a wider C type */
|
||||
}
|
||||
|
||||
static inline uint8_t inb(uint16_t port)
|
||||
{
|
||||
uint8_t ret;
|
||||
__asm__ volatile ( "inb %w1, %b0"
|
||||
: "=a"(ret)
|
||||
: "Nd"(port)
|
||||
: "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define PORT 0x3f8 // COM1
|
||||
|
||||
static int init_serial() {
|
||||
outb(PORT + 1, 0x00); // Disable all interrupts
|
||||
outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
|
||||
outb(PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
|
||||
outb(PORT + 1, 0x00); // (hi byte)
|
||||
outb(PORT + 3, 0x03); // 8 bits, no parity, one stop bit
|
||||
outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
|
||||
outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
|
||||
outb(PORT + 4, 0x1E); // Set in loopback mode, test the serial chip
|
||||
outb(PORT + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
|
||||
|
||||
// Check if serial is faulty (i.e: not same byte as sent)
|
||||
if(inb(PORT + 0) != 0xAE) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// If serial is not faulty set it in normal operation mode
|
||||
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
|
||||
outb(PORT + 4, 0x0F);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_transmit_empty() {
|
||||
return inb(PORT + 5) & 0x20;
|
||||
}
|
||||
|
||||
void write_serial(char a) {
|
||||
while (is_transmit_empty() == 0);
|
||||
|
||||
outb(PORT,a);
|
||||
}
|
||||
|
||||
void serial_puts(const char* s) {
|
||||
do {
|
||||
write_serial(*s);
|
||||
} while(*++s != '\0');
|
||||
}
|
||||
|
||||
void sprintf(const char* fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
for(int i = 0; fmt[i] != '\0'; i++)
|
||||
{
|
||||
switch(fmt[i])
|
||||
{
|
||||
case '%':
|
||||
i++;
|
||||
|
||||
char buf[512];
|
||||
|
||||
size_t width = 0;
|
||||
char padding_char = fmt[i];
|
||||
if(isdigit(fmt[i]) || fmt[i] == ' ') {
|
||||
i++;
|
||||
int pos = 0;
|
||||
while(isdigit(fmt[i])) {
|
||||
buf[pos++] = fmt[i++];
|
||||
}
|
||||
buf[pos] = '\0';
|
||||
width = atoi(buf);
|
||||
}
|
||||
|
||||
const char* out = 0;
|
||||
|
||||
if(fmt[i] == 's')
|
||||
out = va_arg(args, const char*);
|
||||
if(fmt[i] == 'd')
|
||||
out = itoa(va_arg(args, int), buf, 10);
|
||||
if(fmt[i] == 'u')
|
||||
out = ultoa(va_arg(args, uint32_t), buf, 10);
|
||||
if(fmt[i] == 'x')
|
||||
out = ultoa(va_arg(args, uint32_t), buf, 16);
|
||||
if(fmt[i] == 'c')
|
||||
write_serial(va_arg(args, int));
|
||||
|
||||
size_t len = strlen(out);
|
||||
if(width > len) {
|
||||
char padding[256];
|
||||
size_t j = 0;
|
||||
for(; j < width - len; j++)
|
||||
padding[j] = padding_char;
|
||||
padding[j] = '\0';
|
||||
serial_puts(padding);
|
||||
}
|
||||
|
||||
serial_puts(out);
|
||||
break;
|
||||
default:
|
||||
write_serial(fmt[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
#define CHECK_FLAG(flags,bit) ((flags) & (1 << (bit)))
|
||||
|
||||
void kernel_main(uint32_t magic, multiboot_info_t* mbi) {
|
||||
init_vga();
|
||||
init_serial();
|
||||
|
||||
if(magic != MULTIBOOT_BOOTLOADER_MAGIC) {
|
||||
printf("Invalid bootloader magic: %x", magic);
|
||||
hcf();
|
||||
}
|
||||
|
||||
printf("flags: 0x%x\n", mbi->flags);
|
||||
|
||||
uint32_t mem_total = mbi->mem_upper - mbi->mem_lower;
|
||||
printf("mem_lower: %uKB, mem_upper: %uKB, mem_total: %uKB\n", mbi->mem_lower, mbi->mem_upper, mem_total);
|
||||
|
||||
//sprintf("checking for flag");
|
||||
//if (CHECK_FLAG (mbi->flags, 12))
|
||||
//{
|
||||
//sprintf("flag present");
|
||||
multiboot_uint32_t color;
|
||||
unsigned i;
|
||||
void *fb = (void *) (unsigned long) mbi->framebuffer_addr;
|
||||
|
||||
sprintf("fb_addr: %x, fb_width: %u, fb_height: %u", fb, mbi->framebuffer_width, mbi->framebuffer_height);
|
||||
|
||||
switch (mbi->framebuffer_type)
|
||||
{
|
||||
case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED:
|
||||
{
|
||||
//sprintf("indexed");
|
||||
unsigned best_distance, distance;
|
||||
struct multiboot_color *palette;
|
||||
|
||||
palette = (struct multiboot_color *) mbi->framebuffer_palette_addr;
|
||||
|
||||
color = 0;
|
||||
best_distance = 4*256*256;
|
||||
|
||||
for (i = 0; i < mbi->framebuffer_palette_num_colors; i++)
|
||||
{
|
||||
distance = (0xff - palette[i].blue) * (0xff - palette[i].blue)
|
||||
+ palette[i].red * palette[i].red
|
||||
+ palette[i].green * palette[i].green;
|
||||
if (distance < best_distance)
|
||||
{
|
||||
color = i;
|
||||
best_distance = distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MULTIBOOT_FRAMEBUFFER_TYPE_RGB:
|
||||
color = ((1 << mbi->framebuffer_blue_mask_size) - 1)
|
||||
<< mbi->framebuffer_blue_field_position;
|
||||
break;
|
||||
|
||||
case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT:
|
||||
color = '\\' | 0x0100;
|
||||
break;
|
||||
|
||||
default:
|
||||
color = 0xffffffff;
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < mbi->framebuffer_width
|
||||
&& i < mbi->framebuffer_height; i++)
|
||||
{
|
||||
switch (mbi->framebuffer_bpp)
|
||||
{
|
||||
case 8:
|
||||
{
|
||||
multiboot_uint8_t *pixel = fb + mbi->framebuffer_pitch * i + i;
|
||||
*pixel = color;
|
||||
}
|
||||
break;
|
||||
case 15:
|
||||
case 16:
|
||||
{
|
||||
multiboot_uint16_t *pixel
|
||||
= fb + mbi->framebuffer_pitch * i + 2 * i;
|
||||
*pixel = color;
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
{
|
||||
multiboot_uint32_t *pixel
|
||||
= fb + mbi->framebuffer_pitch * i + 3 * i;
|
||||
*pixel = (color & 0xffffff) | (*pixel & 0xff000000);
|
||||
}
|
||||
break;
|
||||
|
||||
case 32:
|
||||
{
|
||||
multiboot_uint32_t *pixel
|
||||
= fb + mbi->framebuffer_pitch * i + 4 * i;
|
||||
*pixel = color;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
//}
|
||||
|
||||
hcf();
|
||||
}
|
274
src/multiboot.h
Normal file
274
src/multiboot.h
Normal file
|
@ -0,0 +1,274 @@
|
|||
/* multiboot.h - Multiboot 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 8192
|
||||
#define MULTIBOOT_HEADER_ALIGN 4
|
||||
|
||||
/* The magic field should contain this. */
|
||||
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
|
||||
|
||||
/* This should be in %eax. */
|
||||
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
|
||||
|
||||
/* Alignment of multiboot modules. */
|
||||
#define MULTIBOOT_MOD_ALIGN 0x00001000
|
||||
|
||||
/* Alignment of the multiboot info structure. */
|
||||
#define MULTIBOOT_INFO_ALIGN 0x00000004
|
||||
|
||||
/* Flags set in the 'flags' member of the multiboot header. */
|
||||
|
||||
/* Align all boot modules on i386 page (4KB) boundaries. */
|
||||
#define MULTIBOOT_PAGE_ALIGN 0x00000001
|
||||
|
||||
/* Must pass memory information to OS. */
|
||||
#define MULTIBOOT_MEMORY_INFO 0x00000002
|
||||
|
||||
/* Must pass video information to OS. */
|
||||
#define MULTIBOOT_VIDEO_MODE 0x00000004
|
||||
|
||||
/* This flag indicates the use of the address fields in the header. */
|
||||
#define MULTIBOOT_AOUT_KLUDGE 0x00010000
|
||||
|
||||
/* Flags to be set in the 'flags' member of the multiboot info structure. */
|
||||
|
||||
/* is there basic lower/upper memory information? */
|
||||
#define MULTIBOOT_INFO_MEMORY 0x00000001
|
||||
/* is there a boot device set? */
|
||||
#define MULTIBOOT_INFO_BOOTDEV 0x00000002
|
||||
/* is the command-line defined? */
|
||||
#define MULTIBOOT_INFO_CMDLINE 0x00000004
|
||||
/* are there modules to do something with? */
|
||||
#define MULTIBOOT_INFO_MODS 0x00000008
|
||||
|
||||
/* These next two are mutually exclusive */
|
||||
|
||||
/* is there a symbol table loaded? */
|
||||
#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010
|
||||
/* is there an ELF section header table? */
|
||||
#define MULTIBOOT_INFO_ELF_SHDR 0X00000020
|
||||
|
||||
/* is there a full memory map? */
|
||||
#define MULTIBOOT_INFO_MEM_MAP 0x00000040
|
||||
|
||||
/* Is there drive info? */
|
||||
#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080
|
||||
|
||||
/* Is there a config table? */
|
||||
#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100
|
||||
|
||||
/* Is there a boot loader name? */
|
||||
#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200
|
||||
|
||||
/* Is there a APM table? */
|
||||
#define MULTIBOOT_INFO_APM_TABLE 0x00000400
|
||||
|
||||
/* Is there video information? */
|
||||
#define MULTIBOOT_INFO_VBE_INFO 0x00000800
|
||||
#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000
|
||||
|
||||
#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;
|
||||
|
||||
/* Feature flags. */
|
||||
multiboot_uint32_t flags;
|
||||
|
||||
/* The above fields plus this one must equal 0 mod 2^32. */
|
||||
multiboot_uint32_t checksum;
|
||||
|
||||
/* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */
|
||||
multiboot_uint32_t header_addr;
|
||||
multiboot_uint32_t load_addr;
|
||||
multiboot_uint32_t load_end_addr;
|
||||
multiboot_uint32_t bss_end_addr;
|
||||
multiboot_uint32_t entry_addr;
|
||||
|
||||
/* These are only valid if MULTIBOOT_VIDEO_MODE is set. */
|
||||
multiboot_uint32_t mode_type;
|
||||
multiboot_uint32_t width;
|
||||
multiboot_uint32_t height;
|
||||
multiboot_uint32_t depth;
|
||||
};
|
||||
|
||||
/* The symbol table for a.out. */
|
||||
struct multiboot_aout_symbol_table
|
||||
{
|
||||
multiboot_uint32_t tabsize;
|
||||
multiboot_uint32_t strsize;
|
||||
multiboot_uint32_t addr;
|
||||
multiboot_uint32_t reserved;
|
||||
};
|
||||
typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
|
||||
|
||||
/* The section header table for ELF. */
|
||||
struct multiboot_elf_section_header_table
|
||||
{
|
||||
multiboot_uint32_t num;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t addr;
|
||||
multiboot_uint32_t shndx;
|
||||
};
|
||||
typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t;
|
||||
|
||||
struct multiboot_info
|
||||
{
|
||||
/* Multiboot info version number */
|
||||
multiboot_uint32_t flags;
|
||||
|
||||
/* Available memory from BIOS */
|
||||
multiboot_uint32_t mem_lower;
|
||||
multiboot_uint32_t mem_upper;
|
||||
|
||||
/* "root" partition */
|
||||
multiboot_uint32_t boot_device;
|
||||
|
||||
/* Kernel command line */
|
||||
multiboot_uint32_t cmdline;
|
||||
|
||||
/* Boot-Module list */
|
||||
multiboot_uint32_t mods_count;
|
||||
multiboot_uint32_t mods_addr;
|
||||
|
||||
union
|
||||
{
|
||||
multiboot_aout_symbol_table_t aout_sym;
|
||||
multiboot_elf_section_header_table_t elf_sec;
|
||||
} u;
|
||||
|
||||
/* Memory Mapping buffer */
|
||||
multiboot_uint32_t mmap_length;
|
||||
multiboot_uint32_t mmap_addr;
|
||||
|
||||
/* Drive Info buffer */
|
||||
multiboot_uint32_t drives_length;
|
||||
multiboot_uint32_t drives_addr;
|
||||
|
||||
/* ROM configuration table */
|
||||
multiboot_uint32_t config_table;
|
||||
|
||||
/* Boot Loader Name */
|
||||
multiboot_uint32_t boot_loader_name;
|
||||
|
||||
/* APM table */
|
||||
multiboot_uint32_t apm_table;
|
||||
|
||||
/* Video */
|
||||
multiboot_uint32_t vbe_control_info;
|
||||
multiboot_uint32_t vbe_mode_info;
|
||||
multiboot_uint16_t vbe_mode;
|
||||
multiboot_uint16_t vbe_interface_seg;
|
||||
multiboot_uint16_t vbe_interface_off;
|
||||
multiboot_uint16_t vbe_interface_len;
|
||||
|
||||
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;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
multiboot_uint32_t framebuffer_palette_addr;
|
||||
multiboot_uint16_t framebuffer_palette_num_colors;
|
||||
};
|
||||
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;
|
||||
};
|
||||
};
|
||||
};
|
||||
typedef struct multiboot_info multiboot_info_t;
|
||||
|
||||
struct multiboot_color
|
||||
{
|
||||
multiboot_uint8_t red;
|
||||
multiboot_uint8_t green;
|
||||
multiboot_uint8_t blue;
|
||||
};
|
||||
|
||||
struct multiboot_mmap_entry
|
||||
{
|
||||
multiboot_uint32_t size;
|
||||
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;
|
||||
} __attribute__((packed));
|
||||
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
|
||||
|
||||
struct multiboot_mod_list
|
||||
{
|
||||
/* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
|
||||
multiboot_uint32_t mod_start;
|
||||
multiboot_uint32_t mod_end;
|
||||
|
||||
/* Module command line */
|
||||
multiboot_uint32_t cmdline;
|
||||
|
||||
/* padding to take it to 16 bytes (must be zero) */
|
||||
multiboot_uint32_t pad;
|
||||
};
|
||||
typedef struct multiboot_mod_list multiboot_module_t;
|
||||
|
||||
/* APM BIOS info. */
|
||||
struct multiboot_apm_info
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
#endif /* ! ASM_FILE */
|
||||
|
||||
#endif /* ! MULTIBOOT_HEADER */
|
76
src/stdio.c
Normal file
76
src/stdio.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <vga.h>
|
||||
|
||||
void putc(char ch) {
|
||||
vga_putc(ch);
|
||||
}
|
||||
|
||||
void puts(const char* str) {
|
||||
do {
|
||||
putc(*str);
|
||||
} while(*++str != '\0');
|
||||
}
|
||||
|
||||
void printf(const char* fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
for(int i = 0; fmt[i] != '\0'; i++)
|
||||
{
|
||||
switch(fmt[i])
|
||||
{
|
||||
case '%':
|
||||
i++;
|
||||
|
||||
char buf[512];
|
||||
|
||||
size_t width = 0;
|
||||
char padding_char = fmt[i];
|
||||
if(isdigit(fmt[i]) || fmt[i] == ' ') {
|
||||
i++;
|
||||
int pos = 0;
|
||||
while(isdigit(fmt[i])) {
|
||||
buf[pos++] = fmt[i++];
|
||||
}
|
||||
buf[pos] = '\0';
|
||||
width = atoi(buf);
|
||||
}
|
||||
|
||||
const char* out = 0;
|
||||
|
||||
if(fmt[i] == 's')
|
||||
out = va_arg(args, const char*);
|
||||
if(fmt[i] == 'd')
|
||||
out = itoa(va_arg(args, int), buf, 10);
|
||||
if(fmt[i] == 'u')
|
||||
out = ultoa(va_arg(args, uint32_t), buf, 10);
|
||||
if(fmt[i] == 'x')
|
||||
out = ultoa(va_arg(args, uint32_t), buf, 16);
|
||||
if(fmt[i] == 'c')
|
||||
putc(va_arg(args, int));
|
||||
|
||||
size_t len = strlen(out);
|
||||
if(width > len) {
|
||||
char padding[256];
|
||||
size_t j = 0;
|
||||
for(; j < width - len; j++)
|
||||
padding[j] = padding_char;
|
||||
padding[j] = '\0';
|
||||
puts(padding);
|
||||
}
|
||||
|
||||
puts(out);
|
||||
break;
|
||||
default:
|
||||
putc(fmt[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
9
src/stdio.h
Normal file
9
src/stdio.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef __STDIO_H__
|
||||
#define __STDIO_H__
|
||||
#include <stdint.h>
|
||||
|
||||
void putc(char ch);
|
||||
void puts(const char* str);
|
||||
void printf(const char* fmt, ...);
|
||||
|
||||
#endif
|
77
src/stdlib.c
Normal file
77
src/stdlib.c
Normal file
|
@ -0,0 +1,77 @@
|
|||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
const char* itoa(int value, char* str, int base)
|
||||
{
|
||||
char* rc;
|
||||
char* ptr;
|
||||
char* low;
|
||||
|
||||
if (base < 2 || base > 36)
|
||||
{
|
||||
*str = '\0';
|
||||
return str;
|
||||
}
|
||||
rc = ptr = str;
|
||||
if (value < 0 && base == 10)
|
||||
{
|
||||
*ptr++ = '-';
|
||||
}
|
||||
|
||||
low = ptr;
|
||||
do
|
||||
{
|
||||
*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + value % base];
|
||||
value /= base;
|
||||
} while (value);
|
||||
|
||||
*ptr-- = '\0';
|
||||
while (low < ptr)
|
||||
{
|
||||
char tmp = *low;
|
||||
*low++ = *ptr;
|
||||
*ptr-- = tmp;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
const char* ultoa(uint32_t value, char* str, int base)
|
||||
{
|
||||
char* rc;
|
||||
char* ptr;
|
||||
char* low;
|
||||
|
||||
if (base < 2 || base > 36)
|
||||
{
|
||||
*str = '\0';
|
||||
return str;
|
||||
}
|
||||
rc = ptr = str;
|
||||
|
||||
low = ptr;
|
||||
do
|
||||
{
|
||||
*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + value % base];
|
||||
value /= base;
|
||||
} while (value);
|
||||
|
||||
*ptr-- = '\0';
|
||||
while (low < ptr)
|
||||
{
|
||||
char tmp = *low;
|
||||
*low++ = *ptr;
|
||||
*ptr-- = tmp;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int atoi(const char* str) {
|
||||
int value = 0;
|
||||
while(isdigit(*str)) {
|
||||
value *= 10;
|
||||
value += (*str)-'0';
|
||||
str++;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
9
src/stdlib.h
Normal file
9
src/stdlib.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef __STDLIB_H__
|
||||
#define __STDLIB_H__
|
||||
#include <stdint.h>
|
||||
|
||||
const char* itoa(int value, char* str, int base);
|
||||
const char* ultoa(uint32_t value, char* str, int base);
|
||||
int atoi(const char* str);
|
||||
|
||||
#endif
|
8
src/string.c
Normal file
8
src/string.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <string.h>
|
||||
|
||||
size_t strlen(const char* str) {
|
||||
size_t len = 0;
|
||||
while (str[len])
|
||||
len++;
|
||||
return len;
|
||||
}
|
7
src/string.h
Normal file
7
src/string.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#ifndef __STRING_H__
|
||||
#define __STRING_H__
|
||||
#include <stddef.h>
|
||||
|
||||
size_t strlen(const char* str);
|
||||
|
||||
#endif
|
39
src/vga.c
Normal file
39
src/vga.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
#include <vga.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct vga_terminal vga_term = { 0 };
|
||||
uint16_t* VGA = (uint16_t*)0xb8000;
|
||||
|
||||
void vga_putc(char ch) {
|
||||
if(ch == '\n') {
|
||||
vga_term.x = 0;
|
||||
vga_term.y++;
|
||||
} else {
|
||||
int index = vga_term.y * VGA_WIDTH + vga_term.x;
|
||||
|
||||
VGA[index] = ch | (vga_term.fg | vga_term.bg << 4) << 8;
|
||||
|
||||
vga_term.x++;
|
||||
if(vga_term.x > VGA_WIDTH) {
|
||||
vga_term.x = 0;
|
||||
vga_term.y++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vga_clear() {
|
||||
vga_term.x = 0;
|
||||
vga_term.y = 0;
|
||||
for(int i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++)
|
||||
putc(' ');
|
||||
}
|
||||
|
||||
void init_vga(void) {
|
||||
vga_term.fg = 7;
|
||||
vga_term.bg = 0;
|
||||
|
||||
vga_clear();
|
||||
|
||||
vga_term.x = 0;
|
||||
vga_term.y = 0;
|
||||
}
|
20
src/vga.h
Normal file
20
src/vga.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef __VGA_H__
|
||||
#define __VGA_H__
|
||||
#include <stdint.h>
|
||||
|
||||
#define VGA_WIDTH 80
|
||||
#define VGA_HEIGHT 25
|
||||
|
||||
struct vga_terminal {
|
||||
uint8_t bg;
|
||||
uint8_t fg;
|
||||
uint8_t x;
|
||||
uint8_t y;
|
||||
};
|
||||
|
||||
extern struct vga_terminal vga_term;
|
||||
|
||||
void init_vga(void);
|
||||
void vga_putc(char ch);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue