Subversion Repositories HelenOS

Rev

Rev 3982 | Rev 4026 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2001-2004 Jakub Jermar
  3.  * Copyright (c) 2009 Jiri Svoboda
  4.  * Copyright (c) 2009 Martin Decky
  5.  * All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * - Redistributions of source code must retain the above copyright
  12.  *   notice, this list of conditions and the following disclaimer.
  13.  * - Redistributions in binary form must reproduce the above copyright
  14.  *   notice, this list of conditions and the following disclaimer in the
  15.  *   documentation and/or other materials provided with the distribution.
  16.  * - The name of the author may not be used to endorse or promote products
  17.  *   derived from this software without specific prior written permission.
  18.  *
  19.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  20.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  21.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  23.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  24.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  28.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29.  */
  30.  
  31. /** @addtogroup ia32
  32.  * @{
  33.  */
  34. /** @file
  35.  */
  36.  
  37. #include <arch.h>
  38.  
  39. #include <arch/types.h>
  40.  
  41. #include <arch/pm.h>
  42.  
  43. #include <genarch/drivers/legacy/ia32/io.h>
  44. #include <genarch/drivers/ega/ega.h>
  45. #include <arch/drivers/vesa.h>
  46. #include <genarch/kbd/i8042.h>
  47. #include <arch/drivers/i8254.h>
  48. #include <arch/drivers/i8259.h>
  49.  
  50. #include <arch/context.h>
  51.  
  52. #include <config.h>
  53.  
  54. #include <arch/interrupt.h>
  55. #include <arch/asm.h>
  56. #include <genarch/acpi/acpi.h>
  57.  
  58. #include <arch/bios/bios.h>
  59.  
  60. #include <interrupt.h>
  61. #include <ddi/irq.h>
  62. #include <arch/debugger.h>
  63. #include <proc/thread.h>
  64. #include <syscall/syscall.h>
  65. #include <console/console.h>
  66. #include <ddi/device.h>
  67. #include <sysinfo/sysinfo.h>
  68. #include <arch/boot/boot.h>
  69. #include <string.h>
  70. #include <macros.h>
  71.  
  72. #ifdef CONFIG_SMP
  73. #include <arch/smp/apic.h>
  74. #endif
  75.  
  76. /** Extract command name from the multiboot module command line.
  77.  *
  78.  * @param buf      Destination buffer (will always null-terminate).
  79.  * @param n        Size of destination buffer.
  80.  * @param cmd_line Input string (the command line).
  81.  *
  82.  */
  83. static void extract_command(char *buf, size_t n, const char *cmd_line)
  84. {
  85.     const char *start, *end, *cp;
  86.     size_t max_len;
  87.    
  88.     /* Find the first space. */
  89.     end = strchr(cmd_line, ' ');
  90.     if (end == NULL)
  91.         end = cmd_line + strlen(cmd_line);
  92.    
  93.     /*
  94.      * Find last occurence of '/' before 'end'. If found, place start at
  95.      * next character. Otherwise, place start at beginning of buffer.
  96.      */
  97.     cp = end;
  98.     start = buf;
  99.     while (cp != start) {
  100.         if (*cp == '/') {
  101.             start = cp + 1;
  102.             break;
  103.         }
  104.         --cp;
  105.     }
  106.    
  107.     /* Copy the command and null-terminate the string. */
  108.     max_len = min(n - 1, (size_t) (end - start));
  109.     strncpy(buf, start, max_len + 1);
  110.     buf[max_len] = '\0';
  111. }
  112.  
  113. /** C part of ia32 boot sequence.
  114.  *
  115.  * @param signature Should contain the multiboot signature.
  116.  * @param mi        Pointer to the multiboot information structure.
  117.  */
  118. void arch_pre_main(uint32_t signature, const mb_info_t *mi)
  119. {
  120.     uint32_t flags;
  121.     mb_mod_t *mods;
  122.     uint32_t i;
  123.    
  124.     if (signature == MULTIBOOT_LOADER_MAGIC)
  125.         flags = mi->flags;
  126.     else {
  127.         /* No multiboot info available. */
  128.         flags = 0;
  129.     }
  130.    
  131.     /* Copy module information. */
  132.    
  133.     if ((flags & MBINFO_FLAGS_MODS) != 0) {
  134.         init.cnt = mi->mods_count;
  135.         mods = mi->mods_addr;
  136.        
  137.         for (i = 0; i < init.cnt; i++) {
  138.             init.tasks[i].addr = mods[i].start + 0x80000000;
  139.             init.tasks[i].size = mods[i].end - mods[i].start;
  140.            
  141.             /* Copy command line, if available. */
  142.             if (mods[i].string) {
  143.                 extract_command(init.tasks[i].name,
  144.                     CONFIG_TASK_NAME_BUFLEN,
  145.                     mods[i].string);
  146.             } else
  147.                 init.tasks[i].name[0] = '\0';
  148.         }
  149.     } else
  150.         init.cnt = 0;
  151.    
  152.     /* Copy memory map. */
  153.    
  154.     int32_t mmap_length;
  155.     mb_mmap_t *mme;
  156.     uint32_t size;
  157.    
  158.     if ((flags & MBINFO_FLAGS_MMAP) != 0) {
  159.         mmap_length = mi->mmap_length;
  160.         mme = mi->mmap_addr;
  161.         e820counter = 0;
  162.        
  163.         i = 0;
  164.         while (mmap_length > 0) {
  165.             e820table[i++] = mme->mm_info;
  166.            
  167.             /* Compute address of next structure. */
  168.             size = sizeof(mme->size) + mme->size;
  169.             mme = ((void *) mme) + size;
  170.             mmap_length -= size;
  171.         }
  172.        
  173.         e820counter = i;
  174.     } else
  175.         e820counter = 0;
  176.    
  177. #ifdef CONFIG_SMP
  178.     /* Copy AP bootstrap routines below 1 MB. */
  179.     memcpy((void *) AP_BOOT_OFFSET, (void *) BOOT_OFFSET,
  180.         (size_t) &_hardcoded_unmapped_size);
  181. #endif
  182. }
  183.  
  184. void arch_pre_mm_init(void)
  185. {
  186.     pm_init();
  187.  
  188.     if (config.cpu_active == 1) {
  189.         interrupt_init();
  190.         bios_init();
  191.        
  192.         /* PIC */
  193.         i8259_init();
  194.     }
  195. }
  196.  
  197. void arch_post_mm_init(void)
  198. {
  199.     if (config.cpu_active == 1) {
  200.         /* Initialize IRQ routing */
  201.         irq_init(IRQ_COUNT, IRQ_COUNT);
  202.        
  203.         /* hard clock */
  204.         i8254_init();
  205.  
  206. #ifdef CONFIG_FB
  207.         if (vesa_present())
  208.             vesa_init();
  209.         else
  210. #endif
  211.             ega_init(EGA_BASE, EGA_VIDEORAM);   /* video */
  212.        
  213.         /* Enable debugger */
  214.         debugger_init();
  215.         /* Merge all memory zones to 1 big zone */
  216.         zone_merge_all();
  217.     }
  218. }
  219.  
  220. void arch_post_cpu_init()
  221. {
  222. #ifdef CONFIG_SMP
  223.         if (config.cpu_active > 1) {
  224.         l_apic_init();
  225.         l_apic_debug();
  226.     }
  227. #endif
  228. }
  229.  
  230. void arch_pre_smp_init(void)
  231. {
  232.     if (config.cpu_active == 1) {
  233. #ifdef CONFIG_SMP
  234.         acpi_init();
  235. #endif /* CONFIG_SMP */
  236.     }
  237. }
  238.  
  239. void arch_post_smp_init(void)
  240. {
  241.     devno_t devno = device_assign_devno();
  242.     /* keyboard controller */
  243.     (void) i8042_init((i8042_t *) I8042_BASE, devno, IRQ_KBD);
  244.  
  245.     /*
  246.      * This is the necessary evil until the userspace driver is entirely
  247.      * self-sufficient.
  248.      */
  249.     sysinfo_set_item_val("kbd", NULL, true);
  250.     sysinfo_set_item_val("kbd.devno", NULL, devno);
  251.     sysinfo_set_item_val("kbd.inr", NULL, IRQ_KBD);
  252. }
  253.  
  254. void calibrate_delay_loop(void)
  255. {
  256.     i8254_calibrate_delay_loop();
  257.     if (config.cpu_active == 1) {
  258.         /*
  259.          * This has to be done only on UP.
  260.          * On SMP, i8254 is not used for time keeping and its interrupt pin remains masked.
  261.          */
  262.         i8254_normal_operation();
  263.     }
  264. }
  265.  
  266. /** Set thread-local-storage pointer
  267.  *
  268.  * TLS pointer is set in GS register. That means, the GS contains
  269.  * selector, and the descriptor->base is the correct address.
  270.  */
  271. unative_t sys_tls_set(unative_t addr)
  272. {
  273.     THREAD->arch.tls = addr;
  274.     set_tls_desc(addr);
  275.  
  276.     return 0;
  277. }
  278.  
  279. /** Acquire console back for kernel
  280.  *
  281.  */
  282. void arch_grab_console(void)
  283. {
  284. #ifdef CONFIG_FB
  285.     vesa_redraw();
  286. #else
  287.     ega_redraw();
  288. #endif
  289. }
  290.  
  291. /** Return console to userspace
  292.  *
  293.  */
  294. void arch_release_console(void)
  295. {
  296. }
  297.  
  298. /** Construct function pointer
  299.  *
  300.  * @param fptr   function pointer structure
  301.  * @param addr   function address
  302.  * @param caller calling function address
  303.  *
  304.  * @return address of the function pointer
  305.  *
  306.  */
  307. void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller)
  308. {
  309.     return addr;
  310. }
  311.  
  312. /** @}
  313.  */
  314.