Advertisement
iocoder

boot/entry.c

Sep 22nd, 2012
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.33 KB | None | 0 0
  1. /*
  2.       +----------------------------------------------------------+
  3.       | +------------------------------------------------------+ |
  4.       | |  Quafios Kernel 1.0.1.                   | |
  5.       | |  -> Kernel code entry (i386).                        | |
  6.       | +------------------------------------------------------+ |
  7.       +----------------------------------------------------------+
  8. */
  9.  
  10. // This file is part of Quafios 1.0.1 source code.
  11. // Copyright (C) 2012  Mostafa Abd El-Aziz Mohamed.
  12.  
  13. // This program is free software: you can redistribute it and/or modify
  14. // it under the terms of the GNU General Public License as published by
  15. // the Free Software Foundation, either version 3 of the License, or
  16. // (at your option) any later version.
  17.  
  18. // This program is distributed in the hope that it will be useful,
  19. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21. // GNU General Public License for more details.
  22.  
  23. // You should have received a copy of the GNU General Public License
  24. // along with Quafios.  If not, see <http://www.gnu.org/licenses/>.
  25.  
  26. // Visit http://www.quafios.com/ for contact information.
  27.  
  28. extern /* "C" */ void entry() __attribute__ ((section(".entry")));
  29. extern /* "C" */ void entry_error() __attribute__ ((section(".entry")));
  30.  
  31. void entry_error(const char *vmsg) {
  32.     unsigned int  i = 0;
  33.     unsigned char col = *((unsigned char *) 0x450);
  34.     unsigned char row = *((unsigned char *) 0x451);
  35.     unsigned int  off = ((row*80)+col)*2;
  36.     unsigned char *vga = (unsigned char *) 0xb8000;
  37.     char *msg = (char *) kvirt_to_phy(vmsg);
  38.     while (msg[i]) {
  39.         vga[off++] = msg[i++];
  40.         vga[off++] = 0x0C;
  41.     }
  42.     idle();
  43. }
  44.  
  45. void entry()  {
  46.  
  47.     // (I) Read Multiboot information:
  48.     // ========================================
  49.     // Multi-boot standard specs says that after kernel load,
  50.     // EAX and EBX registers should contain "Boot magic
  51.     // signature" and a pointer to "Boot info structures"
  52.     // respectively.
  53.     unsigned int boot_magic;
  54.     multiboot_info_t *mbi;
  55.  
  56.     __asm__ ("":"=a"(boot_magic),"=b"(mbi));
  57.  
  58.     // Check if the boot magic signature is invalid:
  59.     if (boot_magic != MULTIBOOT_BOOTLOADER_MAGIC)
  60.         entry_error("Boot Error: Boot loader is not a multi-boot compliant loader.");
  61.  
  62.     // Get info about BIOS memory map from the boot info struct:
  63.     if (!(mbi->flags & MULTIBOOT_INFO_MEM_MAP))
  64.         entry_error("Boot Error: No memory map found.");
  65.  
  66.     unsigned int *map = (unsigned int *) kvirt_to_phy(&pmmap);
  67.     linkedlist *flist = (linkedlist *) kvirt_to_phy(&pfreelist);
  68.  
  69.     // Read BIOS Memory Map, and set RAM Regions as free:
  70.     unsigned int i = 0, j;
  71.     linknode *prev = (linknode *) flist;
  72.    
  73.     while (i < (mbi->mmap_length)) {
  74.         multiboot_memory_map_t *mbmm; // Entry.
  75.  
  76.         mbmm = (multiboot_memory_map_t *) (mbi->mmap_addr + i);
  77.  
  78.         unsigned int addr = mbmm->addr;
  79.         unsigned int size = mbmm->len;
  80.  
  81.         if (mbmm->type == MULTIBOOT_MEMORY_AVAILABLE) {
  82.  
  83.             *kvirt_to_phy(&ram_size) = addr + size;
  84.  
  85.             // Align to 4KB Boundary:
  86.             if (addr & 0xFFF) {
  87.                 size -= 0x1000-(addr&0xFFF);
  88.                 addr = (addr&0xFFFFF000) + 0x1000;
  89.             }
  90.  
  91.             j = 0;
  92.             while(j < size/PAGE_SIZE) {
  93.                
  94.                 unsigned int frame = (addr>>12) + j++;
  95.                 unsigned int page = frame * PAGE_SIZE;
  96.                
  97.                 // Don't mark these pages as free:
  98.                 // Lower Memory:
  99.                 if (page >= LOWER_MEMORY_BASE &&
  100.                     page <  LOWER_MEMORY_SIZE) continue;
  101.                
  102.                 // Kernel Space:
  103.                 if (page >= KERNEL_PHYSICAL_START &&
  104.                     page <  KERNEL_PHYSICAL_END) continue;
  105.                
  106.                 // add the page to free list :)
  107.                 linknode *entry = (linknode *) &map[frame];
  108.                 prev->next = (linknode *) kphy_to_virt(entry);
  109.                 prev = entry;
  110.                 flist->count++;
  111.             }
  112.  
  113.             *kvirt_to_phy(&pmem_usable_pages) += j;
  114.         }
  115.         i += (mbmm->size) + sizeof(mbmm->size);
  116.     }
  117.     prev->next = NULLNODE;
  118.  
  119.     // (II) Initialize general page directory & page tables:
  120.     // ======================================================
  121.     unsigned int membase;
  122.     // Kernel Memory Area Entries in general page table
  123.     // (at 0xC0000000):
  124.     for (i = 768; i < 1024; i++)
  125.         kvirt_to_phy(general_pagedir)[i] = ((unsigned int)
  126.             &kvirt_to_phy(kmem_pagetab)[(i-768)*1024]) | PAGE_ENTRY_KERNEL_MODE;
  127.  
  128.     // 1- Initialize kernel image page tables...
  129.     membase = KERNEL_PHYSICAL_START;
  130.     for (i = 0; membase < KERNEL_PHYSICAL_END; i++) {
  131.         kvirt_to_phy(kmem_pagetab)[i] = membase | PAGE_ENTRY_KERNEL_MODE;
  132.         membase += PAGE_SIZE;
  133.     }
  134.  
  135.     // 2- Initialize lower memory image in kernel memory:
  136.     membase = LOWER_MEMORY_BASE;
  137.     for (; membase < LOWER_MEMORY_END; i++) {
  138.         kvirt_to_phy(kmem_pagetab)[i] = membase | PAGE_ENTRY_KERNEL_MODE;
  139.         membase += PAGE_SIZE;
  140.     }
  141.  
  142.     // Temporarily map ".entry" section:
  143.     kvirt_to_phy(general_pagedir)[0] = ((unsigned int)
  144.                         kvirt_to_phy(temp_pagetab)) |
  145.                         PAGE_ENTRY_KERNEL_MODE;
  146.  
  147.     kvirt_to_phy(temp_pagetab)[ENTRY_SECTION_START/PAGE_SIZE] =
  148.                 ENTRY_SECTION_START | PAGE_ENTRY_KERNEL_MODE;
  149.  
  150.     // (III) Enable Paging:
  151.     // ======================
  152.     // Setup CR3:
  153.     set_cr3(kvirt_to_phy(general_pagedir));
  154.  
  155.     // Write-back and invalidate the cache:
  156.     __asm__ ("wbinvd");
  157.  
  158.     // Enable Paging and Disable Caching:
  159.     set_cr0(CR0_GENERIC);
  160.  
  161.     // (IV) Change Stack:
  162.     // ====================
  163.     __asm__ ("mov %%eax, %%esp"::"a"(&kernel_stack[KERNEL_STACK_SIZE]));
  164.  
  165.     // (V) Initialize kernel:
  166.     // ==========================
  167.     __asm__ ("call main");
  168. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement