Archive / / / boot.c
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)); }