+
# Makefile for arch-dependent kernel code
.include <bsd.own.mk>
io_outl.S \
io_outw.S \
klib.S \
+ klib16.S \
+ multiboot.S \
memory.c \
oxpcie.c \
protect.c \
arch_system.c \
apic.c \
apic_asm.S \
- arch_watchdog.c
+ arch_watchdog.c \
+ pre_init.c
+
+I86CPPFLAGS = -mi86
+I86LDFLAGS = -mi86
+
+CPPFLAGS.klib16.S = ${I86CPPFLAGS}
+LDFLAGS.klib16.S = ${I86LDFLAGS}
#include "oxpcie.h"
#include "kernel/proc.h"
#include "kernel/debug.h"
+#include "multiboot.h"
#ifdef CONFIG_APIC
#include "apic.h"
PRIVATE int osfxsr_feature; /* FXSAVE/FXRSTOR instructions support (SSEx) */
+extern void poweroff_jmp();
+extern void poweroff16();
+extern void poweroff16_end();
/* set MP and NE flags to handle FPU exceptions in native mode. */
#define CR0_MP_NE 0x0022
monitor();
}
+PUBLIC void arch_bios_poweroff(void)
+{
+ u32_t cr0;
+
+ /* Disable paging */
+ cr0 = read_cr0();
+ cr0 &= ~I386_CR0_PG;
+ write_cr0(cr0);
+ /* Copy 16-bit poweroff code to below 1M */
+ phys_copy(
+ FUNC2PHY(&poweroff16),
+ BIOS_POWEROFF_ENTRY,
+ (u32_t)&poweroff16_end-(u32_t)&poweroff16);
+ poweroff_jmp();
+}
+
PUBLIC int cpu_has_tsc;
PUBLIC __dead void arch_shutdown(const int how)
arch_set_params(mybuffer, strlen(mybuffer)+1);
}
- arch_monitor();
+ if(mon_return)
+ arch_monitor();
+ else
+ arch_bios_poweroff();
} else {
/* Reset the system by forcing a processor shutdown. First stop
* the BIOS memory test by setting a soft reset flag.
/* fpu context should be saved in 16-byte aligned memory */
#define FPUALIGN 16
+/* Poweroff 16-bit code address */
+#define BIOS_POWEROFF_ENTRY 0x1000
+
#endif /* _I386_ACONST_H */
#include <minix/config.h>
#include <minix/const.h>
#include <machine/interrupt.h>
+#include <i386/vm.h>
#include "archconst.h"
#include "kernel/const.h"
#include "sconst.h"
+#include "multiboot.h"
/*
* This file contains a number of assembly code utility routines needed by the
0:
ret
+/*===========================================================================*/
+/* poweroff */
+/*===========================================================================*/
+/* PUBLIC void poweroff(); */
+/* Jump to 16-bit poweroff code */
+.globl _poweroff_jmp
+_poweroff_jmp:
+ cli
+ /* Make real mode descriptor */
+ mov $(_gdt + SS_SELECTOR), %edi
+ mov $0x100, %eax
+ movw %ax, 2(%edi)
+ shr $16, %eax
+ movb %al, 4(%edi)
+ and $0xff00, %ax
+ andw $0xff, 6(%edi)
+ or %ax, 6(%edi)
+ mov $0xffff, %eax
+ movw %ax, (%edi)
+ shr $16, %eax
+ and $0xf, %ax
+ andb $0xf0, 6(%edi)
+ or %ax, 6(%edi)
+
+ /* Flush TLB */
+ xor %eax, %eax
+ mov %eax, %cr3
+
+ xor %esp, %esp /* clear esp for real mode*/
+
+ /* Reset IDTR */
+ lidt idt_ptr
+
+ mov $SS_SELECTOR, %ax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+ mov %ax, %ss
+
+ /* Save real mode cr0 in eax */
+ mov %cr0, %eax
+ andl $~I386_CR0_PE, %eax
+
+ /* Jump to 16-bit code that is copied to below 1MB */
+ ljmp $MON_CS_SELECTOR, $0
+
+.data
+idt_ptr:
+ .short 0x3ff
+ .long 0x0
--- /dev/null
+/* sections */
+
+
+#include <minix/config.h>
+#include <minix/const.h>
+#include <machine/interrupt.h>
+#include "archconst.h"
+#include "kernel/const.h"
+#include "sconst.h"
+#include "multiboot.h"
+
+/*
+ * This file contains a number of 16-bit assembly code utility routines needed by the
+ * kernel. They are:
+ */
+
+.globl _poweroff16 /* enter real mode */
+.globl _poweroff16_end
+
+.text
+
+/*===========================================================================*/
+/* poweroff16 */
+/*===========================================================================*/
+/* PUBLIC void poweroff16(); */
+/* Power down system */
+_poweroff16:
+ /* Assume eax is already set to required value of cr0*/
+.byte 0x0F,0x22,0xC0 /* mov %cr0,%eax */
+ jmpf $0,$(BIOS_POWEROFF_ENTRY + real_mode - _poweroff16)
+real_mode:
+ mov $((BIOS_POWEROFF_ENTRY >> 4) + 0x200),%ax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %ss
+ mov $0x1000, %sp
+
+ xorb %ah, %ah
+/* Close gate A20 */
+gate_A20:
+ call kb_wait
+ movb $0xD1,%al
+ outb 0x64
+ call kb_wait
+ movb $0xDD,%al
+ orb %ah,%al
+ outb 0x60
+ call kb_wait
+ movb $0xFF,%al
+ outb 0x64
+ call kb_wait
+
+ /* Connect to APM */
+ mov $0x5301,%ax
+ mov $0x0,%bx
+ int 0x15
+
+ /* Enable power management */
+ mov $0x5308,%ax
+ mov $0x1,%bx
+ mov $0x1,%cx
+ int 0x15
+
+ /* Set power state to off */
+ mov $0x5307,%ax
+ mov $0x01,%bx
+ mov $0x3,%cx
+ int 0x15
+0: hlt
+ jmp 0b
+
+kb_wait:
+ inb 0x64
+ testb $0x02,%al
+ jnz kb_wait
+ ret
+/*mark the end for copy*/
+_poweroff16_end:
* good environment for main().
*
* Kernel is entered either because of kernel-calls, ipc-calls, interrupts or
- * exceptions. TSS is set so that the kernel stack is loaded. The user cotext is
+ * exceptions. TSS is set so that the kernel stack is loaded. The user context is
* saved to the proc table and the handler of the event is called. Once the
* handler is done, switch_to_user() function is called to pick a new process,
* finish what needs to be done for the next process to run, sets its context
#include "kernel/const.h"
#include "kernel/proc.h"
#include "sconst.h"
+#include "multiboot.h"
/* Selected 386 tss offsets. */
#define TSS3_S_SP0 4
*/
.short 0x03FD
nop /* extra byte to sync up disassembler */
-over_flags:
+
+/* Multiboot header here*/
+
+.balign 8
+
+multiboot_magic:
+ .long MULTIBOOT_HEADER_MAGIC
+multiboot_flags:
+ .long MULTIBOOT_FLAGS
+multiboot_checksum:
+ .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_FLAGS)
+multiboot_header_addr:
+ .long (MULTIBOOT_LOAD_ADDRESS + MULTIBOOT_ENTRY_OFFSET + multiboot_magic)
+multiboot_load_addr:
+ .long MULTIBOOT_LOAD_ADDRESS
+multiboot_load_end_addr:
+ .long 0
+multiboot_bss_end_addr:
+ .long 0
+multiboot_entry_addr:
+ .long (MULTIBOOT_LOAD_ADDRESS + MULTIBOOT_ENTRY_OFFSET + multiboot_init)
+/* Video mode */
+multiboot_mode_type:
+ .long MULTIBOOT_VIDEO_MODE_EGA
+multiboot_width:
+ .long MULTIBOOT_CONSOLE_COLS
+multiboot_height:
+ .long MULTIBOOT_CONSOLE_LINES
+multiboot_depth:
+ .long 0
+over_flags:
/* Set up a C stack frame on the monitor stack. (The monitor sets cs and ds */
/* right. The ss descriptor still references the monitor data segment.) */
movzwl %sp, %esp /* monitor stack is a 16 bit stack */
+
+.globl kernel_init
+kernel_init: /* after pre-init*/
push %ebp
mov %esp, %ebp
push %esi
.data
#endif
.short 0x526F /* this must be the first data entry (magic #) */
-
.bss
/*
* the kernel stack
--- /dev/null
+#include "kernel/kernel.h" /* configures the kernel */
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/com.h>
+#include <machine/interrupt.h>
+#include "archconst.h"
+#include "kernel/const.h"
+#include "kernel/proc.h"
+#include "sconst.h"
+#include "multiboot.h"
+
+#define GDT_SET_ENTRY(selector, base, limit) \
+ mov %ebp, %edi; \
+ add $(_gdt + selector), %edi; \
+ mov base, %eax; \
+ movw %ax, 2(%edi); \
+ shr $16, %eax; \
+ movb %al, 4(%edi); \
+ and $0xff00, %ax; \
+ andw $0xff, 6(%edi); \
+ or %ax, 6(%edi); \
+ mov limit, %eax; \
+ movw %ax, (%edi); \
+ shr $16, %eax; \
+ and $0xf, %ax; \
+ andb $0xf0, 6(%edi); \
+ or %ax, 6(%edi); \
+
+.globl _pre_init
+.globl multiboot_init
+.globl kernel_init
+
+multiboot_init:
+ /* Get size of kernel text */
+ mov MULTIBOOT_LOAD_ADDRESS + MULTIBOOT_KERNEL_a_text, %ecx
+
+ /* Get size of kernel text and ceil to 0x1000, and it's the offset
+ of data seg */
+ mov %ecx, %eax
+ dec %eax
+ and $0xfffff000, %eax
+ add $0x1000, %eax
+
+ /* Calculate and save kernel data base address */
+ mov $(MULTIBOOT_LOAD_ADDRESS + MULTIBOOT_ENTRY_OFFSET), %ebp
+ add %eax, %ebp
+ mov %ebp, _kernel_data_addr(%ebp)
+
+ /* Init text seg */
+ GDT_SET_ENTRY(CS_SELECTOR, \
+ $(MULTIBOOT_LOAD_ADDRESS + MULTIBOOT_ENTRY_OFFSET), \
+ %ecx)
+
+ /* Init data seg */
+ GDT_SET_ENTRY(DS_SELECTOR, \
+ %ebp, \
+ MULTIBOOT_LOAD_ADDRESS + MULTIBOOT_KERNEL_a_total)
+
+ /* Make up monitor data seg, the same value as DS, different entry */
+ GDT_SET_ENTRY(SS_SELECTOR, \
+ %ebp, \
+ MULTIBOOT_LOAD_ADDRESS + MULTIBOOT_KERNEL_a_total)
+
+ /* Make up monitor text seg, used to return to real mode when poweroff */
+ GDT_SET_ENTRY(MON_CS_SELECTOR, \
+ $BIOS_POWEROFF_ENTRY, \
+ $0xffff)
+
+ mov $(GDT_SIZE*DESC_SIZE), %eax
+ mov %ebp, %edi
+ add $(_gdt + GDT_SELECTOR), %edi
+ mov %ax, (%edi)
+ mov %ebp, %eax
+ add $_gdt, %eax
+ mov %eax, 2(%edi)
+ lgdt (%edi)
+
+ ljmp $(CS_SELECTOR), $reload_cs
+
+reload_cs:
+ mov $DS_SELECTOR, %eax
+ mov %eax, %ds
+ mov %eax, %ss
+ mov %eax, %es
+
+ mov $(multiboot_stack + MULTIBOOT_STACK_SIZE), %esp
+
+ push %ebx
+ call _pre_init
+
+ add $4, %esp
+
+ /* return to old boot code of kernel */
+ push %eax
+ push $MULTIBOOT_PARAM_BUF_SIZE
+ push $_multiboot_param_buf
+ push $0
+
+ mov $ES_SELECTOR, %eax
+ mov %eax, %es
+
+ jmp kernel_init
+
+.data
+.globl _kernel_data_addr
+_kernel_data_addr:
+.long 0
+.globl _a_out_headers
+_a_out_headers:
+.space NR_BOOT_PROCS * 32 /* is A_MINHDR */
+
+.globl _multiboot_param_buf
+_multiboot_param_buf:
+.space MULTIBOOT_PARAM_BUF_SIZE
+
+multiboot_stack:
+.space MULTIBOOT_STACK_SIZE + 4
--- /dev/null
+#ifndef __MULTIBOOT_H__
+#define __MULTIBOOT_H__
+
+#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
+
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
+
+/* Must pass memory information to OS. */
+#define MULTIBOOT_MEMORY_INFO 0x00000002
+
+#define MULTIBOOT_VIDEO_MODE 0x00000004
+
+#define MULTIBOOT_AOUT_KLUDGE 0x00010000
+
+#define MULTIBOOT_FLAGS (MULTIBOOT_MEMORY_INFO | \
+ MULTIBOOT_VIDEO_MODE | \
+ MULTIBOOT_AOUT_KLUDGE)
+
+/* consts used for Multiboot pre-init */
+
+#define MULTIBOOT_ENTRY_OFFSET 0x200
+
+#define MULTIBOOT_LOAD_ADDRESS 0x200000-MULTIBOOT_ENTRY_OFFSET
+
+#define MULTIBOOT_VIDEO_MODE_EGA 1
+
+#define MULTIBOOT_VIDEO_BUFFER 0xB8000
+
+/* Usable lower memory chunk has a upper bound */
+#define MULTIBOOT_LOWER_MEM_MAX 0x7f800
+
+#define MULTIBOOT_CONSOLE_LINES 25
+#define MULTIBOOT_CONSOLE_COLS 80
+
+
+#define MULTIBOOT_STACK_SIZE 4096
+#define MULTIBOOT_PARAM_BUF_SIZE 1024
+
+#define MULTIBOOT_KERNEL_a_text 0x48
+#define MULTIBOOT_KERNEL_a_data (0x48+4)
+#define MULTIBOOT_KERNEL_a_total (0x48+16)
+
+/* Flags to be set in the ’flags’ member of the multiboot info structure. */
+
+#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
+
+/* get physical address by data pointer*/
+#define PTR2PHY(ptr) (kernel_data_addr+(u32_t)(ptr))
+
+/* get data pointer by physical address*/
+#define PHY2PTR(phy) ((char *)((u32_t)(phy)-kernel_data_addr))
+
+/* Get physical address by function pointer*/
+#define FUNC2PHY(fun) (MULTIBOOT_LOAD_ADDRESS + MULTIBOOT_ENTRY_OFFSET + (u32_t)(fun))
+
+#ifndef __ASSEMBLY__
+
+#include <minix/types.h>
+/* The symbol table for a.out. */
+struct multiboot_aout_symbol_table
+{
+ u32_t tabsize;
+ u32_t strsize;
+ u32_t addr;
+ u32_t reserved;
+};
+/* The section header table for ELF. */
+struct multiboot_elf_section_header_table
+{
+ u32_t num;
+ u32_t size;
+ u32_t addr;
+ u32_t shndx;
+};
+
+typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t;
+typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
+
+struct multiboot_info
+{
+ /* Multiboot info version number */
+ u32_t flags;
+ /* Available memory from BIOS */
+ u32_t mem_lower;
+ u32_t mem_upper;
+ /* "root" partition */
+ u32_t boot_device;
+ /* Kernel command line */
+ u32_t cmdline;
+ /* Boot-Module list */
+ u32_t mods_count;
+ u32_t mods_addr;
+ union
+ {
+ multiboot_aout_symbol_table_t aout_sym;
+ multiboot_elf_section_header_table_t elf_sec;
+ } u;
+ /* Memory Mapping buffer */
+ u32_t mmap_length;
+ u32_t mmap_addr;
+ /* Drive Info buffer */
+ u32_t drives_length;
+ u32_t drives_addr;
+ /* ROM configuration table */
+ u32_t config_table;
+ /* Boot Loader Name */
+ u32_t boot_loader_name;
+ /* APM table */
+ u32_t apm_table;
+ /* Video */
+ u32_t vbe_control_info;
+ u32_t vbe_mode_info;
+ u16_t vbe_mode;
+ u16_t vbe_interface_seg;
+ u16_t vbe_interface_off;
+ u16_t vbe_interface_len;
+};
+typedef struct multiboot_info multiboot_info_t;
+
+/* Buffer for multiboot parameters */
+extern char multiboot_param_buf[];
+
+/* Physical address of kernel data segment */
+extern phys_bytes kernel_data_addr;
+
+#endif /* __ASSEMBLY__ */
+#endif /* __MULTIBOOT_H__ */
--- /dev/null
+#include "kernel/kernel.h"
+#include <minix/minlib.h>
+#include <minix/const.h>
+/*
+ * == IMPORTANT ==
+ * Routines in this file can not use any variable in kernel BSS,
+ * since before image is extracted, no BSS is allocated.
+ * So pay attention to any external call (including library call).
+ *
+ * */
+#include <minix/types.h>
+#include <minix/type.h>
+#include <minix/com.h>
+#include <minix/a.out.h>
+#include <machine/partition.h>
+#include "../../../boot/image.h"
+#include "string.h"
+#include "proto.h"
+#include "multiboot.h"
+
+/* Granularity used in image file and copying */
+#define GRAN 512
+#define SECT_CEIL(x) ((((x) - 1) / GRAN + 1) * GRAN)
+
+/* String length used for mb_itoa */
+#define ITOA_BUFFER_SIZE 20
+
+/* The a.out headers to pass to kernel.
+ * Not using struct exec because only using short form */
+extern char a_out_headers[];
+
+#define mb_load_phymem(buf, phy, len) \
+ phys_copy((phy), PTR2PHY(buf), (len))
+
+#define mb_save_phymem(buf, phy, len) \
+ phys_copy(PTR2PHY(buf), (phy), (len))
+
+PRIVATE void mb_phys_move(u32_t src, u32_t dest, u32_t len)
+{
+ char data[GRAN + 1];
+ int i;
+ /* Move upward (start moving from tail), block by block
+ * len should be aligned to GRAN
+ */
+ if (len % GRAN) {
+ mb_print("fatal: not aligned phys move");
+ /* Spin here */
+ while (1)
+ ;
+ }
+
+ len /= GRAN;
+ for (i = len - 1; i >= 0; i--) {
+ mb_load_phymem(data, src + i * GRAN, GRAN);
+ mb_save_phymem(data, dest + i * GRAN, GRAN);
+ }
+}
+
+PRIVATE void mb_itoa(u32_t val, char * out)
+{
+ char ret[ITOA_BUFFER_SIZE];
+ int i = ITOA_BUFFER_SIZE - 2;
+ /* Although there's a library version of itoa(int n),
+ * we can't use it since that implementation relies on BSS segment
+ */
+ ret[ITOA_BUFFER_SIZE - 2] = '0';
+ if (val) {
+ for (; i >= 0; i--) {
+ char c;
+ if (val == 0) break;
+ c = val % 10;
+ val = val / 10;
+ c += '0';
+ ret[i] = c;
+ }
+ }
+ else
+ i--;
+ ret[ITOA_BUFFER_SIZE - 1] = 0;
+ strcpy(out, ret + i + 1);
+}
+
+PRIVATE void mb_itox(u32_t val, char *out)
+{
+ char ret[9];
+ int i = 7;
+ /* Convert a number to hex string */
+ ret[7] = '0';
+ if (val) {
+ for (; i >= 0; i--) {
+ char c;
+ if (val == 0) break;
+ c = val & 0xF;
+ val = val >> 4;
+ if (c > 9)
+ c += 'A' - 10;
+ else
+ c += '0';
+ ret[i] = c;
+ }
+ }
+ else
+ i--;
+ ret[8] = 0;
+ strcpy(out, ret + i + 1);
+}
+
+PRIVATE void mb_put_char(char c, int line, int col)
+{
+ /* Write a char to vga display buffer. */
+ if (line<MULTIBOOT_CONSOLE_LINES&&col<MULTIBOOT_CONSOLE_COLS)
+ mb_save_phymem(
+ &c,
+ MULTIBOOT_VIDEO_BUFFER
+ + line * MULTIBOOT_CONSOLE_COLS * 2
+ + col * 2,
+ 1);
+}
+
+PRIVATE char mb_get_char(int line, int col)
+{
+ char c;
+ /* Read a char to from display buffer. */
+ if (line < MULTIBOOT_CONSOLE_LINES && col < MULTIBOOT_CONSOLE_COLS)
+ mb_load_phymem(
+ &c,
+ MULTIBOOT_VIDEO_BUFFER
+ + line * MULTIBOOT_CONSOLE_COLS * 2
+ + col * 2,
+ 1);
+ return c;
+}
+
+/* Give non-zero values to avoid them in BSS */
+PRIVATE int print_line = 1, print_col = 1;
+
+PRIVATE void mb_cls(void)
+{
+ int i, j;
+ /* Clear screen */
+ for (i = 0; i < MULTIBOOT_CONSOLE_LINES; i++ )
+ for (j = 0; j < MULTIBOOT_CONSOLE_COLS; j++ )
+ mb_put_char(0, i, j);
+ print_line = print_col = 0;
+}
+
+PRIVATE void mb_scroll_up(int lines)
+{
+ int i, j;
+ for (i = 0; i < MULTIBOOT_CONSOLE_LINES - lines; i++ ) {
+ for (j = 0; j < MULTIBOOT_CONSOLE_COLS; j++ )
+ mb_put_char(mb_get_char(i + lines, j), i, j);
+ }
+ print_line-= lines;
+}
+
+PRIVATE void mb_print(char *str)
+{
+ while (*str) {
+ if (*str == '\n') {
+ str++;
+ print_line++;
+ print_col = 0;
+ continue;
+ }
+ mb_put_char(*str++, print_line, print_col++);
+ if (print_col >= MULTIBOOT_CONSOLE_COLS) {
+ print_line++;
+ print_col = 0;
+ }
+ while (print_line >= MULTIBOOT_CONSOLE_LINES)
+ mb_scroll_up(1);
+ }
+}
+
+PRIVATE void mb_print_hex(u32_t value)
+{
+ int i;
+ char c;
+ char out[9] = "00000000";
+ /* Print a hex value */
+ for (i = 7; i >= 0; i--) {
+ c = value % 0x10;
+ value /= 0x10;
+ if (c < 10)
+ c += '0';
+ else
+ c += 'A'-10;
+ out[i] = c;
+ }
+ mb_print(out);
+}
+
+PRIVATE int mb_set_param(char *name, char *value)
+{
+ char *p = multiboot_param_buf;
+ char *q;
+ int namelen = strlen(name);
+ int valuelen = strlen(value);
+
+ /* Delete the item if already exists */
+ while (*p) {
+ if (strncmp(p, name, namelen) == 0 && p[namelen] == '=') {
+ q = p;
+ while (*q) q++;
+ for (q++;
+ q < multiboot_param_buf + MULTIBOOT_PARAM_BUF_SIZE;
+ q++, p++)
+ *p = *q;
+ break;
+ }
+ while (*p++)
+ ;
+ p++;
+ }
+
+ for (p = multiboot_param_buf;
+ p < multiboot_param_buf + MULTIBOOT_PARAM_BUF_SIZE
+ && (*p || *(p + 1));
+ p++)
+ ;
+ if (p > multiboot_param_buf) p++;
+
+ /* Make sure there's enough space for the new parameter */
+ if (p + namelen + valuelen + 3
+ > multiboot_param_buf + MULTIBOOT_PARAM_BUF_SIZE)
+ return -1;
+
+ strcpy(p, name);
+ p[namelen] = '=';
+ strcpy(p + namelen + 1, value);
+ p[namelen + valuelen + 1] = 0;
+ p[namelen + valuelen + 2] = 0;
+ return 0;
+}
+
+PRIVATE void get_parameters(multiboot_info_t *mbi)
+{
+ char mem_value[40], temp[ITOA_BUFFER_SIZE];
+ int i, r, processor;
+ int dev;
+ int ctrlr;
+ int disk, prim, sub;
+ int var_i,value_i;
+ char *p;
+ const static int dev_cNd0[] = { 0x0300, 0x0800, 0x0A00, 0x0C00, 0x1000 };
+ static char mb_cmd_buff[GRAN] = "add some value to avoid me in BSS";
+ static char var[GRAN] = "add some value to avoid me in BSS";
+ static char value[GRAN] = "add some value to avoid me in BSS";
+ for (i = 0; i < MULTIBOOT_PARAM_BUF_SIZE; i++)
+ multiboot_param_buf[i] = 0;
+
+ if (mbi->flags & MULTIBOOT_INFO_BOOTDEV) {
+ sub = 0xff;
+ disk = ((mbi->boot_device&0xff000000) >> 24)-0x80;
+ prim = (mbi->boot_device&0xff0000) == 0xff0000 ?
+ 0 : (mbi->boot_device & 0xff0000) >> 16;
+ ctrlr = 0;
+ dev = dev_cNd0[ctrlr];
+ /* Determine the value of rootdev */
+ if ((mbi->boot_device & 0xff00) == 0xff00) {
+ dev += disk * (NR_PARTITIONS + 1) + (prim + 1);
+ } else {
+ sub = (mbi->boot_device & 0xff00) >> 8;
+ dev += 0x80
+ + (disk * NR_PARTITIONS + prim) * NR_PARTITIONS
+ + sub;
+ }
+ mb_itoa(dev, temp);
+ mb_set_param("rootdev", temp);
+ mb_set_param("ramimagedev", temp);
+ }
+ mb_set_param("ramsize", "0");
+ mb_set_param("hz", "60");
+ processor = getprocessor();
+ if (processor == 1586) processor = 686;
+ mb_itoa(processor, temp);
+ mb_set_param("processor", temp);
+ mb_set_param("bus", "at");
+ mb_set_param("video", "ega");
+ mb_set_param("chrome", "color");
+
+ if (mbi->flags & MULTIBOOT_INFO_MEMORY)
+ {
+ strcpy(mem_value, "800:");
+ mb_itox(
+ mbi->mem_lower * 1024 > MULTIBOOT_LOWER_MEM_MAX ?
+ MULTIBOOT_LOWER_MEM_MAX : mbi->mem_lower * 1024,
+ temp);
+ strcat(mem_value, temp);
+ strcat(mem_value, ",100000:");
+ mb_itox(mbi->mem_upper * 1024, temp);
+ strcat(mem_value, temp);
+ mb_set_param("memory", mem_value);
+ }
+
+ /* FIXME: this is dummy value,
+ * we can't get real image file name from multiboot */
+ mb_set_param("image", "boot/image_latest");
+
+ if (mbi->flags&MULTIBOOT_INFO_CMDLINE) {
+ /* Override values with cmdline argument */
+ p = mb_cmd_buff;
+ mb_load_phymem(mb_cmd_buff, mbi->cmdline, GRAN);
+ while (*p) {
+ var_i = 0;
+ value_i = 0;
+ while (*p == ' ') p++;
+ if (!*p) break;
+ while (*p && *p != '=' && var_i < GRAN - 1)
+ var[var_i++] = *p++ ;
+ var[var_i] = 0;
+ p++; /* skip '=' */
+ while (*p && *p != ' ' && value_i < GRAN - 1)
+ value[value_i++] = *p++ ;
+ value[value_i] = 0;
+
+ mb_set_param(var, value);
+ }
+ }
+}
+
+PRIVATE void mb_extract_image(void)
+{
+ int i;
+ u32_t text_addr[NR_BOOT_PROCS];
+ u32_t imghdr_addr = MULTIBOOT_LOAD_ADDRESS;
+ int off_sum = 0;
+ struct exec *aout_hdr;
+ int empty, clear_size, j;
+ u32_t p;
+ /* Extract the image to align segments and clear up BSS
+ */
+ for (i = 0; i < LAST_SPECIAL_PROC_NR + 2; i++) {
+ aout_hdr = (struct exec *) (a_out_headers + A_MINHDR * i);
+ mb_load_phymem(aout_hdr, imghdr_addr + IM_NAME_MAX + 1, A_MINHDR);
+ text_addr[i] = imghdr_addr + GRAN;
+ if (aout_hdr->a_flags & A_SEP) {
+ off_sum += CLICK_CEIL(aout_hdr->a_total)
+ - SECT_CEIL(aout_hdr->a_data)
+ + CLICK_CEIL(aout_hdr->a_text)
+ - SECT_CEIL(aout_hdr->a_text)
+ - GRAN;
+ imghdr_addr += SECT_CEIL(aout_hdr->a_text)
+ + SECT_CEIL(aout_hdr->a_data)
+ + GRAN;
+ } else {
+ off_sum += CLICK_CEIL(aout_hdr->a_total)
+ - SECT_CEIL(aout_hdr->a_data + aout_hdr->a_text)
+ - GRAN;
+ imghdr_addr += SECT_CEIL(aout_hdr->a_text + aout_hdr->a_data)
+ + GRAN;
+ }
+ }
+ for (i = LAST_SPECIAL_PROC_NR + 1; i >= 0;i--) {
+ struct exec * aout_hdr = (struct exec *) (a_out_headers + A_MINHDR * i);
+ if (aout_hdr->a_flags & A_SEP)
+ off_sum -= CLICK_CEIL(aout_hdr->a_total)
+ - SECT_CEIL(aout_hdr->a_data)
+ + CLICK_CEIL(aout_hdr->a_text)
+ - SECT_CEIL(aout_hdr->a_text)
+ - GRAN;
+ else
+ off_sum -= CLICK_CEIL(aout_hdr->a_total)
+ - SECT_CEIL(aout_hdr->a_data + aout_hdr->a_text)
+ - GRAN;
+ if (i > 0) { /* if not kernel */
+ if (aout_hdr->a_flags & A_SEP) {
+ mb_phys_move(text_addr[i], text_addr[i] + off_sum,
+ SECT_CEIL(aout_hdr->a_text));
+ mb_phys_move(text_addr[i] + SECT_CEIL(aout_hdr->a_text),
+ text_addr[i] + off_sum + CLICK_CEIL(aout_hdr->a_text),
+ SECT_CEIL(aout_hdr->a_data));
+ } else {
+ mb_phys_move(text_addr[i], text_addr[i] + off_sum,
+ SECT_CEIL(aout_hdr->a_text + aout_hdr->a_data));
+ }
+ }
+ aout_hdr->a_syms = text_addr[i] + off_sum;
+
+ /* Clear out for expanded text, BSS and stack */
+ empty = 0;
+ if (aout_hdr->a_flags & A_SEP) {
+ p = text_addr[i] + off_sum
+ + CLICK_CEIL(aout_hdr->a_text)
+ + aout_hdr->a_data;
+ clear_size = CLICK_CEIL(aout_hdr->a_total) - aout_hdr->a_data;
+ } else {
+ p = text_addr[i] + off_sum
+ + aout_hdr->a_text
+ + aout_hdr->a_data;
+ clear_size = CLICK_CEIL(aout_hdr->a_total)
+ - aout_hdr->a_data
+ - aout_hdr->a_text;
+ }
+ /* FIXME: use faster function */
+ for (j = 0; j < clear_size; j++)
+ mb_save_phymem(&empty, p + j, 1);
+ }
+}
+
+PUBLIC u32_t pre_init(u32_t ebx)
+{
+ multiboot_info_t mbi;
+ /* Do pre-initialization for multiboot, returning physical address of
+ * a_out_headers
+ */
+ mb_cls();
+ mb_print("\nMINIX booting... ");
+ mb_load_phymem(&mbi, ebx, sizeof(mbi));
+ get_parameters(&mbi);
+ mb_print("\nLoading image... ");
+ mb_extract_image();
+ return PTR2PHY(a_out_headers);
+}
u16_t offset_high;
};
-PUBLIC struct segdesc_s gdt[GDT_SIZE]; /* used in klib.s and mpx.s */
+PUBLIC struct segdesc_s gdt[GDT_SIZE]= /* used in klib.s and mpx.s */
+{ {0},
+ {0,0,0,0}, /* GDT descriptor */
+ {0,0,0,0}, /* IDT descriptor */
+ {0xffff,0,0,0x92,0x4f,0}, /* kernel DS */
+ {0xffff,0,0,0x92,0xcf,0}, /* kernel ES (386: flag 4 Gb at startup) */
+ {0xffff,0,0,0x92,0x4f,0}, /* kernel SS (386: monitor SS at startup) */
+ {0xffff,0,0,0x9a,0x4f,0}, /* kernel CS */
+ {0xffff,0,0,0x9a,0x0f,0}, /* temp for BIOS (386: monitor CS at startup) */
+};
PRIVATE struct gatedesc_s idt[IDT_SIZE]; /* zero-init so none present */
PUBLIC struct tss_s tss; /* zero init */
_PROTOTYPE( void ser_putc, (char) );
_PROTOTYPE( __dead void arch_shutdown, (int) );
_PROTOTYPE( __dead void arch_monitor, (void) );
+_PROTOTYPE( void arch_bios_poweroff, (void) );
_PROTOTYPE( void arch_get_aout_headers, (int i, struct exec *h) );
_PROTOTYPE( void restore_user_context, (struct proc * p) );
_PROTOTYPE( void read_tsc, (unsigned long *high, unsigned long *low) );
MDEC= /usr/mdec
# Specify the programs that are part of the system image.
-PROGRAMS= ../kernel/kernel \
+PROGRAMS= kernel \
../servers/ds/ds \
../servers/rs/rs \
../servers/pm/pm \
all: services image
+# for fast complie kernel and generate image, skip servers and drivers
+image_mb: includes
+ cd ../kernel && $(MAKE)
+ padtext ../kernel/kernel kernel
+ installboot -image $@ $(PROGRAMS)
+
image: includes services
+ cd ../kernel && $(MAKE)
+ cd ../servers && $(MAKE) all
+ cd ../drivers && $(MAKE) all
+ padtext ../kernel/kernel kernel
installboot -image $@ $(PROGRAMS)
# rebuild the program or system libraries
$(MAKE) -C ../kernel $@
$(MAKE) -C ../servers $@
$(MAKE) -C ../drivers $@
- rm -rf *.bak image *.iso *.iso.gz cdfdimage rootimage src
+ rm -rf *.bak image kernel *.iso *.iso.gz cdfdimage rootimage src
cleandepend::
$(MAKE) -C ../kernel $@
echo "install image $root:/boot/image/$target"
install -o root -m 600 image $rootdir/boot/image/$target || exit
+ # Tell GRUB which image is newest
+ image_latest="`ls -t $rootdir/boot/image | head -n 1`"
+ if [ -f "$rootdir/boot/image/$image_latest" ]
+ then image_latest="/boot/image/$image_latest"
+ else image_latest=/boot/image_big
+ fi
+ ln -f $image_latest $rootdir/boot/image_latest
+
# Save the revision number.
test "$revision" != "$oldrev" && echo $revision >revision