2 Star 5 Fork 4

稀风 / KOS

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
Build4.py 8.25 KB
一键复制 编辑 原始数据 按行查看 历史
稀风 提交于 2023-01-04 19:50 . Build.py 代码优化
import os
import struct
import json
OUTPUT = "output"
IMG = "a.img"
BOOT_SRC = "boot.asm"
BOOT_BIN = "boot.bin"
LOADER_SRC = "loader.asm"
LOADER_BIN = "loader.bin"
KENTRY_SRC = "kentry.asm"
KENTRY_O = "kentry.o"
KERNEL_OUT = "kernel.out"
KERNEL_BIN = "kernel.bin"
ROOT = os.getcwd() # 获取当前所在路径的绝对路径作为工程根目录
BUILD_CFG = "BUILD.json" # 编译配置文件名
project = {} # 通过递归遍历编译配置文件 BUILD_CFG 后所得信息放入 project 字典中
# 该函数通过递归遍历路径 path 下的所有的 BUILD.json 文件,
# 并将遍历后的结果以 '源文件文件名':['源文件所在路径', ['源文件所包含的头文件路径1', '源文件所包含的头文件路径1']]
# 这种形式的数据添加到字典 project 中
def Parse_BUILD_CFG(path):
JsonPathName = os.path.join(path, BUILD_CFG)
# 以只读方式打开文件 JsonPathName
with open(JsonPathName, 'r') as f:
# 读取文件内容到 json_text
json_text = f.read()
# 将 json_text 内容转为 python 字典 json_dict
json_dict = json.loads(json_text)
# 遍历字典 json_dict
for key in json_dict:
if key == 'src': # 如果是源文件,则将 '源文件文件名':['源文件所在路径', ['源文件所包含的头文件路径1', '源文件所包含的头文件路径1']] 这种形式的数据添加到字典 project 中
if json_dict[key]:
for item in json_dict[key]:
project[item] = [path, json_dict['inc']]
elif key == 'dir': # 如果是文件夹,则进入该文件夹内,递归调用 Parse_BUILD_CFG
if json_dict[key]:
for item in json_dict[key]:
new_path = os.path.join(path, item)
Parse_BUILD_CFG(new_path)
elif key == 'inc': # 如果是头文件路径,则不处理
pass
else:
print("Invalid key")
return project
# 编译 boot
def compile_boot(boot_src, boot_bin):
# 切换到 boot.asm 所在的目录
cmd_str = os.path.join(ROOT, project[boot_src][0])
print('Enter: ' + cmd_str)
os.chdir(cmd_str)
# 编译 boot.asm
src = boot_src
out = os.path.join(ROOT, OUTPUT, boot_bin)
cmd_str = "nasm " + src + " -o " + out
print(cmd_str)
os.system(cmd_str)
# 编译 loader
def compile_loader(loader_src, loader_bin):
# 切换到 loader.asm 所在的目录
cmd_str = os.path.join(ROOT, project[loader_src][0])
print('Enter: ' + cmd_str)
os.chdir(cmd_str)
# 编译 loader.asm
src = loader_src
out = os.path.join(ROOT, OUTPUT, loader_bin)
cmd_str = "nasm " + src + " -o " + out
print(cmd_str)
os.system(cmd_str)
# 编译内核
def compile_kernel(kernel_src):
# 遍历 kernel 源文件
for key in kernel_src:
if key[-2:] == '.c':
# 切换到 .c 源文件所在的目录
cmd_str = os.path.join(ROOT, kernel_src[key][0])
print('Enter: ' + cmd_str)
os.chdir(cmd_str)
# 获取包含头文件路径
include = ''
for item in kernel_src[key][1]:
tmp = ' -I' + os.path.join(ROOT, item)
include += tmp
# 编译 .c 文件
# 例:gcc -m32 -Iinclude -c main.c -o main.o
src = key
obj = key[0:-2] + '.o'
out = os.path.join(ROOT, OUTPUT, obj)
cmd_str = 'gcc -m32 -nostdinc -fno-stack-protector' + include + " -c " + src + " -o " + out
print(cmd_str)
os.system(cmd_str)
elif key[-4:] == '.asm':
# boot.asm 和 loader.asm 已经单独处理过了
if key != 'boot.asm' and key != 'loader.asm':
# 切换到 .asm 源文件所在的目录
cmd_str = os.path.join(ROOT, kernel_src[key][0])
print('Enter: ' + cmd_str)
os.chdir(cmd_str)
# 编译 .asm 文件
src = key
obj = key[0:-4] + '.o'
out = os.path.join(ROOT, OUTPUT, obj)
cmd_str = "nasm -f elf32 " + src + " -o " + out
print(cmd_str)
os.system(cmd_str)
else:
print(key + " is unknow.")
# 链接 kernel obj 临时文件
def ld_kernel_obj(kernel_out):
# 遍历 .o 文件
obj = ''
for item in os.listdir(os.path.join(ROOT, OUTPUT)):
# 排除 kentry.o,它是 kernel 程序的入口,链接时需要放在最前面。其它 .o 文件链接时不考虑先后顺序
if item[-2:] == '.o' and item != 'kentry.o':
tmp = ' ' + item
obj += tmp
# 链接 kernel
src = KENTRY_O + obj
out = kernel_out
cmd_str = "ld -Ttext 0xB000 -s -m elf_i386 -o " + out + " " + src
print(cmd_str)
os.system(cmd_str)
# 提取 elf 程序中的 bin 有效数据
def elf_2_bin(elf, bin):
# 将 kernel.out 转为 kernel.bin
# objcopy -O binary kernel.out kernel.bin
src = elf
out = bin
cmd_str = "objcopy -O binary " + src + " " + out
print(cmd_str)
os.system(cmd_str)
# 生成最终系统镜像
def write_img(boot_bin, loader_bin, kernel_bin):
# 获取 loader.bin 所占扇区数
stats = os.stat(loader_bin)
loader_blocks = int(stats.st_size / 512) + 1
# 获取 kernel.bin 所占扇区数
stats = os.stat(kernel_bin)
kernel_blocks = int(stats.st_size / 512) + 1
# 创建一个 60M 的虚拟硬盘,由于搭了两套开发环境,所以这里 bximage 有两种命令格式
# 使用 “bximage --help” 命令可获得 bximage 的用法
# 另一个:bximage $@ -func="create" -hd=60 -imgmode="flat" -q
# 自动计算虚拟硬盘大小,单位 M
hard_size = int(os.stat(kernel_bin).st_size/1024/1024) + 2
cmd_str = "bximage " + IMG + ' -hd -size=' + str(hard_size) + ' -mode="flat" -q'
print(cmd_str)
os.system(cmd_str)
# 将 boot.bin 写入硬盘 a.img 的扇区 0
cmd_str = "dd if=" + boot_bin + " of=" + IMG + " bs=512 count=1 conv=notrunc"
print(cmd_str)
os.system(cmd_str)
# 将 loader.bin 写入硬盘 a.img 的扇区 2
cmd_str = "dd if=" + loader_bin + " of=" + IMG + " bs=512 count=" + str(loader_blocks) + " seek=2 conv=notrunc"
print(cmd_str)
os.system(cmd_str)
# 将 kernel.bin 写入硬盘 a.img 的扇区 3
# cmd_str = "dd if=" + KERNEL_BIN + " of=" + IMG + " bs=512 count=" + str(kernel_blocks) + " seek=3 conv=notrunc"
cmd_str = "dd if=" + kernel_bin + " of=" + IMG + " bs=512 count=" + str(kernel_blocks) + " seek=" + str(2+loader_blocks) + " conv=notrunc"
print(cmd_str)
os.system(cmd_str)
# 读取 IMG 文件,将 loader.bin 所占扇区数写到扇区 1 的前两个字节中;将 kernel.bin 所占扇区数写到扇区 1 的第 3-4 字节中
img = []
with open(IMG, "rb") as f:
data = f.read()
for i in range(len(data)):
img.append(data[i])
img[512] = loader_blocks
img[513] = loader_blocks>>8
img[514] = kernel_blocks
img[515] = kernel_blocks>>8
with open(IMG, 'wb') as f:
for x in img:
f.write(struct.pack('B', x))
# 打印 project
def print_project(project):
for item in project:
str_print = item + ': ' + str(project[item])
print(str_print)
def main():
# 路径为空即表示当前所在目录
root_path = ''
project = Parse_BUILD_CFG(root_path)
# 打印 project
# print_project(project)
# 创建文件夹 output
if not os.path.exists(OUTPUT):
os.mkdir(OUTPUT)
# 编译 boot
compile_boot(BOOT_SRC, BOOT_BIN)
# 编译 loader
compile_loader(LOADER_SRC, LOADER_BIN)
# 编译 kernel
compile_kernel(project)
# 切换到 OUTPUT 目录下
cmd_str = os.path.join(ROOT, OUTPUT)
print('Enter: ' + cmd_str)
os.chdir(cmd_str)
# 链接 kernel obj 临时文件
ld_kernel_obj(KERNEL_OUT)
# 提取 elf 程序中的 bin 有效数据
elf_2_bin(KERNEL_OUT, KERNEL_BIN)
# 生成最终系统镜像
write_img(BOOT_BIN, LOADER_BIN, KERNEL_BIN)
print("Success!")
if __name__ == '__main__':
main()
1
https://gitee.com/thin-wind/KOS.git
git@gitee.com:thin-wind/KOS.git
thin-wind
KOS
KOS
main

搜索帮助

53164aa7 5694891 3bd8fe86 5694891