/* setup.S
*I don't mean to write the whole OS kernel.I just want to put what I have
*already learned into practice.But what will it be end up looking like.
*I don't know.ALA I have some free time,I will write something.Just like
*linus once said,"Just for fun".I don't care what this small ugly codes
*will be capable of,or does it worth something.I just write it for fun,
*and for practice.
* 10 / 3 / 2010 liangtao
* E-mail:liangtao90s@gmail.com
*As simple as possible.Because I don't have all the information about the
*underlying hardware,So only the currently critical information is obtaind
*by the bios call.Others will be add ASA we need them.
*/
/*
* add memory probe code.as for now, the existed code can generate something
* on the screen.so i think it's time to add this code.it will be more easy
* to debug.just print the memory probe info on the screen. 10 / 12/ 2010
*/
#define __ASM__
#include
#include
#include
#define __DEBUG__ 0
INITSEG = 0x9000
SETUPSEG = 0x9020
.code16
.global begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text
_start:
#if __DEBUG__
movw $SETUPSEG, %ax
movw %ax, %ds
call print_msg
movw $INITSEG, %ax
movw %ax, %ds
#endif
movb $0x03, %ah
int $0x10
movw %dx, (0)
#get the memory map through BIOS call.first try e820h,then e801h, finally
#the traditional 88h way.
#define SMAP 0x534d4150
xorw %ax, %ax
movw %ax, (E820_MAP_NR)
movw $E820_MAP_OFF, %di
xorl %ebx, %ebx
mem_e820_probe:
movw $E820_MAP_SEG, %ax
movw %ax, %es
movl $20, %ecx
movl $SMAP, %edx
movl $0xe820, %eax
int $0x15
jc mem_e801_probe
cmpl $SMAP, %edx
jne mem_e801_probe
movw (E820_MAP_NR), %ax
cmpw $E820_MAP_NR_MAX, %ax
jnl mem_e801_probe
incw (E820_MAP_NR)
movw %di, %ax
addw $20, %ax
movw %ax, %di
cmpl $0, %ebx
jne mem_e820_probe
mem_e801_probe:
xorw %ax, %ax
movw %ax, (E801_FLAG)
movw $0xe801, %ax
int $0x15
jc mem88_probe
incb (E801_FLAG)
andl $0xffff, %eax
movl %eax, (E801_PART1)
andl $0xffff, %ebx
movl %ebx, (E801_PART2)
mem88_probe:
xorb %al, %al
movb %al, (MEM88_FLAG)
movb $0x88, %ah
int $0x15
jc mem_probe_end
incb (MEM88_FLAG)
# andl $0xffff, %eax
movw %ax, (MEM88_EXT)
mem_probe_end:
movw $SETUPSEG, %ax
movw %ax, %ds
#open the a20-gate,prepare to enter the 32-bit protected mode world!
call empty_8042
movb $0xd1, %al
outb %al, $0x64
call empty_8042
movb $0xdf, %al #open it!
out %al, $0x60
call empty_8042
#disable interrupt and nmi.then load idtr and gdtr.
cli
movb $0x80, %al
outb %al, $0x70
movb $0xff, %al #mask all the interrupts
outb %al, $0x21
.word 0x00eb, 0x00eb
outb %al, $0xa1
.word 0x00eb, 0x00eb
lidt idt_48
lgdt gdt_48
#say goodbye to the real mode...
movw $0x0001, %ax
lmsw %ax
jmp flush_instr
flush_instr:
.byte 0x66, 0xea # prefix + jmpi-opcode
.long 0x10000
.word __KERNEL_CS
empty_8042: #taken from linux. setup.S
pushl %ecx #It's more reasonable.
movl $100000, %ecx
empty_8042_loop:
decl %ecx
jz empty_8042_end_loop
call delay
inb $0x64, %al # 8042 status port
testb $1, %al # output buffer?
jz no_output
call delay
inb $0x60, %al # read it
jmp empty_8042_loop
no_output:
testb $2, %al # is input buffer full?
jnz empty_8042_loop # yes - loop
empty_8042_end_loop:
popl %ecx
ret
delay:
outb %al, $0x80
ret
gdt_table:
.long 0, 0 #NULL
.long 0, 0 #reserved
#kernel code segment
.word 0xffff #limit:0-15 bit
.word 0x0000 #base: 0-15 bit
.word 0x9a00 #base: 16-23 bit,type:1010b,s=1,dpl=0,p=1
.word 0x00cf #base: 24-31 bit,G=1,B=1,limit: 16-19
#kernel data segment
.word 0xffff
.word 0x0000
.word 0x9200
.word 0x00cf
idt_48:
.word 0
.word 0, 0
gdt_48:
.word 0x800
.word 0x200+gdt_table, 0x0009 #base address
#if __DEBUG__
msg:
.byte 13, 10
.ascii "I'm in setup"
.byte 13, 10
MSG_LEN = 16
print_msg:
pushw %ax
pushw %bx
pushw %cx
pushw %bp
pushw %es
movw $SETUPSEG, %ax
movw %ax, %es
xorw %bx, %bx
movb $0x03, %ah
int $0x10
movw $MSG_LEN, %cx
movw $0X0007, %bx
movw $msg, %bp
movw $0x1301, %ax
int $0x10
popw %es
popw %bp
popw %cx
popw %bx
popw %ax
ret
#endif
.text
endtext:
.data
enddata:
.bss
endbss:
阅读(2251) | 评论(0) | 转发(0) |