在上一章节,我们验证了在mbr超过512字节时,如何能正确将超出512字节内容加载到内存处,并能正确运行;理解了这点,对于我们下面的加载loader大有帮助。
本章节我们来尝试mbr加载loader.bin文件,并能跳转到loader.bin处执行。
首先,我们得先有个能生成loader.bin的文件才行,我们可以写一个简单的Loader.asm,代码如下:
loader.asm
%include "base_phy.inc"
section code align=16 vstart=0
jmp start
%include "filesystem.inc"
;;;;;;;;;;;栈区空间预留;;;;;;;
stack_rsv:
times 1024 db 0
stack_top:
;;;;;;;;;;;数据区预留;;;;;;;;
loaderMsg db "loader is running...", 0ah,0dh;
loaderMsgLen equ $-loaderMsg
;;;;;;;;;;;代码区;;;;;;;;
start:
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
;栈顶赋值
mov sp, stack_top
;显示loader运行信息
mov cx, loaderMsgLen ; CX = 串长度
push cx
mov cx, loaderMsg
push cx
call showString
pop cx
pop cx
jmp $
;showString(字符串地址,字符串长度)
;在当前当前光标处显示字符串信息
;字符串地址: bp+4
;字符串长度: bp+6
showString:
push bp
mov bp, sp
pusha
mov ax, 0x0300
mov bx, 0
int 0x10
mov cx, [bp+6] ; CX = 串长度
mov bp, [bp+4]
mov ax, 0x1301 ; AH = 0x13, AL = 0x1
mov bx, 0x7 ; 页号为0(BH = 0) 黑底白字(BL = 0x7)
int 0x10 ; int 0x10
popa
pop bp
ret
本章用到的loader.asm代码就这么多,功能也很简单,就是打印个loader is running..., 当前如果能打印出这句话,就说明我们的loader成功获取了cpu执行控制权。
它的效果会如下,我们提前透露下:
为了能运行这个loader.bin,首先要把loader.asm编译成loader.bin, 然后把它磁盘中;在启动bochs后,在mbr里面要能找到这个loader.bin占用的扇区,并能把它的内容加载 到内存指定位置处。
简单来说就是:(1)编译loader.asm -> (2)将loader.bin写入磁盘 -> (3)启动bochs -> (4)mbr寻找并加载Loader.bin ->(5) 控制权给Loader.bin
第一步与第二步其实不难,我们可以用nasm 及在前面说到的文件系统工具(http://blog.csdn.net/b06030927/article/details/73050529)Install_file工具即可。
其实我们的mbr要做的工作主要是:找到Loader.bin并加载它,然后交出控制权。
如何找到loader.bin? 这依赖这个Loader.bin是如何 写入磁盘的。我们使用install_file写入时,这实际是用我们自己的文件系统在组织这个文件的存放。它会占用扇区,Inode相关的信息。我们只要找到它对应的inode,就能找 出它所有的扇区信息。所不同的是我们要用nasm来实现
代码如下:
boot.asm
%include "base_phy.inc"
section mbr align=16 vstart=MACRO_BOOT_ADDR
jmp start
;数据区
bootmsg: db "MBR running..", 0ah,0dh;
bootmsglen: equ $-bootmsg
mbr_left_len dw mbr_end-loader_begin
;代码区
start:
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, MACRO_BOOT_ADDR
;清除屏幕
call clearScreen
;显示mbr加载信息
mov cx, bootmsglen ; CX = 串长度
push cx
mov cx, bootmsg
push cx
call showString
pop cx
pop cx
;计算mbr剩余内容占用的扇区数目,不足一个扇区的按照一个扇区计算
mov dx, 0
mov ax, [mbr_left_len]
add ax, 511
mov bx, 512 ;512字节每扇区
div bx
;MBR只有当前这一个扇区,直接加载loader
cmp ax, 0
jz load_loader
;依次压入起始内存地址,扇区数目,扇区起始号
mov ecx, MACRO_BOOT_LEFT_START_ADDR
push ecx
push ax
mov si, MACRO_BOOT_LEFT_START_SECTOR ;mbr剩余内容的起始扇区
push si
call getDataFromSectors
pop si
pop ax
pop ecx
jmp load_loader
;clearScreen
;清除当前屏所有字符,同时光标设置为起始0,0处
clearScreen:
pusha
mov ax, 0x0600 ; AH = 6, AL = 0
mov bx, 0x0700 ; 黑底白字
mov cx, 0 ; 左上角: (0, 0)
mov dx, 0x184f ; 右下角: (80, 50)
int 0x10 ; int 0x10
mov ax, 0x0200
mov bx, 0
mov dx, 0
int 0x10
popa
ret
;showString(字符串地址,字符串长度)
;在当前当前光标处显示字符串信息
;字符串地址: bp+4
;字符串长度: bp+6
showString:
push bp
mov bp, sp
pusha
mov ax, 0x0300
mov bx, 0
int 0x10
mov cx, [bp+6] ; CX = 串长度
mov bp, [bp+4]
mov ax, 0x1301 ; AH = 0x13, AL = 0x1
mov bx, 0x7 ; 页号为0(BH = 0) 黑底白字(BL = 0x7)
int 0x10 ; int 0x10
popa
pop bp
ret
;getDataFromSectors(起始扇区号,扇区数目,起始内存地址)
;从指定扇区位置处连续加载指定数目个扇区到指定的内存起始位置处
;起始扇区号;bp+4 2字节
;扇区数目; bp+6 2字节
;起始内存地址: bp+8 4字节
getDataFromSectors:
push bp
mov bp, sp
pusha
push es
;加载的内存起始地址
mov ecx, [bp+8]
;要读取的扇区数目
mov ax, [bp+6]
;起始扇区号
mov si, [bp+4]
;剩余内容加载 到es:di起始处
push ecx
shr ecx, 4
mov es, cx
pop ecx
and ecx, 0x000f
mov di, cx
mov dx,0x1f2
out dx,al ;读取的扇区数
inc dx ;0x1f3
mov ax,si
out dx,al ;LBA地址7~0
inc dx ;0x1f4
mov al,ah
out dx,al ;LBA地址15~8
xor ax, ax
inc dx ;0x1f5
out dx,al ;LBA地址23~16
inc dx ;0x1f6
mov al,0xe0 ;LBA28模式,主盘
out dx,al
inc dx ;0x1f7
mov al,0x20 ;读命令
out dx,al
.waits:
in al,dx
and al,0x88
cmp al,0x08
jnz .waits ;不忙,且硬盘已准备好数据传输
;计算要循环读取的字节数目,由于一次读取是2个字节,因此总字节除以2
mov ax, [bp+6]
mov bx, 512
mul bx
mov bx, 2
div bx
mov cx, ax
mov dx,0x1f0
.readw:
in ax,dx
mov [es:di],ax
add di, 2
loop .readw
pop es
popa
pop bp
ret
times 510-($-$$) db 0
db 0x55, 0xaa
;剩余内容
loader_begin:
loadermsg: db "Try to search loader and load it..", 0ah,0dh;
loadermsglen: equ $-loadermsg
loadername db "loader.bin",0h
loadernamelen: equ $-loadername
loadernotfoundmsg: db "Failed to find the loader.bin, quit..", 0ah,0dh;
loadernotfoundmsglen: equ $-loadernotfoundmsg
;临时数据区,用来保存读取一个扇区内容
tempbuffer: times 512 db 0
tempinodeinfobuffer: times 64 db 0
tempoutresult: times 2 db 0
%include "filesystem.inc"
load_loader:
;显示mbr加载信息
mov cx, loadermsglen ; CX = 串长度
push cx
mov cx, loadermsg
push cx
call showString
pop cx
pop cx
;获取系统块区
mov ebx, tempbuffer
push ebx
call getSystemBlockData
pop ebx
cmp dword [tempbuffer+MACRO_DDFS_FILESYSTEM_SYSTEMBLOCK_OFFSET_USEDINODENUM], 0
jz loadernotfound
;2.读取inodebitmap位图,按照位图再读取对应inodeinfo信息,检查是否是Loader.bin
mov ebx, tempbuffer
push ebx
call getInodeBitMapData
pop ebx
mov cx, MACRO_DDFS_FILESYSTEM_INODE_NUM
mov ax, 0
check_bit_is_set:
mov ebx, tempoutresult
push ebx
mov ebx, tempbuffer
push ebx
mov bx, ax
push bx
call checkBitIsSet
pop bx
pop ebx
pop ebx
cmp word [tempoutresult], 1
jz getinodeinfo
search_next_bit:
inc ax
loop check_bit_is_set
jmp loadernotfound
getinodeinfo:
;根据inode索引(保存在dx中)计算它对应的Inodeinfo所有的起始扇区及偏移位置
mov ebx, tempinodeinfobuffer
push ebx
push ax
call getInodeInfoByInodeIndex
pop ax
pop ebx
mov ebx, tempoutresult
push ebx
mov bx, loadernamelen
push bx
mov ebx, loadername
push ebx
mov ebx, tempinodeinfobuffer
push ebx
call checkFileNameIsSame
pop ebx
pop ebx
pop bx
pop ebx
cmp word [tempoutresult], 1
jnz search_next_bit
file_is_same:
;获取文件起始扇区
mov bx, tempinodeinfobuffer
add bx, MACRO_DDFS_FILESYSTEM_INODEINFO_OFFSET_FILESTARTSECTOR
mov ax, [bx] ;起始扇区号
mov ebx, MACRO_LOADER_ADDR
load_all_loader:
push ebx
mov cx, 1
push cx
mov cx, ax
push cx
call getDataFromSectors
pop cx
pop cx
pop ebx
;计算下一个扇区
mov ecx, tempbuffer
push ecx
mov cx, ax
push cx
call getFileSectorListBySector
pop cx
pop ecx
mov cx, [tempbuffer+MACRO_DDFS_FILESYSTEM_FILESECTORLIST_OFFSET_ISNEXTVALID]
cmp cx, 1
jnz jmp_loader
get_next_sector:
mov ax, [tempbuffer+MACRO_DDFS_FILESYSTEM_FILESECTORLIST_OFFSET_NEXTSECTOR]
add ebx, 512
jmp load_all_loader
jmp_loader:
mov ebx, MACRO_LOADER_ADDR
and ebx, 0xf
mov ax, bx
mov ebx, MACRO_LOADER_ADDR
shr ebx, 4
mov [tempbuffer], ax
mov [tempbuffer+2], bx
jmp far [tempbuffer]
loadernotfound:
mov cx, loadernotfoundmsglen ; CX = 串长度
push cx
mov cx, loadernotfoundmsg
push cx
call showString
pop cx
pop cx
jmp $
mbr_end:
上面的loader.asm 与boot.asm都include了一个filesystem.inc, 这是我们新增加的一个文件,用来把文件系统操作的相关的函数 封装在里面,方便我们进行调用。
filesystem.inc如下
filesystem.inc
;文件系统相关的宏定义
MACRO_DDFS_SYSTEMBLOCK_START_SECTOR_NO EQU 1
MACRO_DDFS_SYSTEMBLOCK_SECTOR_NUM EQU 1
MACRO_DDFS_SECTORBITMAP_START_SECTOR_NO EQU 2
MACRO_DDFS_SECTORBITMAP_SECTOR_NUM EQU 1
MACRO_DDFS_INODEBITMAP_START_SECTOR_NO EQU 3
MACRO_DDFS_INODEBITMAP_SECTOR_NUM EQU 1
MACRO_DDFS_INODEINFO_START_SECTOR_NO EQU 4
MACRO_DDFS_INODEINFO_SECTOR_NUM EQU 512
MACRO_DDFS_FILESECTORLIST_START_SECTOR_NO EQU 516
MACRO_DDFS_FILESECTORLIST_SECTOR_NUM EQU 32
MACRO_DDFS_FILEDATA_START_SECTOR_NO EQU 548
MACRO_DDFS_FILEDATA_SECTOR_NUM EQU 3548
MACRO_DDFS_FILESYSTEM_SIZE_SYSTEMBLOCK EQU 16
MACRO_DDFS_FILESYSTEM_SYSTEMBLOCK_OFFSET_TOTALSECTORNUM EQU 0
MACRO_DDFS_FILESYSTEM_SYSTEMBLOCK_OFFSET_USEDSECTORNUM EQU 4
MACRO_DDFS_FILESYSTEM_SYSTEMBLOCK_OFFSET_TOTALINODENUM EQU 8
MACRO_DDFS_FILESYSTEM_SYSTEMBLOCK_OFFSET_USEDINODENUM EQU 12
MACRO_DDFS_FILESYSTEM_SIZE_INODEINFO EQU 64
MACRO_DDFS_FILESYSTEM_INODEINFO_OFFSET_FILENAME EQU 0
MACRO_DDFS_FILESYSTEM_INODEINFO_OFFSET_FILESIZE EQU 32
MACRO_DDFS_FILESYSTEM_INODEINFO_OFFSET_FILESECTORNUM EQU 36
MACRO_DDFS_FILESYSTEM_INODEINFO_OFFSET_FILESTARTSECTOR EQU 40
MACRO_DDFS_FILESYSTEM_SIZE_FILESECTORLIST EQU 8
MACRO_DDFS_FILESYSTEM_FILESECTORLIST_OFFSET_ISNEXTVALID EQU 0
MACRO_DDFS_FILESYSTEM_FILESECTORLIST_OFFSET_NEXTSECTOR EQU 4
MACRO_DDFS_FILESYSTEM_INODE_NUM EQU 4096
globalSectorSpace: times 512 db 0
;-------------------------------------------------------------
;函数名:getDiskDataFromSectors(起始扇区号, 扇区数目, 起始内存地址)
;函数说明:从指定起始扇区处连续加载指定扇区数目的数据到指定的内存起始位置处
;函数参数:
; 参数说明 参数位置 参数大小
; 起始扇区号, bp+4 2字节
; 扇区数目, bp+6 2字节
; 起始内存地址: bp+8 4字节
;返回值:
; 无
;-------------------------------------------------------------
getDiskDataFromSectors:
push bp
mov bp, sp
pushad
push es
;加载的内存起始地址
mov ecx, [bp+8]
;要读取的扇区数目
mov ax, [bp+6]
;起始扇区号
mov si, [bp+4]
;剩余内容加载 到es:di起始处
push ecx
shr ecx, 4
mov es, cx
pop ecx
and ecx, 0x000f
mov di, cx
mov dx,0x1f2
out dx,al ;读取的扇区数
inc dx ;0x1f3
mov ax,si
out dx,al ;LBA地址7~0
inc dx ;0x1f4
mov al,ah
out dx,al ;LBA地址15~8
xor ax, ax
inc dx ;0x1f5
out dx,al ;LBA地址23~16
inc dx ;0x1f6
mov al,0xe0 ;LBA28模式,主盘
out dx,al
inc dx ;0x1f7
mov al,0x20 ;读命令
out dx,al
.waits:
in al,dx
and al,0x88
cmp al,0x08
jnz .waits ;不忙,且硬盘已准备好数据传输
;计算要循环读取的字节数目,由于一次读取是2个字节,因此总字节除以2
mov ax, [bp+6]
mov bx, 512
mul bx
mov bx, 2
div bx
mov cx, ax
mov dx,0x1f0
.readw:
in ax,dx
mov [es:di],ax
add di, 2
loop .readw
pop es
popad
pop bp
ret
;-------------------------------------------------------------
;函数名:getSystemBlockData(buf)
;函数说明:获取文件系统块,保存buf中
;函数参数:
; 参数说明 参数位置 参数大小
; buf bp+4 4字节
;返回值:
; 无
;补充说明:
;-------------------------------------------------------------
getSystemBlockData:
push bp
mov bp, sp
pushad
mov eax, [bp+4]
push eax
mov ax, MACRO_DDFS_SYSTEMBLOCK_SECTOR_NUM
push ax
mov ax, MACRO_DDFS_SYSTEMBLOCK_START_SECTOR_NO
push ax
call getDiskDataFromSectors
pop ax
pop ax
pop eax
popad
pop bp
ret
;-------------------------------------------------------------
;函数名:getInodeBitMapData(buf)
;函数说明:获取inodebitmap,保存到buf中
;函数参数:
; 参数说明 参数位置 参数大小
; buf bp+4 4字节
;返回值:
; 无
;补充说明:
;-------------------------------------------------------------
getInodeBitMapData:
push bp
mov bp, sp
pushad
mov eax, [bp+4]
push eax
mov ax, MACRO_DDFS_INODEBITMAP_SECTOR_NUM
push ax
mov ax, MACRO_DDFS_INODEBITMAP_START_SECTOR_NO
push ax
call getDiskDataFromSectors
pop ax
pop ax
pop eax
popad
pop bp
ret
;-------------------------------------------------------------
;函数名:getInodeInfoByInodeIndex(inodeindex, buf)
;函数说明:通过inode索引获取对应的inodeinfo
;函数参数:
; 参数说明 参数位置 参数大小
; inodeindex bp+4 2
; buf bp+6 4字节
;返回值:
; eax: 0:未使用 1:已经使用
;补充说明:
;-------------------------------------------------------------
getInodeInfoByInodeIndex:
push bp
mov bp, sp
pushad
mov ax, [bp+4]
xor edx, edx
mov bx, MACRO_DDFS_FILESYSTEM_SIZE_INODEINFO
mul bx
;除以512后,ax保存扇区偏移,dx保存扇区内偏移
mov bx, 512
div bx
add ax, MACRO_DDFS_INODEINFO_START_SECTOR_NO
mov ebx, globalSectorSpace
push ebx
mov bx, 1
push bx
mov bx, ax
push bx
call getDiskDataFromSectors
pop bx
pop bx
pop ebx
;将64字节内容拷贝到用户区
push es
push ds
mov ebx, globalSectorSpace
add ebx, edx
push ebx
shr ebx, 4
mov ds, bx
pop ebx
and ebx, 0xf
mov si, bx
mov ebx, [bp+6]
push ebx
shr ebx, 4
mov es, bx
pop ebx
and ebx, 0xf
mov di, bx
mov cx, MACRO_DDFS_FILESYSTEM_SIZE_INODEINFO
cld
rep movsb
pop ds
pop es
popad
pop bp
ret
;-------------------------------------------------------------
;函数名:getFileSectorListBySector(sector, buf)
;函数说明:通过Secto索引获取对应的filesectorlist信息
;函数参数:
; 参数说明 参数位置 参数大小
; sector bp+4 2
; buf bp+6 4字节
;返回值:
; eax: 0:未使用 1:已经使用
;补充说明:
;-------------------------------------------------------------
getFileSectorListBySector:
push bp
mov bp, sp
pushad
mov ax, [bp+4]
xor edx,edx
mov bx, MACRO_DDFS_FILESYSTEM_SIZE_FILESECTORLIST
mul bx
mov bx,512
div bx
mov ebx, globalSectorSpace
push ebx
mov bx, 1
push bx
mov bx, MACRO_DDFS_FILESECTORLIST_START_SECTOR_NO
add bx, ax
push bx
call getDiskDataFromSectors
pop bx
pop bx
pop ebx
;将8字节内容拷贝到用户区
push es
push ds
mov ebx, globalSectorSpace
add ebx, edx
push ebx
shr ebx, 4
mov ds, bx
pop ebx
and ebx, 0xf
mov si, bx
mov ebx, [bp+6]
push ebx
shr ebx, 4
mov es, bx
pop ebx
and ebx, 0xf
mov di, bx
mov cx, MACRO_DDFS_FILESYSTEM_SIZE_FILESECTORLIST
cld
rep movsb
pop ds
pop es
popad
pop bp
ret
;-------------------------------------------------------------
;函数名:checkFileNameIsSame(dstFileName, srcFileName, FileLen, outBuf)
;函数说明:比较指定长度的源目的文件名是否相同
;函数参数:
; 参数说明 参数位置 参数大小
; dstFileName bp+4 4字节
; srcFileName bp+8 4字节
; dstFileName bp+12 2字节
; outBuf bp+14 4字节
;返回值:
; outBuf: 0:不相同 1:相同
;补充说明:
;-------------------------------------------------------------
checkFileNameIsSame:
push bp
mov bp, sp
pushad
push ds
push es
mov ebx, [bp+4]
push ebx
shr ebx, 4
mov ds, bx
pop ebx
and ebx, 0xf
mov si, bx
mov ebx, [bp+8]
push ebx
shr ebx, 4
mov es, bx
pop ebx
and ebx, 0xf
mov di, bx
mov cx, [bp+12]
cld
repz cmpsb
cmp cx, 0
jz file_name_same
mov ebx, [bp+14]
push ebx
shr ebx, 4
mov ds, bx
pop ebx
and ebx, 0xf
mov si, bx
mov word [si], 0
pop es
pop ds
popad
pop bp
ret
file_name_same:
mov ebx, [bp+14]
push ebx
shr ebx, 4
mov ds, bx
pop ebx
and ebx, 0xf
mov si, bx
mov word [si], 1
pop es
pop ds
popad
pop bp
ret
;-------------------------------------------------------------
;函数名:checkFileNameIsSame(bitIndex, bitBuffer, outBuf)
;函数说明:比较指定长度的源目的文件名是否相同
;函数参数:
; 参数说明 参数位置 参数大小
; bitIndex bp+4 2字节
; bitBuffer bp+6 4字节
; outBuf bp+10 4字节
;返回值:
; outBuf: 0:不相同 1:相同
;补充说明:
;-------------------------------------------------------------
checkBitIsSet:
push bp
mov bp, sp
pushad
xor eax, eax
mov ax, [bp+4]
mov ebx, [bp+6]
mov ecx, [bp+10]
push ebx
xor dx, dx
mov bx, 8
div bx
pop ebx
add ebx, eax
push ds
push ebx
shr ebx, 4
mov ds, bx
pop ebx
and ebx, 0xf
mov si, bx
bt [si], dx
jc bit_is_set
push ecx
shr ecx, 4
mov ds, cx
pop ecx
and ecx, 0xf
mov si, cx
mov word [si], 0
pop ds
popad
pop bp
ret
bit_is_set:
push ecx
shr ecx, 4
mov ds, cx
pop ecx
and ecx, 0xf
mov si, cx
mov word [si], 1
pop ds
popad
pop bp
ret
base_phy.inc文件基本没有修改,沿用以前的,从这里面我们能看到Loader会被加载到0x10000内存处(我们的mbr是加载到0x7c00处)
base_phy,inc
MACRO_BOOT_ADDR equ 0x7c00
MACRO_BOOT_LEFT_START_SECTOR equ 4096
MACRO_BOOT_LEFT_START_ADDR equ MACRO_BOOT_ADDR+512
MACRO_LOADER_ADDR equ 0x10000
MACRO_KERNEL_ADDR equ 0x500000
MACRO_GDT_ADDR equ 0x8000
MACRO_PAGEDIR_ADDR equ 0x20000
MACRO_PAGETBL_ADDR equ 0x21000
现在我们涉及到的代码者在上面了,对于 Loader.asm还要新增加它对应的makefile及适配build_all.sh
loader.asm的makeFile
.PHONY : all clean loader loader_clean
all : loader ../include/base_phy.inc ../include/filesystem.inc
loader : loader.asm
$(ASM) $(ASMFLAG) $< -o $(RELEASE_LOADER_NAME)
clean : loader_clean
loader_clean :
rm $(RELEASE_LOADER_NAME)
在build_all.sh中增加对Loader的适配(bulild_loader)
#!/bin/sh
#对变量赋值:
source ./env.sh
function bulild_root()
{
if [ ! -d $RELEASE_BOOT_DIR ]
then
mkdir -p $RELEASE_BOOT_DIR
else
rm -rf $RELEASE_BOOT_DIR/*
fi
make -C boot
if [ ! -f $RELEASE_BOOT_NAME ]
then
echo "Error in build root"
return 1
fi
dd if=/dev/zero of=$IMG_NAME bs=512 count=1 conv=notrunc
dd if=$RELEASE_BOOT_NAME of=$IMG_NAME bs=512 count=1 conv=notrunc
dd if=$RELEASE_BOOT_NAME of=$IMG_NAME bs=1 count=$((`du -b $RELEASE_BOOT_NAME | cut -f 1` - 512)) conv=notrunc skip=512 seek=2097152
return 0
}
function bulild_loader()
{
if [ ! -d $RELEASE_LOADER_DIR ]
then
mkdir -p $RELEASE_LOADER_DIR
else
rm -rf $RELEASE_LOADER_DIR/*
fi
make -C loader
if [ ! -f $RELEASE_LOADER_NAME ]
then
echo "Error in build loader"
return 1
fi
#loaderfilesize=`ls -l $RELEASE_LOADER_NAME | cut -d " " -f 5`
#dd if=/dev/zero of=$IMG_NAME bs=1 count=$loaderfilesize seek=512 conv=notrunc
#dd if=$RELEASE_LOADER_NAME of=$IMG_NAME bs=1 count=$loaderfilesize seek=512 conv=notrunc
$RELEASE_TOOLS_INSTALL_FILE $IMG_NAME $RELEASE_LOADER_NAME
return 0
}
function bulild_kernel()
{
if [ ! -d $RELEASE_KERNEL_DIR ]
then
mkdir -p $RELEASE_KERNEL_DIR
else
rm -rf $RELEASE_KERNEL_DIR/*
fi
make -C kernel
if [ ! -f $RELEASE_KERNEL_NAME ]
then
echo "Error in build kernel"
return 1
fi
kernelfilesize=`ls -l $RELEASE_KERNEL_NAME | cut -d " " -f 5`
dd if=/dev/zero of=$IMG_NAME bs=1 count=$kernelfilesize seek=51200 conv=notrunc
dd if=$RELEASE_KERNEL_NAME of=$IMG_NAME bs=1 count=$kernelfilesize seek=51200 conv=notrunc
return 0
}
if [ -z $1 ] || [ $1 == all ]
then
echo build all
bulild_root
bulild_loader
bulild_kernel
elif [ $1 == boot ]
then
echo build boot
bulild_root
elif [ $1 == loader ]
then
echo build loader
bulild_loader
elif [ $1 == kernel ]
then
echo build kernel
bulild_kernel
else
echo "./build.sh [ boot | loader | kernel | all]"
exit 0
fi
env.sh里面增加Loader路径
#!/bin/sh
#对变量赋值:
export ASM=nasm
export ASMFLAG="-I `pwd`/include/"
export CC=gcc
export RELEASE=`pwd`/release
export IMG_NAME=`pwd`/os.img
#boot
export RELEASE_BOOT_DIR=`pwd`/release/boot
export RELEASE_BOOT_NAME=`pwd`/release/boot/boot.bin
#loader
export RELEASE_LOADER_DIR=`pwd`/release/loader
export RELEASE_LOADER_NAME=`pwd`/release/loader/loader.bin
#kernel
export RELEASE_KERNEL_DIR=`pwd`/release/kernel
export RELEASE_KERNEL_NAME=`pwd`/release/kernel/kernel.bin
#tools
export RELEASE_TOOLS_DIR=`pwd`/release/tools
export RELEASE_TOOLS_READDDFS=`pwd`/release/tools/readddfs
export RELEASE_TOOLS_MKDDFS=`pwd`/release/tools/mkddfs
export RELEASE_TOOLS_INSTALL_FILE=`pwd`/release/tools/install_file
这样我们修改的文件如下:
pengsheng@pengsheng-VirtualBox:/media/sf_E_DRIVE/ubuntu_backup/BRANCHS_OS/DD_OS$ tree
.
├── app
├── bochsrc
├── boot
│ ├── boot.asm
│ └── Makefile
├── build_all.sh
├── env.sh
├── include
│ ├── base_phy.inc
│ └── filesystem.inc
├── kernel
│ ├── kernel.asm
│ └── Makefile
├── loader
│ ├── loader.asm
│ └── Makefile
├── os.img
├── release
│ ├── boot
│ │ └── boot.bin
│ ├── kernel
│ │ └── kernel.bin
│ ├── loader
│ │ └── loader.bin
│ └── tools
│ ├── install_file
│ ├── mkddfs
│ └── readddfs
├── test.img
├── tools
│ ├── ddfs.c
│ ├── ddfs.h
│ ├── install_file.c
│ ├── Makefile
│ ├── mkddfs.c
│ └── readddfs.c
└── 设计相关
├── 临时设计.xls
└── 流程图.vsd
12 directories, 27 files
pengsheng@pengsheng-VirtualBox:/media/sf_E_DRIVE/ubuntu_backup/BRANCHS_OS/DD_OS$
下一章节我们对改装后的boot.asm进行详细讲解。有兴趣的可以尝试下编译。
build_all.sh boot
build_all.sh loader
bochs
ps提供下bochsrc文件。
###############################################################
# Configuration file for Bochs
###############################################################
# how much memory the emulated machine will have
megs: 32
# filename of ROM images
romimage: file=/usr/share/bochs/BIOS-bochs-latest
vgaromimage: file=/usr/share/vgabios/vgabios.bin
# what disk images will be used
#floppya: 1_44=a.img, status=inserted
# hard disk
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
# !! Remember to change these if the hd img is changed:
# 1. include/sys/config.h::MINOR_BOOT
# 2. boot/include/load.inc::ROOT_BASE
# 3. Makefile::HD
# 4. commands/Makefile::HD
ata0-master: type=disk, path="os.img", mode=flat, cylinders=40, heads=16, spt=63
#ata0-master: type=disk, path="20m.img", mode=flat, cylinders=40, heads=16, spt=63
# choose the boot disk.
boot: disk
# where do we send log messages?
# log: bochsout.txt
# disable the mouse
mouse: enabled=0
# enable key mapping, using US layout as default.
keyboard_mapping: enabled=1, map=/usr/share/bochs/keymaps/x11-pc-us.map