Commit 5c80f197 authored by Mathieu Maret's avatar Mathieu Maret

Initial import

parents
SOS: A Simple Operating System
Compilation/Installation/Test instructions
Compilation
===========
IMPORTANT
---------
Don't forget to run 'make clean' before 'make' after you have modified
any source or header file(s).
On a x86 host where grub is correctly installed
-----------------------------------------------
Simply run 'make'
On a non-x86 host (without grub of course !)
--------------------------------------------
See extra/README
On an x86 host without Grub, or with a buggy Grub
-------------------------------------------------
See extra/README
How do I know I have a buggy grub installation ? Answer: in the qemu
PC emulator, Grub hangs while loading the kernel
Installation
============
Nothing special to do besides compiling
Test the SOS Kernel
===================
On a x86 real machine with Grub installed
-----------------------------------------
1st method
=> Boot the sos.elf file (append 'kernel=<path_to>sos.elf' in the
menu.lst or type it on Grub's command line) from a hard disk, a
floppy, or from the network
2nd method
=> Copy the file 'fd.img' to a floppy and boot from it
On a x86 real machine without Grub installed
--------------------------------------------
1st method
=> see extra/README to compile with the grub floppy image we provide,
copy the file 'fd.img' to a floppy, and boot from it
2nd method
=> see extra/README to compile with the boot sector we provide (up to
article 2 only), copy the file 'extra/sos_bsect.img' to a floppy,
and boot from it
Inside a PC emulator (x86 and non-x86 hosts)
--------------------------------------------
Tested on both the bochs emulator (x86/linux, sparc/solaris and
ppc/linux hosts, 'apt-get install bochs-x vgabios' on debian
testing/unstable), and the qemu system emulator (with libsdl
installed: 'apt-get install libsdl1.2-dev' on debian
testing/unstable).
1/ Grub is installed on the host (x86 hosts only)
- - - - - - - - - - - - - - - - - - - - - - - - -
bochs: boot from the file 'fd.img'. Example of a ~/.bochsrc:
floppya: 1_44=/home/d2/sos/fd.img, status=inserted
romimage: file=/usr/share/bochs/BIOS-bochs-latest, address=0xf0000
vgaromimage: /usr/share/vgabios/vgabios.bin
megs:63 # 63 Mo de RAM
qemu: run 'qemu -fda fd.img'
If grub hangs while loading the kernel, please go to method 2/
2/ Grub is not installed (all hosts)
- - - - - - - - - - - - - - - - - -
See extra/README to generate a floppy image with the Grub floppy
image we provide, and:
bochs: boot from the file 'fd.img'
qemu: run 'qemu -fda fd.img'
3/ Bonus: boot with the bootsector we provide (all hosts, up to art. 2 ONLY !)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
See extra/README to generate a floppy image with the boot sector we
provide, and:
bochs: boot from the file 'extra/sos_bsect.img'
qemu: run 'qemu -fda extra/sos_qemu.img'
NOTE: After article 2, this way of booting is not supported: please
use the method 2/ above.
--
David Decotigny
This diff is collapsed.
CC=gcc
CFLAGS = -Wall -nostdlib -nostdinc -ffreestanding -DKERNEL_SOS
LDFLAGS = --warn-common
OBJECTS = bootstrap/multiboot.o \
hwcore/idt.o hwcore/gdt.o \
hwcore/exception.o hwcore/exception_wrappers.o \
hwcore/irq.o hwcore/irq_wrappers.o hwcore/i8259.o \
hwcore/i8254.o drivers/x86_videomem.o drivers/bochs.o \
sos/klibc.o sos/main.o
KERNEL_OBJ = sos.elf
MULTIBOOT_IMAGE = fd.img
PWD := $(shell pwd)
# Main target
all: $(MULTIBOOT_IMAGE)
$(MULTIBOOT_IMAGE): $(KERNEL_OBJ)
./support/build_image.sh $@ $<
$(KERNEL_OBJ): $(OBJECTS) ./support/sos.lds
$(LD) $(LDFLAGS) -T ./support/sos.lds -o $@ $(OBJECTS)
-nm -C $@ | cut -d ' ' -f 1,3 > sos.map
-include .mkvars
# Create objects from C source code
%.o: %.c
$(CC) -I$(PWD) -c $< $(CFLAGS) -o $@
# Create objects from assembler (.S) source code
%.o: %.S
$(CC) -I$(PWD) -c $< $(CFLAGS) -DASM_SOURCE=1 -o $@
# Clean directory
clean:
$(RM) *.img *.o mtoolsrc *~ menu.txt *.img *.elf *.bin *.map
$(RM) *.log *.out bochs*
$(RM) bootstrap/*.o bootstrap/*~
$(RM) drivers/*.o drivers/*~
$(RM) hwcore/*.o hwcore/*~
$(RM) sos/*.o sos/*~
$(RM) support/*~
$(RM) extra/*~
SOS: A Simple Operating System
This is SOS, a Simple Operating System for i386-family
processors. This is as simple as possible to show a way to program a
basic Operating System on real common hardware (PC). The code should
be easily readable and understandable thanks to frequent comments, and
references to external documentation. We chose to implement the basic
features of an OS, thus making design decisions targetting towards
simplicity of understanding, covering most of the OS classical
concepts, but not aiming at proposing yet another full-fledged
competitive OS (Linux is quite good at it). However, for those who
would like to propose some enhancements, we are open to any code
suggestions (patches only, please). And yes, there might be bugs in
the code, so please send us any bug report, and/or patches !
The OS comes as a set of articles (in french) to be published in the
journal "Linux Magazine France". Each month, the part of the code
related to the current article's theme is released (see VERSION file),
and the resulting OS can be successfully compiled and run, by booting
it from a floppy on a real machine (tested AMD k7, Cyrix and Intel P4
pentiums), or through an x86 emulator (bochs or qemu). The resulting
OS is available as a multiboot compliant ELF kernel (sos.elf) and as a
floppy image (fd.img). It provides a very very very basic demo whose
aim is to understand how everything works, not to animate sprites on
the screen with 5:1 dolby sound.
The initial technical features and lack-of-features of the OS are:
- monolithic kernel, fully interruptible, non-preemptible (big kernel
lock), target machines = i386 PC or better
- compiles on any host where the gcc/binutils toolchain (target
i586-gnu) is available. Can be tested on real i486/pentium
hardware, or on any host that can run an i486/pentium PC emulator
(bochs or qemu)
- kernel loaded by grub, or by a sample bootsector (up to article 2
ONLY)
- clear separation of physical memory and virtual memory concepts,
even inside the kernel: no identity-mapping of the physical memory
inside the kernel (allows to move virtual mappings of kernel pages
at run-time, eg to free ISA DMA pages, and to avercome the 4G RAM
barrier)
- slab-type kernel memory allocation
- no swap, no reverse mapping
- VERY simple drivers: keyboard, x86 video memory, IDE disks
- logical devices: partitions, FAT filesystem, "hard-coded"
mountpoints only (~ MSDOS)
- no network stack
- user-level features: ELF loader (no shared libraries), processes,
user threads (kernel-level scheduling only), mmap API, basic VFS
To understand where to look at for what, here is a brief description:
- Makefile: the (ONLY) makefile of the OS. Targets are basically
'all' and 'clean'
- bootstrap/ directory: code to load the kernel. Both the stuff
needed for a multiboot-compliant loader (eg grub) AND a bootsector
are provided. The bootsector may only be used up to article 2.
- sos/ directory: the entry routine for the kernel (main.c), various
systemwide header files, a set of common useful C routines
("nano-klibc"), and kernel subsystems (kernel memory management,
etc...)
- hwcore/ directory: Low-level CPU- and kernel-related routines
(interrupt/exception management, translation tables and segment
registers, ...)
- drivers/ directory: basic kernel drivers for various (non CPU)
devices (keyboard, x86 video memory, bochs 0xe9 port, ...). Used
mainly for debugging
- support/ directory: scripts and configuration files to build the
floppy images
- extra/ directory: a set of configuration files to be customized for
non-x86 host installations (yes, we primarily develop SOS on a ppc, for
the x86 target of course), or for grub-less installations. See
README file in this directory.
The code is licensed under the terms of the GNU GPL version 2 (see
LICENSE file).
Enjoy !
David Decotigny, Thomas Petazzoni, the Kos team
http://sos.enix.org/
http://david.decotigny.free.fr/
http://kos.enix.org/~thomas/
http://kos.enix.org/
--
David Decotigny
PS: Made with a Mac.
SOS -- Simple OS
Copyright (C) 2003,2004 The SOS Team (David Decotigny & Thomas Petazzoni)
Version "Article 2" -- Basic interrupt & processor exception management
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.
See the LICENSE file included in the distribution.
/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.
*/
/* The operating system is booted by Grub, so we almost have nothing
to do to boot it. We only have to conform to the Multiboot
standard, as defined by the Grub documentation */
#define ASM 1
/* The multiboot.h header contains a lot of multiboot standard
definitions */
#include "multiboot.h"
/* The multiboot header itself. It must come first. */
.section ".multiboot"
/* Multiboot header must be aligned on a 4-byte boundary */
.align 4
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 __b_kernel
/* load_end_addr=*/ .long __e_load
/* bss_end_addr= */ .long __e_kernel
/* entry_addr= */ .long multiboot_entry
/* Here is the beginning of the code of our operating system */
.text
.globl start, _start
start:
_start:
multiboot_entry:
/* Set up a stack */
movl $(stack + MULTIBOOT_STACK_SIZE), %ebp
movl %ebp, %esp
/* Set EFLAGS to 0 */
pushl $0
/* pop stack into the EFLAGS register */
popf
/* Push the magic and the address on the stack, so that they
will be the parameters of the cmain function */
pushl %ebx
pushl %eax
/* Call the cmain function (os.c) */
call EXT_C(sos_main)
/* Should never get there */
loop:
hlt
jmp loop
/* Here is the stack */
.comm stack, MULTIBOOT_STACK_SIZE
#ifndef __MULTIBOOT_H__
#define __MULTIBOOT_H__
/* 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 MULTIBOOT_STACK_SIZE 0x4000
#define MULTIBOOT_CMDLINE 4
#define MULTIBOOT_MODS 8
/* 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;
unsigned long drives_length;
unsigned long drives_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;
void dump_multiboot_info(multiboot_info_t *mbi);
#endif /* ! ASM */
#endif /* __MULTIBOOT_H__ */
/* Copyright (C) 2004 David Decotigny
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.
*/
#include <hwcore/ioports.h>
#include <sos/klibc.h>
#include "bochs.h"
/* This is a special hack that is only useful when running the
operating system under the Bochs emulator. */
#define SOS_BOCHS_IOPORT 0xe9
sos_ret_t sos_bochs_setup(void)
{
return SOS_OK;
}
#define sos_bochs_putchar(chr) \
outb((chr), SOS_BOCHS_IOPORT)
sos_ret_t sos_bochs_putstring(const char* str)
{
for ( ; str && (*str != '\0') ; str++)
sos_bochs_putchar(*str);
return SOS_OK;
}
sos_ret_t sos_bochs_puthex(unsigned val, int nbytes)
{
unsigned c;
#define BOCHS_PRTHEX(q) \
({ unsigned char r; if ((q) >= 10) r='a'+(q)-10; \
else r='0'+(q); sos_bochs_putchar(r); })
switch (nbytes)
{
case 4:
c = (val >> 24) & 0xff;
BOCHS_PRTHEX((c >> 4)&0xf);
BOCHS_PRTHEX(c&0xf);
case 3:
c = (val >> 16) & 0xff;
BOCHS_PRTHEX((c >> 4)&0xf);
BOCHS_PRTHEX(c&0xf);
case 2:
c = (val >> 8) & 0xff;
BOCHS_PRTHEX((c >> 4)&0xf);
BOCHS_PRTHEX(c&0xf);
case 1:
c = val & 0xff;
BOCHS_PRTHEX((c >> 4)&0xf);
BOCHS_PRTHEX(c&0xf);
}
return SOS_OK;
}
sos_ret_t sos_bochs_hexdump(const void* addr, int nbytes)
{
int offs;
for (offs = 0 ; offs < nbytes ; offs++)
{
const unsigned char *c;
if ((offs % 16) == 0)
{
sos_bochs_putstring("0x");
sos_bochs_puthex(offs, 4);
}
if ((offs % 8) == 0)
sos_bochs_putstring(" ");
c = (const unsigned char*)(addr + offs);
sos_bochs_puthex(*c, 1);
sos_bochs_putstring(" ");
if (((offs + 1) % 16) == 0)
sos_bochs_putstring("\n");
}
if (offs % 16)
sos_bochs_putstring("\n");
return SOS_OK;
}
sos_ret_t sos_bochs_printf(const char *format, /* args */...)
{
char buff[256];
va_list ap;
va_start(ap, format);
vsnprintf(buff, sizeof(buff), format, ap);
va_end(ap);
return sos_bochs_putstring(buff);
}
/* Copyright (C) 2004 David Decotigny
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.
*/
#ifndef _SOS_BOCHS_H_
#define _SOS_BOCHS_H_
/**
* @file bochs.h
*
* If you compiled Bochs with the --enable-e9-hack, then any character
* printed to the 0xE9 I/O port is printed to the xterm that is
* running Bochs. This may appear to be a detail, but in fact, this
* functionnality is *VERY* precious for debugging purposes. This
* """driver""" handles this feature.
*/
#include <sos/errno.h>
#include <sos/types.h>
sos_ret_t sos_bochs_setup(void);
sos_ret_t sos_bochs_putstring(const char* str);
/** Print the least signficant 32 (nbytes == 4), 24 (nbytes == 3), 16
(nbytes == 2) or 8 (nbytes == 1) bits of val in hexadecimal. */
sos_ret_t sos_bochs_puthex(unsigned val, int nbytes);
/** hexdump-style pretty printing */
sos_ret_t sos_bochs_hexdump(const void* addr, int nbytes);
/**
* Print the formatted string. Very restricted version of printf(3):
* 1/ can print max 255 chars, 2/ supports only %d/%i, %c, %s, %x
* without any support for flag charachters (eg %08x).
*/
sos_ret_t sos_bochs_printf(const char *format, /* args */...)
__attribute__ ((format (printf, 1, 2)));
#endif
/* Copyright (C) 2004 David Decotigny
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.
*/
#include <sos/klibc.h>
#include <hwcore/ioports.h>
#include "x86_videomem.h"
/* The text video memory starts at address 0xB8000. Odd bytes are the
ASCII value of the character, even bytes are attribute for the
preceding character. */
#define VIDEO 0xb8000
/* Console screen size */
#define LINES 25
#define COLUMNS 80
/** The structure of a character element in the video memory. @see
http://webster.cs.ucr.edu/AoA DOS edition chapter 23 */
typedef struct {
unsigned char character;
unsigned char attribute;
} __attribute__ ((packed)) x86_video_mem[LINES*COLUMNS];
/** The base pointer for the video memory */
static volatile x86_video_mem *video = (volatile x86_video_mem*)VIDEO;
sos_ret_t sos_x86_videomem_setup(void)
{
/*
* Hide cursor. @see Ralf Brown's interrupt (and port) list
* http://www-2.cs.cmu.edu/~ralf/files.html
*/
#define CRT_REG_INDEX 0x3d4
#define CRT_REG_DATA 0x3d5
/* CRT index port => ask for access to register 0xa ("cursor
start") */
outb(0x0a, CRT_REG_INDEX);
/* (RBIL Tables 708 & 654) CRT Register 0xa => bit 5 = cursor OFF */
outb(1 << 5, CRT_REG_DATA);
return SOS_OK;
}
sos_ret_t sos_x86_videomem_cls(unsigned char attribute)
{
/* Clears the screen */
int i;
for(i = 0 ; i < LINES*COLUMNS ; i++)
{
(*video)[i].character = 0;
(*video)[i].attribute = attribute;
}
return SOS_OK;
}
sos_ret_t sos_x86_videomem_putstring(unsigned char row, unsigned char col,
unsigned char attribute,
const char *str)
{
unsigned video_offs = row*COLUMNS + col;
if (video_offs >= LINES*COLUMNS)
return -SOS_EINVAL;
for ( ; str && *str && (video_offs < LINES*COLUMNS) ; str++, video_offs++)
{
(*video)[video_offs].character = (unsigned char)*str;
(*video)[video_offs].attribute = attribute;
}
return SOS_OK;
}
sos_ret_t sos_x86_videomem_putchar(unsigned char row, unsigned char col,
unsigned char attribute,
unsigned char c)
{
unsigned video_offs = row*COLUMNS + col;
if