add setup/boot code
This commit is contained in:
254
Makefile
Executable file
254
Makefile
Executable file
@ -0,0 +1,254 @@
|
|||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# M A K E F I L E
|
||||||
|
#
|
||||||
|
# zum HHUos der Lehrveranstaltung 'Betriebssystem-Entwicklung'.
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Compilieren: ‘make'
|
||||||
|
# Ausfuehren mit Qemu: ‘make qemu’
|
||||||
|
# GDB mit Qemu: ‘make qemu-gdb &’ und danach ‘make gdb’
|
||||||
|
# DDD mit Qemu: ‘make qemu-gdb &’ und danach ‘make ddd’
|
||||||
|
#
|
||||||
|
# Aufraeumen mit: ‘make clean’
|
||||||
|
#
|
||||||
|
# Achtung: Erzeugen von bootfaehigen Medien erfordert das Anpassen folgender
|
||||||
|
# Variablen: DRIVE_FD und DRIVE_HD. Aufpassen, ansonsten wir evt.
|
||||||
|
# die System-Disk zerstoert.
|
||||||
|
#
|
||||||
|
# Erzeugen einer bootfaehigen Diskette mit: ‘make bootdisk’
|
||||||
|
# Erzeugen eines bootfaehigen USB-Sticks mit: ‘make bootdisk-usb’
|
||||||
|
# Erzeugen eines bootfaehigen Festplatte mit: ‘make bootdisk-hd’
|
||||||
|
#
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Autor: Olaf Spinzcyk, TU Dortmund
|
||||||
|
#
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Liste der Quelltexte:
|
||||||
|
|
||||||
|
STARTUP_SOURCE = ./startup.asm
|
||||||
|
CC_SOURCES = $(shell find . -name "*.cc")
|
||||||
|
C_SOURCES = $(shell find . -name "*.c")
|
||||||
|
ASM_SOURCES = $(shell find ./kernel -name "*.asm")
|
||||||
|
|
||||||
|
# Einstellungen in Abhaengigkeit vom Generierungssystem:
|
||||||
|
#
|
||||||
|
# ASMOBJFORMAT: Ausgabeformat fuer den Assembler. Das Format muss dem
|
||||||
|
# jeweiligen Format des verwendeten C++ Compilers angepasst
|
||||||
|
# werde, damit gemischte Objektdateien gelinkt werden koennen.
|
||||||
|
# OBJDIR: Verzeichnis, in dem die Objektdateien abgelegt werden
|
||||||
|
# sollen.
|
||||||
|
# DEPDIR: Verzeichnis, in dem die Abhaengigkeitsdateien abgelegt werden
|
||||||
|
# sollen
|
||||||
|
# DRIVE_FD: Diskettenlaufwerk, auf das das System-Image geschrieben wird
|
||||||
|
# (Target: bootdisk)
|
||||||
|
# DRIVE_HD: Festplatten-/USB-Device, auf das das System-Image
|
||||||
|
# geschrieben wird (Target: bootdisk-hd)
|
||||||
|
# DELETE: Name des Kommandos zum Loeschen von Dateien
|
||||||
|
# ASM: Zu benutzender Assembler
|
||||||
|
# CC/CXX: Zu benutzender C/C++-Compiler
|
||||||
|
# CFLAGS: Flags fuer den C-Compileraufruf
|
||||||
|
# CXXFLAGS: Flags fuer den C++-Compileraufruf
|
||||||
|
# LD: Zu benutzender Linker
|
||||||
|
# LDFLAGS: Flags fuer den Linkeraufruf
|
||||||
|
# LDLIBS: Dazuzulinkende Bibliotheken
|
||||||
|
# LDHEAD: Am Anfang zu linkende Dateien
|
||||||
|
# LDTAIL: Am Ende zu linkende Dateien
|
||||||
|
# BOOT: Das Verzeichnis zu Bootsektor und Setup-Code
|
||||||
|
# TOOLS: Das Verzeichnis mit dem Build-Tool
|
||||||
|
|
||||||
|
VERBOSE = @
|
||||||
|
ASMOBJFORMAT = elf
|
||||||
|
OBJDIR = ./build
|
||||||
|
DEPDIR = ./dep
|
||||||
|
DRIVE_FD = /dev/sdb
|
||||||
|
# ACHTUNG: ein falsch angegebenes Laufwerk kann dazu fuehren, dass Daten auf dem
|
||||||
|
# spezifizierten Laufwerk verloren gehen! Nicht mit root-Rechten ausfuehren!
|
||||||
|
DRIVE_HD = /dev/sdb
|
||||||
|
DELETE = rm
|
||||||
|
ASM = nasm
|
||||||
|
CC ?= gcc
|
||||||
|
CXX ?= g++
|
||||||
|
CFLAGS := $(CFLAGS) -m32 -march=i486 -Wall -fno-stack-protector -nostdlib -I. -g -ffreestanding -fno-pie -fno-pic -mpreferred-stack-boundary=2 -Wno-write-strings -mno-sse -mno-sse2 -mmanual-endbr
|
||||||
|
CXXFLAGS := $(CFLAGS) -Wno-non-virtual-dtor -fno-threadsafe-statics -fno-use-cxa-atexit -fno-rtti -fno-exceptions
|
||||||
|
|
||||||
|
BOOT = ../c_boot
|
||||||
|
TOOLS = ../c_tools
|
||||||
|
# BIOS-dev.code:total-tracks:-heads:-sectors:start-track:-head:-sector
|
||||||
|
# Default-Werte fuer Boot von Floppy (USB/HD erkennt bootsect.asm selbst):
|
||||||
|
BOOTDEVICE = 0:80:2:18:0:0:1
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
# Namen der Unterverzeichnisse mit den Quelltexten
|
||||||
|
|
||||||
|
VPATH = $(sort $(dir $(STARTUP_SOURCE) $(CC_SOURCES) $(C_SOURCES) $(ASM_SOURCES)))
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
# Listen mit den Objektdateien, die beim Kompilieren entstehen:
|
||||||
|
|
||||||
|
FIRST_OBJECT = $(addprefix $(OBJDIR)/,$(patsubst %.asm,_%.o, $(notdir $(STARTUP_SOURCE))))
|
||||||
|
C_OBJECTS = $(notdir $(C_SOURCES:.c=.o))
|
||||||
|
CC_OBJECTS = $(notdir $(CC_SOURCES:.cc=.o))
|
||||||
|
|
||||||
|
DEP_FILES = $(patsubst %.o,$(DEPDIR)/%.d,$(C_OBJECTS))
|
||||||
|
DEP_FILES += $(patsubst %.o,$(DEPDIR)/%.d,$(CC_OBJECTS))
|
||||||
|
|
||||||
|
ASM_OBJECTS = $(patsubst %.asm,_%.o, $(notdir $(ASM_SOURCES)))
|
||||||
|
OBJPRE = $(addprefix $(OBJDIR)/,$(ASM_OBJECTS) $(C_OBJECTS) $(CC_OBJECTS))
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Default targets (einfaches Image, Image fuer USB Sticks, Image fuer VMWare
|
||||||
|
# und Boot CDs)
|
||||||
|
|
||||||
|
all: $(OBJDIR)/bootdisk.img $(OBJDIR)/bootdisk.vmi $(OBJDIR)/bootdisk-hd.vmi
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Regeln zur Erzeugung der Abhaengigkeitsdateien
|
||||||
|
|
||||||
|
$(DEPDIR)/%.d : %.c
|
||||||
|
@echo "DEP $@"
|
||||||
|
@if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi
|
||||||
|
$(VERBOSE) $(CC) $(CFLAGS) -MM -MT $(OBJDIR)/$*.o -MF $@ $<
|
||||||
|
|
||||||
|
$(DEPDIR)/%.d : %.cc
|
||||||
|
@echo "DEP $@"
|
||||||
|
@if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi
|
||||||
|
$(VERBOSE) $(CXX) $(CXXFLAGS) -MM -MT $(OBJDIR)/$*.o -MF $@ $<
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Regeln zur Erzeugung der Objektdateien
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o : %.c
|
||||||
|
@echo "CC $@"
|
||||||
|
@if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi
|
||||||
|
$(VERBOSE) $(CC) -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o : %.cc
|
||||||
|
@echo "CXX $@"
|
||||||
|
@if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi
|
||||||
|
$(VERBOSE) $(CXX) -c $(CXXFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/_%.o : %.asm
|
||||||
|
@echo "ASM $@"
|
||||||
|
@if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi
|
||||||
|
$(VERBOSE) $(ASM) -f $(ASMOBJFORMAT) -o $@ $<
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Gelinktes System
|
||||||
|
|
||||||
|
$(OBJDIR)/system: $(FIRST_OBJECT) $(OBJPRE)
|
||||||
|
@echo "LD $@"
|
||||||
|
@if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi
|
||||||
|
$(VERBOSE) $(CXX) $(CXXFLAGS) -static -e startup -T sections -o $(OBJDIR)/system $(FIRST_OBJECT) $(OBJPRE)
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# 'system.img' enthaelt die zu ladenden Sections des eigentlichen Systems
|
||||||
|
|
||||||
|
$(OBJDIR)/system.img : $(OBJDIR)/system
|
||||||
|
@echo "OBJCOPY $@"
|
||||||
|
@if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi
|
||||||
|
$(VERBOSE) objcopy -O binary $< $@
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# 'bootdisk.img' besteht aus dem 'system.img', das um den (parametrisierten)
|
||||||
|
# Bootblock und den Setup-Code erweitert wurde.
|
||||||
|
|
||||||
|
$(OBJDIR)/bootdisk.img : $(OBJDIR)/system.img $(TOOLS)/build $(BOOT)/bootsect $(BOOT)/setup
|
||||||
|
@echo "BUILD $@"
|
||||||
|
@if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi
|
||||||
|
$(VERBOSE) $(TOOLS)/build $(BOOT)/bootsect $(BOOT)/setup $< $(BOOTDEVICE) $@
|
||||||
|
|
||||||
|
# 'bootdisk.vmi' ist eine bootdisk, die auf 1.44 MB mit 0 aufgefuellt ist,
|
||||||
|
# damit VMware damit klarkommt. Des weiteren wird dieses Image benoetigt, um
|
||||||
|
# bootfaehige CDs zu erstellen.
|
||||||
|
# bootdisk-hd.img wird auf etwa 1M mit 0 aufgefuellt, da qemu diese Groesse
|
||||||
|
# auf eine Festplatten-Laufwerkscharakteristik zurueckrechnen kann.
|
||||||
|
|
||||||
|
$(OBJDIR)/bootdisk.vmi: $(OBJDIR)/bootdisk.img
|
||||||
|
dd if=$< of=$@ bs=1474560 conv=sync
|
||||||
|
|
||||||
|
$(OBJDIR)/bootdisk-hd.vmi: $(OBJDIR)/bootdisk.img
|
||||||
|
dd if=$< of=$@ bs=$$((2016*512)) conv=sync
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# 'clean' loescht das generierte System, die Objektdateien und die
|
||||||
|
# Abhaengigkeitsdateien
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo "RM $(OBJDIR)"
|
||||||
|
$(VERBOSE) rm -rf $(OBJDIR)
|
||||||
|
@echo "RM $(DEPDIR)"
|
||||||
|
$(VERBOSE) rm -rf $(DEPDIR)
|
||||||
|
$(MAKE) -C $(BOOT) clean
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# 'bootdisk' erzeugt zunaechst das System, falls das noch nicht geschehen ist.
|
||||||
|
# Danach wird eine Bootdiskette mit dem System erzeugt.
|
||||||
|
|
||||||
|
bootdisk: $(OBJDIR)/bootdisk.img
|
||||||
|
@echo "CP $<"
|
||||||
|
$(VERBOSE) cp $< $(DRIVE_FD)
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# 'bootdisk-hd' erzeugt zunaechst das System, falls das noch nicht geschehen
|
||||||
|
# ist. Danach wird das System auf das spezifizierte Laufwerk geschrieben,
|
||||||
|
# welches sowohl eine Festplatte, als auch ein USB-Stick sein kann.
|
||||||
|
# ACHTUNG: ein falsch angegebenes Laufwerk kann dazu fuehren, dass Daten auf dem
|
||||||
|
# spezifizierten Laufwerk verloren gehen! Nicht mit root-Rechten ausfuehren!
|
||||||
|
|
||||||
|
bootdisk-usb: bootdisk-hd
|
||||||
|
bootdisk-hd: $(OBJDIR)/bootdisk.img
|
||||||
|
@echo "CP $<"
|
||||||
|
$(VERBOSE) cp $< $(DRIVE_HD)
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# 'qemu' ruft den qemu-Emulator mit dem System auf.
|
||||||
|
|
||||||
|
qemu: $(OBJDIR)/bootdisk.vmi
|
||||||
|
qemu-system-i386 -fda $(OBJDIR)/bootdisk.vmi -boot a -k en-us -soundhw pcspk -vga std -cpu 486
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# 'qemu-gdb' ruft den qemu-Emulator mit aktiviertem GDB-Stub mit dem System
|
||||||
|
# auf, sodass es per GDB oder DDD inspiziert werden kann.
|
||||||
|
|
||||||
|
qemu-gdb: $(OBJDIR)/bootdisk.vmi
|
||||||
|
$(VERBOSE) echo "break main" > /tmp/gdbcommands.$(shell id -u)
|
||||||
|
$(VERBOSE) echo "target remote 127.0.0.1:1234" >> /tmp/gdbcommands.$(shell id -u)
|
||||||
|
$(VERBOSE) echo "continue" >> /tmp/gdbcommands.$(shell id -u)
|
||||||
|
qemu-system-i386 -fda $(OBJDIR)/bootdisk.vmi -boot a -k en-us -s -S -soundhw pcspk -vga std -cpu 486
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# 'gdb' startet den GDB-Debugger und verbindet sich mit dem GDB-Stub des vorher
|
||||||
|
# gestarteten Qemu.
|
||||||
|
|
||||||
|
gdb:
|
||||||
|
gdb -x /tmp/gdbcommands.$(shell id -u) $(OBJDIR)/system
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# 'ddd' startet den DDD-Debugger und verbindet sich mit dem GDB-Stub des vorher
|
||||||
|
# gestarteten Qemu.
|
||||||
|
|
||||||
|
ddd:
|
||||||
|
ddd --gdb -x /tmp/gdbcommands.$(shell id -u) $(OBJDIR)/system
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# 'build'-Tool kompilieren.
|
||||||
|
|
||||||
|
$(TOOLS)/build: $(TOOLS)/build.c
|
||||||
|
cd $(TOOLS) && $(CC) -o $@ $<
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Bootsektor und Protected-Mode-Setup-Code kompilieren.
|
||||||
|
|
||||||
|
$(BOOT)/bootsect $(BOOT)/setup: $(BOOT)/bootsect.asm $(BOOT)/setup.asm
|
||||||
|
$(MAKE) -C $(BOOT)
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Einbindung der Abhaengigkeitsdateien
|
||||||
|
|
||||||
|
ifneq ($(MAKECMDGOALS),clean)
|
||||||
|
-include $(DEP_FILES)
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: clean bootdisk bootdisk-hd bootdisk-usb gdb ddd
|
||||||
9
c_boot/Makefile
Executable file
9
c_boot/Makefile
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
# $Id: Makefile 956 2008-10-19 22:24:23Z hsc $
|
||||||
|
|
||||||
|
all: bootsect setup
|
||||||
|
|
||||||
|
% : %.asm
|
||||||
|
nasm -f bin $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *~ bootsect setup
|
||||||
BIN
c_boot/bootsect
Normal file
BIN
c_boot/bootsect
Normal file
Binary file not shown.
324
c_boot/bootsect.asm
Executable file
324
c_boot/bootsect.asm
Executable file
@ -0,0 +1,324 @@
|
|||||||
|
; $Id: bootsect.asm 5001 2012-10-12 11:34:05Z os $
|
||||||
|
|
||||||
|
;******************************************************************************
|
||||||
|
;* Betriebssysteme *
|
||||||
|
;*----------------------------------------------------------------------------*
|
||||||
|
;* *
|
||||||
|
;* B O O T S E C T *
|
||||||
|
;* *
|
||||||
|
;*----------------------------------------------------------------------------*
|
||||||
|
;* Code fuer den Disketten-Bootblock des System-Images. Das BIOS laedt den *
|
||||||
|
;* ersten Block einer Diskette (den Bootblock) beim Starten des Rechner in *
|
||||||
|
;* den Hauptspeicher und fuehrt ihn aus. Der Programmcode des Bootblocks *
|
||||||
|
;* laedt nun das restliche System und fuehrt es aus. *
|
||||||
|
;******************************************************************************
|
||||||
|
|
||||||
|
;
|
||||||
|
; Konstanten
|
||||||
|
;
|
||||||
|
BIOSSEG equ 0x07c0 ; Hierher wird der Bootsector
|
||||||
|
; vom BIOS geladen
|
||||||
|
BOOTSEG equ 0x0060 ; Hierher verschiebt sich der
|
||||||
|
; Boot-Code
|
||||||
|
SETUPSEG equ 0x9000 ; Hierher laedt der Boot-Code den
|
||||||
|
; Setup-Code (max. 64K inkl. Stack)
|
||||||
|
SYSTEMSEG equ 0x1000 ; System-Code (max. 512K)
|
||||||
|
SECTORSZ equ 512 ; Groesse eines Sektors in Bytes
|
||||||
|
|
||||||
|
[SECTION .text]
|
||||||
|
|
||||||
|
;
|
||||||
|
; Boot-Code
|
||||||
|
;
|
||||||
|
bootsector:
|
||||||
|
jmp skip_data
|
||||||
|
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; Datenbereich, der von 'build' beim Erzeugen der Boot-Diskette
|
||||||
|
; gefuellt wird.
|
||||||
|
;
|
||||||
|
pad:
|
||||||
|
times 4+bootsector-$ db 0 ; Bytes zum Auffuellen, damit 'total_tracks' an einer
|
||||||
|
; geraden und tools/build.c bekannten Adresse liegt
|
||||||
|
total_tracks:
|
||||||
|
dw 0 ; Anzahl der Tracks der Diskette
|
||||||
|
total_heads:
|
||||||
|
dw 0 ; Anzahl der Seiten der Diskette
|
||||||
|
total_sectors:
|
||||||
|
dw 0 ; Anzahl der Sektoren pro Track
|
||||||
|
setup_sectors:
|
||||||
|
dw 0 ; Anzahl der Sektoren, die der Setup-Code einnimmt
|
||||||
|
system_sectors:
|
||||||
|
dw 0 ; Anzahl der Sektoren, die das System einnimmt
|
||||||
|
bootdevice:
|
||||||
|
db 0 ; BIOS Geraetecode: 00: Disk A, 01: Disk B, ..., 0x80 HD0, ...
|
||||||
|
curr_track:
|
||||||
|
db 0 ; Track, bei dem die Diskette/Partition beginnt
|
||||||
|
curr_head:
|
||||||
|
db 0 ; Head, bei dem die Diskette/Partition beginnt
|
||||||
|
curr_sector:
|
||||||
|
db 0 ; Sector, bei dem die Diskette/Partition beginnt
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
;
|
||||||
|
; Kopieren des Bootsectors
|
||||||
|
;
|
||||||
|
skip_data:
|
||||||
|
mov bl,dl ; vom BIOS uebergebenes Boot-Device sichern
|
||||||
|
|
||||||
|
mov ax,BIOSSEG
|
||||||
|
mov ds,ax
|
||||||
|
xor si,si
|
||||||
|
mov ax,BOOTSEG
|
||||||
|
mov es,ax
|
||||||
|
xor di,di
|
||||||
|
mov cx,SECTORSZ/2
|
||||||
|
rep movsw
|
||||||
|
;
|
||||||
|
; Ausfuehrung durch die Kopie fortsetzen
|
||||||
|
;
|
||||||
|
jmp BOOTSEG:start
|
||||||
|
;
|
||||||
|
; Segmentregister initialisieren und Platz fuer den Stack schaffen
|
||||||
|
;
|
||||||
|
start:
|
||||||
|
mov ax,cs ; Daten-, Stack- und Codesegment sollen
|
||||||
|
mov ds,ax ; hierher zeigen.
|
||||||
|
mov ss,ax
|
||||||
|
mov sp,4*SECTORSZ ; Drei Sektoren als Stack freilassen
|
||||||
|
|
||||||
|
mov [bootdevice],bl ; zuvor gesichertes Boot-Device permanent ablegen
|
||||||
|
|
||||||
|
;
|
||||||
|
; Ausgabe einer Meldung mit Hilfe eines BIOS-Aufrufs
|
||||||
|
;
|
||||||
|
mov ah,0x03 ; Feststellen der Cursor-Position
|
||||||
|
xor bh,bh
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
mov cx,13
|
||||||
|
mov bx,0x0007 ; page 0, attribute 7 (normal)
|
||||||
|
mov ax,ds
|
||||||
|
mov es,ax
|
||||||
|
mov bp,bootmessage
|
||||||
|
mov ax,0x1301 ; Ausgabe des Textes, Cursor bewegen
|
||||||
|
int 0x10
|
||||||
|
;
|
||||||
|
; Nachladen des Setup-Codes und des Systems selbst.
|
||||||
|
;
|
||||||
|
xor ah,ah ; Reset des Disketten-/Plattencontrollers
|
||||||
|
mov dl,[bootdevice]
|
||||||
|
int 0x13
|
||||||
|
;
|
||||||
|
; Informationen ueber die Laufwerksgeometrie holen
|
||||||
|
;
|
||||||
|
hdd_probe:
|
||||||
|
mov dl,[bootdevice]
|
||||||
|
test dl,0x80
|
||||||
|
jz load_setup ; Floppy mit den Standardparametern laden
|
||||||
|
mov ah,0x8
|
||||||
|
int 0x13
|
||||||
|
jc load_setup ; CF bei Fehler gesetzt
|
||||||
|
mov [total_heads],dh
|
||||||
|
mov ax,cx ; CX sichern
|
||||||
|
and ax,0x3f
|
||||||
|
mov [total_sectors],ax
|
||||||
|
mov ax,cx
|
||||||
|
shr ax,6
|
||||||
|
mov [total_tracks],ax
|
||||||
|
|
||||||
|
;
|
||||||
|
; Weiterstellen der Disketten-/Plattenposition um 1 (Bootblock)
|
||||||
|
;
|
||||||
|
load_setup:
|
||||||
|
call step_disk
|
||||||
|
|
||||||
|
;
|
||||||
|
; Laden des Setup-Codes
|
||||||
|
;
|
||||||
|
mov word [curr_segment],SETUPSEG
|
||||||
|
mov word [curr_offset],0
|
||||||
|
mov ax,[setup_sectors]
|
||||||
|
call load
|
||||||
|
;
|
||||||
|
; Laden des Kernels
|
||||||
|
;
|
||||||
|
mov word [curr_segment],SYSTEMSEG
|
||||||
|
mov word [curr_offset],0
|
||||||
|
mov ax,[system_sectors]
|
||||||
|
call load
|
||||||
|
;
|
||||||
|
; Floppy wieder abschalten
|
||||||
|
;
|
||||||
|
call stop_floppy_motor
|
||||||
|
;
|
||||||
|
; Start des Setup-Codes
|
||||||
|
;
|
||||||
|
mov ax, [system_sectors] ; Speichere Anzahl an System-Sektoren in AX.
|
||||||
|
jmp SETUPSEG:0
|
||||||
|
|
||||||
|
;
|
||||||
|
; load
|
||||||
|
;
|
||||||
|
; Die 'ax' Sektoren von der Diskette in den Hauptspeicher. Die Position auf
|
||||||
|
; der Diskette muss vorher in curr_head/curr_track/curr_sector und die
|
||||||
|
; Position im Hauptspeicher in curr_segment/curr_offset stehen. Die Positionen
|
||||||
|
; werden entsprechend der geladenen Sektoren weitergestellt.
|
||||||
|
;
|
||||||
|
load:
|
||||||
|
mov [to_load],ax
|
||||||
|
l_next_part:
|
||||||
|
mov al,[curr_head]
|
||||||
|
mov [last_head],al
|
||||||
|
mov al,[curr_track]
|
||||||
|
mov [last_track],al
|
||||||
|
mov al,[curr_sector]
|
||||||
|
mov [last_sector],al
|
||||||
|
mov ax,[curr_segment]
|
||||||
|
mov [last_segment],ax
|
||||||
|
mov ax,[curr_offset]
|
||||||
|
mov [last_offset],ax
|
||||||
|
|
||||||
|
mov al,0
|
||||||
|
|
||||||
|
l_loop: call step
|
||||||
|
|
||||||
|
cmp byte [curr_sector],0x01
|
||||||
|
je l_now
|
||||||
|
cmp word [curr_offset],0x0000
|
||||||
|
je l_now
|
||||||
|
cmp al,[to_load]
|
||||||
|
jne l_loop
|
||||||
|
|
||||||
|
l_now:
|
||||||
|
push ax
|
||||||
|
mov dl,[bootdevice]
|
||||||
|
mov dh,[last_head]
|
||||||
|
mov ch,[last_track]
|
||||||
|
mov cl,[last_sector]
|
||||||
|
mov bx,[last_segment]
|
||||||
|
mov es,bx
|
||||||
|
mov bx,[last_offset]
|
||||||
|
mov ah,0x02 ; Funktionscode fuer 'Lesen'
|
||||||
|
int 0x13
|
||||||
|
pop ax
|
||||||
|
|
||||||
|
push ax
|
||||||
|
call print_dot
|
||||||
|
pop ax
|
||||||
|
|
||||||
|
mov ah,0
|
||||||
|
sub [to_load],ax
|
||||||
|
jne l_next_part
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; step
|
||||||
|
;
|
||||||
|
; Stellt die aktuelle Position im Hauptspeicher und auf der Diskette
|
||||||
|
; um einen Sektor (512 Byte) weiter.
|
||||||
|
;
|
||||||
|
step: add al,1
|
||||||
|
call step_disk
|
||||||
|
call step_memory
|
||||||
|
ret
|
||||||
|
|
||||||
|
step_disk:
|
||||||
|
mov bl,[curr_sector]
|
||||||
|
add bl,1
|
||||||
|
mov [curr_sector],bl
|
||||||
|
cmp bl,[total_sectors]
|
||||||
|
jle l_1
|
||||||
|
mov byte [curr_sector],1
|
||||||
|
|
||||||
|
mov bl,[curr_head]
|
||||||
|
add bl,1
|
||||||
|
mov [curr_head],bl
|
||||||
|
cmp bl,[total_heads]
|
||||||
|
jne l_1
|
||||||
|
mov byte [curr_head],0
|
||||||
|
|
||||||
|
mov bl,[curr_track]
|
||||||
|
add bl,1
|
||||||
|
mov [curr_track],bl
|
||||||
|
|
||||||
|
l_1: ret
|
||||||
|
|
||||||
|
step_memory:
|
||||||
|
mov bx,[curr_offset]
|
||||||
|
add bx,SECTORSZ
|
||||||
|
mov [curr_offset],bx
|
||||||
|
test bx,0xffff
|
||||||
|
jne l_2
|
||||||
|
mov bx,[curr_segment]
|
||||||
|
add bx,0x1000 ; 64 KByte weiterstellen
|
||||||
|
mov [curr_segment],bx
|
||||||
|
|
||||||
|
l_2 ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; Ausgabe eines Stern ('*') mit Hilfe eines BIOS-Aufrufs
|
||||||
|
;
|
||||||
|
print_dot:
|
||||||
|
mov ah,0x03 ; Feststellen der Cursor-Position
|
||||||
|
xor bh,bh
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
mov cx,1
|
||||||
|
mov bx,0x0007 ; page 0, attribute 7 (normal)
|
||||||
|
mov ax,ds
|
||||||
|
mov es,ax
|
||||||
|
mov bp,dot
|
||||||
|
mov ax,0x1301 ; Ausgabe des Textes, Cursor bewegen
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; stop_floppy_motor
|
||||||
|
;
|
||||||
|
; Stopt den Motor der Floppy, da das BIOS dazu in Kuerze nicht mehr in
|
||||||
|
; der Lage sein wird. Egal, ob von Floppy oder Platte gebootet wurde.
|
||||||
|
;
|
||||||
|
stop_floppy_motor:
|
||||||
|
mov dx,0x3f2
|
||||||
|
xor al,al
|
||||||
|
out dx,al
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; Datenbereich
|
||||||
|
;
|
||||||
|
|
||||||
|
bootmessage:
|
||||||
|
db 13,10
|
||||||
|
db 'booting ... '
|
||||||
|
|
||||||
|
dot:
|
||||||
|
db '*'
|
||||||
|
|
||||||
|
to_load:
|
||||||
|
dw 0
|
||||||
|
curr_segment:
|
||||||
|
dw 0
|
||||||
|
curr_offset:
|
||||||
|
dw 0
|
||||||
|
|
||||||
|
last_head:
|
||||||
|
db 0
|
||||||
|
last_track:
|
||||||
|
db 0
|
||||||
|
last_sector:
|
||||||
|
db 0
|
||||||
|
last_segment:
|
||||||
|
dw 0
|
||||||
|
last_offset:
|
||||||
|
dw 0
|
||||||
|
|
||||||
|
unused:
|
||||||
|
times bootsector+510-$ db 0
|
||||||
|
|
||||||
|
mark:
|
||||||
|
dw 0xaa55
|
||||||
BIN
c_boot/setup
Normal file
BIN
c_boot/setup
Normal file
Binary file not shown.
195
c_boot/setup.asm
Executable file
195
c_boot/setup.asm
Executable file
@ -0,0 +1,195 @@
|
|||||||
|
; $Id: setup.asm 1484 2009-02-11 21:03:19Z hsc $
|
||||||
|
|
||||||
|
;******************************************************************************
|
||||||
|
;* Betriebssysteme *
|
||||||
|
;*----------------------------------------------------------------------------*
|
||||||
|
;* *
|
||||||
|
;* S E T U P *
|
||||||
|
;* *
|
||||||
|
;*----------------------------------------------------------------------------*
|
||||||
|
;* Der Setup-Code liegt im System-Image direkt hinter dem Bootsektor und wird *
|
||||||
|
;* von diesem direkt nach dem Laden aktiviert. Der Code wird noch im *
|
||||||
|
;* 'Real-Mode' gestartet, so dass zu Beginn auch noch BIOS-Aufrufe erlaubt *
|
||||||
|
;* sind. Dann werden jedoch alle Interrupts verboten, die Adressleitung A20 *
|
||||||
|
;* aktiviert und die Umschaltung in den 'Protected-Mode' vorgenommen. Alles *
|
||||||
|
;* weitere uebernimmt der Startup-Code des Systems. *
|
||||||
|
;******************************************************************************
|
||||||
|
|
||||||
|
;
|
||||||
|
; Konstanten
|
||||||
|
;
|
||||||
|
SETUPSEG equ 0x9000 ; Setup-Code (max. 64K inkl. Stack)
|
||||||
|
SYSTEMSEG equ 0x1000 ; System-Code (max. 512K)
|
||||||
|
SECTORSZ equ 512 ; Groesse eines Sektors in Bytes
|
||||||
|
SYSTEMSTART equ 0x100000 ; Hierhin wird das System nach Umschalten in den
|
||||||
|
; Protected Mode kopiert, da GRUB das auch tut
|
||||||
|
; (und GRUB kann nur an Adressen >1M laden).
|
||||||
|
|
||||||
|
[SECTION .text]
|
||||||
|
[BITS 16]
|
||||||
|
;
|
||||||
|
; Segmentregister initialisieren
|
||||||
|
;
|
||||||
|
start:
|
||||||
|
mov dx, ax ; Anzahl Systemsektoren in DX sichern.
|
||||||
|
|
||||||
|
mov ax,cs ; Daten-, Code- und Stacksegment sollen
|
||||||
|
mov ds,ax ; hierher zeigen.
|
||||||
|
mov ss,ax ; Alle drei Segment duerfen nicht mehr
|
||||||
|
mov sp,0xfffe ; als 64 KByte einnehmen (zusammen).
|
||||||
|
|
||||||
|
mov [system_sectors], dx ; Anzahl der Systemsektoren im Speicher ablegen
|
||||||
|
|
||||||
|
;
|
||||||
|
; Ausgabe einer Meldung mit Hilfe eines BIOS-Aufrufs
|
||||||
|
;
|
||||||
|
mov ah,0x03 ; Feststellen der Cursor-Position
|
||||||
|
xor bh,bh
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
mov cx,14
|
||||||
|
mov bx,0x0007 ; page 0, attribute 7 (normal)
|
||||||
|
mov ax,ds
|
||||||
|
mov es,ax
|
||||||
|
mov bp,setupmessage
|
||||||
|
mov ax,0x1301 ; Ausgabe des Textes, Cursor bewegen
|
||||||
|
int 0x10
|
||||||
|
;
|
||||||
|
; So, jetzt werden die Interrupts abgeschaltet
|
||||||
|
;
|
||||||
|
cli ; Maskierbare Interrupts verbieten
|
||||||
|
mov al,0x80 ; NMI verbieten
|
||||||
|
out 0x70,al
|
||||||
|
;
|
||||||
|
; IDT und GDT setzen
|
||||||
|
;
|
||||||
|
lidt [idt_48]
|
||||||
|
lgdt [gdt_48]
|
||||||
|
;
|
||||||
|
; Aktivieren der Adressleitung A20
|
||||||
|
;
|
||||||
|
call empty_8042
|
||||||
|
mov al,0xd1
|
||||||
|
out 0x64,al
|
||||||
|
call empty_8042
|
||||||
|
mov al,0xdf
|
||||||
|
out 0x60,al
|
||||||
|
call empty_8042
|
||||||
|
mov al,0xff
|
||||||
|
out 0x64,al
|
||||||
|
call empty_8042
|
||||||
|
;
|
||||||
|
; Moeglichen Koprozessor zuruecksetzen
|
||||||
|
;
|
||||||
|
xor ax,ax
|
||||||
|
out 0xf0,al
|
||||||
|
call delay
|
||||||
|
out 0xf1,al
|
||||||
|
call delay
|
||||||
|
;
|
||||||
|
; Umschalten in den Protected Mode
|
||||||
|
;
|
||||||
|
mov eax,cr0 ; Setze PM-Bit im Kontrollregister 1
|
||||||
|
or eax,1
|
||||||
|
mov cr0,eax
|
||||||
|
|
||||||
|
jmp dword 0x08:SETUPSEG*0x10+copy_system ; Far-Jump, um
|
||||||
|
; a) fetch Pipeline zu leeren
|
||||||
|
; b) CS Register sinnvoll zu belegen
|
||||||
|
[BITS 32]
|
||||||
|
; Arbeite jetzt im Protected Mode
|
||||||
|
copy_system:
|
||||||
|
;
|
||||||
|
; Systemcode von 0x10000 nach 0x100000 kopieren.
|
||||||
|
;
|
||||||
|
|
||||||
|
mov ax, 0x10 ; 0x10 entspricht dem Data-Eintrag in der GDT.
|
||||||
|
mov ds, ax ; DS und ES werden von movsd benoetigt.
|
||||||
|
mov es, ax
|
||||||
|
|
||||||
|
xor ecx, ecx ; Anzahl Systemsektoren laden
|
||||||
|
mov cx, [SETUPSEG*0x10+system_sectors]
|
||||||
|
|
||||||
|
imul ecx, SECTORSZ/4
|
||||||
|
|
||||||
|
mov esi, SYSTEMSEG*0x10 ; Hier liegt der Systemcode noch ...
|
||||||
|
mov edi, SYSTEMSTART ; ... und hierhin moechten wir ihn verschieben
|
||||||
|
|
||||||
|
cld ; Nach jedem movsb ESI,EDI inkrementieren
|
||||||
|
rep movsd ; Kopiere 4 Byte von [ESI] nach [EDI] ecx male
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
; Sprung in den Startup-Code des Systems
|
||||||
|
;
|
||||||
|
|
||||||
|
jmp dword 0x08:SYSTEMSTART
|
||||||
|
|
||||||
|
error:
|
||||||
|
hlt
|
||||||
|
[BITS 16]
|
||||||
|
; Ab hier wieder Real-Mode Code fuer die Codeteile
|
||||||
|
; vor der Umschaltung in den Protected Mode
|
||||||
|
|
||||||
|
;
|
||||||
|
; empty_8042
|
||||||
|
;
|
||||||
|
; Ein- und Ausgabepuffer des Tastaturcontrollers leeren
|
||||||
|
;
|
||||||
|
empty_8042:
|
||||||
|
call delay
|
||||||
|
in al,0x64 ; 8042 Status Port
|
||||||
|
test al,1 ; Ausgabepuffer voll?
|
||||||
|
jz no_output
|
||||||
|
call delay
|
||||||
|
in al,0x60 ; wenn ja: ueberlesen
|
||||||
|
jmp empty_8042
|
||||||
|
no_output:
|
||||||
|
test al,2 ; Eingabepuffer voll?
|
||||||
|
jnz empty_8042 ; wenn ja, noch mal testen, irgendwann
|
||||||
|
ret ; muss es weg sein.
|
||||||
|
;
|
||||||
|
; delay:
|
||||||
|
;
|
||||||
|
; Kurze Verzoegerung fuer in/out-Befehle
|
||||||
|
;
|
||||||
|
delay:
|
||||||
|
out 0x80,al
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; Datenbereich
|
||||||
|
;
|
||||||
|
[SECTION .data]
|
||||||
|
|
||||||
|
; Meldung
|
||||||
|
|
||||||
|
system_sectors:
|
||||||
|
dw 0
|
||||||
|
|
||||||
|
setupmessage:
|
||||||
|
db 13,10
|
||||||
|
db 'setup active'
|
||||||
|
;
|
||||||
|
; Descriptor-Tabellen
|
||||||
|
;
|
||||||
|
gdt:
|
||||||
|
dw 0,0,0,0 ; NULL Deskriptor
|
||||||
|
|
||||||
|
dw 0xFFFF ; 4Gb - (0x100000*0x1000 = 4Gb)
|
||||||
|
dw 0x0000 ; base address=0
|
||||||
|
dw 0x9A00 ; code read/exec
|
||||||
|
dw 0x00CF ; granularity=4096, 386 (+5th nibble of limit)
|
||||||
|
|
||||||
|
dw 0xFFFF ; 4Gb - (0x100000*0x1000 = 4Gb)
|
||||||
|
dw 0x0000 ; base address=0
|
||||||
|
dw 0x9200 ; data read/write
|
||||||
|
dw 0x00CF ; granularity=4096, 386 (+5th nibble of limit)
|
||||||
|
|
||||||
|
idt_48:
|
||||||
|
dw 0 ; idt limit=0
|
||||||
|
dw 0,0 ; idt base=0L
|
||||||
|
|
||||||
|
gdt_48:
|
||||||
|
dw 0x18 ; GDT Limit=24, 3 GDT Eintraege
|
||||||
|
dd SETUPSEG*0x10+gdt; Physikalische Adresse der GDT
|
||||||
BIN
c_tools/build
Executable file
BIN
c_tools/build
Executable file
Binary file not shown.
153
c_tools/build.c
Executable file
153
c_tools/build.c
Executable file
@ -0,0 +1,153 @@
|
|||||||
|
#include <stdio.h> /* fprintf */
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h> /* contains exit */
|
||||||
|
#include <unistd.h> /* contains read/write */
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#if !defined(DOS) && !defined(Win32)
|
||||||
|
#define O_BINARY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SECTOR 512
|
||||||
|
|
||||||
|
void die (const char* str)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"%s\n",str);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (int argc, char** argv)
|
||||||
|
{
|
||||||
|
int fd, fd_out;
|
||||||
|
char bootsector[SECTOR];
|
||||||
|
char setupsector[SECTOR];
|
||||||
|
struct stat info;
|
||||||
|
unsigned short setup_size;
|
||||||
|
int bytes_read, to_read;
|
||||||
|
unsigned int dc, st, sh, ss, tt, th, ts;
|
||||||
|
unsigned char bios_device_code, start_track, start_head, start_sector;
|
||||||
|
unsigned short total_tracks, total_heads, total_sectors;
|
||||||
|
unsigned short system_sectors;
|
||||||
|
|
||||||
|
if (argc != 6)
|
||||||
|
die ("usage: build bootsector setup-code system-image dev.info bootdisk-image\n\n"
|
||||||
|
"dev.info: BIOS-dev.code:total-tracks:-heads:-sectors:start-track:-head:-sector\n"
|
||||||
|
"BIOS-devicecode: 0=fd0, 1=fd1, ..., 128=hd0, 129=hd1, ...\n"
|
||||||
|
"Example: to boot from a 3.5\" floppy disk use \"0:80:2:18:0:0:1\"\n");
|
||||||
|
|
||||||
|
sscanf (argv[4], "%u:%u:%u:%u:%u:%u:%u", &dc, &tt, &th, &ts, &st, &sh, &ss);
|
||||||
|
bios_device_code = (unsigned char)dc;
|
||||||
|
total_tracks = (unsigned short)tt;
|
||||||
|
total_sectors = (unsigned short)ts;
|
||||||
|
total_heads = (unsigned short)th;
|
||||||
|
start_track = (unsigned char)st;
|
||||||
|
start_head = (unsigned char)sh;
|
||||||
|
start_sector = (unsigned char)ss;
|
||||||
|
|
||||||
|
printf ("BIOS-devicecode: 0x%x\n", bios_device_code);
|
||||||
|
printf ("Total T/H/S: (%d/%d/%d)\n", total_tracks, total_heads,
|
||||||
|
total_sectors);
|
||||||
|
printf ("Start T/H/S: (%d/%d/%d)\n\n", start_track, start_head,
|
||||||
|
start_sector);
|
||||||
|
|
||||||
|
if ((fd_out = open (argv[5], O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644)) < 0)
|
||||||
|
die ("Unable to open output file.");
|
||||||
|
|
||||||
|
if ((fd = open (argv[1], O_RDONLY|O_BINARY, 0)) < 0)
|
||||||
|
die ("Unable to open input file.");
|
||||||
|
|
||||||
|
if (read (fd, bootsector, SECTOR) < 0)
|
||||||
|
die ("Unable to read bootsector.");
|
||||||
|
|
||||||
|
close (fd);
|
||||||
|
|
||||||
|
if (stat (argv[2], &info) != 0)
|
||||||
|
die ("Can't stat setup file.");
|
||||||
|
|
||||||
|
setup_size = (unsigned short)
|
||||||
|
((info.st_size + SECTOR - 1) / SECTOR);
|
||||||
|
printf ("Setup size is %d sectors.\n", (int)setup_size);
|
||||||
|
|
||||||
|
if (stat (argv[3], &info) != 0)
|
||||||
|
die ("Can't stat system file.");
|
||||||
|
to_read = info.st_size;
|
||||||
|
printf ("System size is %d bytes.\n", to_read);
|
||||||
|
|
||||||
|
system_sectors = (to_read + SECTOR - 1) / SECTOR;
|
||||||
|
printf ("# System sectors is %d.\n", system_sectors);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
*(unsigned short*)(bootsector+4) = total_tracks;
|
||||||
|
*(unsigned short*)(bootsector+6) = total_heads;
|
||||||
|
*(unsigned short*)(bootsector+8) = total_sectors;
|
||||||
|
|
||||||
|
*(unsigned short*)(bootsector+10) = setup_size;
|
||||||
|
*(unsigned short*)(bootsector+12) =
|
||||||
|
(unsigned short)((to_read + SECTOR - 1) / SECTOR);
|
||||||
|
*(unsigned char*)(bootsector+14) = bios_device_code;
|
||||||
|
*(unsigned char*)(bootsector+15) = start_track;
|
||||||
|
*(unsigned char*)(bootsector+16) = start_head;
|
||||||
|
*(unsigned char*)(bootsector+17) = start_sector;
|
||||||
|
#else
|
||||||
|
*(unsigned char*)(bootsector+4) = (total_tracks) & 0xff;
|
||||||
|
*(unsigned char*)(bootsector+5) = (total_tracks >> 8) & 0xff;
|
||||||
|
*(unsigned char*)(bootsector+6) = (total_heads) & 0xff;
|
||||||
|
*(unsigned char*)(bootsector+7) = (total_heads >> 8) & 0xff;
|
||||||
|
*(unsigned char*)(bootsector+8) = (total_sectors) & 0xff;
|
||||||
|
*(unsigned char*)(bootsector+9) = (total_sectors >> 8) & 0xff;
|
||||||
|
|
||||||
|
*(unsigned char*)(bootsector+10) = (setup_size) & 0xff;
|
||||||
|
*(unsigned char*)(bootsector+11) = (setup_size >> 8) & 0xff;
|
||||||
|
*(unsigned char*)(bootsector+12) = system_sectors & 0xff;
|
||||||
|
*(unsigned char*)(bootsector+13) = (system_sectors >> 8) & 0xff;
|
||||||
|
*(unsigned char*)(bootsector+14) = bios_device_code;
|
||||||
|
*(unsigned char*)(bootsector+15) = start_track;
|
||||||
|
*(unsigned char*)(bootsector+16) = start_head;
|
||||||
|
*(unsigned char*)(bootsector+17) = start_sector;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write (fd_out, bootsector, SECTOR);
|
||||||
|
|
||||||
|
if ((fd = open (argv[2], O_RDONLY|O_BINARY, 0)) < 0)
|
||||||
|
die ("Unable to open setup file.");
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ((bytes_read = read (fd, setupsector, SECTOR)) < 0)
|
||||||
|
die ("Unable to read setup.");
|
||||||
|
|
||||||
|
if (bytes_read > 0)
|
||||||
|
write (fd_out, setupsector, SECTOR);
|
||||||
|
|
||||||
|
} while (bytes_read > 0);
|
||||||
|
|
||||||
|
|
||||||
|
close (fd);
|
||||||
|
|
||||||
|
if ((fd = open (argv[3], O_RDONLY|O_BINARY, 0)) < 0)
|
||||||
|
die ("Unable to open system file.");
|
||||||
|
|
||||||
|
while (to_read > 0)
|
||||||
|
{
|
||||||
|
int l;
|
||||||
|
|
||||||
|
l = (to_read < SECTOR)?to_read:SECTOR;
|
||||||
|
|
||||||
|
if ((bytes_read = read (fd, setupsector, l)) != l)
|
||||||
|
die ("Unable to read system.");
|
||||||
|
|
||||||
|
write (fd_out, setupsector, l);
|
||||||
|
|
||||||
|
to_read -= l;
|
||||||
|
}
|
||||||
|
|
||||||
|
close (fd);
|
||||||
|
close (fd_out);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
70
sections
Executable file
70
sections
Executable file
@ -0,0 +1,70 @@
|
|||||||
|
/* $Id: sections 5834 2013-10-08 17:04:08Z os $ */
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x100000; /* Startadresse des Systems */
|
||||||
|
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(".text")
|
||||||
|
*(".text.*")
|
||||||
|
*(".text$")
|
||||||
|
*(".init")
|
||||||
|
*(".fini")
|
||||||
|
*(".gnu.linkonce.*")
|
||||||
|
}
|
||||||
|
|
||||||
|
.init_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__init_array_start = .);
|
||||||
|
KEEP (*(SORT(.init_array.*)))
|
||||||
|
KEEP (*(.init_array))
|
||||||
|
KEEP (*(".ctors"))
|
||||||
|
KEEP (*(".ctor"))
|
||||||
|
PROVIDE_HIDDEN (__init_array_end = .);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fini_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||||
|
KEEP (*(SORT(.fini_array.*)))
|
||||||
|
KEEP (*(.fini_array))
|
||||||
|
KEEP (*(".dtors"))
|
||||||
|
KEEP (*(".dtor"))
|
||||||
|
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||||
|
}
|
||||||
|
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
*(".data")
|
||||||
|
*(".data$")
|
||||||
|
*(".rodata")
|
||||||
|
*(".rodata.*")
|
||||||
|
*(".got")
|
||||||
|
*(".got.plt")
|
||||||
|
*(".eh_frame")
|
||||||
|
*(".eh_fram")
|
||||||
|
*(".jcr")
|
||||||
|
*(".note.*")
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
___BSS_START__ = .;
|
||||||
|
*(".bss")
|
||||||
|
*(".bss.*")
|
||||||
|
___BSS_END__ = .;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
/DISCARD/ :
|
||||||
|
{
|
||||||
|
*(".note")
|
||||||
|
*(".comment")
|
||||||
|
*(".debug_line")
|
||||||
|
*(".debug_info")
|
||||||
|
*(".debug_abbrev")
|
||||||
|
*(".debug_aranges")
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
284
startup.asm
Executable file
284
startup.asm
Executable file
@ -0,0 +1,284 @@
|
|||||||
|
;******************************************************************************
|
||||||
|
;* *
|
||||||
|
;* S T A R T U P . A S M *
|
||||||
|
;* *
|
||||||
|
;*----------------------------------------------------------------------------*
|
||||||
|
;* Beschreibung: 'startup' ist der Eintrittspunkt des eigentlichen Systems.*
|
||||||
|
;* Die Umschaltung in den Protected-Mode ist bereits erfolgt.*
|
||||||
|
;* Es wird alles vorbereitet, damit so schnell wie moeglich *
|
||||||
|
;* die weitere Ausfuehrung durch C-Code erfolgen kann. *
|
||||||
|
;* *
|
||||||
|
;* Autor: Olaf Spinczyk, TU Dortmund *
|
||||||
|
;******************************************************************************
|
||||||
|
|
||||||
|
; Multiboot-Konstanten
|
||||||
|
MULTIBOOT_PAGE_ALIGN equ 1<<0
|
||||||
|
MULTIBOOT_MEMORY_INFO equ 1<<1
|
||||||
|
|
||||||
|
; Magic-Number fuer Multiboot
|
||||||
|
MULTIBOOT_HEADER_MAGIC equ 0x1badb002
|
||||||
|
; Multiboot-Flags (ELF-spezifisch!)
|
||||||
|
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO
|
||||||
|
MULTIBOOT_HEADER_CHKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
|
||||||
|
MULTIBOOT_EAX_MAGIC equ 0x2badb002
|
||||||
|
|
||||||
|
;
|
||||||
|
; System
|
||||||
|
;
|
||||||
|
|
||||||
|
[GLOBAL startup]
|
||||||
|
[GLOBAL idt]
|
||||||
|
[GLOBAL __cxa_pure_virtual]
|
||||||
|
[GLOBAL _ZdlPv]
|
||||||
|
|
||||||
|
[EXTERN main]
|
||||||
|
[EXTERN int_disp]
|
||||||
|
|
||||||
|
[EXTERN ___BSS_START__]
|
||||||
|
[EXTERN ___BSS_END__]
|
||||||
|
[EXTERN __init_array_start]
|
||||||
|
[EXTERN __init_array_end]
|
||||||
|
[EXTERN __fini_array_start]
|
||||||
|
[EXTERN __fini_array_end]
|
||||||
|
|
||||||
|
[SECTION .text]
|
||||||
|
|
||||||
|
startup:
|
||||||
|
jmp skip_multiboot_hdr
|
||||||
|
|
||||||
|
multiboot_header:
|
||||||
|
align 4
|
||||||
|
dd MULTIBOOT_HEADER_MAGIC
|
||||||
|
dd MULTIBOOT_HEADER_FLAGS
|
||||||
|
dd MULTIBOOT_HEADER_CHKSUM
|
||||||
|
|
||||||
|
skip_multiboot_hdr:
|
||||||
|
; GCC-kompilierter Code erwartet das so.
|
||||||
|
|
||||||
|
cld
|
||||||
|
|
||||||
|
cmp eax,MULTIBOOT_EAX_MAGIC
|
||||||
|
jne floppy_boot
|
||||||
|
;
|
||||||
|
; GDT setzen (notwendig, falls wir durch GRUB geladen wurden)
|
||||||
|
;
|
||||||
|
lgdt [gdt_48]
|
||||||
|
|
||||||
|
floppy_boot:
|
||||||
|
|
||||||
|
; Globales Datensegment
|
||||||
|
|
||||||
|
mov ax,0x10
|
||||||
|
mov ds,ax
|
||||||
|
mov es,ax
|
||||||
|
mov fs,ax
|
||||||
|
mov gs,ax
|
||||||
|
|
||||||
|
; Stack festlegen
|
||||||
|
|
||||||
|
mov ss,ax
|
||||||
|
mov esp,init_stack+4096
|
||||||
|
|
||||||
|
; Unterbrechungsbehandlung sicherstellen
|
||||||
|
|
||||||
|
call setup_idt
|
||||||
|
call reprogram_pics
|
||||||
|
|
||||||
|
; BSS loeschen
|
||||||
|
mov edi, ___BSS_START__
|
||||||
|
clear_bss:
|
||||||
|
mov byte [edi], 0
|
||||||
|
inc edi
|
||||||
|
cmp edi, ___BSS_END__
|
||||||
|
jne clear_bss
|
||||||
|
|
||||||
|
; Aufruf des C-Codes
|
||||||
|
|
||||||
|
call _init ; Konstruktoren globaler Objekte ausfuehren
|
||||||
|
call main ; C/C++ Level System
|
||||||
|
call _fini ; Destruktoren
|
||||||
|
hlt
|
||||||
|
|
||||||
|
;; Ausfuehrung der Konstruktoren globaler Objekte
|
||||||
|
_init:
|
||||||
|
mov edi, __init_array_start
|
||||||
|
_init_loop:
|
||||||
|
cmp edi, __init_array_end
|
||||||
|
je _init_done
|
||||||
|
mov eax, [edi]
|
||||||
|
call eax
|
||||||
|
add edi, 4
|
||||||
|
ja _init_loop
|
||||||
|
_init_done:
|
||||||
|
ret
|
||||||
|
|
||||||
|
;; Ausfuehrung der Destruktoren globaler Objekte
|
||||||
|
_fini:
|
||||||
|
mov edi, __fini_array_start
|
||||||
|
_fini_loop:
|
||||||
|
cmp edi, __fini_array_end
|
||||||
|
je _fini_done
|
||||||
|
mov eax, [edi]
|
||||||
|
call eax
|
||||||
|
add edi, 4
|
||||||
|
ja _fini_loop
|
||||||
|
_fini_done:
|
||||||
|
ret
|
||||||
|
|
||||||
|
; Default Interrupt Behandlung
|
||||||
|
|
||||||
|
; Spezifischer Kopf der Unterbrechungsbehandlungsroutinen
|
||||||
|
|
||||||
|
%macro wrapper 1
|
||||||
|
wrapper_%1:
|
||||||
|
push eax
|
||||||
|
mov al,%1
|
||||||
|
jmp wrapper_body
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
; ... wird automatisch erzeugt.
|
||||||
|
%assign i 0
|
||||||
|
%rep 256
|
||||||
|
wrapper i
|
||||||
|
%assign i i+1
|
||||||
|
%endrep
|
||||||
|
|
||||||
|
; Gemeinsamer Rumpf
|
||||||
|
wrapper_body:
|
||||||
|
cld ; das erwartet der gcc so.
|
||||||
|
push ecx ; Sichern der fluechtigen Register
|
||||||
|
push edx
|
||||||
|
and eax,0xff ; Der generierte Wrapper liefert nur 8 Bits
|
||||||
|
push eax ; Nummer der Unterbrechung uebergeben
|
||||||
|
call int_disp
|
||||||
|
add esp,4 ; Parameter vom Stack entfernen
|
||||||
|
pop edx ; fluechtige Register wieder herstellen
|
||||||
|
pop ecx
|
||||||
|
pop eax
|
||||||
|
iret ; fertig!
|
||||||
|
|
||||||
|
;
|
||||||
|
; setup_idt
|
||||||
|
;
|
||||||
|
; Relokation der Eintraege in der IDT und Setzen des IDTR
|
||||||
|
|
||||||
|
setup_idt:
|
||||||
|
mov eax,wrapper_0 ; ax: niederwertige 16 Bit
|
||||||
|
mov ebx,eax
|
||||||
|
shr ebx,16 ; bx: hoeherwertige 16 Bit
|
||||||
|
mov ecx,255 ; Zaehler
|
||||||
|
.loop: add [idt+8*ecx+0],ax
|
||||||
|
adc [idt+8*ecx+6],bx
|
||||||
|
dec ecx
|
||||||
|
jge .loop
|
||||||
|
|
||||||
|
lidt [idt_descr]
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; reprogram_pics
|
||||||
|
;
|
||||||
|
; Neuprogrammierung der PICs (Programmierbare Interrupt-Controller), damit
|
||||||
|
; alle 15 Hardware-Interrupts nacheinander in der idt liegen.
|
||||||
|
|
||||||
|
reprogram_pics:
|
||||||
|
mov al,0x11 ; ICW1: 8086 Modus mit ICW4
|
||||||
|
out 0x20,al
|
||||||
|
call delay
|
||||||
|
out 0xa0,al
|
||||||
|
call delay
|
||||||
|
mov al,0x20 ; ICW2 Master: IRQ # Offset (32)
|
||||||
|
out 0x21,al
|
||||||
|
call delay
|
||||||
|
mov al,0x28 ; ICW2 Slave: IRQ # Offset (40)
|
||||||
|
out 0xa1,al
|
||||||
|
call delay
|
||||||
|
mov al,0x04 ; ICW3 Master: Slaves an IRQs
|
||||||
|
out 0x21,al
|
||||||
|
call delay
|
||||||
|
mov al,0x02 ; ICW3 Slave: Verbunden mit IRQ2 des Masters
|
||||||
|
out 0xa1,al
|
||||||
|
call delay
|
||||||
|
mov al,0x03 ; ICW4: 8086 Modus und automatischer EIO
|
||||||
|
out 0x21,al
|
||||||
|
call delay
|
||||||
|
out 0xa1,al
|
||||||
|
call delay
|
||||||
|
|
||||||
|
mov al,0xff ; Hardware-Interrupts durch PICs
|
||||||
|
out 0xa1,al ; ausmaskieren. Nur der Interrupt 2,
|
||||||
|
call delay ; der der Kaskadierung der beiden
|
||||||
|
mov al,0xfb ; PICs dient, ist erlaubt.
|
||||||
|
out 0x21,al
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
; delay
|
||||||
|
;
|
||||||
|
; Kurze Verzoegerung fuer in/out Befehle.
|
||||||
|
|
||||||
|
delay:
|
||||||
|
jmp .L2
|
||||||
|
.L2: ret
|
||||||
|
|
||||||
|
; Die Funktion wird beim abarbeiten der globalen Konstruktoren aufgerufen
|
||||||
|
; (unter Linux). Das Label muss definiert sein (fuer den Linker). Die
|
||||||
|
; Funktion selbst kann aber leer sein, da bei StuBs keine Freigabe des
|
||||||
|
; Speichers erfolgen muss.
|
||||||
|
|
||||||
|
__cxa_pure_virtual:
|
||||||
|
_ZdlPv:
|
||||||
|
ret
|
||||||
|
|
||||||
|
[SECTION .data]
|
||||||
|
|
||||||
|
; 'interrupt descriptor table' mit 256 Eintraegen.
|
||||||
|
|
||||||
|
idt:
|
||||||
|
|
||||||
|
%macro idt_entry 1
|
||||||
|
dw (wrapper_%1 - wrapper_0) & 0xffff
|
||||||
|
dw 0x0008
|
||||||
|
dw 0x8e00
|
||||||
|
dw ((wrapper_%1 - wrapper_0) & 0xffff0000) >> 16
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
; ... wird automatisch erzeugt.
|
||||||
|
|
||||||
|
%assign i 0
|
||||||
|
%rep 256
|
||||||
|
idt_entry i
|
||||||
|
%assign i i+1
|
||||||
|
%endrep
|
||||||
|
|
||||||
|
idt_descr:
|
||||||
|
dw 256*8-1 ; idt enthaelt 256 Eintraege
|
||||||
|
dd idt
|
||||||
|
|
||||||
|
; Stack und interrupt descriptor table im BSS Bereich
|
||||||
|
|
||||||
|
[SECTION .bss]
|
||||||
|
|
||||||
|
init_stack:
|
||||||
|
resb 4096
|
||||||
|
|
||||||
|
[SECTION .data]
|
||||||
|
;
|
||||||
|
; Descriptor-Tabellen
|
||||||
|
;
|
||||||
|
gdt:
|
||||||
|
dw 0,0,0,0 ; NULL Deskriptor
|
||||||
|
|
||||||
|
dw 0xFFFF ; 4Gb - (0x100000*0x1000 = 4Gb)
|
||||||
|
dw 0x0000 ; base address=0
|
||||||
|
dw 0x9A00 ; code read/exec
|
||||||
|
dw 0x00CF ; granularity=4096, 386 (+5th nibble of limit)
|
||||||
|
|
||||||
|
dw 0xFFFF ; 4Gb - (0x100000*0x1000 = 4Gb)
|
||||||
|
dw 0x0000 ; base address=0
|
||||||
|
dw 0x9200 ; data read/write
|
||||||
|
dw 0x00CF ; granularity=4096, 386 (+5th nibble of limit)
|
||||||
|
|
||||||
|
gdt_48:
|
||||||
|
dw 0x18 ; GDT Limit=24, 3 GDT Eintraege
|
||||||
|
dd gdt ; Physikalische Adresse der GDT
|
||||||
Reference in New Issue
Block a user