最近在EDK II的基础上开发一个程序,实际上是把现有的基于EDK的代码移植到EDK II上。稍微写点心得。
第一步,当然就是搭环境。EDK II申明的是可以在Windows,Linux下编译,支持的编译工具则非常多,在tools_def.txt 里可以看到分别的名称,例如VS2003, VS2005, GCC, DDK3790等,找到自己喜欢的,改到target.txt里的TOOL_CHAIN_TAG变量,就可以开始编译了。
这里要提醒一句的是:edksetup.bat有一个参数是ForceRebuild,这个参数会把BaseTools里的所有现有的exe文件都删掉,但BaseTools的make文件写的不完整,在删掉之后并不能生成所有的exe文件,例如build.exe就不能正常生成(不知道安装python之后是否可以,但安装python之后还需要安装cx_Freeze去用py文件生成exe文件,找cx_Freeze了找了好久没找到,放弃了)
第二步,编译生成emulator,也就是windows下的模拟器,这样在没有硬件提供shell的时候,可以在emulator上验证自己的程序是否符合EDK II的规范。
命令很简单,在windows下用command进入到EDK II source code所在的目录,例如c:\code\edk2\,然后执行“build”,接着“build run“,就能看到emulator出现了。
从SVN上下载的代码在执行模拟器的时候会出来两个窗口,改掉这里,就只有一个窗口了。
文件:Nt32Pkg.dsc
gEfiNt32PkgTokenSpaceGuid.PcdWinNtGop|L"UGA Window 1!UGA Window 2"|VOID*|52
把"!UGA Window 2"删掉就好。在这份文件里面还有一个”PcdWinNtUga“,这里也能看到有两个Window,但这里是否删除并没有影响(或者说影响还没找到,才疏学浅,抱歉)
第三步,编译自己的shell。
把target.txt 里的ACTIVE_PLATFORM改成ShellPkg/ShellPkg.dsc,然后执行build就可以编译生成了。这里编译结束之后应该能够生成shell.efi,是我们想要的,但它的路径非常深,不容易找,所以把make的方式稍微改了一点。
EDK II默认的编译规则是通过build_rule.txt来定义的,在这个文件里面,搜索$(CP) ${dst} $(OUTPUT_DIR),在下面加上$(CP) ${dst} ..\..\..\..\..\..,就可以很方便的在编译结束之后,在$(WORK_SPACE)\Build\ShellPkg\下面找到shell.efi了。
接下来,就看你想怎么玩shell了。我的第一个玩法是:增加一个internal command。
先摸索下它本身的internal command是怎么产生的。
在shell下敲”help“,能列出所有的internal command,我盯上ping这个命令了,它比较简单,对应的文件在ping.c里。help列出的command list里之所以会出现ping,则归功于UefiShellNetwork1CommandsLib.c里的ShellNetwork1CommandsLibConstructor,它通过ShellCommandRegisterCommandName把ping这个命令注册进mCommandList(具体细节请RTFC)。
依葫芦画瓢,我在下面写一个叫”test“的command,注册进去。有点绕的是它的help字串,居然有那么恶心的格式要求:
在uni文件里面有STR_GET_HELP_TEST。(这里要和c代码中一致)
紧接着STR_GET_HELP_TEST的第一行一定要是".TH test 0 "test command string"\r\n",以.TH开始,接着空格,接着command(与c代码中ShellCommandRegisterCommandName第一个参数一致),接着0(这是我最不能理解的),接着是双引号包起来的字串。这些规则都在ShellManParser.c的ManBufferFindTitleSection里可以看到。
保存之后编译,把生成的shell.efi拷贝到$WORK_SPACE\EdkShellBinPkg\Bin\Ia32\Apps下,然后再用前面的emulator去验证。这里的路径是在Nt32Pkg.dsc里定义的,关键字PcdWinNtFileSystem。
当emulator执行的时候,是无法编译shell的,总是会报错说shell.dll找不到。
进阶玩法:不要依赖原来的代码,自己建新的inf,c,h,uni,dsc,dec文件去增加shell internal command。明天再写,回家先。