this source
guodemone via digitalmars-d-ldc
digitalmars-d-ldc at puremagic.com
Sun Oct 25 08:37:23 PDT 2015
#ifndef __BOOT_ASM_H__
#define __BOOT_ASM_H__
/* Assembler macros to create x86 segments */
/* Normal segment */
#define SEG_NULLASM \
.word 0, 0; \
.byte 0, 0, 0, 0
#define SEG_ASM(type,base,lim) \
.word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \
.byte (((base) >> 16) & 0xff), (0x90 | (type)), \
(0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff)
/* Application segment type bits */
#define STA_X 0x8
#define STA_E 0x4
#define STA_C 0x4
#define STA_W 0x2
#define STA_R 0x2
#define STA_A 0x1
#endif /* !__BOOT_ASM_H__ */
*****************************************
#include <asm.h>
# Start the CPU: switch to 32-bit protected mode, jump into C.
# The BIOS loads this code from the first sector of the hard disk
into
# memory at physical address 0x7c00 and starts executing in real
mode
# with %cs=0 %ip=7c00.
.set PROT_MODE_CSEG, 0x8 # kernel code segment selector
.set PROT_MODE_DSEG, 0x10 # kernel data segment selector
.set CR0_PE_ON, 0x1 # protected mode enable flag
.globl start
start:
.code16 # Assemble for 16-bit mode
cli
cld
# Set up the important data segment registers (DS, ES, SS).
xorw %ax, %ax # Segment number zero
movw %ax, %ds # -> Data Segment
movw %ax, %es # -> Extra Segment
movw %ax, %ss # -> Stack Segment
seta20.1:
inb $0x64, %al # Wait for not busy
testb $0x2, %al
jnz seta20.1
movb $0xd1, %al # 0xd1 -> port 0x64
outb %al, $0x64
seta20.2:
inb $0x64, %al # Wait for not busy
testb $0x2, %al
jnz seta20.2
movb $0xdf, %al # 0xdf -> port 0x60
outb %al, $0x60
lgdt gdtdesc
movl %cr0, %eax
orl $CR0_PE_ON, %eax
movl %eax, %cr0
ljmp $PROT_MODE_CSEG, $protcseg
.code32 # Assemble for 32-bit mode
protcseg:
movw $PROT_MODE_DSEG, %ax
movw %ax, %ds # -> DS: Data Segment
movw %ax, %es # -> ES: Extra Segment
movw %ax, %fs # -> FS
movw %ax, %gs # -> GS
movw %ax, %ss # -> SS: Stack Segment
movl $0x0, %ebp
movl $start, %esp
call bootmain
spin:
jmp spin
.p2align 2
gdt:
SEG_NULLASM
SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff)
SEG_ASM(STA_W, 0x0, 0xffffffff)
gdtdesc:
.word 0x17
.long gdt
****************************************
module bootmain;
import types;
import x86;
const COM1 = 0x3F8;
const CRTPORT = 0x3D4;
const LPTPORT = 0x378;
const COM_TX = 0;
const COM_LSR = 5;
const COM_LSR_TXRDY = 20;
extern (C){
uint8_t inb(uint16_t port);
void outb(uint16_t port, uint8_t data);
uint16_t *crt; // CGA memory
}
static this(){
uint16_t *crt = cast(uint16_t *)0xB8000;
}
/* stupid I/O delay routine necessitated by historical PC design
flaws */
static void
delay() {
inb(0x84);
inb(0x84);
inb(0x84);
inb(0x84);
}
/* lpt_putc - copy console output to parallel port */
static void
lpt_putc(int c) {
int i;
for (i = 0; !(inb(LPTPORT + 1) & 0x80) && i < 12800; i ++) {
delay();
}
outb(LPTPORT + 0, cast(uint8_t)c);
outb(LPTPORT + 2, 0x08 | 0x04 | 0x01);
outb(LPTPORT + 2, 0x08);
}
/* cga_putc - print character to console */
static void
cga_putc(int c) {
int pos;
// cursor position: col + 80*row.
outb(CRTPORT, 14);
pos = inb(CRTPORT + 1) << 8;
outb(CRTPORT, 15);
pos |= inb(CRTPORT + 1);
if (c == '\n') {
pos += 80 - pos % 80;
}
else {
crt[pos ++] = (c & 0xff) | 0x0700;
}
outb(CRTPORT, 14);
outb(CRTPORT + 1, cast(uint8_t)(pos >> 8));
outb(CRTPORT, 15);
outb(CRTPORT + 1, cast(uint8_t)pos);
}
/* serial_putc - copy console output to serial port */
static void
serial_putc(int c) {
int i;
for (i = 0; !(inb(COM1 + COM_LSR) & COM_LSR_TXRDY) && i < 12800;
i ++) {
delay();
}
outb(COM1 + COM_TX, cast(uint8_t)c);
}
/* cons_putc - print a single character to console*/
static void
cons_putc(int c) {
lpt_putc(c);
cga_putc(c);
serial_putc(c);
}
/* cons_puts - print a string to console */
static void
cons_puts(const char *str) {
int i;
for (i = 0; *str != '\0'; i ++) {
cons_putc(str[i]);
}
}
/* bootmain - the entry of bootloader */
static void
bootmain() {
cons_puts("This is a bootloader: Hello world!!");
/* do nothing */
while (true){}
}
****************************
module types;
extern (C):
alias int BOOL;
alias char int8_t;
//C typedef unsigned char uint8_t;
alias ubyte uint8_t;
//C typedef short int16_t;
alias short int16_t;
//C typedef unsigned short uint16_t;
alias ushort uint16_t;
//C typedef int int32_t;
alias int int32_t;
//C typedef unsigned int uint32_t;
alias uint uint32_t;
//C typedef long long int64_t;
alias long int64_t;
//C typedef unsigned long long uint64_t;
alias ulong uint64_t;
********************************
module x86;
import types;
extern (C){
uint8_t inb(uint16_t port);
void outb(uint16_t port, uint8_t data);
}
extern (C) uint8_t inb(uint16_t port) {
uint8_t data;
asm
{
mov DX,port;
in AL,DX;
mov data,AL;
}
return data;
}
extern (C) void outb(uint16_t port, uint8_t data) {
asm
{
mov DX,port;
mov AL,data;
out DX,AL;
}
}
*****************************
bootasm:bootasm.S asm.h
rm obj\*.o -rf
gcc -I. -fno-builtin -Wall -ggdb -m16 -nostdinc
-fno-stack-protector -Os -nostdinc -c bootasm.S -o obj/bootasm.o
bootmain:bootmain.d types.d x86.d
ldc2 -L=Os -c $^ -odobj
all:bootasm bootmain
******************************
bootblock:bootasm.o bootmain.o x86.o types.o
ld -m elf_i386 -N -e start -Ttext 0x7C00 $^ -o bootblock.o
objdump -S bootblock.o > bootblock.asm
objcopy -S -O binary bootblock.o bootblock.out
rm bootblock -f
./writeHDD bootblock.out bootblock
dd if=/dev/zero of=ucore.img count=10000
dd if=bootblock of=ucore.img conv=notrunc
More information about the digitalmars-d-ldc
mailing list