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