2004-07-29 07:13:24 UTC
previous
next
#define VGA_WHITE 0x0F
#define VGA_RED 0x0C
#define VGA_GREY 0x07
typedef char* mem_address_t;
typedef struct memory_map
{
unsigned long size;
unsigned long base_addr_low;
unsigned long base_addr_high;
unsigned long length_low;
unsigned long length_high;
unsigned long type;
} memory_map_t;
struct multiboot_info_t {
unsigned long flags;
unsigned long mem_lower;
unsigned long mem_upper;
unsigned long boot_device;
char* cmdline;
unsigned long mods_count;
unsigned long mods_addr;
unsigned long syms[4];
unsigned long mmap_length;
memory_map_t* mmap_addr;
unsigned long drives_length;
unsigned long drives_addr;
unsigned long config_table;
char* boot_loader_name;
};
void start(unsigned long magic, struct multiboot_info_t* mb_info);
void boot_printf(unsigned char color, char* format_string, ...);
void boot_printf_char(unsigned char color, char character) __attribute__ ((regparm (2)));
inline void boot_printf_number(char numbertype, unsigned char color, unsigned int number);
inline unsigned char inportb(unsigned int port);
inline void outportb(unsigned int port, unsigned char value);
void scroll_screen(void);
extern void hang(void);
extern char boot_message_buffer[16000];
char* message_buffer_location;
mem_address_t video_mem;
// Here is where the real programming starts;
// we currently have a 100 dword long stack to use
// and so we must quickly parse the multiboot structure,
// change to virtual memory mode and jump to main()
// using a 'real' stack
void start(unsigned long magic, struct multiboot_info_t* mb_info)
{
message_buffer_location = boot_message_buffer;
boot_printf(VGA_WHITE, "Starting kryptOS...\n\n");
boot_printf(VGA_GREY, "Checking multiboot information...\n");
if (magic != 0x2BADB002) {
boot_printf(VGA_RED, "\nError: ");
boot_printf(VGA_GREY, "Please use a multiboot compatiable boot loader to use kryptOS");
hang();
}
boot_printf(VGA_GREY, "Boot loader name.....[%s]\n", mb_info->boot_loader_name);
boot_printf(VGA_GREY, "Kernel command line..[%s]\n", mb_info->cmdline);
boot_printf(VGA_GREY, "Memory layout:\n");
memory_map_t *mmap;
/* boot_printf (VGA_GREY, "mmap_addr = 0x%x, mmap_length = 0x%x\n",
(unsigned) mb_info->mmap_addr, (unsigned) mb_info->mmap_length);
for (mmap = (memory_map_t *) mb_info->mmap_addr;
(unsigned long) mmap < mb_info->mmap_addr + mb_info->mmap_length;
mmap = (memory_map_t *) ((unsigned long) mmap
+ mmap->size + sizeof (mmap->size)))
boot_printf (VGA_GREY, " size = 0x%x, base_addr = 0x%x%x,"
" length = 0x%x%x, type = 0x%x\n",
(unsigned) mmap->size,
(unsigned) mmap->base_addr_high,
(unsigned) mmap->base_addr_low,
(unsigned) mmap->length_high,
(unsigned) mmap->length_low,
(unsigned) mmap->type); */
for (mmap = (memory_map_t *)mb_info->mmap_addr;
(unsigned long) mmap < (unsigned long)mb_info->mmap_addr + mb_info->mmap_length;
mmap = (memory_map_t*)((unsigned long) mmap + mmap->size + 4))
{
boot_printf(VGA_GREY, "0x%X - 0x%X - [", mmap->base_addr_low, mmap->base_addr_low + mmap->length_low);
if (mmap->type == 1) {
boot_printf(VGA_WHITE, "free");
} else {
boot_printf(VGA_WHITE, "reserved");
}
boot_printf(VGA_GREY, "]\n");
}
}
void boot_printf(unsigned char color, char* format_string, ...)
{
mem_address_t arg;
char* arg_string;
arg = (mem_address_t)&format_string + 4; // Pointer to argument after format_string
outportb(0x3d4, 0x0E); // Get first byte of screen cursor offset
video_mem = (mem_address_t)((int)inportb(0x3d5));
video_mem = (mem_address_t)((int)video_mem << 8);
outportb(0x3d4, 0x0F); // Get second byte
video_mem += inportb(0x3d5);
video_mem = (mem_address_t)((int)video_mem << 1); // Multiply by two (since each character in video memory
video_mem += 0xb8000; // takes 2 byes) and add 0xb8000 to get the memory address
do {
if (*format_string != '%') {
boot_printf_char(color, *format_string);
continue;
}
format_string++; // Advance to character after the %
switch (*format_string) {
case 'c':
boot_printf_char(color, *arg);
arg += 4;
continue;
case 'u':
case 'x':
case 'X':
boot_printf_number(*format_string, color, *((unsigned int*)arg));
arg += 4;
continue;
case 's':
arg_string = *((char**)arg); // arg is a pointer to a pointer to a string
boot_printf_char(color, *arg_string);
while (*(++arg_string)) boot_printf_char(color, *arg_string);
arg += 4;
continue;
case '%':
boot_printf_char(color, '%');
continue;
}
} while(*(++format_string));
if ((int)video_mem > 0xB8FA0) scroll_screen();
video_mem -= 0xb8000;
video_mem = (mem_address_t)((int)video_mem >> 1);
outportb(0x3d4, 0x0E);
outportb(0x3d5, (int)video_mem >> 8);
outportb(0x3d4, 0x0F);
outportb(0x3d5, (int)video_mem & 0xFF);
}
void scroll_screen(void)
{
int lines_over = (((int)video_mem - 0xB8FA0) / 160) + 1;
char* src = (char*)(0xb8000 + (lines_over*160));
char* dest = (char*)0xb8000;
for(;src < video_mem; *dest = *src, dest++, src++);
video_mem = dest;
for(;(int)dest < 0xB8FA0; *dest = 0, dest++);
}
void boot_printf_char(unsigned char color, char character)
{
if (character != '\n') {
*video_mem = character;
video_mem++;
*video_mem = color;
video_mem++;
return;
}
video_mem = (mem_address_t)((((int)video_mem - 0xb8000) / 160) + 1);
video_mem = (mem_address_t)(((int)video_mem * 160) + 0xb8000);
}
// This function is inline because it is only called from one place
inline void boot_printf_number(char numbertype, unsigned char color, unsigned int number)
{
char digit_string[11];
char* current_digit = digit_string;
char base;
if (numbertype == 'u') {
base = 10;
} else {
base = 16;
}
if (number == 0) {
boot_printf_char(color, '0');
return;
}
while (number > 0) {
*current_digit = (number % base) + '0';
if (*current_digit > '9') {
if (numbertype == 'X') {
*current_digit += 'A' - ('9'+1);
} else {
*current_digit += 'a' - ('9'+1);
}
}
current_digit++;
number /= base;
}
// Print digit_string in reverse order starting with current_digit
for (;(--current_digit) >= digit_string; boot_printf_char(color, *current_digit));
}
inline unsigned char inportb(unsigned int port)
{
unsigned char ret;
asm volatile ("inb %%dx,%%al":"=a" (ret):"d" (port));
return ret;
}
inline void outportb(unsigned int port, unsigned char value)
{
asm volatile ("outb %%al,%%dx": :"d" (port), "a" (value));
}