add an example Multiboot kernel.

This commit is contained in:
okuji 1999-10-16 10:30:43 +00:00
parent 0263e922f1
commit ec2469fa84
11 changed files with 1053 additions and 12 deletions

View file

@ -1,3 +1,23 @@
1999-10-16 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
* docs/multiboot.texi: Include the example source files of a
Multiboot kernel.
* docs/src2texi: New file.
* docs/boot.S: Likewise.
* docs/multiboot.h: Likewise.
* docs/kernel.c: Likewise.
* docs/boot.S.texi: Likewise.
* docs/multiboot.h.texi: Likewise.
* docs/kernel.c.texi: Likewise.
* docs/Makefile.am (EXAMPLES): New varilable.
(multiboot_TEXINFOS): Likewise.
(SRC2TEXI): Likewise.
(noinst_SCRIPTS): Added $(SRC2TEXI).
(EXTRA_DIST): Added $(EXAMPLES) and $(multiboot_TEXINFOS).
(%.c.texi): New target.
(%.h.texi): Likewise.
(%.S.texi): Likewise.
1999-09-22 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp> 1999-09-22 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
* multiboot.texi (BIOS device mapping techniques): New section. * multiboot.texi (BIOS device mapping techniques): New section.

View file

@ -1,9 +1,22 @@
info_TEXINFOS = grub.texi multiboot.texi info_TEXINFOS = grub.texi multiboot.texi
EXAMPLES = boot.S kernel.c multiboot.h
multiboot_TEXINFOS = boot.S.texi kernel.c.texi multiboot.h.texi
man_MANS = grub.8 man_MANS = grub.8
HELP2MAN = help2man HELP2MAN = help2man
noinst_SCRIPTS = $(HELP2MAN) SRC2TEXI = src2texi
noinst_SCRIPTS = $(HELP2MAN) $(SRC2TEXI)
EXTRA_DIST = menu.lst $(man_MANS) $(noinst_SCRIPTS) EXTRA_DIST = menu.lst $(man_MANS) $(noinst_SCRIPTS) \
$(EXAMPLES) $(multiboot_TEXINFOS)
%.c.texi: %.c $(srcdir)/$(SRC2TEXI)
/bin/sh $(srcdir)/$(SRC2TEXI) $(srcdir) $< $@
%.h.texi: %.h $(srcdir)/$(SRC2TEXI)
/bin/sh $(srcdir)/$(SRC2TEXI) $(srcdir) $< $@
%.S.texi: %.S $(srcdir)/$(SRC2TEXI)
/bin/sh $(srcdir)/$(SRC2TEXI) $(srcdir) $< $@
# FIXME: Use this rule until Debian has the new Texinfo. # FIXME: Use this rule until Debian has the new Texinfo.
grub.info: grub.texi grub.info: grub.texi

View file

@ -83,11 +83,16 @@ install_sh = @install_sh@
info_TEXINFOS = grub.texi multiboot.texi info_TEXINFOS = grub.texi multiboot.texi
EXAMPLES = boot.S kernel.c multiboot.h
multiboot_TEXINFOS = boot.S.texi kernel.c.texi multiboot.h.texi
man_MANS = grub.8 man_MANS = grub.8
HELP2MAN = help2man HELP2MAN = help2man
noinst_SCRIPTS = $(HELP2MAN) SRC2TEXI = src2texi
noinst_SCRIPTS = $(HELP2MAN) $(SRC2TEXI)
EXTRA_DIST = menu.lst $(man_MANS) $(noinst_SCRIPTS) \
$(EXAMPLES) $(multiboot_TEXINFOS)
EXTRA_DIST = menu.lst $(man_MANS) $(noinst_SCRIPTS)
subdir = docs subdir = docs
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../config.h CONFIG_HEADER = ../config.h
@ -103,8 +108,8 @@ man8dir = $(mandir)/man8
MANS = $(man_MANS) MANS = $(man_MANS)
NROFF = nroff NROFF = nroff
DIST_COMMON = Makefile.am Makefile.in mdate-sh stamp-vti texinfo.tex \ DIST_COMMON = $(multiboot_TEXINFOS) Makefile.am Makefile.in mdate-sh \
version.texi stamp-vti texinfo.tex version.texi
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@ -148,8 +153,8 @@ grub.info: grub.texi version.texi
grub.dvi: grub.texi version.texi grub.dvi: grub.texi version.texi
multiboot.info: multiboot.texi multiboot.info: multiboot.texi $(multiboot_TEXINFOS)
multiboot.dvi: multiboot.texi multiboot.dvi: multiboot.texi $(multiboot_TEXINFOS)
DVIPS = dvips DVIPS = dvips
@ -402,6 +407,15 @@ distclean-generic clean-generic maintainer-clean-generic clean \
mostlyclean distclean maintainer-clean mostlyclean distclean maintainer-clean
%.c.texi: %.c $(srcdir)/$(SRC2TEXI)
/bin/sh $(srcdir)/$(SRC2TEXI) $(srcdir) $< $@
%.h.texi: %.h $(srcdir)/$(SRC2TEXI)
/bin/sh $(srcdir)/$(SRC2TEXI) $(srcdir) $< $@
%.S.texi: %.S $(srcdir)/$(SRC2TEXI)
/bin/sh $(srcdir)/$(SRC2TEXI) $(srcdir) $< $@
# FIXME: Use this rule until Debian has the new Texinfo. # FIXME: Use this rule until Debian has the new Texinfo.
grub.info: grub.texi grub.info: grub.texi
@cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9] @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9]

80
docs/boot.S Normal file
View file

@ -0,0 +1,80 @@
/* boot.S - bootstrap the kernel */
/* Copyright (C) 1999 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define ASM 1
#include <multiboot.h>
.text
.globl start, _start
/* This entry is not used actually. */
start:
_start:
jmp multiboot_entry
/* Align 32 bits boundary. */
.align 4
/* Multiboot header. */
multiboot_header:
/* magic */
.long MULTIBOOT_HEADER_MAGIC
/* flags */
.long MULTIBOOT_HEADER_FLAGS
/* checksum */
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
/* header_addr */
.long multiboot_header
/* load_addr */
.long _start
/* load_end_addr */
.long _edata
/* bss_end_addr */
.long _end
/* entry_addr */
.long multiboot_entry
multiboot_entry:
/* Initialize the stack pointer. */
movl $(stack + STACK_SIZE), %esp
/* Reset EFLAGS. */
pushl $0
popf
/* Push the pointer to the Multiboot information structure. */
pushl %ebx
/* Push the magic value. */
pushl %eax
/* Now enter the C main function... */
call EXT_C(cmain)
/* Halt. */
pushl $halt_message
call EXT_C(printf)
loop: hlt
jmp loop
halt_message:
.asciz "Halted."
/* Our stack area. */
.comm stack, STACK_SIZE

80
docs/boot.S.texi Normal file
View file

@ -0,0 +1,80 @@
/* @r{boot.S - bootstrap the kernel} */
/* @r{Copyright (C) 1999 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.} */
#define ASM 1
#include <multiboot.h>
.text
.globl start, _start
/* @r{This entry is not used actually.} */
start:
_start:
jmp multiboot_entry
/* @r{Align 32 bits boundary.} */
.align 4
/* @r{Multiboot header.} */
multiboot_header:
/* @r{magic} */
.long MULTIBOOT_HEADER_MAGIC
/* @r{flags} */
.long MULTIBOOT_HEADER_FLAGS
/* @r{checksum} */
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
/* @r{header_addr} */
.long multiboot_header
/* @r{load_addr} */
.long _start
/* @r{load_end_addr} */
.long _edata
/* @r{bss_end_addr} */
.long _end
/* @r{entry_addr} */
.long multiboot_entry
multiboot_entry:
/* @r{Initialize the stack pointer.} */
movl $(stack + STACK_SIZE), %esp
/* @r{Reset EFLAGS.} */
pushl $0
popf
/* @r{Push the pointer to the Multiboot information structure.} */
pushl %ebx
/* @r{Push the magic value.} */
pushl %eax
/* @r{Now enter the C main function...} */
call EXT_C(cmain)
/* @r{Halt.} */
pushl $halt_message
call EXT_C(printf)
loop: hlt
jmp loop
halt_message:
.asciz "Halted."
/* @r{Our stack area.} */
.comm stack, STACK_SIZE

274
docs/kernel.c Normal file
View file

@ -0,0 +1,274 @@
/* kernel.c - the C part of the kernel */
/* Copyright (C) 1999 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <multiboot.h>
/* Macros. */
/* Check if the bit BIT in FLAGS is set. */
#define CHECK_FLAG(flags,bit) ((flags) & (1 << (bit)))
/* Some screen stuff. */
/* The number of columns. */
#define COLUMNS 80
/* The number of lines. */
#define LINES 24
/* The attribute of an character. */
#define ATTRIBUTE 7
/* The video memory address. */
#define VIDEO 0xB8000
/* Variables. */
/* Save the X position. */
static int xpos;
/* Save the Y position. */
static int ypos;
/* Point to the video memory. */
static volatile unsigned char *video;
/* Forward declarations. */
void cmain (unsigned long magic, unsigned long addr);
static void cls (void);
static void itoa (char *buf, int base, int d);
static void putchar (int c);
void printf (const char *format, ...);
/* Check if MAGIC is valid and print the Multiboot information structure
pointed by ADDR. */
void
cmain (unsigned long magic, unsigned long addr)
{
multiboot_info_t *mbi;
/* Clear the screen. */
cls ();
/* Am I booted by a Multiboot-compliant boot loader? */
if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
{
printf ("Invalid magic number: 0x%x\n", magic);
return;
}
/* Set MBI to the address of the Multiboot information structure. */
mbi = (multiboot_info_t *) addr;
/* Print out the flags. */
printf ("flags = 0x%x\n", mbi->flags);
/* Are mem_* valid? */
if (CHECK_FLAG (mbi->flags, 0))
printf ("mem_lower = %dKB, mem_upper = %dKB\n",
mbi->mem_lower, mbi->mem_upper);
/* Is boot_device valid? */
if (CHECK_FLAG (mbi->flags, 1))
printf ("boot_device = 0x%x\n", mbi->boot_device);
/* Is the command line passed? */
if (CHECK_FLAG (mbi->flags, 2))
printf ("cmdline = %s\n", (char *) mbi->cmdline);
/* Are mods_* valid? */
if (CHECK_FLAG (mbi->flags, 3))
{
module_t *mod;
int i;
printf ("mods_count = %d, mods_addr = 0x%x\n",
mbi->mods_count, mbi->mods_addr);
for (i = 0, mod = (module_t *) mbi->mods_addr;
i < mbi->mods_count;
i++, mod += sizeof (module_t))
printf (" mod_start = 0x%x, mod_end = 0x%x, string = %s\n",
mod->mod_start, mod->mod_end, (char *) mod->string);
}
/* Bits 4 and 5 are mutually exclusive! */
if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG (mbi->flags, 5))
{
printf ("Both bits 4 and 5 are set.\n");
return;
}
/* Is the symbol table of a.out valid? */
if (CHECK_FLAG (mbi->flags, 4))
{
aout_symbol_table_t *aout_sym = &(mbi->u.aout_sym);
printf ("aout_symbol_table: tabsize = 0x%0x, "
"strsize = 0x%x, addr = 0x%x\n",
aout_sym->tabsize, aout_sym->strsize, aout_sym->addr);
}
/* Is the section header table of ELF valid? */
if (CHECK_FLAG (mbi->flags, 5))
{
elf_section_header_table_t *elf_sec = &(mbi->u.elf_sec);
printf ("elf_sec: num = %d, size = 0x%x, addr = 0x%x, shndx = 0x%x\n",
elf_sec->num, elf_sec->size, elf_sec->addr, elf_sec->shndx);
}
/* Are mmap_* valid? */
if (CHECK_FLAG (mbi->flags, 6))
{
memory_map_t *mmap;
printf ("mmap_addr = 0x%x, mmap_length = 0x%x\n",
mbi->mmap_addr, mbi->mmap_length);
for (mmap = (memory_map_t *) mbi->mmap_addr;
(unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length;
mmap = (memory_map_t *) ((unsigned long) mmap
+ mmap->size + sizeof (mmap->size)))
printf (" size = 0x%x, base_addr = 0x%x%x,"
" length = 0x%x%x, type = 0x%x\n",
mmap->size, mmap->base_addr_high, mmap->base_addr_low,
mmap->length_high, mmap->length_low, mmap->type);
}
}
/* Clear the screen and initialize VIDEO, XPOS and YPOS. */
static void
cls (void)
{
int i;
video = (unsigned char *) VIDEO;
for (i = 0; i < COLUMNS * LINES * 2; i++)
*(video + i) = 0;
xpos = 0;
ypos = 0;
}
/* Convert the integer D to a string and save the string in BUF. If
BASE is equal to 'd', interpret that D is decimal, and if BASE is
equal to 'x', interpret that D is hexadecimal. */
static void
itoa (char *buf, int base, int d)
{
char *p = buf;
char *p1, *p2;
unsigned long ud = d;
int divisor = 10;
/* If %d is specified and D is minus, put `-' in the head. */
if (base == 'd' && d < 0)
{
*p++ = '-';
buf++;
ud = -d;
}
else if (base == 'x')
divisor = 16;
/* Divide UD by DIVISOR until UD == 0. */
do
{
int remainder = ud % divisor;
*p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;
}
while (ud /= divisor);
/* Terminate BUF. */
*p = 0;
/* Reverse BUF. */
p1 = buf;
p2 = p - 1;
while (p1 < p2)
{
char tmp = *p1;
*p1 = *p2;
*p2 = tmp;
p1++;
p2--;
}
}
/* Put the character C on the screen. */
static void
putchar (int c)
{
if (c == '\n' || c == '\r')
{
newline:
xpos = 0;
ypos++;
if (ypos >= LINES)
ypos = 0;
return;
}
*(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF;
*(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE;
xpos++;
if (xpos >= COLUMNS)
goto newline;
}
/* Format a string and print it on the screen, just like the libc
function printf. */
void
printf (const char *format, ...)
{
char **arg = (char **) &format;
int c;
char buf[20];
arg++;
while ((c = *format++) != 0)
{
if (c != '%')
putchar (c);
else
{
char *p;
c = *format++;
switch (c)
{
case 'd':
case 'u':
case 'x':
itoa (buf, c, *((int *) arg++));
p = buf;
goto string;
break;
case 's':
p = *arg++;
if (! p)
p = "(null)";
string:
while (*p)
putchar (*p++);
break;
default:
putchar (*((int *) arg++));
break;
}
}
}
}

274
docs/kernel.c.texi Normal file
View file

@ -0,0 +1,274 @@
/* @r{kernel.c - the C part of the kernel} */
/* @r{Copyright (C) 1999 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.} */
#include <multiboot.h>
/* @r{Macros.} */
/* @r{Check if the bit BIT in FLAGS is set.} */
#define CHECK_FLAG(flags,bit) ((flags) & (1 << (bit)))
/* @r{Some screen stuff.} */
/* @r{The number of columns.} */
#define COLUMNS 80
/* @r{The number of lines.} */
#define LINES 24
/* @r{The attribute of an character.} */
#define ATTRIBUTE 7
/* @r{The video memory address.} */
#define VIDEO 0xB8000
/* @r{Variables.} */
/* @r{Save the X position.} */
static int xpos;
/* @r{Save the Y position.} */
static int ypos;
/* @r{Point to the video memory.} */
static volatile unsigned char *video;
/* @r{Forward declarations.} */
void cmain (unsigned long magic, unsigned long addr);
static void cls (void);
static void itoa (char *buf, int base, int d);
static void putchar (int c);
void printf (const char *format, ...);
/* @r{Check if MAGIC is valid and print the Multiboot information structure
pointed by ADDR.} */
void
cmain (unsigned long magic, unsigned long addr)
@{
multiboot_info_t *mbi;
/* @r{Clear the screen.} */
cls ();
/* @r{Am I booted by a Multiboot-compliant boot loader?} */
if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
@{
printf ("Invalid magic number: 0x%x\n", magic);
return;
@}
/* @r{Set MBI to the address of the Multiboot information structure.} */
mbi = (multiboot_info_t *) addr;
/* @r{Print out the flags.} */
printf ("flags = 0x%x\n", mbi->flags);
/* @r{Are mem_* valid?} */
if (CHECK_FLAG (mbi->flags, 0))
printf ("mem_lower = %dKB, mem_upper = %dKB\n",
mbi->mem_lower, mbi->mem_upper);
/* @r{Is boot_device valid?} */
if (CHECK_FLAG (mbi->flags, 1))
printf ("boot_device = 0x%x\n", mbi->boot_device);
/* @r{Is the command line passed?} */
if (CHECK_FLAG (mbi->flags, 2))
printf ("cmdline = %s\n", (char *) mbi->cmdline);
/* @r{Are mods_* valid?} */
if (CHECK_FLAG (mbi->flags, 3))
@{
module_t *mod;
int i;
printf ("mods_count = %d, mods_addr = 0x%x\n",
mbi->mods_count, mbi->mods_addr);
for (i = 0, mod = (module_t *) mbi->mods_addr;
i < mbi->mods_count;
i++, mod += sizeof (module_t))
printf (" mod_start = 0x%x, mod_end = 0x%x, string = %s\n",
mod->mod_start, mod->mod_end, (char *) mod->string);
@}
/* @r{Bits 4 and 5 are mutually exclusive!} */
if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG (mbi->flags, 5))
@{
printf ("Both bits 4 and 5 are set.\n");
return;
@}
/* @r{Is the symbol table of a.out valid?} */
if (CHECK_FLAG (mbi->flags, 4))
@{
aout_symbol_table_t *aout_sym = &(mbi->u.aout_sym);
printf ("aout_symbol_table: tabsize = 0x%0x, "
"strsize = 0x%x, addr = 0x%x\n",
aout_sym->tabsize, aout_sym->strsize, aout_sym->addr);
@}
/* @r{Is the section header table of ELF valid?} */
if (CHECK_FLAG (mbi->flags, 5))
@{
elf_section_header_table_t *elf_sec = &(mbi->u.elf_sec);
printf ("elf_sec: num = %d, size = 0x%x, addr = 0x%x, shndx = 0x%x\n",
elf_sec->num, elf_sec->size, elf_sec->addr, elf_sec->shndx);
@}
/* @r{Are mmap_* valid?} */
if (CHECK_FLAG (mbi->flags, 6))
@{
memory_map_t *mmap;
printf ("mmap_addr = 0x%x, mmap_length = 0x%x\n",
mbi->mmap_addr, mbi->mmap_length);
for (mmap = (memory_map_t *) mbi->mmap_addr;
(unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length;
mmap = (memory_map_t *) ((unsigned long) mmap
+ mmap->size + sizeof (mmap->size)))
printf (" size = 0x%x, base_addr = 0x%x%x,"
" length = 0x%x%x, type = 0x%x\n",
mmap->size, mmap->base_addr_high, mmap->base_addr_low,
mmap->length_high, mmap->length_low, mmap->type);
@}
@}
/* @r{Clear the screen and initialize VIDEO, XPOS and YPOS.} */
static void
cls (void)
@{
int i;
video = (unsigned char *) VIDEO;
for (i = 0; i < COLUMNS * LINES * 2; i++)
*(video + i) = 0;
xpos = 0;
ypos = 0;
@}
/* @r{Convert the integer D to a string and save the string in BUF. If
BASE is equal to 'd', interpret that D is decimal, and if BASE is
equal to 'x', interpret that D is hexadecimal.} */
static void
itoa (char *buf, int base, int d)
@{
char *p = buf;
char *p1, *p2;
unsigned long ud = d;
int divisor = 10;
/* @r{If %d is specified and D is minus, put `-' in the head.} */
if (base == 'd' && d < 0)
@{
*p++ = '-';
buf++;
ud = -d;
@}
else if (base == 'x')
divisor = 16;
/* @r{Divide UD by DIVISOR until UD == 0.} */
do
@{
int remainder = ud % divisor;
*p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;
@}
while (ud /= divisor);
/* @r{Terminate BUF.} */
*p = 0;
/* @r{Reverse BUF.} */
p1 = buf;
p2 = p - 1;
while (p1 < p2)
@{
char tmp = *p1;
*p1 = *p2;
*p2 = tmp;
p1++;
p2--;
@}
@}
/* @r{Put the character C on the screen.} */
static void
putchar (int c)
@{
if (c == '\n' || c == '\r')
@{
newline:
xpos = 0;
ypos++;
if (ypos >= LINES)
ypos = 0;
return;
@}
*(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF;
*(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE;
xpos++;
if (xpos >= COLUMNS)
goto newline;
@}
/* @r{Format a string and print it on the screen, just like the libc
function printf.} */
void
printf (const char *format, ...)
@{
char **arg = (char **) &format;
int c;
char buf[20];
arg++;
while ((c = *format++) != 0)
@{
if (c != '%')
putchar (c);
else
@{
char *p;
c = *format++;
switch (c)
@{
case 'd':
case 'u':
case 'x':
itoa (buf, c, *((int *) arg++));
p = buf;
goto string;
break;
case 's':
p = *arg++;
if (! p)
p = "(null)";
string:
while (*p)
putchar (*p++);
break;
default:
putchar (*((int *) arg++));
break;
@}
@}
@}
@}

115
docs/multiboot.h Normal file
View file

@ -0,0 +1,115 @@
/* multiboot.h - the header for Multiboot */
/* Copyright (C) 1999 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Macros. */
/* The magic number for the Multiboot header. */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
/* The flags for the Multiboot header. */
#define MULTIBOOT_HEADER_FLAGS 0x00010003
/* The magic number passed by a Multiboot-compliant boot loader. */
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
/* The size of our stack (16KB). */
#define STACK_SIZE 0x4000
/* C symbol format. HAVE_ASM_USCORE is defined by configure. */
#ifdef HAVE_ASM_USCORE
# define EXT_C(sym) _ ## sym
#else
# define EXT_C(sym) sym
#endif
#ifndef ASM
/* Do not include here in boot.S. */
/* Types. */
/* The Multiboot header. */
typedef struct multiboot_header
{
unsigned long magic;
unsigned long flags;
unsigned long checksum;
unsigned long header_addr;
unsigned long load_addr;
unsigned long load_end_addr;
unsigned long bss_end_addr;
unsigned long entry_addr;
} multiboot_header_t;
/* The symbol table for a.out. */
typedef struct aout_symbol_table
{
unsigned long tabsize;
unsigned long strsize;
unsigned long addr;
unsigned long reserved;
} aout_symbol_table_t;
/* The section header table for ELF. */
typedef struct elf_section_header_table
{
unsigned long num;
unsigned long size;
unsigned long addr;
unsigned long shndx;
} elf_section_header_table_t;
/* The Multiboot information. */
typedef struct multiboot_info
{
unsigned long flags;
unsigned long mem_lower;
unsigned long mem_upper;
unsigned long boot_device;
unsigned long cmdline;
unsigned long mods_count;
unsigned long mods_addr;
union
{
aout_symbol_table_t aout_sym;
elf_section_header_table_t elf_sec;
} u;
unsigned long mmap_length;
unsigned long mmap_addr;
} multiboot_info_t;
/* The module structure. */
typedef struct module
{
unsigned long mod_start;
unsigned long mod_end;
unsigned long string;
unsigned long reserved;
} module_t;
/* The memory map. Be careful that the offset 0 is base_addr_low
but no size. */
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;
#endif /* ! ASM */

115
docs/multiboot.h.texi Normal file
View file

@ -0,0 +1,115 @@
/* @r{multiboot.h - the header for Multiboot} */
/* @r{Copyright (C) 1999 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.} */
/* @r{Macros.} */
/* @r{The magic number for the Multiboot header.} */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
/* @r{The flags for the Multiboot header.} */
#define MULTIBOOT_HEADER_FLAGS 0x00010003
/* @r{The magic number passed by a Multiboot-compliant boot loader.} */
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
/* @r{The size of our stack (16KB).} */
#define STACK_SIZE 0x4000
/* @r{C symbol format. HAVE_ASM_USCORE is defined by configure.} */
#ifdef HAVE_ASM_USCORE
# define EXT_C(sym) _ ## sym
#else
# define EXT_C(sym) sym
#endif
#ifndef ASM
/* @r{Do not include here in boot.S.} */
/* @r{Types.} */
/* @r{The Multiboot header.} */
typedef struct multiboot_header
@{
unsigned long magic;
unsigned long flags;
unsigned long checksum;
unsigned long header_addr;
unsigned long load_addr;
unsigned long load_end_addr;
unsigned long bss_end_addr;
unsigned long entry_addr;
@} multiboot_header_t;
/* @r{The symbol table for a.out.} */
typedef struct aout_symbol_table
@{
unsigned long tabsize;
unsigned long strsize;
unsigned long addr;
unsigned long reserved;
@} aout_symbol_table_t;
/* @r{The section header table for ELF.} */
typedef struct elf_section_header_table
@{
unsigned long num;
unsigned long size;
unsigned long addr;
unsigned long shndx;
@} elf_section_header_table_t;
/* @r{The Multiboot information.} */
typedef struct multiboot_info
@{
unsigned long flags;
unsigned long mem_lower;
unsigned long mem_upper;
unsigned long boot_device;
unsigned long cmdline;
unsigned long mods_count;
unsigned long mods_addr;
union
@{
aout_symbol_table_t aout_sym;
elf_section_header_table_t elf_sec;
@} u;
unsigned long mmap_length;
unsigned long mmap_addr;
@} multiboot_info_t;
/* @r{The module structure.} */
typedef struct module
@{
unsigned long mod_start;
unsigned long mod_end;
unsigned long string;
unsigned long reserved;
@} module_t;
/* @r{The memory map. Be careful that the offset 0 is base_addr_low
but no size.} */
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;
#endif /* @r{! ASM} */

View file

@ -865,9 +865,8 @@ In this distribution, the example Multiboot kernel @file{kernel} is
included. The kernel just prints out the Multiboot information structure included. The kernel just prints out the Multiboot information structure
on the screen, so you can make use of the kernel to test a on the screen, so you can make use of the kernel to test a
Multiboot-compliant boot loader and for reference to how to implement a Multiboot-compliant boot loader and for reference to how to implement a
Multiboot kernel. The image and the source files can be found in the Multiboot kernel. The source files can be found under the directory
data directory (usually, @file{/usr/share/multiboot} or @file{docs} in the GRUB distribution.
@file{/usr/local/share/multiboot}).
The kernel @file{kernel} consists of only three files: @file{boot.S}, The kernel @file{kernel} consists of only three files: @file{boot.S},
@file{kernel.c} and @file{multiboot.h}. The assembly source @file{kernel.c} and @file{multiboot.h}. The assembly source
@ -883,7 +882,48 @@ which checks if the magic number passed by the boot loader is valid and
so on, and some functions to print messages on the screen. The file so on, and some functions to print messages on the screen. The file
@file{multiboot.h} defines some macros, such as the magic number for the @file{multiboot.h} defines some macros, such as the magic number for the
Multiboot header, the Multiboot header structure and the Multiboot Multiboot header, the Multiboot header structure and the Multiboot
information structure. See the source files for more information. information structure.
@menu
* multiboot.h::
* boot.S::
* kernel.c::
* Other Multiboot kernels::
@end menu
@node multiboot.h
@subsection multiboot.h
This is the source code in the file @file{multiboot.h}:
@example
@include multiboot.h.texi
@end example
@node boot.S
@subsection boot.S
In the file @file{boot.S}:
@example
@include boot.S.texi
@end example
@node kernel.c
@subsection kernel.c
And, in the file @file{kernel.c}:
@example
@include kernel.c.texi
@end example
@node Other Multiboot kernels
@subsection Other Multiboot kernels
Other useful information should be available in Multiboot kernels, such Other useful information should be available in Multiboot kernels, such
as GNU Mach and Fiasco @url{http://os.inf.tu-dresden.de/fiasco/}. And, as GNU Mach and Fiasco @url{http://os.inf.tu-dresden.de/fiasco/}. And,

16
docs/src2texi Normal file
View file

@ -0,0 +1,16 @@
#!/bin/sh
#
# Convert a source file to a TeXinfo file. Stolen from glibc.
#
# Usage: src2texi SRCDIR SRC TEXI
dir=$1
src=`basename $2`
texi=`basename $3`
sed -e 's,[{}],@&,g' \
-e 's,/\*\(@.*\)\*/,\1,g' \
-e 's,/\* *,/* @r{,g' -e 's, *\*/,} */,' \
-e 's/\(@[a-z][a-z]*\)@{\([^}]*\)@}/\1{\2}/g' \
${dir}/${src} | expand > ${texi}.new
mv -f ${texi}.new ${dir}/${texi}