Multiboot support (contributed by Feiran "Fam" Zheng);

keep in mind that GRUB needs to be patched to read MFS for now;
use /boot/image_latest to boot the last compiled image in GRUB
This commit is contained in:
Erik van der Kouwe 2010-07-23 14:24:34 +00:00
parent 9212eab21f
commit df0ba02a38
13 changed files with 904 additions and 8 deletions

View file

@ -1,3 +1,4 @@
# Makefile for arch-dependent kernel code
.include <bsd.own.mk>
@ -20,10 +21,19 @@ SRCS+= arch_do_vmctl.c \
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}

View file

@ -22,6 +22,7 @@
#include "oxpcie.h"
#include "kernel/proc.h"
#include "kernel/debug.h"
#include "multiboot.h"
#ifdef CONFIG_APIC
#include "apic.h"
@ -29,6 +30,9 @@
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
@ -44,6 +48,22 @@ PUBLIC __dead void arch_monitor(void)
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)
@ -107,7 +127,10 @@ 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.

View file

@ -153,4 +153,7 @@
/* 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 */

View file

@ -4,9 +4,11 @@
#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
@ -908,3 +910,54 @@ _switch_address_space:
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

78
kernel/arch/i386/klib16.S Normal file
View file

@ -0,0 +1,78 @@
/* 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:

View file

@ -6,7 +6,7 @@
* 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
@ -52,6 +52,7 @@ begbss:
#include "kernel/const.h"
#include "kernel/proc.h"
#include "sconst.h"
#include "multiboot.h"
/* Selected 386 tss offsets. */
#define TSS3_S_SP0 4
@ -133,11 +134,44 @@ flags:
*/
.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
@ -658,7 +692,6 @@ _reload_cr3:
.data
#endif
.short 0x526F /* this must be the first data entry (magic #) */
.bss
/*
* the kernel stack

View file

@ -0,0 +1,117 @@
#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

View file

@ -0,0 +1,136 @@
#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__ */

415
kernel/arch/i386/pre_init.c Normal file
View file

@ -0,0 +1,415 @@
#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);
}

View file

@ -25,7 +25,16 @@ struct gatedesc_s {
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 */

View file

@ -171,6 +171,7 @@ _PROTOTYPE( void arch_init, (void) );
_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) );

View file

@ -4,7 +4,7 @@ u=/usr
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 \
@ -42,7 +42,17 @@ usage:
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
@ -79,7 +89,7 @@ clean:
$(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 $@

View file

@ -109,6 +109,14 @@ hdboot)
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