diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..672762f0 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,84 @@ +name: grub4dos-build + +on: + push: + branches: [ "master","efi","0.4.6a" ] + pull_request: + types: [ opened , synchronize ] + +jobs: + build-pr: + if: ${{ github.event_name == 'pull_request' }} + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 10 + - uses: yaya2007/grub4dos-build@main + with: + useQemu: 0 + - name: 上传文件到1 transfer.sh + run: | + echo transfer_url=`curl -H "Max-Downloads: 100" -H "Max-Days: 5" --upload-file ./$GRUB4DOS_BIN https://transfer.sh` >> $GITHUB_ENV + - name: 发送本次 pr 的编译结果 + env: + URL: ${{ github.event.pull_request.comments_url }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + curl -X POST $URL -H "Content-Type: application/json" -H "Authorization: token $GITHUB_TOKEN" --data "{ \"body\": \"$transfer_url\" }" + build-push: + if: ${{ github.event_name == 'push' }} + runs-on: ubuntu-22.04 + environment: + name: PAGES + env: + COMMIT_RANGE: "${{ github.event.before || github.event.pull_request.base.sha }}...${{ github.sha }}" + steps: + - name: 安装依赖项并进行环境变量配置 + run: sudo apt -y install p7zip-full + - name: + uses: actions/checkout@v3 + with: + fetch-depth: 10 + - name: 下载 ipxe 源码 + if: ${{ contains(github.ref, '0.4.6') }} + uses: actions/checkout@v3 + with: + repository: ipxe/ipxe + path: ipxe + ref: v1.21.1 + - name: 调用专用编译环境进行编译 + uses: yaya2007/grub4dos-build@main + with: + useQemu: 0 + - name: 发布到 github + if: ${{ github.event_name == 'push' }} + continue-on-error: true + working-directory: ${{ env.GITHUB_WORKSPACE }} + run: | + gh release delete "${{ env.GRUB4DOS_VER }}" --cleanup-tag --yes + gh release create "${{ env.GRUB4DOS_VER }}" --target efi -t "${{ env.GRUB4DOS_BIN }}" *.7z + env: + GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + - name: 生成对应下载页源码并上传 + run: "${{ secrets.BUILD_PAGE }}" + env: + AK: ${{ secrets.AK }} + SK: ${{ secrets.SK }} + - name: 下载发布站点代码 + uses: actions/checkout@v3 + with: + repository: chenall/grub4dos.site + ref: master + path: grub4dos.site + ssh-key: "${{ secrets.DEPLOY_KEY }}" + - name: 更新发布站 + run: | + cp *.md grub4dos.site/source/_posts/downloads/ + cd grub4dos.site + git config --global user.name "chenall" + git config --global user.email "chenall.cn@gmail.com" + git add source/_posts/downloads/*.md + git commit -m "`date -u +%Y-%m-%d` $GRUB4DOS_VER build from ${GITHUB_SHA:0:8} " + git push + diff --git a/.travis.yml b/.travis.yml index 5bba2963..8a146cc5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: c sudo: enabled -compiler: gcc-4.6 +compiler: gcc-4.8 os: - linux addons: @@ -9,7 +9,7 @@ addons: - git.coding.net - git.dev.tencent.com apt: - packages: [gcc-4.6,gcc-4.6-multilib,nasm,upx,p7zip-full,zip,autoconf,automake,make,patch,npm] + packages: [gcc-4.8,gcc-4.8-multilib,nasm,upx,p7zip-full,zip,autoconf,automake,make,patch,npm] sources: - ubuntu-toolchain-r-test @@ -42,7 +42,7 @@ before_deploy: - git tag $TRAVIS_TAG branches: - only: 0.4.6a + only: efi deploy: provider: releases @@ -51,4 +51,4 @@ deploy: skip_cleanup: true overwrite: true on: - branch: 0.4.6a + branch: efi diff --git a/ChangeLog_UEFI.txt b/ChangeLog_UEFI.txt new file mode 100644 index 00000000..bfad0c82 --- /dev/null +++ b/ChangeLog_UEFI.txt @@ -0,0 +1,339 @@ +更新说明: +2025-11-25 (yaya) + 支持gcc-15(由memoarfaa提供)。 + 修正RUN失效。 + 修正md5crypt函数。 + +2025-11-11 (yaya) + 修正iso映射。 + +2025-10-29 (yaya) + 消除http断点续传时连续读一字节。 + 网起时,http服务优先。 + +2025-10-20 (yaya) + 支持ipxe启动g4e传入参数: chain /bootg4e.efi proxy=${proxydhcp/next-server} + +2025-10-11 (yaya) + 如果HTTP服务支持断点续传,则采用分块传输(即不整体加载到内存)。 + 函数"find --set-root",网起时不再读文件到内存。 + 减少探测压缩文件的读次数。 + 消除栈内过大的数组。 + +2025-09-08 (yaya) + 网起支持proxydhcp模式(由江南一根葱提供)。 + 非网起时,开启网络功能(需要开启服务器)。pxe init + +2025-08-19 (yaya) + 解除NTFS文件系统对压缩与稀疏文件读挂钩的限制。 + +2025-08-14 (yaya) + http支持断点续传。 + +2025-07-02 (yaya) + 改进http网起。 + +2025-05-10 (yaya) + 改进http网起。 + +2025-03-26 (yaya) + 改进http网起。 + 支持 FAT/12/16/32 分区类型的 img 软盘仿真为硬盘。例如:map /imgs/fdd.img (hd) + 函数 ls 增加参数 --test,用于测试文件、文件夹是否存在,文件夹是否为空。例如: ls --test (hd0,0)/imgs/fdd.img + 修复启动失败回滚时菜单的图像及中文字库丢失。 + 修复碎片插槽数量。 + 网起文件名支持中文及空格。需加载外部文件gbk2uni。例如:set gbk2uni=/efi/grub/ext/gbk2uni + 如果在网起dir.txt专用文件内部,文件名小写,文件夹大写,这样显示时文件夹会高亮(与其他文件系统相同)。 + +2024-12-16 (yaya) + 支持http网起。 + 例如:map (http)/imgs/pe.iso (cd) + chainloader (cd-1) + boor + 例如:/efi/grub/ext/ntboot (http)/imgs/pe.wim + +2024-09-01 (yaya) + 修正函数 map --unmap= + 增加参数 map --alloc-only,用于批处理分配自由内存。 + 例如:map --alloc-only (md)0+0x1b61b0 (3) //分配0x1b61b0扇区自由扇区 + map --status=3 + set add=%?% //返回分配的自由内存 + 加快非压缩文件(img,iso,静态vhd)加载到虚拟机内存的速度。 + +2024-02-26 (yaya) + 改进uuid/vol函数,支持10个以上分区。 + +2023-11-27 (yaya) + 修正碎片插槽计算。 + 改进pxe。 + +2023-10-14 (yaya) + 修正增加变量menu_tab_ext引入的问题。 + 修正font函数。 + +2023-09-22 (yaya) + 修正切换分辨率花屏问题。 + 增加从入口点启动方法。 + 增加变量menu_tab_ext,避免重入主菜单时重复设置图形模式、加载背景图及字库。 + 例如:calc *0x8312&1 > nul || graphicsmode -1 800 + calc *0x8312&2 > nul || splashimage /boot/grub/lt.jpg + calc *0x8312&4 > nul || font /boot/grub/unifont.hex.gz + +2023-08-18 (yaya) + 改进find函数的查找分区顺序为0,1,2.... + 改进有些UEFI固件返回大写字母无法识别的问题。 issues #423 + +2023-07-15 (yaya) + 外部命令可以尾续压缩文件 + +2023-07-08 (yaya) + 修正缺失MBR逻辑分区磁盘ID + +2023-07-01 (yaya) + 修正缺失GPT磁盘GUID + +2023-06-23 (yaya) + 修正configfile函数文件名溢出。 + 碎片数由39增加到126。 + 修正分区签名丢失。 + 修正BOOTIA32.EFI启动时进不了菜单而重启。 + 改进color函数帮助信息。issues #414 + 避免分区项空洞。issues #416 + +2023-06-06 (yaya) + 适应gcc-11高版本编译。 + +2023-05-10 (yaya) + 修正udf光盘加载到2Gb以上内存失败的问题。 + 确定引导驱动器恒定为0x80。 + 支持 USB 逻辑单元设备。 + kernel 函数增加 --handover 和 --loadfile2 参数,以便强制使用 EFI Handover Protocol 或 LoadFile2 协议。 + 增加打印路径的内部函数,以便不支持设备路径到文本协议的设备使用。 + 改进设备启动。issues #404, issues #405 + +2023-03-29 (yaya) + 完善外部命令进度条。 + 改进ISO启动。 + 修正splashimage函数。issues #401 + 修正partnew函数。issues #402 + 修正map函数的unmap功能。issues #403 + +2023-03-19 (a1ive) + 支持多行 initrd 命令 + 支持 cpio newc initrd + +2023-03-14 (a1ive) + 修正 setkey 函数。 + chainloader 和 kernel 命令行支持非 ASCII 字符。 + +2023-03-11 (a1ive) + 放弃使用 EFI Handover Protocol 启动 Linux,改用 LoadFile2 提供 initrd 加载功能。 + Linux 6.2 将已废弃的 EFI Handover Protocol 设为可选项: + https://github.com/torvalds/linux/commit/cc3fdda2876e58a7e83e558ab51853cf106afb6a + 不再支持 x64 UEFI 下启动 32 位内核 (或者反过来)。 + 不再支持 ntloader v1 版本,请使用 ntloader v2 版本。 + +2023-02-23 (yaya) + 增加外部定时器。(应用之一,外部命令进度条ProgressBar)。 + 修正菜单最后一行没有换行符而缺失的问题。 + 修正切换视频模式菜单框失误的问题。 + 修正文本模式菜单显示。 + graphicsmode函数增加参数test。 + 示例:graphicsmode --test 水平像素 垂直像素 + 返回:分辨率存在返回模式号,否则返回0。 + +2022-12-27 (yaya) + 支持差分VHD。(如果使用svbus,请加载到内存) + +2022-12-22 (yaya) + 撤销issues #384补丁。会使得外部命令SISO、RUN列表文件时,扩展名只显示前2个。 + 修正parttype函数。issues #389 + graphicsmode函数增加'--info'参数,显示当前支持的图形模式信息。 + +2022-11-28 (yaya) + 修正splashimage函数的动画功能。issues #387 + 修正graphics函数,避免图形模式时,在命令行滚屏,第24行被有其他属性的空格清屏. + 消除echo @%*@结尾多余的空格字符。issues #384 + 避免echo$[0xf0]输出00字符。issues #385 + +2022-10-27 (yaya) + calc函数支持64位除法。增加变量@retval64,返回calc函数的64位计算值。 + echo函数的 [-P:XXYY] 功能,允许XX(YY)为十六进制值。 + 修正在控制台设置模式3会死机的问题。 + 启动时显示内存信息。 + +2022-09-15 (yaya) + partnew函数增加'--force'参数,允许覆盖独立分区。 + +2022-03-26 (yaya) + 改进启动功能。 + 修正 ext4 读函数。 + 修正挂载外部命令缓存溢出。 + +2022-01-18 (yaya) + 配合支持碎片的svbus。 + 加快实机命令行滚屏速度。 + 撤销吸收命令行尾部的空格。 + 取消使用设备路径实用程序协议(低版本UEFI固件不支持)。 + 增加变量:当前水平像素(0x834c)。 + map函数增加参数:--no-hook(不挂载)。 + 允许挂载多个虚拟磁盘。 + +2021-11-05 (yaya) + 修复管道符‘|’后面紧接call(或者goto)标签时,必须补空格。issues #341 + 迁就有bug的ISO光盘镜像。 + +2021-10-13 (yaya) + 增强菜单项目、项目注释以及菜单字符串的文字颜色功能。例如: + title boot $[0xff00ff]Windows $[]10x64 + 修正 NTFS 有偏移时的写操作错误。 + 修正 dd 函数在同一文件向后移动时的错误。 + 吸收命令行尾部的空格。 + 增加 map --unmap= 实际功能,可以卸载映射驱动器。 + 修正卸载碎片插槽的错误。 + 改进启动功能。 + +2021-08-18 (yaya) + 安装虚拟分区,不再占用映射插槽。 + 改进启动存在的磁盘。 + +2021-08-17 (yaya) + 在 debug 函数增加 ctrl-c-trap= 参数。为零时,不检测批处理的 ctrl+c 按键。 + 解除 dd 与 write 函数的安全限制。 + 修正 errnum 序号错位。 + +2021-07-23 (a1ive) + 添加 beep 命令。 + +2021-07-22 (a1ive) + 添加 parttype 命令。 + +2021-06-19 (yaya) + 增加 ADDR_RET_STR 以便外部命令使用。 + +2021-06-02 (a1ive) + 支持嵌入字库、模块(.mod文件)。 + mkimage.exe -d 目录 -p /efi/grub -o BOOTX64.EFI -O x86_64-efi -c 嵌入菜单 -f 嵌入字库 -m 嵌入模块 + mkimage.exe -d 目录 -p /efi/grub -o BOOTIA32.EFI -O i386-efi -c 嵌入菜单 -f 嵌入字库 -m 嵌入模块 + +2021-05-28 (yaya) + 改进热键。可以把菜单项中的任意英文字母作为热键。 + 增加参数:setmenu --hotkey-color=COLOR 设置热键颜色。 + 例如: + setmenu --hotkey-color=0xffff + hotkey -A [F3] "reboot" [Ctrl+d] "commandline" + title [F4] Boot Win + title Boot ^Win 10 + +2021-05-19 (yaya) + 热键函数外置。 + 使用方法:hotkey 参数 + +2021-05-01 (yaya) + 修复不能读写ud隐藏分区的问题。 + +2021-04-24 (yaya) + 1. 支持嵌入菜单。把 kernel.img 与 grub-mkimage.exe 放在同一目录。 + grub-mkimage.exe -d 目录 -p /efi/grub -o BOOTX64.EFI -O x86_64-efi -c 嵌入菜单 + grub-mkimage.exe -d 目录 -p /efi/grub -o BOOTIA32.EFI -O i386-efi -c 嵌入菜单 + 2. 改进批处理调试,使用行号作为断点,可使用10个断点。 + debug 批处理文件名 参数 + b 设置断点(10个)。 例如: b 45 (当前批处理, 45行); b p2,134 (2号批处理, 134行) + b l 显示断点 (断点号,批处理号,批处理行号) + b c 清除断点 例如: c2 (清除2号断点); c (清除全部断点) + n 运行至断点 + c 进入命令行 按'ESC'键返回批处理调试 + s 跳过本行 + e 运行批处理至结束 + q 退出批处理 + p 单步执行(跨过子程序) + 其他 单步执行(遇到子程序进入) + 3. 内置 0x20-0x7f、0x2191、0x2193 unicode 16*16 点阵字符。 + +2021-02-10 (a1ive) + 优先使用 ACPI 关机。 + +2021-01-31 (yaya) + 支持启动一级差分VHD镜像。 + +2021-01-12 (a1ive) + 支持加载多个 initrd 文件。 + +2021-01-12 (yaya) + 增加变量 @uefi。值为64/32,用于判断UEFI系统是64/32位。00是BIOS系统。 + 修正外部命令。 + +2021-01-09 (yaya) + 启动 bootmgfw.efi 。 + 修正 graphicsmode,displaymem 函数。 + 新设内部变量: 0x8272(1字节) UEFI 启动环境(32/64位)。 + +2020-12-15 (a1ive) + 添加 load 命令以加载 EFI 驱动。 + +2020-12-14 (yaya) + 一次编译完成32位、64位版本。 + +2020-12-10 (yaya) + 使用 "./build i386" 编译 BOOTIA32.EFI 。 + 可以使用参数 "--top" 将镜像强制加载到 4Gb 以上内存。 + 修正字符串颜色显示,修正映射磁盘读写。 + +2020-11-26 (yaya) + 合并 i386 与 x86_64 源代码。 + 修正 hotkey 及 exit_g4d 函数。 + +2020-11-19 (a1ive) + 支持使用 kernel 和 initrd 命令启动 linux 内核。 + +2020-11-18 (yaya) + 1. 菜单目录更改为:/efi/grub/menu.lst + 2. 支持实体光盘、硬盘启动。 + 3. 多个光盘时,启动光盘调整为第一光盘,以适应 windows。 + 4. 增加退出 GRUB4DOS 函数 exit_g4d。 + 5. 批处理变更: + 函数下标不变,参数由 32 位变更为 64 位。(Fn.下标 参数1 参数2 ...) + 变量地址由 0x8304 变更为 0x8308,由 32 位变更为 64 位。 + call Fn 函数,如果使用变量 0x8200-0x8400(不含) 则要在前面加g4e,如 g4e0x8217。 + 批处理增加 else 函数。增加 {脚本集} 表示法。 + 如: + if 条件 + { + 脚本集 + if 条件 { + 脚本集 } + else { + 脚本集 } + } + else if 条件 + { + 脚本集 + } + else + { + 脚本集 + } + 注意: + 1. 大括弧必须是一行的结尾。 + 2. 脚本集可多行书写。 + 3. 大括弧内部可以嵌套。 + +2020-10-29 (yaya) + 使用于 UEFI 环境的 GRUB4DOS。 + + 这是一个庞大的工程,几乎所有的代码都捋了一遍。修改了控制台键盘输入输出,控制台屏幕输出,内存控制, + 驱动器控制,获取日期时间,暂停控制,图形模式及Unicode字体实现,PXE 网启,等等。 + + 开发过程中,参考了 GRUB2 源码。有关映射,参考了 wintoflash 的源码。 + + 1. 可以启动 efi 文件。 + 2. 可以启动 iso 及 img 文件。 + + 与旧版本不同之处: + 1. 可以通过 graphicsmode 命令查看系统支持的图形模式。 + 2. map 函数执行后即挂载。不需要执行 --hook 指令。 + 3. 取消 --hook,--unhook,--rehook,--unmap=,--floppies=,--harddrives= 指令。 + 4. 在 UEFI 环境,可以从 0x80 以外的磁盘启动,因此不需要交换磁盘操作,如 map (hd0) (hd1)。 + 5. 取消删除磁盘功能,如 map (hd1) (hd1)。 + 6. 目前 PXE 网启只支持 tftp。 + diff --git a/acinclude.m4 b/acinclude.m4 index d508ad88..200aa014 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -61,7 +61,7 @@ for link_addr in 2000 8000 7C00; do else AC_MSG_ERROR([${CC-cc} cannot link at address $link_addr]) fi - if AC_TRY_COMMAND([${OBJCOPY-objcopy} -O binary conftest.exec conftest]); then : + if AC_TRY_COMMAND([${OBJCOPY-objcopy} --only-section=.text -O binary conftest.exec conftest]); then : else AC_MSG_ERROR([${OBJCOPY-objcopy} cannot create binary files]) fi @@ -91,7 +91,7 @@ dnl stage1/stage1.S. AC_DEFUN([grub_ASM_ADDR32], [AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([grub_ASM_PREFIX_REQUIREMENT]) -AC_MSG_CHECKING([for .code16 addr32 assembler support]) +AC_MSG_CHECKING([for .code16 addr64 assembler support]) AC_CACHE_VAL(grub_cv_asm_addr32, [cat > conftest.s.in <<\EOF .code16 @@ -99,9 +99,9 @@ l1: @ADDR32@ movb %al, l1 EOF if test "x$grub_cv_asm_prefix_requirement" = xyes; then - sed -e s/@ADDR32@/addr32/ < conftest.s.in > conftest.s + sed -e s/@ADDR32@/addr64/ < conftest.s.in > conftest.s else - sed -e s/@ADDR32@/addr32\;/ < conftest.s.in > conftest.s + sed -e s/@ADDR32@/addr64\;/ < conftest.s.in > conftest.s fi if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -c conftest.s]) && test -s conftest.o; then @@ -137,17 +137,17 @@ fi rm -f conftest*]) if test "x$grub_cv_asm_prefix_requirement" = xyes; then - grub_tmp_addr32="addr32" - grub_tmp_data32="data32" + grub_tmp_addr32="addr64" + grub_tmp_data32="data64" else - grub_tmp_addr32="addr32;" - grub_tmp_data32="data32;" + grub_tmp_addr32="addr64;" + grub_tmp_data32="data64;" fi AC_DEFINE_UNQUOTED([ADDR32], $grub_tmp_addr32, - [Define it to \"addr32\" or \"addr32;\" to make GAS happy]) -AC_DEFINE_UNQUOTED([DATA32], $grub_tmp_data32, - [Define it to \"data32\" or \"data32;\" to make GAS happy]) + [Define it to \"addr64\" or \"addr64;\" to make GAS happy]) +AC_DEFINE_UNQUOTED([DATA64], $grub_tmp_data32, + [Define it to \"data64\" or \"data64;\" to make GAS happy]) AC_MSG_RESULT([$grub_cv_asm_prefix_requirement])]) diff --git a/build b/build index a027d93c..a0fd5ecd 100755 --- a/build +++ b/build @@ -1,24 +1,32 @@ #! /bin/sh # -# Script to build binary +# Script to build binary 生成二进制文件的脚本 # # Usage: # sh build # or # ./build +#此时在根目录 /home/dev/grub4efi + +#源目录 SOURCE_DIR=`pwd` +#版本 VER=`cat grub4dos_version` +#日期 DATE=`date -u +%Y-%m-%d` +#发布日期 RELEASE=grub4dos-${VER}-${DATE} -COPY_FILES="COPYING README_GRUB4DOS*.txt ChangeLog_*.txt \ - config.sys default menu.lst grub.pif \ - stage2/grldr stage2/grub.exe stage2/badgrub.exe stage2/grldr.mbr stage2/bootlace.com \ - stage2/hmload.com stage2/grldr.pbr stage2/grldr_cd.bin" +#定义复制文件集 +#COPY_FILES="COPYING README_GRUB4DOS*.txt ChangeLog_*.txt \ +# config.sys default menu.lst grub.pif config.h\ +# stage2/pre_stage2.exec" -rm -rf *.zip *.7z *~ || exit $? +#删除*.zip *.7z *~ +#rm -rf *.zip *.7z *~ || exit $? +#定义临时编译目录 GRUB4DOS_TEMP [ -z "$GRUB4DOS_TEMP" ] && GRUB4DOS_TEMP=/tmp/grub4dos-temp if svn export . ${GRUB4DOS_TEMP} --force 2>/dev/null ; then -# check for svn version +# check for svn version 检查svn版本 export LC_ALL=C svninfo=$(svn info) if [ "$svninfo" ]; then @@ -38,19 +46,20 @@ EOF [ "$SVN_URL" = "" ] && SVN_URL="https://github.com/chenall/grub4dos" [ "$CURR_REVISION" = "" ] && CURR_REVISION=rHEAD Get_source="\tsvn co -$CURR_REVISION $SVN_URL grub4dos\r\n\tcd grub4dos\r\n\r\n" - # Generate patch file +# Generate patch file 生成修补程序文件 svn diff . > ${GRUB4DOS_TEMP}/grub4dos_${CURR_REVISION}.diff 2>/dev/null - +#核实索引 elif git checkout-index -a -f --prefix=${GRUB4DOS_TEMP}/ 2>/dev/null ; then -# check for git version +# check for git version 检查git版本 CURR_REVISION=$(git log -1 --pretty=format:%h) Get_source="\tgit clone git://github.com/chenall/grub4dos.git\r\n\tcd grub4dos\r\n\tgit checkout $CURR_REVISION -b build\r\n\r\n" - # Generate patch file +# Generate patch file 生成修补程序文件 git diff --no-prefix > ${GRUB4DOS_TEMP}/grub4dos_${CURR_REVISION}.diff 2> /dev/null if [ -s ${GRUB4DOS_TEMP}/grub4dos_${CURR_REVISION}.diff ]; then cd ${GRUB4DOS_TEMP} || exit $? patch -p0 < grub4dos_${CURR_REVISION}.diff fi +#此时在 /tmp/grub4dos-temp/ else files=$(echo *) if ! [ -d ${GRUB4DOS_TEMP} ] ; then @@ -58,9 +67,11 @@ else fi cp -a $files ${GRUB4DOS_TEMP} || exit $? fi - +#此时在 /tmp/grub4dos-temp/ +#转到 GRUB4DOS_TEMP 目录 cd ${GRUB4DOS_TEMP} || exit $? +#生成 Get_Source_of_This_Build.txt 文件 if [ "$Get_source" ]; then echo -n -e "Get the source code of this build in this way:\r\n\r\n${Get_source}" > Get_Source_of_This_Build.txt if [ -s grub4dos_${CURR_REVISION}.diff ]; then @@ -70,64 +81,101 @@ if [ "$Get_source" ]; then echo -n -e "and now you may do a \"make\" to compile.\r\n\r\n" >> Get_Source_of_This_Build.txt fi -############################################# -# Build english version -############################################# - -./configure --enable-preset-menu=preset_menu.lst || exit $? +#********************************************** +# 编译 BOOTX64.EFI +#********************************************** +#配置 +./configure || exit $? +#清洁 make clean +#编译 make || exit $? -rm -rf grub4dos-${VER} -mkdir grub4dos-${VER} || exit $? -[ -f stage2/eltorito.sys ] && cp stage2/eltorito.sys grub4dos-${VER} -cp $COPY_FILES grub4dos-${VER} || exit $? -cd grub4dos-${VER} + +#建立 grub4dos-${VER} 目录 +#rm -rf grub4dos-${VER} +#mkdir grub4dos-${VER} || exit $? + +#复制 stage2/eltorito.sys 到 grub4dos-${VER} +#[ -f stage2/eltorito.sys ] && cp stage2/eltorito.sys grub4dos-${VER} + +#复制 $COPY_FILES 到 grub4dos-${VER} +#cp $COPY_FILES grub4dos-${VER} || exit $? + +#转到 grub4dos-${VER} 目录 +#cd grub4dos-${VER} + +#生成 bootlace64.com # generate bootlace64.com -if [ -f bootlace.com ]; then - Seek=$((0x`objdump -s bootlace.com|awk '/7f45/{print $1|"sed s/4/0/"}'`)) - dd if=bootlace.com of=bootlace.head bs=1 count=64 skip=$Seek - dd if=bootlace.com of=bootlace.body bs=1 skip=64 - cat bootlace.head bootlace.body > bootlace64.com - chmod a+x bootlace64.com - rm -f bootlace.body bootlace.head -fi -mkdir docs && mv *.txt docs/ -mkdir sample && mv menu.lst default config.sys sample/ -cd .. -if [ -f Get_Source_of_This_Build.txt ]; then - cp Get_Source_of_This_Build.txt grub4dos-${VER} - if [ -s grub4dos_${CURR_REVISION}.diff ]; then - cp grub4dos_${CURR_REVISION}.diff grub4dos-${VER} - fi -fi -############################################# -# Build chinese version -############################################# +#建立 docs 目录,并且移动 *.txt 到本目录 +#mkdir docs && mv *.txt docs/ -#patch -p1 < patch-chinese.diff || exit $? -#make || exit $? +#建立 sample 目录,并且移动 menu.lst default config.sys 到本目录 +#mkdir sample && mv menu.lst default config.sys sample/ -#mkdir grub4dos-${VER}/chinese || exit $? -#cp README_GRUB4DOS_CN.txt stage2/grldr stage2/grub.exe stage2/badgrub.exe grub4dos-${VER}/chinese || exit $? +#返回上一级 GRUB4DOS_TEMP 目录 +#cd .. -############################################# -# Create ZIP ball or TAR ball -############################################# +#如果存在,则复制 Get_Source_of_This_Build.txt 及 grub4dos_${CURR_REVISION}.diff 到 grub4dos-${VER} +#if [ -f Get_Source_of_This_Build.txt ]; then +# cp Get_Source_of_This_Build.txt grub4dos-${VER} +# if [ -s grub4dos_${CURR_REVISION}.diff ]; then +# cp grub4dos_${CURR_REVISION}.diff grub4dos-${VER} +# fi +#fi -cd $SOURCE_DIR -if [ -d ipxe ] ; then - cd ipxe/src - [ -d .git ] && git pull - make bin/undionly.kpxe EMBED=$SOURCE_DIR/ipxegrldr.ipxe,${GRUB4DOS_TEMP}/grub4dos-${VER}/grldr && cp -af bin/undionly.kpxe ${GRUB4DOS_TEMP}/grub4dos-${VER}/ipxegrldr - cd $SOURCE_DIR +#如果存在 ipxe,则转到 ipxe/src 目录,编译并推送...,然后返回 $SOURCE_DIR 目录 +#if [ -d ipxe ] ; then +# cd ipxe/src +# [ -d .git ] && git pull +# make bin/undionly.kpxe EMBED=$SOURCE_DIR/ipxegrldr.ipxe,${GRUB4DOS_TEMP}/grub4dos-${VER}/grldr && cp -af bin/undionly.kpxe ${GRUB4DOS_TEMP}/grub4dos-${VER}/ipxegrldr +# cd $SOURCE_DIR +#fi + +#此时在 /tmp/grub4dos-temp/ +#复制pre_stage2.exec +mkdir $GRUB4DOS_TEMP/x86_64-efi +cp stage2/pre_stage2.exec $GRUB4DOS_TEMP/x86_64-efi/kernel.img +platform=`uname -m` +if [ $platform = 'x86_64' ] +then + $SOURCE_DIR/mkimage -d $GRUB4DOS_TEMP/x86_64-efi -p /efi/grub -o BOOTX64.EFI -O x86_64-efi +else + $SOURCE_DIR/mkimage.i386 -d $GRUB4DOS_TEMP/x86_64-efi -p /efi/grub -o BOOTX64.EFI -O x86_64-efi +fi + +#********************************************** +# 编译 BOOTIA32.EFI +#********************************************** +#编译切换 +mv stage2/Makefile.in stage2/Makefile.in-64 +mv stage2/Makefile.in-i386 stage2/Makefile.in +#配置 +./configure || exit $? +#清洁 +make clean +#编译 +make || exit $? +mkdir $GRUB4DOS_TEMP/i386-efi +cp stage2/pre_stage2.exec $GRUB4DOS_TEMP/i386-efi/kernel.img +if [ $platform = 'x86_64' ] +then + $SOURCE_DIR/mkimage -d $GRUB4DOS_TEMP/i386-efi -p /efi/grub -o BOOTIA32.EFI -O i386-efi +else + $SOURCE_DIR/mkimage.i386 -d $GRUB4DOS_TEMP/i386-efi -p /efi/grub -o BOOTIA32.EFI -O i386-efi fi + +#转到源目录 +cd $SOURCE_DIR +#此时在 /tmp/grub4dos-temp/ +#cd / +#此时在 /home/ 的上一级目录,但不是 /g4d_dev/ + rm -f ${RELEASE}.zip ${RELEASE}.rar ${RELEASE}.tar.gz || exit $? -if ! 7z a ${RELEASE}.7z ${GRUB4DOS_TEMP}/grub4dos-${VER} ; then +if ! 7z a ${RELEASE}.7z ${GRUB4DOS_TEMP}/BOOTX64.EFI ${GRUB4DOS_TEMP}/BOOTIA32.EFI $SOURCE_DIR/ChangeLog_UEFI.txt \ + $SOURCE_DIR/menu.lst $SOURCE_DIR/default ${GRUB4DOS_TEMP}/Get_Source_of_This_Build.txt ${GRUB4DOS_TEMP}/grub4dos_${CURR_REVISION}.diff \ + ${GRUB4DOS_TEMP}/i386-efi ${GRUB4DOS_TEMP}/x86_64-efi mkimage.exe; then echo 7z failed. Continue with zip or tar... - if ! zip -r -q ${RELEASE}.zip ${GRUB4DOS_TEMP}/grub4dos-${VER} ; then - tar -czf ${RELEASE}.tar.gz ${GRUB4DOS_TEMP}/grub4dos-${VER} - fi fi -# Do not remove grub4dos-temp as we can check and re-use it later. +# Do not remove grub4dos-temp as we can check and re-use it later. 不要删除grub4dos temp,因为我们可以稍后检查并重新使用它。 diff --git a/config.h.in b/config.h.in index 6ecbf80e..ca53b228 100644 --- a/config.h.in +++ b/config.h.in @@ -4,13 +4,13 @@ #undef ABSOLUTE_WITHOUT_ASTERISK /* Define it to \"addr32\" or \"addr32;\" to make GAS happy */ -#undef ADDR32 +#undef ADDR64 /* Define if you don't want to pass the mem= option to Linux */ #undef AUTO_LINUX_MEM_OPT /* Define it to \"data32\" or \"data32;\" to make GAS happy */ -#undef DATA32 +#undef DATA64 /* Define if C symbols get an underscore after compilation */ #undef HAVE_ASM_USCORE diff --git a/configure b/configure index a4061854..6e81f395 100755 --- a/configure +++ b/configure @@ -4169,7 +4169,7 @@ if test "x$ac_env_CFLAGS_set" = x; then fi if test "x$host_cpu" = xx86_64; then - CFLAGS="-m32 -mno-sse $CFLAGS" + CFLAGS="-m64 -mno-sse $CFLAGS" fi @@ -5317,9 +5317,9 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $grub_cv_cc_Os" >&5 $as_echo "$grub_cv_cc_Os" >&6; } if test "x$grub_cv_cc_Os" = xyes; then - STAGE2_CFLAGS="-Os -mpreferred-stack-boundary=2 -momit-leaf-frame-pointer -fno-strict-aliasing -fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables" + STAGE2_CFLAGS="-Os -mpreferred-stack-boundary=8 -momit-leaf-frame-pointer -fno-strict-aliasing -fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables" else - STAGE2_CFLAGS="-O2 -fno-strength-reduce -fno-unroll-loops -mpreferred-stack-boundary=2 -momit-leaf-frame-pointer -fno-strict-aliasing -fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables" + STAGE2_CFLAGS="-O2 -fno-strength-reduce -fno-unroll-loops -mpreferred-stack-boundary=8 -momit-leaf-frame-pointer -fno-strict-aliasing -fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables" fi # OpenBSD has a GCC extension for protecting applications from # stack smashing attacks, but GRUB doesn't want this feature. @@ -5507,6 +5507,85 @@ LDFLAGS="$save_LDFLAGS" if test "x$build_id_flag" = xyes; then LDFLAGS="$LDFLAGS -Wl,--build-id=none" fi +#gcc 5 and newer has builded with enable-default-pie by defualt so we add -no-pie to linker flag + +# Check if gcc has enable pie by default +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether gcc has enable pie by default" >&5 +$as_echo_n "checking whether gcc has enable pie by default... " >&6; } +save_LDFLAGS="$LDFLAGS" +LDFLAGS="$LDFLAGS -no-pie -fno-pic" +if [[ -n "`$CC -v -E 2>&1 | grep 'Configured with' | sed 's/--/\n--/g' | grep enable-default-pie`" ]]; then : + no_pie_linker_flag=yes +else + no_pie_linker_flag=no +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $no_pie_linker_flag" >&5 +$as_echo "$no_pie_linker_flag" >&6; } +LDFLAGS="$save_LDFLAGS" +if test "x$no_pie_linker_flag" = xyes; then + LDFLAGS="$LDFLAGS -no-pie -fno-pic" +fi +#gcc newer than 4.8 required adding -fgnu89-inline in STAGE2_CFLAGS to disable warning: inline function + +# Check if gcc version newer than gcc 4.8 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether gcc is newer than gcc 4.8 to disable warning about inline function" >&5 +$as_echo_n "checking whether gcc is newer than gcc 4.8 to disable warning about inline function... " >&6; } +currentgccver="$($CC -dumpversion)" +gcc48="4.8.0" + +if [ "$(printf '%s\n' "$gcc48" "$currentgccver" | sort -V | head -n1)" = "$gcc48" ]; then + fgnu89_inline_flag=yes +else + fgnu89_inline_flag=no +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $fgnu89_inline_flag" >&5 +$as_echo "$fgnu89_inline_flag" >&6; } + +if test "x$fgnu89_inline_flag" = xyes; then + STAGE2_CFLAGS="$STAGE2_CFLAGS -fgnu89-inline" +fi +#gcc 10 and newer has builded with -fno-common by defualt so we add -fcommon to STAGE2_CFLAGS + +# Check if gcc 10 or newer +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether gcc 10 or newer builded with -fno-common by defualt" >&5 +$as_echo_n "checking whether gcc 10 or newer builded with -fno-common by defualt... " >&6; } +currentgccver="$($CC -dumpversion)" +gcc10="9.9.0" + +if [ "$(printf '%s\n' "$gcc10" "$currentgccver" | sort -V | head -n1)" = "$gcc10" ]; then + fno_common_flag=yes +else + fno_common_flag=no +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $fno_common_flag" >&5 +$as_echo "$fno_common_flag" >&6; } + +if test "x$fno_common_flag" = xyes; then + STAGE2_CFLAGS="$STAGE2_CFLAGS -fcommon" +fi + +#gcc 15 and newer has built with -std=gnu23 by default so we add -std=gnu17 to CFLAGS +# Check if gcc 15 or newer +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether gcc 15 or newer built with -std=gnu23 by default" >&5 +$as_echo_n "checking whether gcc 15 or newer built with -std=gnu23 by default... " >&6; } +currentgccver="$($CC -dumpversion)" +gcc15="14.9.0" + +if [ "$(printf '%s\n' "$gcc15" "$currentgccver" | sort -V | head -n1)" = "$gcc15" ]; then + C17_common_flag=yes +else + C17_common_flag=no +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $C17_common_flag" >&5 +$as_echo "$C17_common_flag" >&6; } + +if test "x$C17_common_flag" = xyes; then + CFLAGS="-std=gnu17 $CFLAGS" +fi if test "x$with_binutils" != x; then # Extract the first word of "objcopy", so it can be a program name with args. @@ -5742,7 +5821,7 @@ for link_addr in 2000 8000 7C00; do else as_fn_error $? "${CC-cc} cannot link at address $link_addr" "$LINENO" 5 fi - if { ac_try='${OBJCOPY-objcopy} -O binary conftest.exec conftest' + if { ac_try='${OBJCOPY-objcopy} --only-section=.text -O binary conftest.exec conftest' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 (eval $ac_try) 2>&5 ac_status=$? diff --git a/configure.ac b/configure.ac index 249e3def..813ff27c 100644 --- a/configure.ac +++ b/configure.ac @@ -53,7 +53,7 @@ if test "x$ac_env_CFLAGS_set" = x; then fi if test "x$host_cpu" = xx86_64; then - CFLAGS="-m32 -mno-sse $CFLAGS" + CFLAGS="-m64 -mno-sse $CFLAGS" fi AC_SUBST(default_CFLAGS) @@ -100,9 +100,9 @@ if test "x$ac_cv_c_compiler_gnu" = xyes; then CFLAGS=$saved_CFLAGS ]) if test "x$grub_cv_cc_Os" = xyes; then - STAGE2_CFLAGS="-Os -mpreferred-stack-boundary=2 -momit-leaf-frame-pointer -fno-strict-aliasing -fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables" + STAGE2_CFLAGS="-Os -mpreferred-stack-boundary=8 -momit-leaf-frame-pointer -fno-strict-aliasing -fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables" else - STAGE2_CFLAGS="-O2 -fno-strength-reduce -fno-unroll-loops -mpreferred-stack-boundary=2 -momit-leaf-frame-pointer -fno-strict-aliasing -fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables" + STAGE2_CFLAGS="-O2 -fno-strength-reduce -fno-unroll-loops -mpreferred-stack-boundary=8 -momit-leaf-frame-pointer -fno-strict-aliasing -fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables" fi # OpenBSD has a GCC extension for protecting applications from # stack smashing attacks, but GRUB doesn't want this feature. @@ -173,6 +173,17 @@ if test "x$grub_cv_cc_Wundef" = xyes; then CPPFLAGS="$CPPFLAGS -Wundef" fi +#gcc 5 and newer has builded with enable-default-pie by defualt so we add -no-pie to linker flag +AC_MSG_CHECKING([checking whether gcc has enable pie by default]) +saved_LDFLAGS="$LDFLAGS" +LDFLAGS="-no-pie -fno-pic" +AC_TRY_LINK(, , no_pie_linker_flag=yes, no_pie_linker_flag=no) +AC_MSG_RESULT([$no_pie_linker_flag]) +LDFLAGS=$saved_LDFLAGS +if test "x$no_pie_linker_flag" = xyes; then + LDFLAGS="$LDFLAGS -no-pie -fno-pic" +fi + # Check if build ID can be disabled in the linker AC_MSG_CHECKING([whether linker accepts `--build-id=none']) save_LDFLAGS="$LDFLAGS" diff --git a/grub4dos_version b/grub4dos_version index b8a53393..44456ad3 100644 --- a/grub4dos_version +++ b/grub4dos_version @@ -1 +1 @@ -0.4.6a +for_UEFI diff --git a/menu.lst b/menu.lst index 27ce716c..a6c77710 100644 --- a/menu.lst +++ b/menu.lst @@ -1,151 +1,158 @@ -# This is a sample menu.lst file. You should make some changes to it. -# The old install method of booting via the stage-files has been removed. -# Please install GRLDR boot strap code to MBR with the bootlace.com -# utility under DOS/Win9x or Linux. -# -# It must be UTF-8 encoding for multi-lingual support. Font lines can be -# appended to the file. The font lines should be in the unifont.hex format. - -color blue/green yellow/red white/magenta white/magenta -timeout 30 -## menu border color -color border=0xEEFFEE -## set vbe mode -graphicsmode -1 640:800 480:600 24:32 || graphicsmode -1 -1 -1 24:32 -## loading splashimage -splashimage /boot/grub/splashimage.xpm || splashimage /boot/grub/splashimage.bmp -default /default -## Menu AutoNumber -write 0x8274 0x2001 - -title find and load NTLDR of Windows NT/2K/XP\n find and load NTLDR of Windows NT/2K/XP -fallback +1 -find --set-root --ignore-floppies --ignore-cd /ntldr -map () (hd0) -map (hd0) () -map --rehook -find --set-root --ignore-floppies --ignore-cd /ntldr -chainloader /ntldr -savedefault --wait=2 - -#iftitle only show when command in [] returns true -# set a variable named bootmgr where /bootmgr is found. -iftitle [find --set-root --devices=h /bootmgr && call set bootmgr=%@root^%] load BOOTMGR of Windows VISTA/WIN7/WIN2008 on %bootmgr% -fallback +1 -chainloader %bootmgr%/bootmgr -savedefault --wait=2 - -title find and load CMLDR, the Recovery Console of Windows NT/2K/XP -fallback +1 -find --set-root --ignore-floppies --ignore-cd /cmldr -map () (hd0) -map (hd0) () -map --rehook -find --set-root --ignore-floppies --ignore-cd /cmldr -chainloader /cmldr -##################################################################### -# write string "cmdcons" to memory 0000:7C03 in 2 steps: -##################################################################### -# step 1. Write 4 chars "cmdc" at 0000:7C03 -#write 0x7C03 0x63646D63 -# step 2. Write 3 chars "ons" and an ending null at 0000:7C07 -#write 0x7C07 0x00736E6F - -# or. -#write --offset=3 (md)0x3e+1 cmdcons\0 -# or -calc *0x7c03=0x00736E6F63646D63 - -savedefault --wait=2 - -title Chainload IO.SYS for booting MS-DOS/Windows 9x/Me -fallback +1 -find --set-root --ignore-floppies --ignore-cd /io.sys -chainloader /io.sys -savedefault --wait=2 -# -# Or in this way: -# -# find --set-root --ignore-floppies --ignore-cd chainloader /io.sys -# boot -# -# The above boot command is needed in this case. -# See "Delimitors or comments between titles" in grub4dos_readme.txt. - -title find /boot/grub/menu.lst for booting Linux (Mageia, Mandriva, etc) -fallback +1 -find --set-root --ignore-floppies --ignore-cd /boot/grub/menu.lst -configfile /boot/grub/menu.lst - -title Switch to GRUB2 core.img for booting Linux (Ubuntu, etc) -fallback +1 -find --set-root --ignore-floppies --ignore-cd /boot/grub/i386-pc/core.img -kernel /boot/grub/i386-pc/core.img - -title commandline -commandline +# 这是一个样品 menu.lst 文件。你应该对它做些改动。 +# 它必须是 UTF-8 编码,以支持多种语言。 +# 字体应该是 unifont.hex 格式。 -title 0PE LiveISO -find --set-root --ignore-floppies --ignore-cd /0PE.ISO -map /0PE.ISO (0xff) -map --hook -chainloader (0xff) -savedefault --wait=2 -title MicroPE LiveISO -find --set-root --ignore-floppies --ignore-cd /boot/MicroPE.ISO -map /boot/MicroPE.ISO (0xff) -map --hook -chainloader (0xff) -savedefault --wait=2 -title Parted Magic LiveISO -find --set-root --ignore-floppies --ignore-cd /pmagic.iso -map /pmagic.iso (0xff) -map --hook -chainloader (0xff) -savedefault --wait=2 +#设置倒计时(秒) +timeout 30 -title Ultimate Boot CD LiveISO -find --set-root --ignore-floppies --ignore-cd /ubcd.iso -map /ubcd.iso (0xff) -map --hook +#设置第一项为默认值 +default 1 + +#设置字符颜色(高32位是背景色,低32位是前景色。在命令行执行:echo -rrggbb,可查看对应的颜色。) +#color normal=0xff9933 highlight=0xffff00 helptext=0xff00ff heading=0x66ff00 + +#设置图形模式(可使用 graphicsmode 探测系统支持的图形模式) +#graphicsmode -1 800(水平像素) + +#加载背景图 +#splashimage /efi/grub/splashimage.jpg || splashimage /boot/grub/splashimage.bmp +#加载unifont字体(如果不是 16*16 字体,需增加参数,如 --font-high=24) +#font /efi/grub/unifont.hex.gz + +#获取水平像素,加载不同尺寸的字体及背景图 +#calc *0x834c > nul ;; set a=%@retval% +#if %a%>=801 && font --font-high=40 /efi/grub/menu40.hex +#if %a%<=800 && font /efi/grub/unifont.hex.gz && splashimage /efi/grub/lt.jpg + +#判断启动环境:if %@uefi%==64 0/32/64=bios/uefi_x86/uefi_x64 + +#设置菜单框 +#setmenu --box x=4 w=60 y=6 h=9 l=2 +#设置中文菜单按键帮助 +#setmenu --lang=zh +#设置自动菜单编号 +#setmenu --auto-num-on +#设置字符串信息 +#setmenu --string=x=y=颜色="字符串" +#设置日期时间 +#setmenu --string=x=y=颜色="date&time=yyyy-MM-dd HH:mm:ss" +#设置倒计时 +#setmenu --timeout=x=y=颜色 +#更多菜单编辑功能、动画、图像菜单等等,可参考http://bbs.wuyou.net/forum.php?mod=viewthread&tid=369720&extra=page%3D3 + +title 启动 efi 文件 +chainloader /efi/boot/grub2x64.efi + +title 启动 windows +chainloader /efi/microsoft/boot/bootmgfw.efi + +title 启动虚拟光盘 +find --set-root /cdrom.iso +map /cdrom.iso (0xff) chainloader (0xff) -savedefault --wait=2 -title SliTaz LiveISO -find --set-root --ignore-floppies --ignore-cd /slitaz.iso -map /slitaz.iso (0xff) -map --hook +title 启动虚拟光盘(加载到内存) +find --set-root /cdrom.iso +map --mem /cdrom.iso (0xff) chainloader (0xff) -title Mageia Installation ISO -find --set-root --ignore-floppies --ignore-cd /Mageia-2-x86_64-DVD.iso -map /Mageia-2-x86_64-DVD.iso (0xff) -map --hook -chainloader (0xff) +title 启动存在的光盘(cd0) +chainloader (cd0) + +title 启动虚拟硬盘 +find --set-root /boot/hdd.img +map /boot/hdd.img (hd) +chainloader (hd-1) + +title 启动虚拟硬盘(加载到内存) +find --set-root /boot/hdd.img +map --mem /boot/hdd.img (hd) +chainloader (hd-1) + +title 启动存在的硬盘(hd0) +chainloader (hd0) + +title 启动其他菜单 +configfile /efi/grub/menu2.lst + +title 启动 Linux Porteus 5.0 x86_64 openbox +kernel /porteus/vmlinuz copy2ram +initrd /porteus/initrd.xz + +#假设外部命令位于 /efi/grub/ext/ +#假设 WIM/VHD(或者启动文件夹) 位于 (hdx,y)/boot/imgs/ +#假设 windows 的 winload.efi 位于 (hdx,y) + +title 使用外部命令 ntloader 启动 WIM/VHD (kernel方案1) +uuid (hdx,y) +kernel /efi/grub/ext/ntloader uuid=%?% file=/boot/imgs/winpe.wim +initrd /efi/grub/ext/initrd.lz1 + +title 使用外部命令 ntloader 启动 WIM/VHD (kernel 方案2) +find --set-root /boot/imgs/winpe.wim +uuid () +find --set-root /efi/grub/ext/ntloader +kernel /efi/grub/ext/ntloader uuid=%?% file=/boot/imgs/winpe.wim +initrd /efi/grub/ext/initrd.lz1 + +title 使用外部命令 ntloader 启动 WIM/VHD (chainloader 方案1) +uuid (hdx,y) +chainloader /efi/grub/ext/ntloader initrd=/efi/grub/ext/initrd.lz1 uuid=%?% file=/boot/imgs/winpe.wim + +title 使用外部命令 ntloader 启动 WIM/VHD (chainloader 方案2) +find --set-root /boot/imgs/winpe.wim +uuid () +find --set-root /efi/grub/ext/ntloader +chainloader /efi/grub/ext/ntloader initrd=/efi/grub/ext/initrd.lz1 uuid=%?% file=/boot/imgs/winpe.wim + +title 使用外部命令 ntloader 启动 Windows 系统 (kernel 方案) +uuid (hdx,y) +kernel /efi/grub/ext/ntloader uuid=%?% +initrd /efi/grub/ext/initrd.lz1 + +title 使用外部命令 ntloader 启动 Windows 系统 (chainloader 方案) +uuid (hdx,y) +chainloader /efi/grub/ext/ntloader initrd=/efi/grub/ext/initrd.lz1 uuid=%?% + +title 使用外部命令 NTBOOT 启动 WIM/VHD (方案1) +find /efi/grub/ext/ntboot | set bd= +find --set-root /boot/imgs/winpe.wim +%bd%/efi/grub/ext/ntboot /boot/imgs/winpe.wim +boot + +title 使用外部命令 NTBOOT 启动 WIM/VHD (方案2) +find /boot/imgs/winpe.vhd | set bd= +/efi/grub/ext/ntboot %bd%/boot/imgs/winpe.vhd winload=/Windows/System32/boot/winload.efi minint=1 +boot + +title 使用外部命令 NTBOOT 启动 Windows 系统 +/efi/grub/ext/ntboot (hdx,y)/win +boot + +title 使用 http 网起 iso 或者 img 镜象 +map (http)/imgs/pe.iso (cd) +chainloader (cd-1) +boor + +title 使用 http 及外部命令 NTBOOT 网启 wim 镜象 +/efi/grub/ext/ntboot (http)/imgs/pe.wim +boot + +title 命令行 +commandline -title reboot (重启) +title 退出grub4dos +exit_g4d + +title 重启 reboot -title halt (关机) +title 关机 halt -title MAXDOS.IMG -find --set-root --ignore-floppies --ignore-cd /boot/MAXDOS.IMG -map --mem /boot/MAXDOS.IMG (fd0) -map --hook -chainloader (fd0)+1 -rootnoverify (fd0) - -# In the end, font lines for unicode chars in unifont.hex format. -# It should include all unicode chars used in the above menu code. -# Surely normal ASCII chars are not necessary to be included here. - -5173:10100810082000003FF8010001000100FFFE010002800280044008203018C006 -542F:010000801FFC1004100410041FFC10001000100017FC24042404440487FC0404 -673A:100011F011101110FD10111031103910551055109110111211121212120E1400 -91CD:001000F83F000100FFFE01001FF011101FF011101FF001003FF80100FFFE0000 + diff --git a/mkimage b/mkimage new file mode 100755 index 00000000..2e3da29b Binary files /dev/null and b/mkimage differ diff --git a/mkimage.exe b/mkimage.exe new file mode 100644 index 00000000..a2b2c422 Binary files /dev/null and b/mkimage.exe differ diff --git a/mkimage.i386 b/mkimage.i386 new file mode 100755 index 00000000..b6df63be Binary files /dev/null and b/mkimage.i386 differ diff --git a/preset_menu.lst b/preset_menu.lst index e6e51d0e..1fb92404 100644 --- a/preset_menu.lst +++ b/preset_menu.lst @@ -1,19 +1,11 @@ -pxe detect -configfile default 0 -timeout 1 +timeout 0 -title find /menu.lst, /boot/grub/menu.lst, /grub/menu.lst - errorcheck off - configfile /boot/grub/menu.lst - configfile /grub/menu.lst - if "%@root%"=="(ud)" && calc *0x82A0=*0x82b9&0xff - if "%@root:~1,1%"=="f" && find --set-root --devices=f /menu.lst && configfile /menu.lst - find --set-root --ignore-floppies --ignore-cd /menu.lst && configfile /menu.lst - find --set-root --ignore-floppies --ignore-cd /boot/grub/menu.lst && configfile /boot/grub/menu.lst - find --set-root --ignore-floppies --ignore-cd /grub/menu.lst && configfile /grub/menu.lst - configfile http://b.chenall.net/menu.lst - errorcheck on +title find /efi/grub/menu.lst +# errorcheck off +# find --set-root /efi/grub/menu.lst + configfile /efi/grub/menu.lst +# errorcheck on commandline title commandline diff --git a/stage2/Makefile.am b/stage2/Makefile.am deleted file mode 100644 index 253e5433..00000000 --- a/stage2/Makefile.am +++ /dev/null @@ -1,175 +0,0 @@ -# For test target. -#TESTS = size_test -TESTS = -noinst_SCRIPTS = $(TESTS) - -# For silencing OBJCOPY output. -AM_V_OBJCOPY_0 = @echo " OBJ $@";$(OBJCOPY) -AM_V_OBJCOPY_1 = $(OBJCOPY) -AM_V_OBJCOPY_ = $(AM_V_OBJCOPY_$(AM_DEFAULT_VERBOSITY)) -AM_V_OBJCOPY = $(AM_V_OBJCOPY_$(V)) -# For dist target. -noinst_HEADERS = fat.h filesys.h freebsd.h hercules.h \ - iso9660.h jfs.h mb_header.h mb_info.h md5.h \ - pc_slice.h serial.h shared.h term.h \ - terminfo.h tparm.h ufs2.h vstafs.h xfs.h pxe.h ipxe.h graphics.h fsys_initrd.h fsys_ipxe.h cpio.h -EXTRA_DIST = $(noinst_SCRIPTS) - -# Stage 2 and Stage 1.5's. -datalibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor) - -EXTRA_PROGRAMS = nbloader.exec pxeloader.exec diskless.exec - - -datalib_DATA = grub.exe badgrub.exe grldr grldr.mbr bootlace.com hmload.com eltorito.sys -noinst_DATA = pre_stage2 dosstart badgrubstart grldrstart mbrstart bootlacestart hmloadstart pre_stage2_fullsize pre_stage2_head pre_stage2_tail -noinst_PROGRAMS = pre_stage2.exec dosstart.exec badgrubstart.exec grldrstart.exec mbrstart.exec bootlacestart.exec hmloadstart.exec - -MOSTLYCLEANFILES = $(noinst_PROGRAMS) - -PRE_STAGE2_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8200 $(BIN_LDFLAGS) -START_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8000 $(BIN_LDFLAGS) - -if SERIAL_SUPPORT -SERIAL_FLAGS = -DSUPPORT_SERIAL=1 -else -SERIAL_FLAGS = -endif - -if HERCULES_SUPPORT -HERCULES_FLAGS = -DSUPPORT_HERCULES=1 -else -HERCULES_FLAGS = -endif - -if GRAPHICS_SUPPORT -GRAPHICS_FLAGS = -DSUPPORT_GRAPHICS=1 -else -GRAPHICS_FLAGS = -endif - -if GFX_SUPPORT -GFX_FLAGS = -DSUPPORT_GFX=1 -else -GFX_FLAGS = -endif - -STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \ - $(SERIAL_FLAGS) $(HERCULES_FLAGS) $(GRAPHICS_FLAGS) \ - $(GFX_FLAGS) - -# For stage2 target. -pre_stage2_exec_SOURCES = asm.S bios.c boot.c builtins.c char_io.c \ - cmdline.c common.c console.c dec_lz4.c dec_lzma.c dec_vhd.c disk_io.c fsys_ext2fs.c \ - fsys_fat.c fsys_ntfs.c fsys_ffs.c fsys_iso9660.c fsys_jfs.c fsys_minix.c \ - fsys_reiserfs.c fsys_ufs2.c fsys_vstafs.c fsys_xfs.c fsys_pxe.c fsys_initrd.c fsys_ipxe.c fsys_fb.c gunzip.c \ - hercules.c md5.c serial.c stage2.c terminfo.c tparm.c graphics.c -pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) -pre_stage2_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) -pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK) - -CLEANFILES = $(datalib_DATA) $(noinst_DATA) $(BUILT_SOURCES) - -stage2_size.h: pre_stage2 - $(AM_V_at)-rm -f stage2_size.h - $(AM_V_at)set dummy `ls -l pre_stage2`; \ - echo "#define STAGE2_SIZE $$6" > stage2_size.h - -dosstart_exec_SOURCES = dosstart.S -dosstart_exec_CCASFLAGS = $(STAGE2_COMPILE) -dosstart_exec_LDFLAGS = $(START_LINK) - -dosstart_exec-dosstart.$(OBJEXT): stage2_size.h - -grub.exe: pre_stage2 dosstart - $(AM_V_GEN) - $(AM_V_at)-rm -f grub.exe - $(AM_V_at)echo -n -e "\000\000\000\000\000\000\000\000\000\000\000\000" | cat dosstart pre_stage2 - > grub.exe - $(AM_V_at)if [ -f ../preset_menu_used ]; then cat ../preset_menu_used >> grub.exe ;fi - $(AM_V_at)dd if=/dev/zero bs=4128 count=1 >> grub.exe 2>/dev/null || echo "DD failed!" - -badgrubstart_exec_SOURCES = badgrubstart.S -badgrubstart_exec_CCASFLAGS = $(STAGE2_COMPILE) -badgrubstart_exec_LDFLAGS = $(START_LINK) - -badgrubstart_exec-badgrubstart.$(OBJEXT): stage2_size.h dosstart.S - -badgrub.exe: pre_stage2 badgrubstart - $(AM_V_GEN) - $(AM_V_at)-rm -f badgrub.exe - $(AM_V_at)echo -n -e "\000\000\000\000\000\000\000\000\000\000\000\000" | cat badgrubstart pre_stage2 - > badgrub.exe - $(AM_V_at)if [ -f ../preset_menu_used ]; then cat ../preset_menu_used >> badgrub.exe ;fi - $(AM_V_at)dd if=/dev/zero bs=4128 count=1 >> badgrub.exe 2>/dev/null || echo "DD failed!" - -grldrstart_exec_SOURCES = grldrstart.S -grldrstart_exec_CCASFLAGS = $(STAGE2_COMPILE) -grldrstart_exec_LDFLAGS = $(START_LINK) - -grldrstart_exec-grldrstart.$(OBJEXT): stage2_size.h - -grldr: pre_stage2 grldrstart - $(AM_V_GEN) - $(AM_V_at)-rm -f grldr - $(AM_V_at)echo -n -e "\000\000\000\000\000\000\000\000\000\000\000\000" | cat grldrstart pre_stage2 - > grldr - $(AM_V_at)if [ -f ../preset_menu_used ]; then cat ../preset_menu_used >> grldr ;fi - -mbrstart_exec_SOURCES = mbrstart.S -mbrstart_exec_CCASFLAGS = $(STAGE2_COMPILE) -mbrstart_exec_LDFLAGS = $(START_LINK) - -mbrstart_exec-mbrstart.$(OBJEXT): stage2_size.h grldrstart.S - -grldr.mbr: mbrstart - $(AM_V_GEN) - $(AM_V_at)-rm -f grldr.mbr - $(AM_V_at)cat mbrstart > grldr.mbr - -bootlacestart_exec_SOURCES = bootlacestart.S -bootlacestart_exec_CCASFLAGS = $(STAGE2_COMPILE) -bootlacestart_exec_LDFLAGS = -nostdlib -Wl,-N -Wl,-Ttext -Wl,08048000 $(BIN_LDFLAGS) - -bootlacestart_exec-bootlacestart.$(OBJEXT): stage2_size.h bootlace.inc grldrstart.S - -bootlace.com: bootlacestart #Note: Synchronous modifications build - $(AM_V_GEN) - $(AM_V_at)-rm -f bootlace.com - $(AM_V_at)-rm -f grldr.pbr - $(AM_V_at)cp bootlacestart bootlace.com && chmod a+x bootlace.com - $(AM_V_at)dd if=bootlace.com of=grldr.pbr bs=512 skip=57 count=10 #skip(1): "EB 58 90 00" position in the bootlace.com redress: skip +(-) 1 - $(AM_V_at)dd if=bootlace.com of=grldr_cd.bin bs=512 skip=67 count=1 #skip(2): = skip(1) + 10 - $(AM_V_at)dd if=bootlace.com of=grldr.pbr bs=512 skip=68 seek=10 count=1 #skip(3): = skip(2) + 1 - $(AM_V_at)cat grldr.mbr >> bootlace.com - -hmloadstart_exec_SOURCES = hmloadstart.S -hmloadstart_exec_CCASFLAGS = $(STAGE2_COMPILE) -hmloadstart_exec_LDFLAGS = -nostdlib -Wl,-N -Wl,-Ttext -Wl,08048000 $(BIN_LDFLAGS) - -hmloadstart_exec-hmloadstart.$(OBJEXT): stage2_size.h - -hmload.com: hmloadstart - $(AM_V_GEN) - $(AM_V_at)-rm -f hmload.com - $(AM_V_at)cp hmloadstart hmload.com && chmod a-x hmload.com - -eltorito.sys: eltorito.asm - $(AM_V_at)nasm -Ox -f bin -o $@ $< || echo "Failed in building eltorito.sys!" - $(AM_V_at)upx --ultra-brute --lzma $@ || upx --ultra-brute $@ || echo "upx command not found!" - -asm.S: a20.inc - touch asm.S - -dosstart.S: a20.inc - touch dosstart.S - -badgrubstart.S: a20.inc - touch badgrubstart.S - -# General rule for making a raw binary. -SUFFIXES = .exec -%: %.exec$(EXEEXT) - $(AM_V_OBJCOPY) -O binary $< $@ - $(AM_V_at)if [ $@ = pre_stage2 ]; then dd if=pre_stage2 of=pre_stage2_fullsize bs=65536 skip=48 2>/dev/null || echo "DD failed!" ;fi - $(AM_V_at)if [ $@ = pre_stage2 ]; then sed -e "1s/^\x00*//" pre_stage2_fullsize > pre_stage2_tail ;fi - $(AM_V_at)if [ $@ = pre_stage2 ]; then set dummy `ls -l pre_stage2_fullsize`; set $$6 `ls -l pre_stage2_tail`; if [ $$1 -le $$6 ]; then set `cmp pre_stage2_fullsize /dev/zero` ; while [ "$$1" != "" ]; do t1="$${1%%[^0-9]*}"; if [ "$$t1" != "" ]; then if [ "$$t1" -gt 2000 ]; then t1=`expr $$t1 - 1`; dd if=pre_stage2_fullsize of=pre_stage2_tail bs=1 skip=$$t1 2>/dev/null || echo "DD failed!" ; break; fi; fi; shift; done; fi; fi - $(AM_V_at)if [ $@ = pre_stage2 ]; then set dummy `ls -l pre_stage2_fullsize`; set $$6 `ls -l pre_stage2_tail`; dd if=pre_stage2 of=pre_stage2_head bs=`expr $$1 - $$6` count=1 2>/dev/null || echo "DD failed!" ; cat pre_stage2_head pre_stage2_tail > pre_stage2 ;fi - $(AM_V_at)if [ $@ = pre_stage2 ]; then echo -n -e "\0260\002\032\0316" >> $@ ;fi diff --git a/stage2/Makefile.in b/stage2/Makefile.in index 19f5a0bc..a0f590c5 100644 --- a/stage2/Makefile.in +++ b/stage2/Makefile.in @@ -68,9 +68,13 @@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c +#install_sh_DATA = $(install_sh) -mcmodel=large -m64 -c -m 644 +#install_sh_PROGRAM = $(install_sh) -mcmodel=large -m64 -c +#install_sh_SCRIPT = $(install_sh) -mcmodel=large -m64 -c 适应gcc高版本 2023-06-06 +install_sh_DATA = $(install_sh) -c -m64 -mcmodel=large -no-pie -fno-pic -m 644 +install_sh_PROGRAM = $(install_sh) -c -m64 -mcmodel=large -no-pie -fno-pic +install_sh_SCRIPT = $(install_sh) -c -m64 -mcmodel=large -no-pie -fno-pic +PARAMETER = -c -m64 -mcmodel=large -no-pie -fno-pic INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : @@ -84,10 +88,7 @@ host_triplet = @host@ TESTS = EXTRA_PROGRAMS = nbloader.exec$(EXEEXT) pxeloader.exec$(EXEEXT) \ diskless.exec$(EXEEXT) -noinst_PROGRAMS = pre_stage2.exec$(EXEEXT) dosstart.exec$(EXEEXT) \ - badgrubstart.exec$(EXEEXT) grldrstart.exec$(EXEEXT) \ - mbrstart.exec$(EXEEXT) bootlacestart.exec$(EXEEXT) \ - hmloadstart.exec$(EXEEXT) +noinst_PROGRAMS = pre_stage2.exec$(EXEEXT) subdir = stage2 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/mkinstalldirs $(top_srcdir)/depcomp \ @@ -102,46 +103,8 @@ CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = PROGRAMS = $(noinst_PROGRAMS) -am_badgrubstart_exec_OBJECTS = \ - badgrubstart_exec-badgrubstart.$(OBJEXT) -badgrubstart_exec_OBJECTS = $(am_badgrubstart_exec_OBJECTS) -badgrubstart_exec_LDADD = $(LDADD) -badgrubstart_exec_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(badgrubstart_exec_LDFLAGS) $(LDFLAGS) -o $@ -am_bootlacestart_exec_OBJECTS = \ - bootlacestart_exec-bootlacestart.$(OBJEXT) -bootlacestart_exec_OBJECTS = $(am_bootlacestart_exec_OBJECTS) -bootlacestart_exec_LDADD = $(LDADD) -bootlacestart_exec_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(bootlacestart_exec_LDFLAGS) $(LDFLAGS) -o $@ -diskless_exec_SOURCES = diskless.c -diskless_exec_OBJECTS = diskless.$(OBJEXT) -diskless_exec_LDADD = $(LDADD) -am_dosstart_exec_OBJECTS = dosstart_exec-dosstart.$(OBJEXT) -dosstart_exec_OBJECTS = $(am_dosstart_exec_OBJECTS) -dosstart_exec_LDADD = $(LDADD) -dosstart_exec_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(dosstart_exec_LDFLAGS) $(LDFLAGS) -o $@ -am_grldrstart_exec_OBJECTS = grldrstart_exec-grldrstart.$(OBJEXT) -grldrstart_exec_OBJECTS = $(am_grldrstart_exec_OBJECTS) -grldrstart_exec_LDADD = $(LDADD) -grldrstart_exec_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(grldrstart_exec_LDFLAGS) $(LDFLAGS) -o $@ -am_hmloadstart_exec_OBJECTS = hmloadstart_exec-hmloadstart.$(OBJEXT) -hmloadstart_exec_OBJECTS = $(am_hmloadstart_exec_OBJECTS) -hmloadstart_exec_LDADD = $(LDADD) -hmloadstart_exec_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(hmloadstart_exec_LDFLAGS) $(LDFLAGS) -o $@ -am_mbrstart_exec_OBJECTS = mbrstart_exec-mbrstart.$(OBJEXT) -mbrstart_exec_OBJECTS = $(am_mbrstart_exec_OBJECTS) -mbrstart_exec_LDADD = $(LDADD) -mbrstart_exec_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(mbrstart_exec_LDFLAGS) $(LDFLAGS) -o $@ -nbloader_exec_SOURCES = nbloader.c -nbloader_exec_OBJECTS = nbloader.$(OBJEXT) -nbloader_exec_LDADD = $(LDADD) am_pre_stage2_exec_OBJECTS = pre_stage2_exec-asm.$(OBJEXT) \ - pre_stage2_exec-bios.$(OBJEXT) pre_stage2_exec-boot.$(OBJEXT) \ + pre_stage2_exec-boot.$(OBJEXT) \ pre_stage2_exec-builtins.$(OBJEXT) \ pre_stage2_exec-char_io.$(OBJEXT) \ pre_stage2_exec-cmdline.$(OBJEXT) \ @@ -154,24 +117,14 @@ am_pre_stage2_exec_OBJECTS = pre_stage2_exec-asm.$(OBJEXT) \ pre_stage2_exec-fsys_ext2fs.$(OBJEXT) \ pre_stage2_exec-fsys_fat.$(OBJEXT) \ pre_stage2_exec-fsys_ntfs.$(OBJEXT) \ - pre_stage2_exec-fsys_ffs.$(OBJEXT) \ pre_stage2_exec-fsys_iso9660.$(OBJEXT) \ - pre_stage2_exec-fsys_jfs.$(OBJEXT) \ - pre_stage2_exec-fsys_minix.$(OBJEXT) \ - pre_stage2_exec-fsys_reiserfs.$(OBJEXT) \ - pre_stage2_exec-fsys_ufs2.$(OBJEXT) \ - pre_stage2_exec-fsys_vstafs.$(OBJEXT) \ - pre_stage2_exec-fsys_xfs.$(OBJEXT) \ pre_stage2_exec-fsys_pxe.$(OBJEXT) \ - pre_stage2_exec-fsys_initrd.$(OBJEXT) \ pre_stage2_exec-fsys_ipxe.$(OBJEXT) \ pre_stage2_exec-fsys_fb.$(OBJEXT) \ + pre_stage2_exec-fsys_initrd.$(OBJEXT) \ pre_stage2_exec-gunzip.$(OBJEXT) \ - pre_stage2_exec-hercules.$(OBJEXT) \ - pre_stage2_exec-md5.$(OBJEXT) pre_stage2_exec-serial.$(OBJEXT) \ + pre_stage2_exec-md5.$(OBJEXT) \ pre_stage2_exec-stage2.$(OBJEXT) \ - pre_stage2_exec-terminfo.$(OBJEXT) \ - pre_stage2_exec-tparm.$(OBJEXT) \ pre_stage2_exec-graphics.$(OBJEXT) pre_stage2_exec_OBJECTS = $(am_pre_stage2_exec_OBJECTS) pre_stage2_exec_LDADD = $(LDADD) @@ -219,15 +172,21 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = -SOURCES = $(badgrubstart_exec_SOURCES) $(bootlacestart_exec_SOURCES) \ - diskless.c $(dosstart_exec_SOURCES) $(grldrstart_exec_SOURCES) \ - $(hmloadstart_exec_SOURCES) $(mbrstart_exec_SOURCES) \ - nbloader.c $(pre_stage2_exec_SOURCES) pxeloader.c -DIST_SOURCES = $(badgrubstart_exec_SOURCES) \ - $(bootlacestart_exec_SOURCES) diskless.c \ - $(dosstart_exec_SOURCES) $(grldrstart_exec_SOURCES) \ - $(hmloadstart_exec_SOURCES) $(mbrstart_exec_SOURCES) \ - nbloader.c $(pre_stage2_exec_SOURCES) pxeloader.c +SOURCES = $(pre_stage2_exec_SOURCES) + +#SOURCES = $(badgrubstart_exec_SOURCES) $(bootlacestart_exec_SOURCES) \ +# diskless.c $(dosstart_exec_SOURCES) $(grldrstart_exec_SOURCES) \ +# $(hmloadstart_exec_SOURCES) $(mbrstart_exec_SOURCES) \ +# nbloader.c $(pre_stage2_exec_SOURCES) pxeloader.c + + +DIST_SOURCES = $(pre_stage2_exec_SOURCES) + +#DIST_SOURCES = $(badgrubstart_exec_SOURCES) \ +# $(bootlacestart_exec_SOURCES) diskless.c \ +# $(dosstart_exec_SOURCES) $(grldrstart_exec_SOURCES) \ +# $(hmloadstart_exec_SOURCES) $(mbrstart_exec_SOURCES) \ +# nbloader.c $(pre_stage2_exec_SOURCES) pxeloader.c am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -576,62 +535,42 @@ AM_V_OBJCOPY_1 = $(OBJCOPY) AM_V_OBJCOPY_ = $(AM_V_OBJCOPY_$(AM_DEFAULT_VERBOSITY)) AM_V_OBJCOPY = $(AM_V_OBJCOPY_$(V)) # For dist target. -noinst_HEADERS = fat.h filesys.h freebsd.h hercules.h \ - iso9660.h jfs.h mb_header.h mb_info.h md5.h \ - pc_slice.h serial.h shared.h term.h \ - terminfo.h tparm.h ufs2.h vstafs.h xfs.h pxe.h ipxe.h graphics.h fsys_initrd.h fsys_ipxe.h cpio.h +noinst_HEADERS = fat.h filesys.h freebsd.h \ + iso9660.h mb_header.h mb_info.h md5.h \ + pc_slice.h shared.h term.h \ + pxe.h ipxe.h graphics.h fsys_ipxe.h cpio.h fsys_initrd.h EXTRA_DIST = $(noinst_SCRIPTS) # Stage 2 and Stage 1.5's. datalibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor) -datalib_DATA = grub.exe badgrub.exe grldr grldr.mbr bootlace.com hmload.com eltorito.sys -noinst_DATA = pre_stage2 dosstart badgrubstart grldrstart mbrstart bootlacestart hmloadstart pre_stage2_fullsize pre_stage2_head pre_stage2_tail + +noinst_DATA = pre_stage2 + MOSTLYCLEANFILES = $(noinst_PROGRAMS) -PRE_STAGE2_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8200 $(BIN_LDFLAGS) -START_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8000 $(BIN_LDFLAGS) -@SERIAL_SUPPORT_FALSE@SERIAL_FLAGS = -@SERIAL_SUPPORT_TRUE@SERIAL_FLAGS = -DSUPPORT_SERIAL=1 -@HERCULES_SUPPORT_FALSE@HERCULES_FLAGS = -@HERCULES_SUPPORT_TRUE@HERCULES_FLAGS = -DSUPPORT_HERCULES=1 +#PRE_STAGE2_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8200 $(BIN_LDFLAGS) 以下替代 +#PRE_STAGE2_LINK = -nostdlib -Wl,-N -Wl,-melf_x86_64 -Wl,-x -Wl,--build-id=none -Wl,-r,-d $(BIN_LDFLAGS) 适应gcc高版本 2023-06-06 +PRE_STAGE2_LINK = -nostdlib -no-pie -fno-pic -Wl,-N -Wl,-melf_x86_64 -Wl,-x -Wl,--build-id=none -Wl,-r,-d $(BIN_LDFLAGS) @GRAPHICS_SUPPORT_FALSE@GRAPHICS_FLAGS = @GRAPHICS_SUPPORT_TRUE@GRAPHICS_FLAGS = -DSUPPORT_GRAPHICS=1 @GFX_SUPPORT_FALSE@GFX_FLAGS = @GFX_SUPPORT_TRUE@GFX_FLAGS = -DSUPPORT_GFX=1 STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \ - $(SERIAL_FLAGS) $(HERCULES_FLAGS) $(GRAPHICS_FLAGS) \ + $(GRAPHICS_FLAGS) \ $(GFX_FLAGS) # For stage2 target. -pre_stage2_exec_SOURCES = asm.S bios.c boot.c builtins.c char_io.c \ +pre_stage2_exec_SOURCES = asm.S boot.c builtins.c char_io.c \ cmdline.c common.c console.c dec_lz4.c dec_lzma.c dec_vhd.c disk_io.c fsys_ext2fs.c \ - fsys_fat.c fsys_ntfs.c fsys_ffs.c fsys_iso9660.c fsys_jfs.c fsys_minix.c \ - fsys_reiserfs.c fsys_ufs2.c fsys_vstafs.c fsys_xfs.c fsys_pxe.c fsys_initrd.c fsys_ipxe.c fsys_fb.c gunzip.c \ - hercules.c md5.c serial.c stage2.c terminfo.c tparm.c graphics.c + fsys_fat.c fsys_ntfs.c fsys_iso9660.c \ + fsys_pxe.c fsys_ipxe.c fsys_fb.c gunzip.c \ + md5.c stage2.c graphics.c fsys_initrd.c pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) pre_stage2_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK) CLEANFILES = $(datalib_DATA) $(noinst_DATA) $(BUILT_SOURCES) -dosstart_exec_SOURCES = dosstart.S -dosstart_exec_CCASFLAGS = $(STAGE2_COMPILE) -dosstart_exec_LDFLAGS = $(START_LINK) -badgrubstart_exec_SOURCES = badgrubstart.S -badgrubstart_exec_CCASFLAGS = $(STAGE2_COMPILE) -badgrubstart_exec_LDFLAGS = $(START_LINK) -grldrstart_exec_SOURCES = grldrstart.S -grldrstart_exec_CCASFLAGS = $(STAGE2_COMPILE) -grldrstart_exec_LDFLAGS = $(START_LINK) -mbrstart_exec_SOURCES = mbrstart.S -mbrstart_exec_CCASFLAGS = $(STAGE2_COMPILE) -mbrstart_exec_LDFLAGS = $(START_LINK) -bootlacestart_exec_SOURCES = bootlacestart.S -bootlacestart_exec_CCASFLAGS = $(STAGE2_COMPILE) -bootlacestart_exec_LDFLAGS = -nostdlib -Wl,-N -Wl,-Ttext -Wl,08048000 $(BIN_LDFLAGS) -hmloadstart_exec_SOURCES = hmloadstart.S -hmloadstart_exec_CCASFLAGS = $(STAGE2_COMPILE) -hmloadstart_exec_LDFLAGS = -nostdlib -Wl,-N -Wl,-Ttext -Wl,08048000 $(BIN_LDFLAGS) # General rule for making a raw binary. SUFFIXES = .exec @@ -673,38 +612,6 @@ $(am__aclocal_m4_deps): clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) -badgrubstart.exec$(EXEEXT): $(badgrubstart_exec_OBJECTS) $(badgrubstart_exec_DEPENDENCIES) $(EXTRA_badgrubstart_exec_DEPENDENCIES) - @rm -f badgrubstart.exec$(EXEEXT) - $(AM_V_CCLD)$(badgrubstart_exec_LINK) $(badgrubstart_exec_OBJECTS) $(badgrubstart_exec_LDADD) $(LIBS) - -bootlacestart.exec$(EXEEXT): $(bootlacestart_exec_OBJECTS) $(bootlacestart_exec_DEPENDENCIES) $(EXTRA_bootlacestart_exec_DEPENDENCIES) - @rm -f bootlacestart.exec$(EXEEXT) - $(AM_V_CCLD)$(bootlacestart_exec_LINK) $(bootlacestart_exec_OBJECTS) $(bootlacestart_exec_LDADD) $(LIBS) - -diskless.exec$(EXEEXT): $(diskless_exec_OBJECTS) $(diskless_exec_DEPENDENCIES) $(EXTRA_diskless_exec_DEPENDENCIES) - @rm -f diskless.exec$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(diskless_exec_OBJECTS) $(diskless_exec_LDADD) $(LIBS) - -dosstart.exec$(EXEEXT): $(dosstart_exec_OBJECTS) $(dosstart_exec_DEPENDENCIES) $(EXTRA_dosstart_exec_DEPENDENCIES) - @rm -f dosstart.exec$(EXEEXT) - $(AM_V_CCLD)$(dosstart_exec_LINK) $(dosstart_exec_OBJECTS) $(dosstart_exec_LDADD) $(LIBS) - -grldrstart.exec$(EXEEXT): $(grldrstart_exec_OBJECTS) $(grldrstart_exec_DEPENDENCIES) $(EXTRA_grldrstart_exec_DEPENDENCIES) - @rm -f grldrstart.exec$(EXEEXT) - $(AM_V_CCLD)$(grldrstart_exec_LINK) $(grldrstart_exec_OBJECTS) $(grldrstart_exec_LDADD) $(LIBS) - -hmloadstart.exec$(EXEEXT): $(hmloadstart_exec_OBJECTS) $(hmloadstart_exec_DEPENDENCIES) $(EXTRA_hmloadstart_exec_DEPENDENCIES) - @rm -f hmloadstart.exec$(EXEEXT) - $(AM_V_CCLD)$(hmloadstart_exec_LINK) $(hmloadstart_exec_OBJECTS) $(hmloadstart_exec_LDADD) $(LIBS) - -mbrstart.exec$(EXEEXT): $(mbrstart_exec_OBJECTS) $(mbrstart_exec_DEPENDENCIES) $(EXTRA_mbrstart_exec_DEPENDENCIES) - @rm -f mbrstart.exec$(EXEEXT) - $(AM_V_CCLD)$(mbrstart_exec_LINK) $(mbrstart_exec_OBJECTS) $(mbrstart_exec_LDADD) $(LIBS) - -nbloader.exec$(EXEEXT): $(nbloader_exec_OBJECTS) $(nbloader_exec_DEPENDENCIES) $(EXTRA_nbloader_exec_DEPENDENCIES) - @rm -f nbloader.exec$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nbloader_exec_OBJECTS) $(nbloader_exec_LDADD) $(LIBS) - pre_stage2.exec$(EXEEXT): $(pre_stage2_exec_OBJECTS) $(pre_stage2_exec_DEPENDENCIES) $(EXTRA_pre_stage2_exec_DEPENDENCIES) @rm -f pre_stage2.exec$(EXEEXT) $(AM_V_CCLD)$(pre_stage2_exec_LINK) $(pre_stage2_exec_OBJECTS) $(pre_stage2_exec_LDADD) $(LIBS) @@ -719,16 +626,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/badgrubstart_exec-badgrubstart.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bootlacestart_exec-bootlacestart.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/diskless.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dosstart_exec-dosstart.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grldrstart_exec-grldrstart.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hmloadstart_exec-hmloadstart.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbrstart_exec-mbrstart.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nbloader.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-asm.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-bios.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-boot.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-builtins.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-char_io.Po@am__quote@ @@ -742,629 +640,365 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_ext2fs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_fat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_fb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_ffs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_initrd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_ipxe.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_iso9660.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_jfs.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_minix.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_ntfs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_pxe.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_reiserfs.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_ufs2.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_vstafs.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_xfs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-graphics.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-gunzip.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-hercules.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-md5.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-serial.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-stage2.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-terminfo.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-tparm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pxeloader.Po@am__quote@ .S.o: -@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo $(PARAMETER) -o $@ $< @am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CPPASCOMPILE) -c -o $@ $< +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CPPASCOMPILE) $(PARAMETER) -o $@ $< .S.obj: -@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo $(PARAMETER) -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CPPASCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -badgrubstart_exec-badgrubstart.o: badgrubstart.S -@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(badgrubstart_exec_CCASFLAGS) $(CCASFLAGS) -MT badgrubstart_exec-badgrubstart.o -MD -MP -MF $(DEPDIR)/badgrubstart_exec-badgrubstart.Tpo -c -o badgrubstart_exec-badgrubstart.o `test -f 'badgrubstart.S' || echo '$(srcdir)/'`badgrubstart.S -@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/badgrubstart_exec-badgrubstart.Tpo $(DEPDIR)/badgrubstart_exec-badgrubstart.Po -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='badgrubstart.S' object='badgrubstart_exec-badgrubstart.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(badgrubstart_exec_CCASFLAGS) $(CCASFLAGS) -c -o badgrubstart_exec-badgrubstart.o `test -f 'badgrubstart.S' || echo '$(srcdir)/'`badgrubstart.S - -badgrubstart_exec-badgrubstart.obj: badgrubstart.S -@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(badgrubstart_exec_CCASFLAGS) $(CCASFLAGS) -MT badgrubstart_exec-badgrubstart.obj -MD -MP -MF $(DEPDIR)/badgrubstart_exec-badgrubstart.Tpo -c -o badgrubstart_exec-badgrubstart.obj `if test -f 'badgrubstart.S'; then $(CYGPATH_W) 'badgrubstart.S'; else $(CYGPATH_W) '$(srcdir)/badgrubstart.S'; fi` -@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/badgrubstart_exec-badgrubstart.Tpo $(DEPDIR)/badgrubstart_exec-badgrubstart.Po -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='badgrubstart.S' object='badgrubstart_exec-badgrubstart.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(badgrubstart_exec_CCASFLAGS) $(CCASFLAGS) -c -o badgrubstart_exec-badgrubstart.obj `if test -f 'badgrubstart.S'; then $(CYGPATH_W) 'badgrubstart.S'; else $(CYGPATH_W) '$(srcdir)/badgrubstart.S'; fi` - -bootlacestart_exec-bootlacestart.o: bootlacestart.S -@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(bootlacestart_exec_CCASFLAGS) $(CCASFLAGS) -MT bootlacestart_exec-bootlacestart.o -MD -MP -MF $(DEPDIR)/bootlacestart_exec-bootlacestart.Tpo -c -o bootlacestart_exec-bootlacestart.o `test -f 'bootlacestart.S' || echo '$(srcdir)/'`bootlacestart.S -@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/bootlacestart_exec-bootlacestart.Tpo $(DEPDIR)/bootlacestart_exec-bootlacestart.Po -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='bootlacestart.S' object='bootlacestart_exec-bootlacestart.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(bootlacestart_exec_CCASFLAGS) $(CCASFLAGS) -c -o bootlacestart_exec-bootlacestart.o `test -f 'bootlacestart.S' || echo '$(srcdir)/'`bootlacestart.S - -bootlacestart_exec-bootlacestart.obj: bootlacestart.S -@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(bootlacestart_exec_CCASFLAGS) $(CCASFLAGS) -MT bootlacestart_exec-bootlacestart.obj -MD -MP -MF $(DEPDIR)/bootlacestart_exec-bootlacestart.Tpo -c -o bootlacestart_exec-bootlacestart.obj `if test -f 'bootlacestart.S'; then $(CYGPATH_W) 'bootlacestart.S'; else $(CYGPATH_W) '$(srcdir)/bootlacestart.S'; fi` -@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/bootlacestart_exec-bootlacestart.Tpo $(DEPDIR)/bootlacestart_exec-bootlacestart.Po -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='bootlacestart.S' object='bootlacestart_exec-bootlacestart.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(bootlacestart_exec_CCASFLAGS) $(CCASFLAGS) -c -o bootlacestart_exec-bootlacestart.obj `if test -f 'bootlacestart.S'; then $(CYGPATH_W) 'bootlacestart.S'; else $(CYGPATH_W) '$(srcdir)/bootlacestart.S'; fi` - -dosstart_exec-dosstart.o: dosstart.S -@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dosstart_exec_CCASFLAGS) $(CCASFLAGS) -MT dosstart_exec-dosstart.o -MD -MP -MF $(DEPDIR)/dosstart_exec-dosstart.Tpo -c -o dosstart_exec-dosstart.o `test -f 'dosstart.S' || echo '$(srcdir)/'`dosstart.S -@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dosstart_exec-dosstart.Tpo $(DEPDIR)/dosstart_exec-dosstart.Po -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='dosstart.S' object='dosstart_exec-dosstart.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dosstart_exec_CCASFLAGS) $(CCASFLAGS) -c -o dosstart_exec-dosstart.o `test -f 'dosstart.S' || echo '$(srcdir)/'`dosstart.S - -dosstart_exec-dosstart.obj: dosstart.S -@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dosstart_exec_CCASFLAGS) $(CCASFLAGS) -MT dosstart_exec-dosstart.obj -MD -MP -MF $(DEPDIR)/dosstart_exec-dosstart.Tpo -c -o dosstart_exec-dosstart.obj `if test -f 'dosstart.S'; then $(CYGPATH_W) 'dosstart.S'; else $(CYGPATH_W) '$(srcdir)/dosstart.S'; fi` -@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dosstart_exec-dosstart.Tpo $(DEPDIR)/dosstart_exec-dosstart.Po -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='dosstart.S' object='dosstart_exec-dosstart.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dosstart_exec_CCASFLAGS) $(CCASFLAGS) -c -o dosstart_exec-dosstart.obj `if test -f 'dosstart.S'; then $(CYGPATH_W) 'dosstart.S'; else $(CYGPATH_W) '$(srcdir)/dosstart.S'; fi` - -grldrstart_exec-grldrstart.o: grldrstart.S -@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grldrstart_exec_CCASFLAGS) $(CCASFLAGS) -MT grldrstart_exec-grldrstart.o -MD -MP -MF $(DEPDIR)/grldrstart_exec-grldrstart.Tpo -c -o grldrstart_exec-grldrstart.o `test -f 'grldrstart.S' || echo '$(srcdir)/'`grldrstart.S -@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/grldrstart_exec-grldrstart.Tpo $(DEPDIR)/grldrstart_exec-grldrstart.Po -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='grldrstart.S' object='grldrstart_exec-grldrstart.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grldrstart_exec_CCASFLAGS) $(CCASFLAGS) -c -o grldrstart_exec-grldrstart.o `test -f 'grldrstart.S' || echo '$(srcdir)/'`grldrstart.S - -grldrstart_exec-grldrstart.obj: grldrstart.S -@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grldrstart_exec_CCASFLAGS) $(CCASFLAGS) -MT grldrstart_exec-grldrstart.obj -MD -MP -MF $(DEPDIR)/grldrstart_exec-grldrstart.Tpo -c -o grldrstart_exec-grldrstart.obj `if test -f 'grldrstart.S'; then $(CYGPATH_W) 'grldrstart.S'; else $(CYGPATH_W) '$(srcdir)/grldrstart.S'; fi` -@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/grldrstart_exec-grldrstart.Tpo $(DEPDIR)/grldrstart_exec-grldrstart.Po -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='grldrstart.S' object='grldrstart_exec-grldrstart.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grldrstart_exec_CCASFLAGS) $(CCASFLAGS) -c -o grldrstart_exec-grldrstart.obj `if test -f 'grldrstart.S'; then $(CYGPATH_W) 'grldrstart.S'; else $(CYGPATH_W) '$(srcdir)/grldrstart.S'; fi` - -hmloadstart_exec-hmloadstart.o: hmloadstart.S -@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hmloadstart_exec_CCASFLAGS) $(CCASFLAGS) -MT hmloadstart_exec-hmloadstart.o -MD -MP -MF $(DEPDIR)/hmloadstart_exec-hmloadstart.Tpo -c -o hmloadstart_exec-hmloadstart.o `test -f 'hmloadstart.S' || echo '$(srcdir)/'`hmloadstart.S -@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/hmloadstart_exec-hmloadstart.Tpo $(DEPDIR)/hmloadstart_exec-hmloadstart.Po -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='hmloadstart.S' object='hmloadstart_exec-hmloadstart.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hmloadstart_exec_CCASFLAGS) $(CCASFLAGS) -c -o hmloadstart_exec-hmloadstart.o `test -f 'hmloadstart.S' || echo '$(srcdir)/'`hmloadstart.S - -hmloadstart_exec-hmloadstart.obj: hmloadstart.S -@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hmloadstart_exec_CCASFLAGS) $(CCASFLAGS) -MT hmloadstart_exec-hmloadstart.obj -MD -MP -MF $(DEPDIR)/hmloadstart_exec-hmloadstart.Tpo -c -o hmloadstart_exec-hmloadstart.obj `if test -f 'hmloadstart.S'; then $(CYGPATH_W) 'hmloadstart.S'; else $(CYGPATH_W) '$(srcdir)/hmloadstart.S'; fi` -@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/hmloadstart_exec-hmloadstart.Tpo $(DEPDIR)/hmloadstart_exec-hmloadstart.Po -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='hmloadstart.S' object='hmloadstart_exec-hmloadstart.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hmloadstart_exec_CCASFLAGS) $(CCASFLAGS) -c -o hmloadstart_exec-hmloadstart.obj `if test -f 'hmloadstart.S'; then $(CYGPATH_W) 'hmloadstart.S'; else $(CYGPATH_W) '$(srcdir)/hmloadstart.S'; fi` - -mbrstart_exec-mbrstart.o: mbrstart.S -@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mbrstart_exec_CCASFLAGS) $(CCASFLAGS) -MT mbrstart_exec-mbrstart.o -MD -MP -MF $(DEPDIR)/mbrstart_exec-mbrstart.Tpo -c -o mbrstart_exec-mbrstart.o `test -f 'mbrstart.S' || echo '$(srcdir)/'`mbrstart.S -@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mbrstart_exec-mbrstart.Tpo $(DEPDIR)/mbrstart_exec-mbrstart.Po -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='mbrstart.S' object='mbrstart_exec-mbrstart.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mbrstart_exec_CCASFLAGS) $(CCASFLAGS) -c -o mbrstart_exec-mbrstart.o `test -f 'mbrstart.S' || echo '$(srcdir)/'`mbrstart.S - -mbrstart_exec-mbrstart.obj: mbrstart.S -@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mbrstart_exec_CCASFLAGS) $(CCASFLAGS) -MT mbrstart_exec-mbrstart.obj -MD -MP -MF $(DEPDIR)/mbrstart_exec-mbrstart.Tpo -c -o mbrstart_exec-mbrstart.obj `if test -f 'mbrstart.S'; then $(CYGPATH_W) 'mbrstart.S'; else $(CYGPATH_W) '$(srcdir)/mbrstart.S'; fi` -@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mbrstart_exec-mbrstart.Tpo $(DEPDIR)/mbrstart_exec-mbrstart.Po -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='mbrstart.S' object='mbrstart_exec-mbrstart.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mbrstart_exec_CCASFLAGS) $(CCASFLAGS) -c -o mbrstart_exec-mbrstart.obj `if test -f 'mbrstart.S'; then $(CYGPATH_W) 'mbrstart.S'; else $(CYGPATH_W) '$(srcdir)/mbrstart.S'; fi` +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CPPASCOMPILE) $(PARAMETER) -o $@ `$(CYGPATH_W) '$<'` pre_stage2_exec-asm.o: asm.S -@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CCASFLAGS) $(CCASFLAGS) -MT pre_stage2_exec-asm.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-asm.Tpo -c -o pre_stage2_exec-asm.o `test -f 'asm.S' || echo '$(srcdir)/'`asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CCASFLAGS) $(CCASFLAGS) -MT pre_stage2_exec-asm.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-asm.Tpo $(PARAMETER) -o pre_stage2_exec-asm.o `test -f 'asm.S' || echo '$(srcdir)/'`asm.S @am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-asm.Tpo $(DEPDIR)/pre_stage2_exec-asm.Po @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='asm.S' object='pre_stage2_exec-asm.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CCASFLAGS) $(CCASFLAGS) -c -o pre_stage2_exec-asm.o `test -f 'asm.S' || echo '$(srcdir)/'`asm.S +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CCASFLAGS) $(CCASFLAGS) $(PARAMETER) -o pre_stage2_exec-asm.o `test -f 'asm.S' || echo '$(srcdir)/'`asm.S pre_stage2_exec-asm.obj: asm.S -@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CCASFLAGS) $(CCASFLAGS) -MT pre_stage2_exec-asm.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-asm.Tpo -c -o pre_stage2_exec-asm.obj `if test -f 'asm.S'; then $(CYGPATH_W) 'asm.S'; else $(CYGPATH_W) '$(srcdir)/asm.S'; fi` +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CCASFLAGS) $(CCASFLAGS) -MT pre_stage2_exec-asm.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-asm.Tpo $(PARAMETER) -o pre_stage2_exec-asm.obj `if test -f 'asm.S'; then $(CYGPATH_W) 'asm.S'; else $(CYGPATH_W) '$(srcdir)/asm.S'; fi` @am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-asm.Tpo $(DEPDIR)/pre_stage2_exec-asm.Po @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='asm.S' object='pre_stage2_exec-asm.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CCASFLAGS) $(CCASFLAGS) -c -o pre_stage2_exec-asm.obj `if test -f 'asm.S'; then $(CYGPATH_W) 'asm.S'; else $(CYGPATH_W) '$(srcdir)/asm.S'; fi` +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CCASFLAGS) $(CCASFLAGS) $(PARAMETER) -o pre_stage2_exec-asm.obj `if test -f 'asm.S'; then $(CYGPATH_W) 'asm.S'; else $(CYGPATH_W) '$(srcdir)/asm.S'; fi` .c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo $(PARAMETER) -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) $(PARAMETER) -o $@ $< .c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo $(PARAMETER) -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -pre_stage2_exec-bios.o: bios.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-bios.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-bios.Tpo -c -o pre_stage2_exec-bios.o `test -f 'bios.c' || echo '$(srcdir)/'`bios.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-bios.Tpo $(DEPDIR)/pre_stage2_exec-bios.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bios.c' object='pre_stage2_exec-bios.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-bios.o `test -f 'bios.c' || echo '$(srcdir)/'`bios.c - -pre_stage2_exec-bios.obj: bios.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-bios.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-bios.Tpo -c -o pre_stage2_exec-bios.obj `if test -f 'bios.c'; then $(CYGPATH_W) 'bios.c'; else $(CYGPATH_W) '$(srcdir)/bios.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-bios.Tpo $(DEPDIR)/pre_stage2_exec-bios.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bios.c' object='pre_stage2_exec-bios.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-bios.obj `if test -f 'bios.c'; then $(CYGPATH_W) 'bios.c'; else $(CYGPATH_W) '$(srcdir)/bios.c'; fi` - +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) $(PARAMETER) -o $@ `$(CYGPATH_W) '$<'` pre_stage2_exec-boot.o: boot.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-boot.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-boot.Tpo -c -o pre_stage2_exec-boot.o `test -f 'boot.c' || echo '$(srcdir)/'`boot.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-boot.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-boot.Tpo $(PARAMETER) -o pre_stage2_exec-boot.o `test -f 'boot.c' || echo '$(srcdir)/'`boot.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-boot.Tpo $(DEPDIR)/pre_stage2_exec-boot.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='boot.c' object='pre_stage2_exec-boot.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-boot.o `test -f 'boot.c' || echo '$(srcdir)/'`boot.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-boot.o `test -f 'boot.c' || echo '$(srcdir)/'`boot.c pre_stage2_exec-boot.obj: boot.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-boot.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-boot.Tpo -c -o pre_stage2_exec-boot.obj `if test -f 'boot.c'; then $(CYGPATH_W) 'boot.c'; else $(CYGPATH_W) '$(srcdir)/boot.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-boot.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-boot.Tpo $(PARAMETER) -o pre_stage2_exec-boot.obj `if test -f 'boot.c'; then $(CYGPATH_W) 'boot.c'; else $(CYGPATH_W) '$(srcdir)/boot.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-boot.Tpo $(DEPDIR)/pre_stage2_exec-boot.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='boot.c' object='pre_stage2_exec-boot.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-boot.obj `if test -f 'boot.c'; then $(CYGPATH_W) 'boot.c'; else $(CYGPATH_W) '$(srcdir)/boot.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-boot.obj `if test -f 'boot.c'; then $(CYGPATH_W) 'boot.c'; else $(CYGPATH_W) '$(srcdir)/boot.c'; fi` pre_stage2_exec-builtins.o: builtins.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-builtins.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-builtins.Tpo -c -o pre_stage2_exec-builtins.o `test -f 'builtins.c' || echo '$(srcdir)/'`builtins.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-builtins.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-builtins.Tpo $(PARAMETER) -o pre_stage2_exec-builtins.o `test -f 'builtins.c' || echo '$(srcdir)/'`builtins.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-builtins.Tpo $(DEPDIR)/pre_stage2_exec-builtins.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='builtins.c' object='pre_stage2_exec-builtins.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-builtins.o `test -f 'builtins.c' || echo '$(srcdir)/'`builtins.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-builtins.o `test -f 'builtins.c' || echo '$(srcdir)/'`builtins.c pre_stage2_exec-builtins.obj: builtins.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-builtins.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-builtins.Tpo -c -o pre_stage2_exec-builtins.obj `if test -f 'builtins.c'; then $(CYGPATH_W) 'builtins.c'; else $(CYGPATH_W) '$(srcdir)/builtins.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-builtins.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-builtins.Tpo $(PARAMETER) -o pre_stage2_exec-builtins.obj `if test -f 'builtins.c'; then $(CYGPATH_W) 'builtins.c'; else $(CYGPATH_W) '$(srcdir)/builtins.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-builtins.Tpo $(DEPDIR)/pre_stage2_exec-builtins.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='builtins.c' object='pre_stage2_exec-builtins.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-builtins.obj `if test -f 'builtins.c'; then $(CYGPATH_W) 'builtins.c'; else $(CYGPATH_W) '$(srcdir)/builtins.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-builtins.obj `if test -f 'builtins.c'; then $(CYGPATH_W) 'builtins.c'; else $(CYGPATH_W) '$(srcdir)/builtins.c'; fi` pre_stage2_exec-char_io.o: char_io.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-char_io.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-char_io.Tpo -c -o pre_stage2_exec-char_io.o `test -f 'char_io.c' || echo '$(srcdir)/'`char_io.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-char_io.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-char_io.Tpo $(PARAMETER) -o pre_stage2_exec-char_io.o `test -f 'char_io.c' || echo '$(srcdir)/'`char_io.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-char_io.Tpo $(DEPDIR)/pre_stage2_exec-char_io.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='char_io.c' object='pre_stage2_exec-char_io.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-char_io.o `test -f 'char_io.c' || echo '$(srcdir)/'`char_io.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-char_io.o `test -f 'char_io.c' || echo '$(srcdir)/'`char_io.c pre_stage2_exec-char_io.obj: char_io.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-char_io.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-char_io.Tpo -c -o pre_stage2_exec-char_io.obj `if test -f 'char_io.c'; then $(CYGPATH_W) 'char_io.c'; else $(CYGPATH_W) '$(srcdir)/char_io.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-char_io.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-char_io.Tpo $(PARAMETER) -o pre_stage2_exec-char_io.obj `if test -f 'char_io.c'; then $(CYGPATH_W) 'char_io.c'; else $(CYGPATH_W) '$(srcdir)/char_io.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-char_io.Tpo $(DEPDIR)/pre_stage2_exec-char_io.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='char_io.c' object='pre_stage2_exec-char_io.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-char_io.obj `if test -f 'char_io.c'; then $(CYGPATH_W) 'char_io.c'; else $(CYGPATH_W) '$(srcdir)/char_io.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-char_io.obj `if test -f 'char_io.c'; then $(CYGPATH_W) 'char_io.c'; else $(CYGPATH_W) '$(srcdir)/char_io.c'; fi` pre_stage2_exec-cmdline.o: cmdline.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-cmdline.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-cmdline.Tpo -c -o pre_stage2_exec-cmdline.o `test -f 'cmdline.c' || echo '$(srcdir)/'`cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-cmdline.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-cmdline.Tpo $(PARAMETER) -o pre_stage2_exec-cmdline.o `test -f 'cmdline.c' || echo '$(srcdir)/'`cmdline.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-cmdline.Tpo $(DEPDIR)/pre_stage2_exec-cmdline.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmdline.c' object='pre_stage2_exec-cmdline.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-cmdline.o `test -f 'cmdline.c' || echo '$(srcdir)/'`cmdline.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-cmdline.o `test -f 'cmdline.c' || echo '$(srcdir)/'`cmdline.c pre_stage2_exec-cmdline.obj: cmdline.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-cmdline.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-cmdline.Tpo -c -o pre_stage2_exec-cmdline.obj `if test -f 'cmdline.c'; then $(CYGPATH_W) 'cmdline.c'; else $(CYGPATH_W) '$(srcdir)/cmdline.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-cmdline.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-cmdline.Tpo $(PARAMETER) -o pre_stage2_exec-cmdline.obj `if test -f 'cmdline.c'; then $(CYGPATH_W) 'cmdline.c'; else $(CYGPATH_W) '$(srcdir)/cmdline.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-cmdline.Tpo $(DEPDIR)/pre_stage2_exec-cmdline.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmdline.c' object='pre_stage2_exec-cmdline.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-cmdline.obj `if test -f 'cmdline.c'; then $(CYGPATH_W) 'cmdline.c'; else $(CYGPATH_W) '$(srcdir)/cmdline.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-cmdline.obj `if test -f 'cmdline.c'; then $(CYGPATH_W) 'cmdline.c'; else $(CYGPATH_W) '$(srcdir)/cmdline.c'; fi` pre_stage2_exec-common.o: common.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-common.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-common.Tpo -c -o pre_stage2_exec-common.o `test -f 'common.c' || echo '$(srcdir)/'`common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-common.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-common.Tpo $(PARAMETER) -o pre_stage2_exec-common.o `test -f 'common.c' || echo '$(srcdir)/'`common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-common.Tpo $(DEPDIR)/pre_stage2_exec-common.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common.c' object='pre_stage2_exec-common.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-common.o `test -f 'common.c' || echo '$(srcdir)/'`common.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-common.o `test -f 'common.c' || echo '$(srcdir)/'`common.c pre_stage2_exec-common.obj: common.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-common.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-common.Tpo -c -o pre_stage2_exec-common.obj `if test -f 'common.c'; then $(CYGPATH_W) 'common.c'; else $(CYGPATH_W) '$(srcdir)/common.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-common.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-common.Tpo $(PARAMETER) -o pre_stage2_exec-common.obj `if test -f 'common.c'; then $(CYGPATH_W) 'common.c'; else $(CYGPATH_W) '$(srcdir)/common.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-common.Tpo $(DEPDIR)/pre_stage2_exec-common.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common.c' object='pre_stage2_exec-common.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-common.obj `if test -f 'common.c'; then $(CYGPATH_W) 'common.c'; else $(CYGPATH_W) '$(srcdir)/common.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-common.obj `if test -f 'common.c'; then $(CYGPATH_W) 'common.c'; else $(CYGPATH_W) '$(srcdir)/common.c'; fi` pre_stage2_exec-console.o: console.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-console.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-console.Tpo -c -o pre_stage2_exec-console.o `test -f 'console.c' || echo '$(srcdir)/'`console.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-console.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-console.Tpo $(PARAMETER) -o pre_stage2_exec-console.o `test -f 'console.c' || echo '$(srcdir)/'`console.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-console.Tpo $(DEPDIR)/pre_stage2_exec-console.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='console.c' object='pre_stage2_exec-console.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-console.o `test -f 'console.c' || echo '$(srcdir)/'`console.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-console.o `test -f 'console.c' || echo '$(srcdir)/'`console.c pre_stage2_exec-console.obj: console.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-console.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-console.Tpo -c -o pre_stage2_exec-console.obj `if test -f 'console.c'; then $(CYGPATH_W) 'console.c'; else $(CYGPATH_W) '$(srcdir)/console.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-console.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-console.Tpo $(PARAMETER) -o pre_stage2_exec-console.obj `if test -f 'console.c'; then $(CYGPATH_W) 'console.c'; else $(CYGPATH_W) '$(srcdir)/console.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-console.Tpo $(DEPDIR)/pre_stage2_exec-console.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='console.c' object='pre_stage2_exec-console.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-console.obj `if test -f 'console.c'; then $(CYGPATH_W) 'console.c'; else $(CYGPATH_W) '$(srcdir)/console.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-console.obj `if test -f 'console.c'; then $(CYGPATH_W) 'console.c'; else $(CYGPATH_W) '$(srcdir)/console.c'; fi` pre_stage2_exec-dec_lz4.o: dec_lz4.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-dec_lz4.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-dec_lz4.Tpo -c -o pre_stage2_exec-dec_lz4.o `test -f 'dec_lz4.c' || echo '$(srcdir)/'`dec_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-dec_lz4.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-dec_lz4.Tpo $(PARAMETER) -o pre_stage2_exec-dec_lz4.o `test -f 'dec_lz4.c' || echo '$(srcdir)/'`dec_lz4.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-dec_lz4.Tpo $(DEPDIR)/pre_stage2_exec-dec_lz4.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dec_lz4.c' object='pre_stage2_exec-dec_lz4.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-dec_lz4.o `test -f 'dec_lz4.c' || echo '$(srcdir)/'`dec_lz4.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-dec_lz4.o `test -f 'dec_lz4.c' || echo '$(srcdir)/'`dec_lz4.c pre_stage2_exec-dec_lz4.obj: dec_lz4.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-dec_lz4.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-dec_lz4.Tpo -c -o pre_stage2_exec-dec_lz4.obj `if test -f 'dec_lz4.c'; then $(CYGPATH_W) 'dec_lz4.c'; else $(CYGPATH_W) '$(srcdir)/dec_lz4.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-dec_lz4.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-dec_lz4.Tpo $(PARAMETER) -o pre_stage2_exec-dec_lz4.obj `if test -f 'dec_lz4.c'; then $(CYGPATH_W) 'dec_lz4.c'; else $(CYGPATH_W) '$(srcdir)/dec_lz4.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-dec_lz4.Tpo $(DEPDIR)/pre_stage2_exec-dec_lz4.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dec_lz4.c' object='pre_stage2_exec-dec_lz4.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-dec_lz4.obj `if test -f 'dec_lz4.c'; then $(CYGPATH_W) 'dec_lz4.c'; else $(CYGPATH_W) '$(srcdir)/dec_lz4.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-dec_lz4.obj `if test -f 'dec_lz4.c'; then $(CYGPATH_W) 'dec_lz4.c'; else $(CYGPATH_W) '$(srcdir)/dec_lz4.c'; fi` pre_stage2_exec-dec_lzma.o: dec_lzma.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-dec_lzma.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-dec_lzma.Tpo -c -o pre_stage2_exec-dec_lzma.o `test -f 'dec_lzma.c' || echo '$(srcdir)/'`dec_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-dec_lzma.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-dec_lzma.Tpo $(PARAMETER) -o pre_stage2_exec-dec_lzma.o `test -f 'dec_lzma.c' || echo '$(srcdir)/'`dec_lzma.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-dec_lzma.Tpo $(DEPDIR)/pre_stage2_exec-dec_lzma.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dec_lzma.c' object='pre_stage2_exec-dec_lzma.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-dec_lzma.o `test -f 'dec_lzma.c' || echo '$(srcdir)/'`dec_lzma.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-dec_lzma.o `test -f 'dec_lzma.c' || echo '$(srcdir)/'`dec_lzma.c pre_stage2_exec-dec_lzma.obj: dec_lzma.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-dec_lzma.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-dec_lzma.Tpo -c -o pre_stage2_exec-dec_lzma.obj `if test -f 'dec_lzma.c'; then $(CYGPATH_W) 'dec_lzma.c'; else $(CYGPATH_W) '$(srcdir)/dec_lzma.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-dec_lzma.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-dec_lzma.Tpo $(PARAMETER) -o pre_stage2_exec-dec_lzma.obj `if test -f 'dec_lzma.c'; then $(CYGPATH_W) 'dec_lzma.c'; else $(CYGPATH_W) '$(srcdir)/dec_lzma.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-dec_lzma.Tpo $(DEPDIR)/pre_stage2_exec-dec_lzma.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dec_lzma.c' object='pre_stage2_exec-dec_lzma.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-dec_lzma.obj `if test -f 'dec_lzma.c'; then $(CYGPATH_W) 'dec_lzma.c'; else $(CYGPATH_W) '$(srcdir)/dec_lzma.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-dec_lzma.obj `if test -f 'dec_lzma.c'; then $(CYGPATH_W) 'dec_lzma.c'; else $(CYGPATH_W) '$(srcdir)/dec_lzma.c'; fi` pre_stage2_exec-dec_vhd.o: dec_vhd.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-dec_vhd.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-dec_vhd.Tpo -c -o pre_stage2_exec-dec_vhd.o `test -f 'dec_vhd.c' || echo '$(srcdir)/'`dec_vhd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-dec_vhd.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-dec_vhd.Tpo $(PARAMETER) -o pre_stage2_exec-dec_vhd.o `test -f 'dec_vhd.c' || echo '$(srcdir)/'`dec_vhd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-dec_vhd.Tpo $(DEPDIR)/pre_stage2_exec-dec_vhd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dec_vhd.c' object='pre_stage2_exec-dec_vhd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-dec_vhd.o `test -f 'dec_vhd.c' || echo '$(srcdir)/'`dec_vhd.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-dec_vhd.o `test -f 'dec_vhd.c' || echo '$(srcdir)/'`dec_vhd.c pre_stage2_exec-dec_vhd.obj: dec_vhd.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-dec_vhd.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-dec_vhd.Tpo -c -o pre_stage2_exec-dec_vhd.obj `if test -f 'dec_vhd.c'; then $(CYGPATH_W) 'dec_vhd.c'; else $(CYGPATH_W) '$(srcdir)/dec_vhd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-dec_vhd.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-dec_vhd.Tpo $(PARAMETER) -o pre_stage2_exec-dec_vhd.obj `if test -f 'dec_vhd.c'; then $(CYGPATH_W) 'dec_vhd.c'; else $(CYGPATH_W) '$(srcdir)/dec_vhd.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-dec_vhd.Tpo $(DEPDIR)/pre_stage2_exec-dec_vhd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dec_vhd.c' object='pre_stage2_exec-dec_vhd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-dec_vhd.obj `if test -f 'dec_vhd.c'; then $(CYGPATH_W) 'dec_vhd.c'; else $(CYGPATH_W) '$(srcdir)/dec_vhd.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-dec_vhd.obj `if test -f 'dec_vhd.c'; then $(CYGPATH_W) 'dec_vhd.c'; else $(CYGPATH_W) '$(srcdir)/dec_vhd.c'; fi` pre_stage2_exec-disk_io.o: disk_io.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-disk_io.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-disk_io.Tpo -c -o pre_stage2_exec-disk_io.o `test -f 'disk_io.c' || echo '$(srcdir)/'`disk_io.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-disk_io.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-disk_io.Tpo $(PARAMETER) -o pre_stage2_exec-disk_io.o `test -f 'disk_io.c' || echo '$(srcdir)/'`disk_io.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-disk_io.Tpo $(DEPDIR)/pre_stage2_exec-disk_io.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='disk_io.c' object='pre_stage2_exec-disk_io.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-disk_io.o `test -f 'disk_io.c' || echo '$(srcdir)/'`disk_io.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-disk_io.o `test -f 'disk_io.c' || echo '$(srcdir)/'`disk_io.c pre_stage2_exec-disk_io.obj: disk_io.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-disk_io.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-disk_io.Tpo -c -o pre_stage2_exec-disk_io.obj `if test -f 'disk_io.c'; then $(CYGPATH_W) 'disk_io.c'; else $(CYGPATH_W) '$(srcdir)/disk_io.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-disk_io.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-disk_io.Tpo $(PARAMETER) -o pre_stage2_exec-disk_io.obj `if test -f 'disk_io.c'; then $(CYGPATH_W) 'disk_io.c'; else $(CYGPATH_W) '$(srcdir)/disk_io.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-disk_io.Tpo $(DEPDIR)/pre_stage2_exec-disk_io.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='disk_io.c' object='pre_stage2_exec-disk_io.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-disk_io.obj `if test -f 'disk_io.c'; then $(CYGPATH_W) 'disk_io.c'; else $(CYGPATH_W) '$(srcdir)/disk_io.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-disk_io.obj `if test -f 'disk_io.c'; then $(CYGPATH_W) 'disk_io.c'; else $(CYGPATH_W) '$(srcdir)/disk_io.c'; fi` pre_stage2_exec-fsys_ext2fs.o: fsys_ext2fs.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ext2fs.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ext2fs.Tpo -c -o pre_stage2_exec-fsys_ext2fs.o `test -f 'fsys_ext2fs.c' || echo '$(srcdir)/'`fsys_ext2fs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ext2fs.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ext2fs.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_ext2fs.o `test -f 'fsys_ext2fs.c' || echo '$(srcdir)/'`fsys_ext2fs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_ext2fs.Tpo $(DEPDIR)/pre_stage2_exec-fsys_ext2fs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_ext2fs.c' object='pre_stage2_exec-fsys_ext2fs.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_ext2fs.o `test -f 'fsys_ext2fs.c' || echo '$(srcdir)/'`fsys_ext2fs.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_ext2fs.o `test -f 'fsys_ext2fs.c' || echo '$(srcdir)/'`fsys_ext2fs.c pre_stage2_exec-fsys_ext2fs.obj: fsys_ext2fs.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ext2fs.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ext2fs.Tpo -c -o pre_stage2_exec-fsys_ext2fs.obj `if test -f 'fsys_ext2fs.c'; then $(CYGPATH_W) 'fsys_ext2fs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ext2fs.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ext2fs.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ext2fs.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_ext2fs.obj `if test -f 'fsys_ext2fs.c'; then $(CYGPATH_W) 'fsys_ext2fs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ext2fs.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_ext2fs.Tpo $(DEPDIR)/pre_stage2_exec-fsys_ext2fs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_ext2fs.c' object='pre_stage2_exec-fsys_ext2fs.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_ext2fs.obj `if test -f 'fsys_ext2fs.c'; then $(CYGPATH_W) 'fsys_ext2fs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ext2fs.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_ext2fs.obj `if test -f 'fsys_ext2fs.c'; then $(CYGPATH_W) 'fsys_ext2fs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ext2fs.c'; fi` pre_stage2_exec-fsys_fat.o: fsys_fat.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_fat.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_fat.Tpo -c -o pre_stage2_exec-fsys_fat.o `test -f 'fsys_fat.c' || echo '$(srcdir)/'`fsys_fat.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_fat.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_fat.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_fat.o `test -f 'fsys_fat.c' || echo '$(srcdir)/'`fsys_fat.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_fat.Tpo $(DEPDIR)/pre_stage2_exec-fsys_fat.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_fat.c' object='pre_stage2_exec-fsys_fat.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_fat.o `test -f 'fsys_fat.c' || echo '$(srcdir)/'`fsys_fat.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_fat.o `test -f 'fsys_fat.c' || echo '$(srcdir)/'`fsys_fat.c pre_stage2_exec-fsys_fat.obj: fsys_fat.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_fat.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_fat.Tpo -c -o pre_stage2_exec-fsys_fat.obj `if test -f 'fsys_fat.c'; then $(CYGPATH_W) 'fsys_fat.c'; else $(CYGPATH_W) '$(srcdir)/fsys_fat.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_fat.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_fat.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_fat.obj `if test -f 'fsys_fat.c'; then $(CYGPATH_W) 'fsys_fat.c'; else $(CYGPATH_W) '$(srcdir)/fsys_fat.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_fat.Tpo $(DEPDIR)/pre_stage2_exec-fsys_fat.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_fat.c' object='pre_stage2_exec-fsys_fat.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_fat.obj `if test -f 'fsys_fat.c'; then $(CYGPATH_W) 'fsys_fat.c'; else $(CYGPATH_W) '$(srcdir)/fsys_fat.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_fat.obj `if test -f 'fsys_fat.c'; then $(CYGPATH_W) 'fsys_fat.c'; else $(CYGPATH_W) '$(srcdir)/fsys_fat.c'; fi` pre_stage2_exec-fsys_ntfs.o: fsys_ntfs.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ntfs.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ntfs.Tpo -c -o pre_stage2_exec-fsys_ntfs.o `test -f 'fsys_ntfs.c' || echo '$(srcdir)/'`fsys_ntfs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ntfs.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ntfs.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_ntfs.o `test -f 'fsys_ntfs.c' || echo '$(srcdir)/'`fsys_ntfs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_ntfs.Tpo $(DEPDIR)/pre_stage2_exec-fsys_ntfs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_ntfs.c' object='pre_stage2_exec-fsys_ntfs.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_ntfs.o `test -f 'fsys_ntfs.c' || echo '$(srcdir)/'`fsys_ntfs.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_ntfs.o `test -f 'fsys_ntfs.c' || echo '$(srcdir)/'`fsys_ntfs.c pre_stage2_exec-fsys_ntfs.obj: fsys_ntfs.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ntfs.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ntfs.Tpo -c -o pre_stage2_exec-fsys_ntfs.obj `if test -f 'fsys_ntfs.c'; then $(CYGPATH_W) 'fsys_ntfs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ntfs.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ntfs.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ntfs.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_ntfs.obj `if test -f 'fsys_ntfs.c'; then $(CYGPATH_W) 'fsys_ntfs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ntfs.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_ntfs.Tpo $(DEPDIR)/pre_stage2_exec-fsys_ntfs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_ntfs.c' object='pre_stage2_exec-fsys_ntfs.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_ntfs.obj `if test -f 'fsys_ntfs.c'; then $(CYGPATH_W) 'fsys_ntfs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ntfs.c'; fi` - -pre_stage2_exec-fsys_ffs.o: fsys_ffs.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ffs.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ffs.Tpo -c -o pre_stage2_exec-fsys_ffs.o `test -f 'fsys_ffs.c' || echo '$(srcdir)/'`fsys_ffs.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_ffs.Tpo $(DEPDIR)/pre_stage2_exec-fsys_ffs.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_ffs.c' object='pre_stage2_exec-fsys_ffs.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_ffs.o `test -f 'fsys_ffs.c' || echo '$(srcdir)/'`fsys_ffs.c - -pre_stage2_exec-fsys_ffs.obj: fsys_ffs.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ffs.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ffs.Tpo -c -o pre_stage2_exec-fsys_ffs.obj `if test -f 'fsys_ffs.c'; then $(CYGPATH_W) 'fsys_ffs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ffs.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_ffs.Tpo $(DEPDIR)/pre_stage2_exec-fsys_ffs.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_ffs.c' object='pre_stage2_exec-fsys_ffs.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_ffs.obj `if test -f 'fsys_ffs.c'; then $(CYGPATH_W) 'fsys_ffs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ffs.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_ntfs.obj `if test -f 'fsys_ntfs.c'; then $(CYGPATH_W) 'fsys_ntfs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ntfs.c'; fi` pre_stage2_exec-fsys_iso9660.o: fsys_iso9660.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_iso9660.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_iso9660.Tpo -c -o pre_stage2_exec-fsys_iso9660.o `test -f 'fsys_iso9660.c' || echo '$(srcdir)/'`fsys_iso9660.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_iso9660.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_iso9660.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_iso9660.o `test -f 'fsys_iso9660.c' || echo '$(srcdir)/'`fsys_iso9660.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_iso9660.Tpo $(DEPDIR)/pre_stage2_exec-fsys_iso9660.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_iso9660.c' object='pre_stage2_exec-fsys_iso9660.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_iso9660.o `test -f 'fsys_iso9660.c' || echo '$(srcdir)/'`fsys_iso9660.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_iso9660.o `test -f 'fsys_iso9660.c' || echo '$(srcdir)/'`fsys_iso9660.c pre_stage2_exec-fsys_iso9660.obj: fsys_iso9660.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_iso9660.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_iso9660.Tpo -c -o pre_stage2_exec-fsys_iso9660.obj `if test -f 'fsys_iso9660.c'; then $(CYGPATH_W) 'fsys_iso9660.c'; else $(CYGPATH_W) '$(srcdir)/fsys_iso9660.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_iso9660.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_iso9660.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_iso9660.obj `if test -f 'fsys_iso9660.c'; then $(CYGPATH_W) 'fsys_iso9660.c'; else $(CYGPATH_W) '$(srcdir)/fsys_iso9660.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_iso9660.Tpo $(DEPDIR)/pre_stage2_exec-fsys_iso9660.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_iso9660.c' object='pre_stage2_exec-fsys_iso9660.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_iso9660.obj `if test -f 'fsys_iso9660.c'; then $(CYGPATH_W) 'fsys_iso9660.c'; else $(CYGPATH_W) '$(srcdir)/fsys_iso9660.c'; fi` - -pre_stage2_exec-fsys_jfs.o: fsys_jfs.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_jfs.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_jfs.Tpo -c -o pre_stage2_exec-fsys_jfs.o `test -f 'fsys_jfs.c' || echo '$(srcdir)/'`fsys_jfs.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_jfs.Tpo $(DEPDIR)/pre_stage2_exec-fsys_jfs.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_jfs.c' object='pre_stage2_exec-fsys_jfs.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_jfs.o `test -f 'fsys_jfs.c' || echo '$(srcdir)/'`fsys_jfs.c - -pre_stage2_exec-fsys_jfs.obj: fsys_jfs.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_jfs.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_jfs.Tpo -c -o pre_stage2_exec-fsys_jfs.obj `if test -f 'fsys_jfs.c'; then $(CYGPATH_W) 'fsys_jfs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_jfs.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_jfs.Tpo $(DEPDIR)/pre_stage2_exec-fsys_jfs.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_jfs.c' object='pre_stage2_exec-fsys_jfs.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_jfs.obj `if test -f 'fsys_jfs.c'; then $(CYGPATH_W) 'fsys_jfs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_jfs.c'; fi` - -pre_stage2_exec-fsys_minix.o: fsys_minix.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_minix.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_minix.Tpo -c -o pre_stage2_exec-fsys_minix.o `test -f 'fsys_minix.c' || echo '$(srcdir)/'`fsys_minix.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_minix.Tpo $(DEPDIR)/pre_stage2_exec-fsys_minix.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_minix.c' object='pre_stage2_exec-fsys_minix.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_minix.o `test -f 'fsys_minix.c' || echo '$(srcdir)/'`fsys_minix.c - -pre_stage2_exec-fsys_minix.obj: fsys_minix.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_minix.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_minix.Tpo -c -o pre_stage2_exec-fsys_minix.obj `if test -f 'fsys_minix.c'; then $(CYGPATH_W) 'fsys_minix.c'; else $(CYGPATH_W) '$(srcdir)/fsys_minix.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_minix.Tpo $(DEPDIR)/pre_stage2_exec-fsys_minix.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_minix.c' object='pre_stage2_exec-fsys_minix.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_minix.obj `if test -f 'fsys_minix.c'; then $(CYGPATH_W) 'fsys_minix.c'; else $(CYGPATH_W) '$(srcdir)/fsys_minix.c'; fi` - -pre_stage2_exec-fsys_reiserfs.o: fsys_reiserfs.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_reiserfs.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_reiserfs.Tpo -c -o pre_stage2_exec-fsys_reiserfs.o `test -f 'fsys_reiserfs.c' || echo '$(srcdir)/'`fsys_reiserfs.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_reiserfs.Tpo $(DEPDIR)/pre_stage2_exec-fsys_reiserfs.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_reiserfs.c' object='pre_stage2_exec-fsys_reiserfs.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_reiserfs.o `test -f 'fsys_reiserfs.c' || echo '$(srcdir)/'`fsys_reiserfs.c - -pre_stage2_exec-fsys_reiserfs.obj: fsys_reiserfs.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_reiserfs.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_reiserfs.Tpo -c -o pre_stage2_exec-fsys_reiserfs.obj `if test -f 'fsys_reiserfs.c'; then $(CYGPATH_W) 'fsys_reiserfs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_reiserfs.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_reiserfs.Tpo $(DEPDIR)/pre_stage2_exec-fsys_reiserfs.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_reiserfs.c' object='pre_stage2_exec-fsys_reiserfs.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_reiserfs.obj `if test -f 'fsys_reiserfs.c'; then $(CYGPATH_W) 'fsys_reiserfs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_reiserfs.c'; fi` - -pre_stage2_exec-fsys_ufs2.o: fsys_ufs2.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ufs2.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ufs2.Tpo -c -o pre_stage2_exec-fsys_ufs2.o `test -f 'fsys_ufs2.c' || echo '$(srcdir)/'`fsys_ufs2.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_ufs2.Tpo $(DEPDIR)/pre_stage2_exec-fsys_ufs2.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_ufs2.c' object='pre_stage2_exec-fsys_ufs2.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_ufs2.o `test -f 'fsys_ufs2.c' || echo '$(srcdir)/'`fsys_ufs2.c - -pre_stage2_exec-fsys_ufs2.obj: fsys_ufs2.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ufs2.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ufs2.Tpo -c -o pre_stage2_exec-fsys_ufs2.obj `if test -f 'fsys_ufs2.c'; then $(CYGPATH_W) 'fsys_ufs2.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ufs2.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_ufs2.Tpo $(DEPDIR)/pre_stage2_exec-fsys_ufs2.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_ufs2.c' object='pre_stage2_exec-fsys_ufs2.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_ufs2.obj `if test -f 'fsys_ufs2.c'; then $(CYGPATH_W) 'fsys_ufs2.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ufs2.c'; fi` - -pre_stage2_exec-fsys_vstafs.o: fsys_vstafs.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_vstafs.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_vstafs.Tpo -c -o pre_stage2_exec-fsys_vstafs.o `test -f 'fsys_vstafs.c' || echo '$(srcdir)/'`fsys_vstafs.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_vstafs.Tpo $(DEPDIR)/pre_stage2_exec-fsys_vstafs.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_vstafs.c' object='pre_stage2_exec-fsys_vstafs.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_vstafs.o `test -f 'fsys_vstafs.c' || echo '$(srcdir)/'`fsys_vstafs.c - -pre_stage2_exec-fsys_vstafs.obj: fsys_vstafs.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_vstafs.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_vstafs.Tpo -c -o pre_stage2_exec-fsys_vstafs.obj `if test -f 'fsys_vstafs.c'; then $(CYGPATH_W) 'fsys_vstafs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_vstafs.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_vstafs.Tpo $(DEPDIR)/pre_stage2_exec-fsys_vstafs.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_vstafs.c' object='pre_stage2_exec-fsys_vstafs.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_vstafs.obj `if test -f 'fsys_vstafs.c'; then $(CYGPATH_W) 'fsys_vstafs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_vstafs.c'; fi` - -pre_stage2_exec-fsys_xfs.o: fsys_xfs.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_xfs.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_xfs.Tpo -c -o pre_stage2_exec-fsys_xfs.o `test -f 'fsys_xfs.c' || echo '$(srcdir)/'`fsys_xfs.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_xfs.Tpo $(DEPDIR)/pre_stage2_exec-fsys_xfs.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_xfs.c' object='pre_stage2_exec-fsys_xfs.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_xfs.o `test -f 'fsys_xfs.c' || echo '$(srcdir)/'`fsys_xfs.c - -pre_stage2_exec-fsys_xfs.obj: fsys_xfs.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_xfs.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_xfs.Tpo -c -o pre_stage2_exec-fsys_xfs.obj `if test -f 'fsys_xfs.c'; then $(CYGPATH_W) 'fsys_xfs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_xfs.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_xfs.Tpo $(DEPDIR)/pre_stage2_exec-fsys_xfs.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_xfs.c' object='pre_stage2_exec-fsys_xfs.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_xfs.obj `if test -f 'fsys_xfs.c'; then $(CYGPATH_W) 'fsys_xfs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_xfs.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_iso9660.obj `if test -f 'fsys_iso9660.c'; then $(CYGPATH_W) 'fsys_iso9660.c'; else $(CYGPATH_W) '$(srcdir)/fsys_iso9660.c'; fi` pre_stage2_exec-fsys_pxe.o: fsys_pxe.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_pxe.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_pxe.Tpo -c -o pre_stage2_exec-fsys_pxe.o `test -f 'fsys_pxe.c' || echo '$(srcdir)/'`fsys_pxe.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_pxe.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_pxe.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_pxe.o `test -f 'fsys_pxe.c' || echo '$(srcdir)/'`fsys_pxe.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_pxe.Tpo $(DEPDIR)/pre_stage2_exec-fsys_pxe.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_pxe.c' object='pre_stage2_exec-fsys_pxe.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_pxe.o `test -f 'fsys_pxe.c' || echo '$(srcdir)/'`fsys_pxe.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_pxe.o `test -f 'fsys_pxe.c' || echo '$(srcdir)/'`fsys_pxe.c pre_stage2_exec-fsys_pxe.obj: fsys_pxe.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_pxe.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_pxe.Tpo -c -o pre_stage2_exec-fsys_pxe.obj `if test -f 'fsys_pxe.c'; then $(CYGPATH_W) 'fsys_pxe.c'; else $(CYGPATH_W) '$(srcdir)/fsys_pxe.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_pxe.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_pxe.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_pxe.obj `if test -f 'fsys_pxe.c'; then $(CYGPATH_W) 'fsys_pxe.c'; else $(CYGPATH_W) '$(srcdir)/fsys_pxe.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_pxe.Tpo $(DEPDIR)/pre_stage2_exec-fsys_pxe.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_pxe.c' object='pre_stage2_exec-fsys_pxe.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_pxe.obj `if test -f 'fsys_pxe.c'; then $(CYGPATH_W) 'fsys_pxe.c'; else $(CYGPATH_W) '$(srcdir)/fsys_pxe.c'; fi` - -pre_stage2_exec-fsys_initrd.o: fsys_initrd.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_initrd.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_initrd.Tpo -c -o pre_stage2_exec-fsys_initrd.o `test -f 'fsys_initrd.c' || echo '$(srcdir)/'`fsys_initrd.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_initrd.Tpo $(DEPDIR)/pre_stage2_exec-fsys_initrd.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_initrd.c' object='pre_stage2_exec-fsys_initrd.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_initrd.o `test -f 'fsys_initrd.c' || echo '$(srcdir)/'`fsys_initrd.c - -pre_stage2_exec-fsys_initrd.obj: fsys_initrd.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_initrd.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_initrd.Tpo -c -o pre_stage2_exec-fsys_initrd.obj `if test -f 'fsys_initrd.c'; then $(CYGPATH_W) 'fsys_initrd.c'; else $(CYGPATH_W) '$(srcdir)/fsys_initrd.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_initrd.Tpo $(DEPDIR)/pre_stage2_exec-fsys_initrd.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_initrd.c' object='pre_stage2_exec-fsys_initrd.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_initrd.obj `if test -f 'fsys_initrd.c'; then $(CYGPATH_W) 'fsys_initrd.c'; else $(CYGPATH_W) '$(srcdir)/fsys_initrd.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_pxe.obj `if test -f 'fsys_pxe.c'; then $(CYGPATH_W) 'fsys_pxe.c'; else $(CYGPATH_W) '$(srcdir)/fsys_pxe.c'; fi` pre_stage2_exec-fsys_ipxe.o: fsys_ipxe.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ipxe.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ipxe.Tpo -c -o pre_stage2_exec-fsys_ipxe.o `test -f 'fsys_ipxe.c' || echo '$(srcdir)/'`fsys_ipxe.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ipxe.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ipxe.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_ipxe.o `test -f 'fsys_ipxe.c' || echo '$(srcdir)/'`fsys_ipxe.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_ipxe.Tpo $(DEPDIR)/pre_stage2_exec-fsys_ipxe.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_ipxe.c' object='pre_stage2_exec-fsys_ipxe.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_ipxe.o `test -f 'fsys_ipxe.c' || echo '$(srcdir)/'`fsys_ipxe.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_ipxe.o `test -f 'fsys_ipxe.c' || echo '$(srcdir)/'`fsys_ipxe.c pre_stage2_exec-fsys_ipxe.obj: fsys_ipxe.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ipxe.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ipxe.Tpo -c -o pre_stage2_exec-fsys_ipxe.obj `if test -f 'fsys_ipxe.c'; then $(CYGPATH_W) 'fsys_ipxe.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ipxe.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ipxe.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ipxe.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_ipxe.obj `if test -f 'fsys_ipxe.c'; then $(CYGPATH_W) 'fsys_ipxe.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ipxe.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_ipxe.Tpo $(DEPDIR)/pre_stage2_exec-fsys_ipxe.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_ipxe.c' object='pre_stage2_exec-fsys_ipxe.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_ipxe.obj `if test -f 'fsys_ipxe.c'; then $(CYGPATH_W) 'fsys_ipxe.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ipxe.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_ipxe.obj `if test -f 'fsys_ipxe.c'; then $(CYGPATH_W) 'fsys_ipxe.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ipxe.c'; fi` pre_stage2_exec-fsys_fb.o: fsys_fb.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_fb.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_fb.Tpo -c -o pre_stage2_exec-fsys_fb.o `test -f 'fsys_fb.c' || echo '$(srcdir)/'`fsys_fb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_fb.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_fb.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_fb.o `test -f 'fsys_fb.c' || echo '$(srcdir)/'`fsys_fb.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_fb.Tpo $(DEPDIR)/pre_stage2_exec-fsys_fb.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_fb.c' object='pre_stage2_exec-fsys_fb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_fb.o `test -f 'fsys_fb.c' || echo '$(srcdir)/'`fsys_fb.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_fb.o `test -f 'fsys_fb.c' || echo '$(srcdir)/'`fsys_fb.c pre_stage2_exec-fsys_fb.obj: fsys_fb.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_fb.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_fb.Tpo -c -o pre_stage2_exec-fsys_fb.obj `if test -f 'fsys_fb.c'; then $(CYGPATH_W) 'fsys_fb.c'; else $(CYGPATH_W) '$(srcdir)/fsys_fb.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_fb.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_fb.Tpov -o pre_stage2_exec-fsys_fb.obj `if test -f 'fsys_fb.c'; then $(CYGPATH_W) 'fsys_fb.c'; else $(CYGPATH_W) '$(srcdir)/fsys_fb.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_fb.Tpo $(DEPDIR)/pre_stage2_exec-fsys_fb.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_fb.c' object='pre_stage2_exec-fsys_fb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-fsys_fb.obj `if test -f 'fsys_fb.c'; then $(CYGPATH_W) 'fsys_fb.c'; else $(CYGPATH_W) '$(srcdir)/fsys_fb.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_fb.obj `if test -f 'fsys_fb.c'; then $(CYGPATH_W) 'fsys_fb.c'; else $(CYGPATH_W) '$(srcdir)/fsys_fb.c'; fi` + +pre_stage2_exec-fsys_initrd.o: fsys_initrd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_initrd.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_initrd.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_initrd.o `test -f 'fsys_initrd.c' || echo '$(srcdir)/'`fsys_initrd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_initrd.Tpo $(DEPDIR)/pre_stage2_exec-fsys_initrd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_initrd.c' object='pre_stage2_exec-fsys_initrd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_initrd.o `test -f 'fsys_initrd.c' || echo '$(srcdir)/'`fsys_initrd.c + +pre_stage2_exec-fsys_initrd.obj: fsys_initrd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_initrd.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_initrd.Tpov -o pre_stage2_exec-fsys_initrd.obj `if test -f 'fsys_initrd.c'; then $(CYGPATH_W) 'fsys_initrd.c'; else $(CYGPATH_W) '$(srcdir)/fsys_initrd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_initrd.Tpo $(DEPDIR)/pre_stage2_exec-fsys_initrd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_initrd.c' object='pre_stage2_exec-fsys_initrd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_initrd.obj `if test -f 'fsys_initrd.c'; then $(CYGPATH_W) 'fsys_initrd.c'; else $(CYGPATH_W) '$(srcdir)/fsys_initrd.c'; fi` pre_stage2_exec-gunzip.o: gunzip.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-gunzip.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-gunzip.Tpo -c -o pre_stage2_exec-gunzip.o `test -f 'gunzip.c' || echo '$(srcdir)/'`gunzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-gunzip.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-gunzip.Tpo $(PARAMETER) -o pre_stage2_exec-gunzip.o `test -f 'gunzip.c' || echo '$(srcdir)/'`gunzip.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-gunzip.Tpo $(DEPDIR)/pre_stage2_exec-gunzip.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gunzip.c' object='pre_stage2_exec-gunzip.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-gunzip.o `test -f 'gunzip.c' || echo '$(srcdir)/'`gunzip.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-gunzip.o `test -f 'gunzip.c' || echo '$(srcdir)/'`gunzip.c pre_stage2_exec-gunzip.obj: gunzip.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-gunzip.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-gunzip.Tpo -c -o pre_stage2_exec-gunzip.obj `if test -f 'gunzip.c'; then $(CYGPATH_W) 'gunzip.c'; else $(CYGPATH_W) '$(srcdir)/gunzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-gunzip.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-gunzip.Tpo $(PARAMETER) -o pre_stage2_exec-gunzip.obj `if test -f 'gunzip.c'; then $(CYGPATH_W) 'gunzip.c'; else $(CYGPATH_W) '$(srcdir)/gunzip.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-gunzip.Tpo $(DEPDIR)/pre_stage2_exec-gunzip.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gunzip.c' object='pre_stage2_exec-gunzip.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-gunzip.obj `if test -f 'gunzip.c'; then $(CYGPATH_W) 'gunzip.c'; else $(CYGPATH_W) '$(srcdir)/gunzip.c'; fi` - -pre_stage2_exec-hercules.o: hercules.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-hercules.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-hercules.Tpo -c -o pre_stage2_exec-hercules.o `test -f 'hercules.c' || echo '$(srcdir)/'`hercules.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-hercules.Tpo $(DEPDIR)/pre_stage2_exec-hercules.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hercules.c' object='pre_stage2_exec-hercules.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-hercules.o `test -f 'hercules.c' || echo '$(srcdir)/'`hercules.c - -pre_stage2_exec-hercules.obj: hercules.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-hercules.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-hercules.Tpo -c -o pre_stage2_exec-hercules.obj `if test -f 'hercules.c'; then $(CYGPATH_W) 'hercules.c'; else $(CYGPATH_W) '$(srcdir)/hercules.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-hercules.Tpo $(DEPDIR)/pre_stage2_exec-hercules.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hercules.c' object='pre_stage2_exec-hercules.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-hercules.obj `if test -f 'hercules.c'; then $(CYGPATH_W) 'hercules.c'; else $(CYGPATH_W) '$(srcdir)/hercules.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-gunzip.obj `if test -f 'gunzip.c'; then $(CYGPATH_W) 'gunzip.c'; else $(CYGPATH_W) '$(srcdir)/gunzip.c'; fi` pre_stage2_exec-md5.o: md5.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-md5.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-md5.Tpo -c -o pre_stage2_exec-md5.o `test -f 'md5.c' || echo '$(srcdir)/'`md5.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-md5.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-md5.Tpo $(PARAMETER) -o pre_stage2_exec-md5.o `test -f 'md5.c' || echo '$(srcdir)/'`md5.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-md5.Tpo $(DEPDIR)/pre_stage2_exec-md5.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='md5.c' object='pre_stage2_exec-md5.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-md5.o `test -f 'md5.c' || echo '$(srcdir)/'`md5.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-md5.o `test -f 'md5.c' || echo '$(srcdir)/'`md5.c pre_stage2_exec-md5.obj: md5.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-md5.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-md5.Tpo -c -o pre_stage2_exec-md5.obj `if test -f 'md5.c'; then $(CYGPATH_W) 'md5.c'; else $(CYGPATH_W) '$(srcdir)/md5.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-md5.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-md5.Tpo $(PARAMETER) -o pre_stage2_exec-md5.obj `if test -f 'md5.c'; then $(CYGPATH_W) 'md5.c'; else $(CYGPATH_W) '$(srcdir)/md5.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-md5.Tpo $(DEPDIR)/pre_stage2_exec-md5.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='md5.c' object='pre_stage2_exec-md5.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-md5.obj `if test -f 'md5.c'; then $(CYGPATH_W) 'md5.c'; else $(CYGPATH_W) '$(srcdir)/md5.c'; fi` - -pre_stage2_exec-serial.o: serial.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-serial.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-serial.Tpo -c -o pre_stage2_exec-serial.o `test -f 'serial.c' || echo '$(srcdir)/'`serial.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-serial.Tpo $(DEPDIR)/pre_stage2_exec-serial.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='serial.c' object='pre_stage2_exec-serial.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-serial.o `test -f 'serial.c' || echo '$(srcdir)/'`serial.c - -pre_stage2_exec-serial.obj: serial.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-serial.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-serial.Tpo -c -o pre_stage2_exec-serial.obj `if test -f 'serial.c'; then $(CYGPATH_W) 'serial.c'; else $(CYGPATH_W) '$(srcdir)/serial.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-serial.Tpo $(DEPDIR)/pre_stage2_exec-serial.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='serial.c' object='pre_stage2_exec-serial.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-serial.obj `if test -f 'serial.c'; then $(CYGPATH_W) 'serial.c'; else $(CYGPATH_W) '$(srcdir)/serial.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-md5.obj `if test -f 'md5.c'; then $(CYGPATH_W) 'md5.c'; else $(CYGPATH_W) '$(srcdir)/md5.c'; fi` pre_stage2_exec-stage2.o: stage2.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-stage2.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-stage2.Tpo -c -o pre_stage2_exec-stage2.o `test -f 'stage2.c' || echo '$(srcdir)/'`stage2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-stage2.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-stage2.Tpo $(PARAMETER) -o pre_stage2_exec-stage2.o `test -f 'stage2.c' || echo '$(srcdir)/'`stage2.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-stage2.Tpo $(DEPDIR)/pre_stage2_exec-stage2.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stage2.c' object='pre_stage2_exec-stage2.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-stage2.o `test -f 'stage2.c' || echo '$(srcdir)/'`stage2.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-stage2.o `test -f 'stage2.c' || echo '$(srcdir)/'`stage2.c pre_stage2_exec-stage2.obj: stage2.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-stage2.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-stage2.Tpo -c -o pre_stage2_exec-stage2.obj `if test -f 'stage2.c'; then $(CYGPATH_W) 'stage2.c'; else $(CYGPATH_W) '$(srcdir)/stage2.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-stage2.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-stage2.Tpo $(PARAMETER) -o pre_stage2_exec-stage2.obj `if test -f 'stage2.c'; then $(CYGPATH_W) 'stage2.c'; else $(CYGPATH_W) '$(srcdir)/stage2.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-stage2.Tpo $(DEPDIR)/pre_stage2_exec-stage2.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stage2.c' object='pre_stage2_exec-stage2.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-stage2.obj `if test -f 'stage2.c'; then $(CYGPATH_W) 'stage2.c'; else $(CYGPATH_W) '$(srcdir)/stage2.c'; fi` - -pre_stage2_exec-terminfo.o: terminfo.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-terminfo.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-terminfo.Tpo -c -o pre_stage2_exec-terminfo.o `test -f 'terminfo.c' || echo '$(srcdir)/'`terminfo.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-terminfo.Tpo $(DEPDIR)/pre_stage2_exec-terminfo.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminfo.c' object='pre_stage2_exec-terminfo.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-terminfo.o `test -f 'terminfo.c' || echo '$(srcdir)/'`terminfo.c - -pre_stage2_exec-terminfo.obj: terminfo.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-terminfo.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-terminfo.Tpo -c -o pre_stage2_exec-terminfo.obj `if test -f 'terminfo.c'; then $(CYGPATH_W) 'terminfo.c'; else $(CYGPATH_W) '$(srcdir)/terminfo.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-terminfo.Tpo $(DEPDIR)/pre_stage2_exec-terminfo.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminfo.c' object='pre_stage2_exec-terminfo.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-terminfo.obj `if test -f 'terminfo.c'; then $(CYGPATH_W) 'terminfo.c'; else $(CYGPATH_W) '$(srcdir)/terminfo.c'; fi` - -pre_stage2_exec-tparm.o: tparm.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-tparm.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-tparm.Tpo -c -o pre_stage2_exec-tparm.o `test -f 'tparm.c' || echo '$(srcdir)/'`tparm.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-tparm.Tpo $(DEPDIR)/pre_stage2_exec-tparm.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tparm.c' object='pre_stage2_exec-tparm.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-tparm.o `test -f 'tparm.c' || echo '$(srcdir)/'`tparm.c - -pre_stage2_exec-tparm.obj: tparm.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-tparm.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-tparm.Tpo -c -o pre_stage2_exec-tparm.obj `if test -f 'tparm.c'; then $(CYGPATH_W) 'tparm.c'; else $(CYGPATH_W) '$(srcdir)/tparm.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-tparm.Tpo $(DEPDIR)/pre_stage2_exec-tparm.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tparm.c' object='pre_stage2_exec-tparm.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-tparm.obj `if test -f 'tparm.c'; then $(CYGPATH_W) 'tparm.c'; else $(CYGPATH_W) '$(srcdir)/tparm.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-stage2.obj `if test -f 'stage2.c'; then $(CYGPATH_W) 'stage2.c'; else $(CYGPATH_W) '$(srcdir)/stage2.c'; fi` pre_stage2_exec-graphics.o: graphics.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-graphics.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-graphics.Tpo -c -o pre_stage2_exec-graphics.o `test -f 'graphics.c' || echo '$(srcdir)/'`graphics.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-graphics.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-graphics.Tpo $(PARAMETER) -o pre_stage2_exec-graphics.o `test -f 'graphics.c' || echo '$(srcdir)/'`graphics.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-graphics.Tpo $(DEPDIR)/pre_stage2_exec-graphics.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='graphics.c' object='pre_stage2_exec-graphics.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-graphics.o `test -f 'graphics.c' || echo '$(srcdir)/'`graphics.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-graphics.o `test -f 'graphics.c' || echo '$(srcdir)/'`graphics.c pre_stage2_exec-graphics.obj: graphics.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-graphics.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-graphics.Tpo -c -o pre_stage2_exec-graphics.obj `if test -f 'graphics.c'; then $(CYGPATH_W) 'graphics.c'; else $(CYGPATH_W) '$(srcdir)/graphics.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-graphics.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-graphics.Tpo $(PARAMETER) -o pre_stage2_exec-graphics.obj `if test -f 'graphics.c'; then $(CYGPATH_W) 'graphics.c'; else $(CYGPATH_W) '$(srcdir)/graphics.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-graphics.Tpo $(DEPDIR)/pre_stage2_exec-graphics.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='graphics.c' object='pre_stage2_exec-graphics.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-graphics.obj `if test -f 'graphics.c'; then $(CYGPATH_W) 'graphics.c'; else $(CYGPATH_W) '$(srcdir)/graphics.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-graphics.obj `if test -f 'graphics.c'; then $(CYGPATH_W) 'graphics.c'; else $(CYGPATH_W) '$(srcdir)/graphics.c'; fi` install-datalibDATA: $(datalib_DATA) @$(NORMAL_INSTALL) @list='$(datalib_DATA)'; test -n "$(datalibdir)" || list=; \ @@ -1752,84 +1386,27 @@ uninstall-am: uninstall-datalibDATA maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am recheck tags tags-am \ uninstall uninstall-am uninstall-datalibDATA - - -stage2_size.h: pre_stage2 - $(AM_V_at)-rm -f stage2_size.h - $(AM_V_at)set dummy `ls -l pre_stage2`; \ - echo "#define STAGE2_SIZE $$6" > stage2_size.h - -dosstart_exec-dosstart.$(OBJEXT): stage2_size.h - -grub.exe: pre_stage2 dosstart - $(AM_V_GEN) - $(AM_V_at)-rm -f grub.exe - $(AM_V_at)echo -n -e "\000\000\000\000\000\000\000\000\000\000\000\000" | cat dosstart pre_stage2 - > grub.exe - $(AM_V_at)if [ -f ../preset_menu_used ]; then cat ../preset_menu_used >> grub.exe ;fi - $(AM_V_at)dd if=/dev/zero bs=4128 count=1 >> grub.exe 2>/dev/null || echo "DD failed!" - -badgrubstart_exec-badgrubstart.$(OBJEXT): stage2_size.h dosstart.S - -badgrub.exe: pre_stage2 badgrubstart - $(AM_V_GEN) - $(AM_V_at)-rm -f badgrub.exe - $(AM_V_at)echo -n -e "\000\000\000\000\000\000\000\000\000\000\000\000" | cat badgrubstart pre_stage2 - > badgrub.exe - $(AM_V_at)if [ -f ../preset_menu_used ]; then cat ../preset_menu_used >> badgrub.exe ;fi - $(AM_V_at)dd if=/dev/zero bs=4128 count=1 >> badgrub.exe 2>/dev/null || echo "DD failed!" - -grldrstart_exec-grldrstart.$(OBJEXT): stage2_size.h - -grldr: pre_stage2 grldrstart - $(AM_V_GEN) - $(AM_V_at)-rm -f grldr - $(AM_V_at)echo -n -e "\000\000\000\000\000\000\000\000\000\000\000\000" | cat grldrstart pre_stage2 - > grldr - $(AM_V_at)if [ -f ../preset_menu_used ]; then cat ../preset_menu_used >> grldr ;fi - -mbrstart_exec-mbrstart.$(OBJEXT): stage2_size.h grldrstart.S - -grldr.mbr: mbrstart - $(AM_V_GEN) - $(AM_V_at)-rm -f grldr.mbr - $(AM_V_at)cat mbrstart > grldr.mbr - -bootlacestart_exec-bootlacestart.$(OBJEXT): stage2_size.h bootlace.inc grldrstart.S - -bootlace.com: bootlacestart #Note: Synchronous modifications build - $(AM_V_GEN) - $(AM_V_at)-rm -f bootlace.com - $(AM_V_at)-rm -f grldr.pbr - $(AM_V_at)cp bootlacestart bootlace.com && chmod a+x bootlace.com - $(AM_V_at)dd if=bootlace.com of=grldr.pbr bs=512 skip=57 count=10 #skip(1): "EB 58 90 00" position in the bootlace.com redress: skip +(-) 1 - $(AM_V_at)dd if=bootlace.com of=grldr_cd.bin bs=512 skip=67 count=1 #skip(2): = skip(1) + 10 - $(AM_V_at)dd if=bootlace.com of=grldr.pbr bs=512 skip=68 seek=10 count=1 #skip(3): = skip(2) + 1 - $(AM_V_at)cat grldr.mbr >> bootlace.com - -hmloadstart_exec-hmloadstart.$(OBJEXT): stage2_size.h - -hmload.com: hmloadstart - $(AM_V_GEN) - $(AM_V_at)-rm -f hmload.com - $(AM_V_at)cp hmloadstart hmload.com && chmod a-x hmload.com - -eltorito.sys: eltorito.asm - $(AM_V_at)nasm -Ox -f bin -o $@ $< || echo "Failed in building eltorito.sys!" - $(AM_V_at)upx --ultra-brute --lzma $@ || upx --ultra-brute $@ || echo "upx command not found!" - -asm.S: a20.inc - touch asm.S - -dosstart.S: a20.inc - touch dosstart.S - -badgrubstart.S: a20.inc - touch badgrubstart.S + %: %.exec$(EXEEXT) $(AM_V_OBJCOPY) -O binary $< $@ - $(AM_V_at)if [ $@ = pre_stage2 ]; then dd if=pre_stage2 of=pre_stage2_fullsize bs=65536 skip=48 2>/dev/null || echo "DD failed!" ;fi - $(AM_V_at)if [ $@ = pre_stage2 ]; then sed -e "1s/^\x00*//" pre_stage2_fullsize > pre_stage2_tail ;fi - $(AM_V_at)if [ $@ = pre_stage2 ]; then set dummy `ls -l pre_stage2_fullsize`; set $$6 `ls -l pre_stage2_tail`; if [ $$1 -le $$6 ]; then set `cmp pre_stage2_fullsize /dev/zero` ; while [ "$$1" != "" ]; do t1="$${1%%[^0-9]*}"; if [ "$$t1" != "" ]; then if [ "$$t1" -gt 2000 ]; then t1=`expr $$t1 - 1`; dd if=pre_stage2_fullsize of=pre_stage2_tail bs=1 skip=$$t1 2>/dev/null || echo "DD failed!" ; break; fi; fi; shift; done; fi; fi - $(AM_V_at)if [ $@ = pre_stage2 ]; then set dummy `ls -l pre_stage2_fullsize`; set $$6 `ls -l pre_stage2_tail`; dd if=pre_stage2 of=pre_stage2_head bs=`expr $$1 - $$6` count=1 2>/dev/null || echo "DD failed!" ; cat pre_stage2_head pre_stage2_tail > pre_stage2 ;fi - $(AM_V_at)if [ $@ = pre_stage2 ]; then echo -n -e "\0260\002\032\0316" >> $@ ;fi + +# $(AM_V_OBJCOPY) -O binary $< $@ +# $(AM_V_at)if [ $@ = pre_stage2 ]; then dd if=pre_stage2 of=pre_stage2_fullsize bs=65536 skip=48 2>/dev/null || echo "DD failed!" ;fi +# $(AM_V_at)if [ $@ = pre_stage2 ]; then sed -e "1s/^\x00*//" pre_stage2_fullsize > pre_stage2_tail ;fi +# $(AM_V_at)if [ $@ = pre_stage2 ]; then set dummy `ls -l pre_stage2_fullsize`; set $$6 `ls -l pre_stage2_tail`; if [ $$1 -le $$6 ]; then set `cmp pre_stage2_fullsize /dev/zero` ; while [ "$$1" != "" ]; do t1="$${1%%[^0-9]*}"; if [ "$$t1" != "" ]; then if [ "$$t1" -gt 2000 ]; then t1=`expr $$t1 - 1`; dd if=pre_stage2_fullsize of=pre_stage2_tail bs=1 skip=$$t1 2>/dev/null || echo "DD failed!" ; break; fi; fi; shift; done; fi; fi +# $(AM_V_at)if [ $@ = pre_stage2 ]; then set dummy `ls -l pre_stage2_fullsize`; set $$6 `ls -l pre_stage2_tail`; dd if=pre_stage2 of=pre_stage2_head bs=`expr $$1 - $$6` count=1 2>/dev/null || echo "DD failed!" ; cat pre_stage2_head pre_stage2_tail > pre_stage2 ;fi +# $(AM_V_at)if [ $@ = pre_stage2 ]; then echo -n -e "\0260\002\032\0316" >> $@ ;fi + +#pre_stage2_head 头部(0x13d4). 从"ENTRY(main)"开始, 至"VARIABLE(end_of_low_16bit_code)", 即16位代码结束地址; +#pre_stage2_tail 尾部(0x42d64). 从".space 0x300000"开始, 即32位代码开始地址, 至c代码结束, 包含程序代码及静态数据; +#pre_stage2_fullsize 全尺寸(0x44138). 即头部(0x13d4)加尾部(0x42d64); +#pre_stage2 (0x4413c). 在pre_stage2_fullsize全尺寸(0x44138)尾部, 增加签名(B0 02 1A CE); +#pre_stage2_exec (3d491c). ELF头部(0x200), 加全尺寸(0x44138), 加3Mb插入的0, 加GCC编译信息; +#bs=65536=0x10000 skip=48=0x30; 意思是跳过3Mb +#sed:Stream Editor文本流编辑; e :直接在命令行模式上进行sed动作编辑; +#ls -l //显示不隐藏的文件与文件夹的详细信息; +#[ $$1 -le $$6 ] 变量$$1小于等于$$6; +#"\0260\002\032\0316"="\xB0\x02\x1A\xCE"=签名 # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/stage2/Makefile.in-i386 b/stage2/Makefile.in-i386 new file mode 100644 index 00000000..b7e3842a --- /dev/null +++ b/stage2/Makefile.in-i386 @@ -0,0 +1,1414 @@ +# Makefile.in generated by automake 1.14 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +#install_sh_DATA = $(install_sh) -c -m32 -m 644 适应gcc高版本 2023-06-06 +#install_sh_PROGRAM = $(install_sh) -c -m32 +#install_sh_SCRIPT = $(install_sh) -c -m32 +install_sh_DATA = $(install_sh) -c -m32 -no-pie -fno-pic -m 644 +install_sh_PROGRAM = $(install_sh) -c -m32 -no-pie -fno-pic +install_sh_SCRIPT = $(install_sh) -c -m32 -no-pie -fno-pic +PARAMETER = -c -m32 -no-pie -fno-pic +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +TESTS = +EXTRA_PROGRAMS = nbloader.exec$(EXEEXT) pxeloader.exec$(EXEEXT) \ + diskless.exec$(EXEEXT) +noinst_PROGRAMS = pre_stage2.exec$(EXEEXT) +subdir = stage2 +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/mkinstalldirs $(top_srcdir)/depcomp \ + $(noinst_HEADERS) $(top_srcdir)/test-driver +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +am_pre_stage2_exec_OBJECTS = pre_stage2_exec-asm.$(OBJEXT) \ + pre_stage2_exec-boot.$(OBJEXT) \ + pre_stage2_exec-builtins.$(OBJEXT) \ + pre_stage2_exec-char_io.$(OBJEXT) \ + pre_stage2_exec-cmdline.$(OBJEXT) \ + pre_stage2_exec-common.$(OBJEXT) \ + pre_stage2_exec-console.$(OBJEXT) \ + pre_stage2_exec-dec_lz4.$(OBJEXT) \ + pre_stage2_exec-dec_lzma.$(OBJEXT) \ + pre_stage2_exec-dec_vhd.$(OBJEXT) \ + pre_stage2_exec-disk_io.$(OBJEXT) \ + pre_stage2_exec-fsys_ext2fs.$(OBJEXT) \ + pre_stage2_exec-fsys_fat.$(OBJEXT) \ + pre_stage2_exec-fsys_ntfs.$(OBJEXT) \ + pre_stage2_exec-fsys_iso9660.$(OBJEXT) \ + pre_stage2_exec-fsys_pxe.$(OBJEXT) \ + pre_stage2_exec-fsys_ipxe.$(OBJEXT) \ + pre_stage2_exec-fsys_fb.$(OBJEXT) \ + pre_stage2_exec-fsys_initrd.$(OBJEXT) \ + pre_stage2_exec-gunzip.$(OBJEXT) \ + pre_stage2_exec-md5.$(OBJEXT) \ + pre_stage2_exec-stage2.$(OBJEXT) \ + pre_stage2_exec-graphics.$(OBJEXT) +pre_stage2_exec_OBJECTS = $(am_pre_stage2_exec_OBJECTS) +pre_stage2_exec_LDADD = $(LDADD) +pre_stage2_exec_LINK = $(CCLD) $(pre_stage2_exec_CFLAGS) $(CFLAGS) \ + $(pre_stage2_exec_LDFLAGS) $(LDFLAGS) -o $@ +pxeloader_exec_SOURCES = pxeloader.c +pxeloader_exec_OBJECTS = pxeloader.$(OBJEXT) +pxeloader_exec_LDADD = $(LDADD) +SCRIPTS = $(noinst_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +CPPASCOMPILE = $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) +AM_V_CPPAS = $(am__v_CPPAS_@AM_V@) +am__v_CPPAS_ = $(am__v_CPPAS_@AM_DEFAULT_V@) +am__v_CPPAS_0 = @echo " CPPAS " $@; +am__v_CPPAS_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(pre_stage2_exec_SOURCES) + +#SOURCES = $(badgrubstart_exec_SOURCES) $(bootlacestart_exec_SOURCES) \ +# diskless.c $(dosstart_exec_SOURCES) $(grldrstart_exec_SOURCES) \ +# $(hmloadstart_exec_SOURCES) $(mbrstart_exec_SOURCES) \ +# nbloader.c $(pre_stage2_exec_SOURCES) pxeloader.c + + +DIST_SOURCES = $(pre_stage2_exec_SOURCES) + +#DIST_SOURCES = $(badgrubstart_exec_SOURCES) \ +# $(bootlacestart_exec_SOURCES) diskless.c \ +# $(dosstart_exec_SOURCES) $(grldrstart_exec_SOURCES) \ +# $(hmloadstart_exec_SOURCES) $(mbrstart_exec_SOURCES) \ +# nbloader.c $(pre_stage2_exec_SOURCES) pxeloader.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(datalibdir)" +DATA = $(datalib_DATA) $(noinst_DATA) +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BIN_LDFLAGS = @BIN_LDFLAGS@ +BUILD_DIRS = @BUILD_DIRS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FSYS_CFLAGS = @FSYS_CFLAGS@ +GREP = @GREP@ +GRUB_CFLAGS = @GRUB_CFLAGS@ +GRUB_LIBS = @GRUB_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJCOPY = @OBJCOPY@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STAGE1_CFLAGS = @STAGE1_CFLAGS@ +STAGE2_CFLAGS = @STAGE2_CFLAGS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +default_CFLAGS = @default_CFLAGS@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_SCRIPTS = $(TESTS) + +# For silencing OBJCOPY output. +AM_V_OBJCOPY_0 = @echo " OBJ $@";$(OBJCOPY) +AM_V_OBJCOPY_1 = $(OBJCOPY) +AM_V_OBJCOPY_ = $(AM_V_OBJCOPY_$(AM_DEFAULT_VERBOSITY)) +AM_V_OBJCOPY = $(AM_V_OBJCOPY_$(V)) +# For dist target. +noinst_HEADERS = fat.h filesys.h freebsd.h \ + iso9660.h mb_header.h mb_info.h md5.h \ + pc_slice.h shared.h term.h \ + pxe.h ipxe.h graphics.h fsys_ipxe.h cpio.h fsys_initrd.h + +EXTRA_DIST = $(noinst_SCRIPTS) + +# Stage 2 and Stage 1.5's. +datalibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor) + +noinst_DATA = pre_stage2 + +MOSTLYCLEANFILES = $(noinst_PROGRAMS) +#PRE_STAGE2_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8200 $(BIN_LDFLAGS) 以下替代 +#PRE_STAGE2_LINK = -nostdlib -Wl,-N -Wl,-melf_i386 -Wl,--build-id=none -Wl,-r,-d $(BIN_LDFLAGS) 适应gcc高版本 2023-06-06 +PRE_STAGE2_LINK = -nostdlib -no-pie -fno-pic -Wl,-N -Wl,-melf_i386 -Wl,--build-id=none -Wl,-r,-d $(BIN_LDFLAGS) +@GRAPHICS_SUPPORT_FALSE@GRAPHICS_FLAGS = +@GRAPHICS_SUPPORT_TRUE@GRAPHICS_FLAGS = -DSUPPORT_GRAPHICS=1 +@GFX_SUPPORT_FALSE@GFX_FLAGS = +@GFX_SUPPORT_TRUE@GFX_FLAGS = -DSUPPORT_GFX=1 +STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \ + $(GRAPHICS_FLAGS) \ + $(GFX_FLAGS) + + +# For stage2 target. +pre_stage2_exec_SOURCES = asm.S boot.c builtins.c char_io.c \ + cmdline.c common.c console.c dec_lz4.c dec_lzma.c dec_vhd.c disk_io.c fsys_ext2fs.c \ + fsys_fat.c fsys_ntfs.c fsys_iso9660.c \ + fsys_pxe.c fsys_ipxe.c fsys_fb.c gunzip.c \ + md5.c stage2.c graphics.c fsys_initrd.c + +pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) +pre_stage2_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) +pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK) +CLEANFILES = $(datalib_DATA) $(noinst_DATA) $(BUILT_SOURCES) + +# General rule for making a raw binary. +SUFFIXES = .exec +all: all-am + +.SUFFIXES: +.SUFFIXES: .exec .S .c .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu stage2/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu stage2/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) + +pre_stage2.exec$(EXEEXT): $(pre_stage2_exec_OBJECTS) $(pre_stage2_exec_DEPENDENCIES) $(EXTRA_pre_stage2_exec_DEPENDENCIES) + @rm -f pre_stage2.exec$(EXEEXT) + $(AM_V_CCLD)$(pre_stage2_exec_LINK) $(pre_stage2_exec_OBJECTS) $(pre_stage2_exec_LDADD) $(LIBS) + +pxeloader.exec$(EXEEXT): $(pxeloader_exec_OBJECTS) $(pxeloader_exec_DEPENDENCIES) $(EXTRA_pxeloader_exec_DEPENDENCIES) + @rm -f pxeloader.exec$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pxeloader_exec_OBJECTS) $(pxeloader_exec_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-asm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-boot.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-builtins.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-char_io.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-cmdline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-common.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-console.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-dec_lz4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-dec_lzma.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-dec_vhd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-disk_io.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_ext2fs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_fat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_fb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_initrd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_ipxe.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_iso9660.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_ntfs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-fsys_pxe.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-graphics.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-gunzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-md5.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_stage2_exec-stage2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pxeloader.Po@am__quote@ + +.S.o: +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo $(PARAMETER) -o $@ $< +@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CPPASCOMPILE) $(PARAMETER) -o $@ $< + +.S.obj: +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo $(PARAMETER) -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CPPASCOMPILE) $(PARAMETER) -o $@ `$(CYGPATH_W) '$<'` + +pre_stage2_exec-asm.o: asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CCASFLAGS) $(CCASFLAGS) -MT pre_stage2_exec-asm.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-asm.Tpo $(PARAMETER) -o pre_stage2_exec-asm.o `test -f 'asm.S' || echo '$(srcdir)/'`asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-asm.Tpo $(DEPDIR)/pre_stage2_exec-asm.Po +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='asm.S' object='pre_stage2_exec-asm.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CCASFLAGS) $(CCASFLAGS) $(PARAMETER) -o pre_stage2_exec-asm.o `test -f 'asm.S' || echo '$(srcdir)/'`asm.S + +pre_stage2_exec-asm.obj: asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CCASFLAGS) $(CCASFLAGS) -MT pre_stage2_exec-asm.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-asm.Tpo $(PARAMETER) -o pre_stage2_exec-asm.obj `if test -f 'asm.S'; then $(CYGPATH_W) 'asm.S'; else $(CYGPATH_W) '$(srcdir)/asm.S'; fi` +@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-asm.Tpo $(DEPDIR)/pre_stage2_exec-asm.Po +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='asm.S' object='pre_stage2_exec-asm.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CCASFLAGS) $(CCASFLAGS) $(PARAMETER) -o pre_stage2_exec-asm.obj `if test -f 'asm.S'; then $(CYGPATH_W) 'asm.S'; else $(CYGPATH_W) '$(srcdir)/asm.S'; fi` + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo $(PARAMETER) -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) $(PARAMETER) -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo $(PARAMETER) -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) $(PARAMETER) -o $@ `$(CYGPATH_W) '$<'` + +pre_stage2_exec-boot.o: boot.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-boot.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-boot.Tpo $(PARAMETER) -o pre_stage2_exec-boot.o `test -f 'boot.c' || echo '$(srcdir)/'`boot.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-boot.Tpo $(DEPDIR)/pre_stage2_exec-boot.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='boot.c' object='pre_stage2_exec-boot.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-boot.o `test -f 'boot.c' || echo '$(srcdir)/'`boot.c + +pre_stage2_exec-boot.obj: boot.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-boot.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-boot.Tpo $(PARAMETER) -o pre_stage2_exec-boot.obj `if test -f 'boot.c'; then $(CYGPATH_W) 'boot.c'; else $(CYGPATH_W) '$(srcdir)/boot.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-boot.Tpo $(DEPDIR)/pre_stage2_exec-boot.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='boot.c' object='pre_stage2_exec-boot.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-boot.obj `if test -f 'boot.c'; then $(CYGPATH_W) 'boot.c'; else $(CYGPATH_W) '$(srcdir)/boot.c'; fi` + +pre_stage2_exec-builtins.o: builtins.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-builtins.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-builtins.Tpo $(PARAMETER) -o pre_stage2_exec-builtins.o `test -f 'builtins.c' || echo '$(srcdir)/'`builtins.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-builtins.Tpo $(DEPDIR)/pre_stage2_exec-builtins.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='builtins.c' object='pre_stage2_exec-builtins.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-builtins.o `test -f 'builtins.c' || echo '$(srcdir)/'`builtins.c + +pre_stage2_exec-builtins.obj: builtins.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-builtins.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-builtins.Tpo $(PARAMETER) -o pre_stage2_exec-builtins.obj `if test -f 'builtins.c'; then $(CYGPATH_W) 'builtins.c'; else $(CYGPATH_W) '$(srcdir)/builtins.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-builtins.Tpo $(DEPDIR)/pre_stage2_exec-builtins.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='builtins.c' object='pre_stage2_exec-builtins.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-builtins.obj `if test -f 'builtins.c'; then $(CYGPATH_W) 'builtins.c'; else $(CYGPATH_W) '$(srcdir)/builtins.c'; fi` + +pre_stage2_exec-char_io.o: char_io.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-char_io.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-char_io.Tpo $(PARAMETER) -o pre_stage2_exec-char_io.o `test -f 'char_io.c' || echo '$(srcdir)/'`char_io.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-char_io.Tpo $(DEPDIR)/pre_stage2_exec-char_io.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='char_io.c' object='pre_stage2_exec-char_io.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-char_io.o `test -f 'char_io.c' || echo '$(srcdir)/'`char_io.c + +pre_stage2_exec-char_io.obj: char_io.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-char_io.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-char_io.Tpo $(PARAMETER) -o pre_stage2_exec-char_io.obj `if test -f 'char_io.c'; then $(CYGPATH_W) 'char_io.c'; else $(CYGPATH_W) '$(srcdir)/char_io.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-char_io.Tpo $(DEPDIR)/pre_stage2_exec-char_io.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='char_io.c' object='pre_stage2_exec-char_io.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-char_io.obj `if test -f 'char_io.c'; then $(CYGPATH_W) 'char_io.c'; else $(CYGPATH_W) '$(srcdir)/char_io.c'; fi` + +pre_stage2_exec-cmdline.o: cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-cmdline.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-cmdline.Tpo $(PARAMETER) -o pre_stage2_exec-cmdline.o `test -f 'cmdline.c' || echo '$(srcdir)/'`cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-cmdline.Tpo $(DEPDIR)/pre_stage2_exec-cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmdline.c' object='pre_stage2_exec-cmdline.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-cmdline.o `test -f 'cmdline.c' || echo '$(srcdir)/'`cmdline.c + +pre_stage2_exec-cmdline.obj: cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-cmdline.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-cmdline.Tpo $(PARAMETER) -o pre_stage2_exec-cmdline.obj `if test -f 'cmdline.c'; then $(CYGPATH_W) 'cmdline.c'; else $(CYGPATH_W) '$(srcdir)/cmdline.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-cmdline.Tpo $(DEPDIR)/pre_stage2_exec-cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmdline.c' object='pre_stage2_exec-cmdline.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-cmdline.obj `if test -f 'cmdline.c'; then $(CYGPATH_W) 'cmdline.c'; else $(CYGPATH_W) '$(srcdir)/cmdline.c'; fi` + +pre_stage2_exec-common.o: common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-common.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-common.Tpo $(PARAMETER) -o pre_stage2_exec-common.o `test -f 'common.c' || echo '$(srcdir)/'`common.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-common.Tpo $(DEPDIR)/pre_stage2_exec-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common.c' object='pre_stage2_exec-common.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-common.o `test -f 'common.c' || echo '$(srcdir)/'`common.c + +pre_stage2_exec-common.obj: common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-common.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-common.Tpo $(PARAMETER) -o pre_stage2_exec-common.obj `if test -f 'common.c'; then $(CYGPATH_W) 'common.c'; else $(CYGPATH_W) '$(srcdir)/common.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-common.Tpo $(DEPDIR)/pre_stage2_exec-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common.c' object='pre_stage2_exec-common.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-common.obj `if test -f 'common.c'; then $(CYGPATH_W) 'common.c'; else $(CYGPATH_W) '$(srcdir)/common.c'; fi` + +pre_stage2_exec-console.o: console.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-console.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-console.Tpo $(PARAMETER) -o pre_stage2_exec-console.o `test -f 'console.c' || echo '$(srcdir)/'`console.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-console.Tpo $(DEPDIR)/pre_stage2_exec-console.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='console.c' object='pre_stage2_exec-console.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-console.o `test -f 'console.c' || echo '$(srcdir)/'`console.c + +pre_stage2_exec-console.obj: console.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-console.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-console.Tpo $(PARAMETER) -o pre_stage2_exec-console.obj `if test -f 'console.c'; then $(CYGPATH_W) 'console.c'; else $(CYGPATH_W) '$(srcdir)/console.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-console.Tpo $(DEPDIR)/pre_stage2_exec-console.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='console.c' object='pre_stage2_exec-console.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-console.obj `if test -f 'console.c'; then $(CYGPATH_W) 'console.c'; else $(CYGPATH_W) '$(srcdir)/console.c'; fi` + +pre_stage2_exec-dec_lz4.o: dec_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-dec_lz4.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-dec_lz4.Tpo $(PARAMETER) -o pre_stage2_exec-dec_lz4.o `test -f 'dec_lz4.c' || echo '$(srcdir)/'`dec_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-dec_lz4.Tpo $(DEPDIR)/pre_stage2_exec-dec_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dec_lz4.c' object='pre_stage2_exec-dec_lz4.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-dec_lz4.o `test -f 'dec_lz4.c' || echo '$(srcdir)/'`dec_lz4.c + +pre_stage2_exec-dec_lz4.obj: dec_lz4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-dec_lz4.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-dec_lz4.Tpo $(PARAMETER) -o pre_stage2_exec-dec_lz4.obj `if test -f 'dec_lz4.c'; then $(CYGPATH_W) 'dec_lz4.c'; else $(CYGPATH_W) '$(srcdir)/dec_lz4.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-dec_lz4.Tpo $(DEPDIR)/pre_stage2_exec-dec_lz4.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dec_lz4.c' object='pre_stage2_exec-dec_lz4.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-dec_lz4.obj `if test -f 'dec_lz4.c'; then $(CYGPATH_W) 'dec_lz4.c'; else $(CYGPATH_W) '$(srcdir)/dec_lz4.c'; fi` + +pre_stage2_exec-dec_lzma.o: dec_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-dec_lzma.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-dec_lzma.Tpo $(PARAMETER) -o pre_stage2_exec-dec_lzma.o `test -f 'dec_lzma.c' || echo '$(srcdir)/'`dec_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-dec_lzma.Tpo $(DEPDIR)/pre_stage2_exec-dec_lzma.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dec_lzma.c' object='pre_stage2_exec-dec_lzma.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-dec_lzma.o `test -f 'dec_lzma.c' || echo '$(srcdir)/'`dec_lzma.c + +pre_stage2_exec-dec_lzma.obj: dec_lzma.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-dec_lzma.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-dec_lzma.Tpo $(PARAMETER) -o pre_stage2_exec-dec_lzma.obj `if test -f 'dec_lzma.c'; then $(CYGPATH_W) 'dec_lzma.c'; else $(CYGPATH_W) '$(srcdir)/dec_lzma.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-dec_lzma.Tpo $(DEPDIR)/pre_stage2_exec-dec_lzma.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dec_lzma.c' object='pre_stage2_exec-dec_lzma.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-dec_lzma.obj `if test -f 'dec_lzma.c'; then $(CYGPATH_W) 'dec_lzma.c'; else $(CYGPATH_W) '$(srcdir)/dec_lzma.c'; fi` + +pre_stage2_exec-dec_vhd.o: dec_vhd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-dec_vhd.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-dec_vhd.Tpo $(PARAMETER) -o pre_stage2_exec-dec_vhd.o `test -f 'dec_vhd.c' || echo '$(srcdir)/'`dec_vhd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-dec_vhd.Tpo $(DEPDIR)/pre_stage2_exec-dec_vhd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dec_vhd.c' object='pre_stage2_exec-dec_vhd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-dec_vhd.o `test -f 'dec_vhd.c' || echo '$(srcdir)/'`dec_vhd.c + +pre_stage2_exec-dec_vhd.obj: dec_vhd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-dec_vhd.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-dec_vhd.Tpo $(PARAMETER) -o pre_stage2_exec-dec_vhd.obj `if test -f 'dec_vhd.c'; then $(CYGPATH_W) 'dec_vhd.c'; else $(CYGPATH_W) '$(srcdir)/dec_vhd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-dec_vhd.Tpo $(DEPDIR)/pre_stage2_exec-dec_vhd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dec_vhd.c' object='pre_stage2_exec-dec_vhd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-dec_vhd.obj `if test -f 'dec_vhd.c'; then $(CYGPATH_W) 'dec_vhd.c'; else $(CYGPATH_W) '$(srcdir)/dec_vhd.c'; fi` + +pre_stage2_exec-disk_io.o: disk_io.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-disk_io.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-disk_io.Tpo $(PARAMETER) -o pre_stage2_exec-disk_io.o `test -f 'disk_io.c' || echo '$(srcdir)/'`disk_io.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-disk_io.Tpo $(DEPDIR)/pre_stage2_exec-disk_io.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='disk_io.c' object='pre_stage2_exec-disk_io.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-disk_io.o `test -f 'disk_io.c' || echo '$(srcdir)/'`disk_io.c + +pre_stage2_exec-disk_io.obj: disk_io.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-disk_io.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-disk_io.Tpo $(PARAMETER) -o pre_stage2_exec-disk_io.obj `if test -f 'disk_io.c'; then $(CYGPATH_W) 'disk_io.c'; else $(CYGPATH_W) '$(srcdir)/disk_io.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-disk_io.Tpo $(DEPDIR)/pre_stage2_exec-disk_io.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='disk_io.c' object='pre_stage2_exec-disk_io.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-disk_io.obj `if test -f 'disk_io.c'; then $(CYGPATH_W) 'disk_io.c'; else $(CYGPATH_W) '$(srcdir)/disk_io.c'; fi` + +pre_stage2_exec-fsys_ext2fs.o: fsys_ext2fs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ext2fs.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ext2fs.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_ext2fs.o `test -f 'fsys_ext2fs.c' || echo '$(srcdir)/'`fsys_ext2fs.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_ext2fs.Tpo $(DEPDIR)/pre_stage2_exec-fsys_ext2fs.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_ext2fs.c' object='pre_stage2_exec-fsys_ext2fs.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_ext2fs.o `test -f 'fsys_ext2fs.c' || echo '$(srcdir)/'`fsys_ext2fs.c + +pre_stage2_exec-fsys_ext2fs.obj: fsys_ext2fs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ext2fs.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ext2fs.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_ext2fs.obj `if test -f 'fsys_ext2fs.c'; then $(CYGPATH_W) 'fsys_ext2fs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ext2fs.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_ext2fs.Tpo $(DEPDIR)/pre_stage2_exec-fsys_ext2fs.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_ext2fs.c' object='pre_stage2_exec-fsys_ext2fs.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_ext2fs.obj `if test -f 'fsys_ext2fs.c'; then $(CYGPATH_W) 'fsys_ext2fs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ext2fs.c'; fi` + +pre_stage2_exec-fsys_fat.o: fsys_fat.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_fat.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_fat.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_fat.o `test -f 'fsys_fat.c' || echo '$(srcdir)/'`fsys_fat.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_fat.Tpo $(DEPDIR)/pre_stage2_exec-fsys_fat.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_fat.c' object='pre_stage2_exec-fsys_fat.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_fat.o `test -f 'fsys_fat.c' || echo '$(srcdir)/'`fsys_fat.c + +pre_stage2_exec-fsys_fat.obj: fsys_fat.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_fat.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_fat.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_fat.obj `if test -f 'fsys_fat.c'; then $(CYGPATH_W) 'fsys_fat.c'; else $(CYGPATH_W) '$(srcdir)/fsys_fat.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_fat.Tpo $(DEPDIR)/pre_stage2_exec-fsys_fat.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_fat.c' object='pre_stage2_exec-fsys_fat.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_fat.obj `if test -f 'fsys_fat.c'; then $(CYGPATH_W) 'fsys_fat.c'; else $(CYGPATH_W) '$(srcdir)/fsys_fat.c'; fi` + +pre_stage2_exec-fsys_ntfs.o: fsys_ntfs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ntfs.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ntfs.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_ntfs.o `test -f 'fsys_ntfs.c' || echo '$(srcdir)/'`fsys_ntfs.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_ntfs.Tpo $(DEPDIR)/pre_stage2_exec-fsys_ntfs.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_ntfs.c' object='pre_stage2_exec-fsys_ntfs.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_ntfs.o `test -f 'fsys_ntfs.c' || echo '$(srcdir)/'`fsys_ntfs.c + +pre_stage2_exec-fsys_ntfs.obj: fsys_ntfs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ntfs.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ntfs.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_ntfs.obj `if test -f 'fsys_ntfs.c'; then $(CYGPATH_W) 'fsys_ntfs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ntfs.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_ntfs.Tpo $(DEPDIR)/pre_stage2_exec-fsys_ntfs.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_ntfs.c' object='pre_stage2_exec-fsys_ntfs.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_ntfs.obj `if test -f 'fsys_ntfs.c'; then $(CYGPATH_W) 'fsys_ntfs.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ntfs.c'; fi` + +pre_stage2_exec-fsys_iso9660.o: fsys_iso9660.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_iso9660.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_iso9660.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_iso9660.o `test -f 'fsys_iso9660.c' || echo '$(srcdir)/'`fsys_iso9660.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_iso9660.Tpo $(DEPDIR)/pre_stage2_exec-fsys_iso9660.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_iso9660.c' object='pre_stage2_exec-fsys_iso9660.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_iso9660.o `test -f 'fsys_iso9660.c' || echo '$(srcdir)/'`fsys_iso9660.c + +pre_stage2_exec-fsys_iso9660.obj: fsys_iso9660.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_iso9660.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_iso9660.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_iso9660.obj `if test -f 'fsys_iso9660.c'; then $(CYGPATH_W) 'fsys_iso9660.c'; else $(CYGPATH_W) '$(srcdir)/fsys_iso9660.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_iso9660.Tpo $(DEPDIR)/pre_stage2_exec-fsys_iso9660.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_iso9660.c' object='pre_stage2_exec-fsys_iso9660.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_iso9660.obj `if test -f 'fsys_iso9660.c'; then $(CYGPATH_W) 'fsys_iso9660.c'; else $(CYGPATH_W) '$(srcdir)/fsys_iso9660.c'; fi` + +pre_stage2_exec-fsys_pxe.o: fsys_pxe.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_pxe.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_pxe.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_pxe.o `test -f 'fsys_pxe.c' || echo '$(srcdir)/'`fsys_pxe.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_pxe.Tpo $(DEPDIR)/pre_stage2_exec-fsys_pxe.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_pxe.c' object='pre_stage2_exec-fsys_pxe.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_pxe.o `test -f 'fsys_pxe.c' || echo '$(srcdir)/'`fsys_pxe.c + +pre_stage2_exec-fsys_pxe.obj: fsys_pxe.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_pxe.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_pxe.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_pxe.obj `if test -f 'fsys_pxe.c'; then $(CYGPATH_W) 'fsys_pxe.c'; else $(CYGPATH_W) '$(srcdir)/fsys_pxe.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_pxe.Tpo $(DEPDIR)/pre_stage2_exec-fsys_pxe.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_pxe.c' object='pre_stage2_exec-fsys_pxe.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_pxe.obj `if test -f 'fsys_pxe.c'; then $(CYGPATH_W) 'fsys_pxe.c'; else $(CYGPATH_W) '$(srcdir)/fsys_pxe.c'; fi` + +pre_stage2_exec-fsys_ipxe.o: fsys_ipxe.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ipxe.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ipxe.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_ipxe.o `test -f 'fsys_ipxe.c' || echo '$(srcdir)/'`fsys_ipxe.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_ipxe.Tpo $(DEPDIR)/pre_stage2_exec-fsys_ipxe.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_ipxe.c' object='pre_stage2_exec-fsys_ipxe.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_ipxe.o `test -f 'fsys_ipxe.c' || echo '$(srcdir)/'`fsys_ipxe.c + +pre_stage2_exec-fsys_ipxe.obj: fsys_ipxe.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_ipxe.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_ipxe.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_ipxe.obj `if test -f 'fsys_ipxe.c'; then $(CYGPATH_W) 'fsys_ipxe.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ipxe.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_ipxe.Tpo $(DEPDIR)/pre_stage2_exec-fsys_ipxe.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_ipxe.c' object='pre_stage2_exec-fsys_ipxe.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_ipxe.obj `if test -f 'fsys_ipxe.c'; then $(CYGPATH_W) 'fsys_ipxe.c'; else $(CYGPATH_W) '$(srcdir)/fsys_ipxe.c'; fi` + +pre_stage2_exec-fsys_fb.o: fsys_fb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_fb.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_fb.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_fb.o `test -f 'fsys_fb.c' || echo '$(srcdir)/'`fsys_fb.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_fb.Tpo $(DEPDIR)/pre_stage2_exec-fsys_fb.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_fb.c' object='pre_stage2_exec-fsys_fb.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_fb.o `test -f 'fsys_fb.c' || echo '$(srcdir)/'`fsys_fb.c + +pre_stage2_exec-fsys_fb.obj: fsys_fb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_fb.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_fb.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_fb.obj `if test -f 'fsys_fb.c'; then $(CYGPATH_W) 'fsys_fb.c'; else $(CYGPATH_W) '$(srcdir)/fsys_fb.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_fb.Tpo $(DEPDIR)/pre_stage2_exec-fsys_fb.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_fb.c' object='pre_stage2_exec-fsys_fb.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_fb.obj `if test -f 'fsys_fb.c'; then $(CYGPATH_W) 'fsys_fb.c'; else $(CYGPATH_W) '$(srcdir)/fsys_fb.c'; fi` + +pre_stage2_exec-fsys_initrd.o: fsys_initrd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_initrd.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_initrd.Tpo $(PARAMETER) -o pre_stage2_exec-fsys_initrd.o `test -f 'fsys_initrd.c' || echo '$(srcdir)/'`fsys_initrd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_initrd.Tpo $(DEPDIR)/pre_stage2_exec-fsys_initrd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_initrd.c' object='pre_stage2_exec-fsys_initrd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_initrd.o `test -f 'fsys_initrd.c' || echo '$(srcdir)/'`fsys_initrd.c + +pre_stage2_exec-fsys_initrd.obj: fsys_initrd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-fsys_initrd.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-fsys_initrd.Tpov -o pre_stage2_exec-fsys_initrd.obj `if test -f 'fsys_initrd.c'; then $(CYGPATH_W) 'fsys_initrd.c'; else $(CYGPATH_W) '$(srcdir)/fsys_initrd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-fsys_initrd.Tpo $(DEPDIR)/pre_stage2_exec-fsys_initrd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsys_initrd.c' object='pre_stage2_exec-fsys_initrd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-fsys_initrd.obj `if test -f 'fsys_initrd.c'; then $(CYGPATH_W) 'fsys_initrd.c'; else $(CYGPATH_W) '$(srcdir)/fsys_initrd.c'; fi` + +pre_stage2_exec-gunzip.o: gunzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-gunzip.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-gunzip.Tpo $(PARAMETER) -o pre_stage2_exec-gunzip.o `test -f 'gunzip.c' || echo '$(srcdir)/'`gunzip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-gunzip.Tpo $(DEPDIR)/pre_stage2_exec-gunzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gunzip.c' object='pre_stage2_exec-gunzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-gunzip.o `test -f 'gunzip.c' || echo '$(srcdir)/'`gunzip.c + +pre_stage2_exec-gunzip.obj: gunzip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-gunzip.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-gunzip.Tpo $(PARAMETER) -o pre_stage2_exec-gunzip.obj `if test -f 'gunzip.c'; then $(CYGPATH_W) 'gunzip.c'; else $(CYGPATH_W) '$(srcdir)/gunzip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-gunzip.Tpo $(DEPDIR)/pre_stage2_exec-gunzip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gunzip.c' object='pre_stage2_exec-gunzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-gunzip.obj `if test -f 'gunzip.c'; then $(CYGPATH_W) 'gunzip.c'; else $(CYGPATH_W) '$(srcdir)/gunzip.c'; fi` + +pre_stage2_exec-md5.o: md5.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-md5.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-md5.Tpo $(PARAMETER) -o pre_stage2_exec-md5.o `test -f 'md5.c' || echo '$(srcdir)/'`md5.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-md5.Tpo $(DEPDIR)/pre_stage2_exec-md5.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='md5.c' object='pre_stage2_exec-md5.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-md5.o `test -f 'md5.c' || echo '$(srcdir)/'`md5.c + +pre_stage2_exec-md5.obj: md5.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-md5.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-md5.Tpo $(PARAMETER) -o pre_stage2_exec-md5.obj `if test -f 'md5.c'; then $(CYGPATH_W) 'md5.c'; else $(CYGPATH_W) '$(srcdir)/md5.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-md5.Tpo $(DEPDIR)/pre_stage2_exec-md5.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='md5.c' object='pre_stage2_exec-md5.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-md5.obj `if test -f 'md5.c'; then $(CYGPATH_W) 'md5.c'; else $(CYGPATH_W) '$(srcdir)/md5.c'; fi` + +pre_stage2_exec-stage2.o: stage2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-stage2.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-stage2.Tpo $(PARAMETER) -o pre_stage2_exec-stage2.o `test -f 'stage2.c' || echo '$(srcdir)/'`stage2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-stage2.Tpo $(DEPDIR)/pre_stage2_exec-stage2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stage2.c' object='pre_stage2_exec-stage2.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-stage2.o `test -f 'stage2.c' || echo '$(srcdir)/'`stage2.c + +pre_stage2_exec-stage2.obj: stage2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-stage2.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-stage2.Tpo $(PARAMETER) -o pre_stage2_exec-stage2.obj `if test -f 'stage2.c'; then $(CYGPATH_W) 'stage2.c'; else $(CYGPATH_W) '$(srcdir)/stage2.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-stage2.Tpo $(DEPDIR)/pre_stage2_exec-stage2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stage2.c' object='pre_stage2_exec-stage2.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-stage2.obj `if test -f 'stage2.c'; then $(CYGPATH_W) 'stage2.c'; else $(CYGPATH_W) '$(srcdir)/stage2.c'; fi` + +pre_stage2_exec-graphics.o: graphics.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-graphics.o -MD -MP -MF $(DEPDIR)/pre_stage2_exec-graphics.Tpo $(PARAMETER) -o pre_stage2_exec-graphics.o `test -f 'graphics.c' || echo '$(srcdir)/'`graphics.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-graphics.Tpo $(DEPDIR)/pre_stage2_exec-graphics.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='graphics.c' object='pre_stage2_exec-graphics.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-graphics.o `test -f 'graphics.c' || echo '$(srcdir)/'`graphics.c + +pre_stage2_exec-graphics.obj: graphics.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -MT pre_stage2_exec-graphics.obj -MD -MP -MF $(DEPDIR)/pre_stage2_exec-graphics.Tpo $(PARAMETER) -o pre_stage2_exec-graphics.obj `if test -f 'graphics.c'; then $(CYGPATH_W) 'graphics.c'; else $(CYGPATH_W) '$(srcdir)/graphics.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pre_stage2_exec-graphics.Tpo $(DEPDIR)/pre_stage2_exec-graphics.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='graphics.c' object='pre_stage2_exec-graphics.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) $(PARAMETER) -o pre_stage2_exec-graphics.obj `if test -f 'graphics.c'; then $(CYGPATH_W) 'graphics.c'; else $(CYGPATH_W) '$(srcdir)/graphics.c'; fi` +install-datalibDATA: $(datalib_DATA) + @$(NORMAL_INSTALL) + @list='$(datalib_DATA)'; test -n "$(datalibdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(datalibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(datalibdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(datalibdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(datalibdir)" || exit $$?; \ + done + +uninstall-datalibDATA: + @$(NORMAL_UNINSTALL) + @list='$(datalib_DATA)'; test -n "$(datalibdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(datalibdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + else \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(PROGRAMS) $(SCRIPTS) $(DATA) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(datalibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-datalibDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-datalibDATA + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ + clean-generic clean-noinstPROGRAMS cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-datalibDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am recheck tags tags-am \ + uninstall uninstall-am uninstall-datalibDATA + +%: %.exec$(EXEEXT) + $(AM_V_OBJCOPY) -O binary $< $@ + +# $(AM_V_OBJCOPY) -O binary $< $@ +# $(AM_V_at)if [ $@ = pre_stage2 ]; then dd if=pre_stage2 of=pre_stage2_fullsize bs=65536 skip=48 2>/dev/null || echo "DD failed!" ;fi +# $(AM_V_at)if [ $@ = pre_stage2 ]; then sed -e "1s/^\x00*//" pre_stage2_fullsize > pre_stage2_tail ;fi +# $(AM_V_at)if [ $@ = pre_stage2 ]; then set dummy `ls -l pre_stage2_fullsize`; set $$6 `ls -l pre_stage2_tail`; if [ $$1 -le $$6 ]; then set `cmp pre_stage2_fullsize /dev/zero` ; while [ "$$1" != "" ]; do t1="$${1%%[^0-9]*}"; if [ "$$t1" != "" ]; then if [ "$$t1" -gt 2000 ]; then t1=`expr $$t1 - 1`; dd if=pre_stage2_fullsize of=pre_stage2_tail bs=1 skip=$$t1 2>/dev/null || echo "DD failed!" ; break; fi; fi; shift; done; fi; fi +# $(AM_V_at)if [ $@ = pre_stage2 ]; then set dummy `ls -l pre_stage2_fullsize`; set $$6 `ls -l pre_stage2_tail`; dd if=pre_stage2 of=pre_stage2_head bs=`expr $$1 - $$6` count=1 2>/dev/null || echo "DD failed!" ; cat pre_stage2_head pre_stage2_tail > pre_stage2 ;fi +# $(AM_V_at)if [ $@ = pre_stage2 ]; then echo -n -e "\0260\002\032\0316" >> $@ ;fi + +#pre_stage2_head 头部(0x13d4). 从"ENTRY(main)"开始, 至"VARIABLE(end_of_low_16bit_code)", 即16位代码结束地址; +#pre_stage2_tail 尾部(0x42d64). 从".space 0x300000"开始, 即32位代码开始地址, 至c代码结束, 包含程序代码及静态数据; +#pre_stage2_fullsize 全尺寸(0x44138). 即头部(0x13d4)加尾部(0x42d64); +#pre_stage2 (0x4413c). 在pre_stage2_fullsize全尺寸(0x44138)尾部, 增加签名(B0 02 1A CE); +#pre_stage2_exec (3d491c). ELF头部(0x200), 加全尺寸(0x44138), 加3Mb插入的0, 加GCC编译信息; +#bs=65536=0x10000 skip=48=0x30; 意思是跳过3Mb +#sed:Stream Editor文本流编辑; e :直接在命令行模式上进行sed动作编辑; +#ls -l //显示不隐藏的文件与文件夹的详细信息; +#[ $$1 -le $$6 ] 变量$$1小于等于$$6; +#"\0260\002\032\0316"="\xB0\x02\x1A\xCE"=签名 + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/stage2/a20.inc b/stage2/a20.inc deleted file mode 100644 index 82c11a6b..00000000 --- a/stage2/a20.inc +++ /dev/null @@ -1,692 +0,0 @@ -/* real-mode A20 gate control code for grub4dos. - * - * Copyright (C) 2008 Tinybit - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* The code is based on bcopy32.c from syslinux-3.63. Here is the original - * copyright notice: - * - * ----------------------------------------------------------------------- - * - * Copyright 1994-2008 H. Peter Anvin - All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, Inc., 53 Temple Place Ste 330, - * Boston MA 02111-1307, USA; either version 2 of the License, or - * (at your option) any later version; incorporated herein by reference. - * - * ----------------------------------------------------------------------- - */ - -# -# Routines to enable and disable (yuck) A20. These routines are gathered -# from tips from a couple of sources, including the Linux kernel and -# http://www.x86.org/. The need for the delay to be as large as given here -# is indicated by Donnie Barnes of RedHat, the problematic system being an -# IBM ThinkPad 760EL. -# -# We typically toggle A20 twice for every 64K transferred. -# - -#define DISABLE_CPU_CACHE 0 - -#define IO_DELAY_PORT 0x80 /* Invalid port (we hope!) */ - -# Note the skip of 2 here -#define A20_DUNNO 0 /* A20 type unknown */ -#define A20_NONE 2 /* A20 always on? */ -#define A20_BIOS 4 /* A20 BIOS enable */ -#define A20_KBC 6 /* A20 through KBC */ -#define A20_FAST 8 /* A20 through port 92h */ - - /* Align Dword here so that other alignments below could work - * as expected. - */ - - .align 4 - -enable_disable_a20: - - ################################################################### - # input: DL=0 disable a20 - # DL=non-zero enable a20 - # DH=0 a20 debug off - # DH=non-zero a20 debug on - # CX=loops to try when failure - # - # output: ZF=0 failed - # ZF=1 completed ok. If ZF=CF=1, then - # the A20 status needn't change and - # was not touched. - # EAX modified - # CX modified - ################################################################### - - # First, see if the A20 status is already what we desired. - pushl %ecx - movl $0x2, %ecx - call a20_test_match - popl %ecx - /* ZF=1(means equal) for desired and we needn't do anything. */ - jnz 1f - stc - ret - -assign_base_pointer: - call base_addr -base_addr: - popw %bp - ret - -1: - /********************************************/ - /** Now we have to enable or disable A20 **/ - /********************************************/ - - pushl %ebp - call assign_base_pointer /* BP points to base_addr */ - /* save original EBP */ - popl %cs:(A20_old_ebp - base_addr)(%bp) - - /* save original return address */ - popw %cs:(A20ReturnAddress - base_addr)(%bp) - - movl %eax, %cs:(A20_old_eax - base_addr)(%bp) - movl %ebx, %cs:(A20_old_ebx - base_addr)(%bp) - movl %ecx, %cs:(A20_old_ecx - base_addr)(%bp) - movl %edx, %cs:(A20_old_edx - base_addr)(%bp) - movl %esi, %cs:(A20_old_esi - base_addr)(%bp) - movl %edi, %cs:(A20_old_edi - base_addr)(%bp) - -// pushal # save all - - movw $200, %cx - testb %dl, %dl - jnz 1f - movw $20, %cx -1: - - # Times to try to make this work - movw %cx, %cs:(A20Tries - base_addr)(%bp) - - /* save original IF, DF */ - pushfw - popw %cs:(A20Flags - base_addr)(%bp) - -a20_try_again: - - ###################################################################### - ## If the A20 type is known, jump straight to type - ###################################################################### - - call assign_base_pointer /* BP points to base_addr */ - movw %cs:(A20Type - base_addr)(%bp), %si - movw %bp, %bx - addw %cs:(A20List - base_addr)(%bp, %si), %bx - jmp *%bx - - ###################################################################### - ## First, see if we are on a system with no A20 gate - ###################################################################### - /* - * If the system has no A20 gate, then we needn't enable it and could - * return SUCCESS right now without calling A20_TEST. - */ -a20_none: - testb %dl, %dl - jz a20_done_fail -// cmpb %dl, %dl # set ZF=1 for success -// jmp a20_done - -a20_dunno: - //movb $A20_DUNNO, %cs:(A20Type - base_addr)(%bp) - call a20_debug_print - - pushl %ecx - movl $0x2, %ecx - call a20_test_match - popl %ecx - /* ZF=1(means equal) for desired and we needn't do anything. */ - jz a20_done - - ####################################################### - ## Next, try the BIOS (INT 15h AX=240xh) - ####################################################### -a20_bios: -#if 0 - /* dell hangs on the A20 BIOS call, so we avoid calling it. */ - - testb %dl, %dl - jz 1f - call assign_base_pointer /* BP points to base_addr */ - movb $A20_BIOS, %cs:(A20Type - base_addr)(%bp) - call a20_debug_print -1: - pushw %bp /* in case it is destroyed by int 15 */ - pushw %dx /* in case it is destroyed by int 15 */ - pushfw # Some BIOSes muck with IF - - testb %dl, %dl - setnz %al - movb $0x24, %ah - -.ifdef int13_handler -.ifdef ROM_int15 - /* we are inside asm.S */ - pushfw - lcall %cs:*(ROM_int15 - int13_handler) -.else - int $0x15 -.endif -.else - int $0x15 -.endif - - popfw - popw %dx - popw %bp - - pushl %ecx - movl $0x2, %ecx - call a20_test_match - popl %ecx - /* ZF=1(means equal) for desired and we needn't do anything. */ - jz a20_done -#endif - ####################################################### - ## Enable the keyboard controller A20 gate - ####################################################### -a20_kbc: - call empty_8042 - - pushfw # ZF=0 indicates there is no 8042 - pushl %ecx - movl $0x2, %ecx - call a20_test_match - popl %ecx - popw %ax # flags - /* ZF=1(means equal) for desired and we needn't do anything. */ - jz a20_done # A20 live, no need to use KBC - - pushw %ax # flags - popfw - jnz a20_fast # failure, no 8042, try next - - testb %dl, %dl - jz 1f - call assign_base_pointer /* BP points to base_addr */ - movb $A20_KBC, %cs:(A20Type - base_addr)(%bp) - call a20_debug_print -1: - movb $0xD1, %al # 8042 command byte to write output port - outb %al, $0x64 # write command to port 64h - call empty_8042 - - movb $0xDD, %al # 0xDD is for disable, 0xDF is for enable - testb %dl, %dl - setne %ah - shlb $1, %ah - orb %ah, %al - outb %al, $0x60 - call empty_8042 - - pushl %ecx - movl $0x2, %ecx - call a20_test_match - popl %ecx - /* ZF=1(means equal) for desired and we needn't do anything. */ - pushfw # ZF=1 for "A20 is OK" - - /* output a dummy command (USB keyboard hack) */ - movb $0xFF, %al - outb %al, $0x64 - call empty_8042 - - popfw # ZF=1 for "A20 is OK" - jz a20_done # A20 live, no need to use KBC - - pushl %ecx - movl $0x2, %ecx # 0x200000 is too big - call a20_test_match - popl %ecx - /* ZF=1(means equal) for desired and we needn't do anything. */ - jz a20_done - - ###################################################################### - ## Fast A20 Gate: System Control Port A - ###################################################################### - -a20_fast: - inb $0x92, %al - testb %dl, %dl - jz 2f - /* enable a20 */ - call assign_base_pointer /* BP points to base_addr */ - movb $A20_FAST, %cs:(A20Type - base_addr)(%bp) - call a20_debug_print - testb $0x02, %al - jnz 1f # chipset bug: do nothing if already set - orb $0x02, %al # "fast A20" version - andb $0xFE, %al # don't accidentally reset the cpu - jmp 3f -2: - /* disable a20 */ - testb $0x02, %al - jz 1f # chipset bug: do nothing if already cleared - andb $0xFC, %al # don't accidentally reset the cpu -3: - outb %al, $0x92 -1: - - pushl %ecx - movl $0x8, %ecx # 0x200000 is too big - call a20_test_match - popl %ecx - /* ZF=1(means equal) for desired and we needn't do anything. */ - jz a20_done - - #================================================================== - # A20 is not responding. Try again. - #================================================================== - - /* A20Type is now A20_FAST, so it must be reset!! */ - call assign_base_pointer /* BP points to base_addr */ - movb $A20_DUNNO, %cs:(A20Type - base_addr)(%bp) - call a20_debug_print - decw %cs:(A20Tries - base_addr)(%bp) - jnz a20_try_again - - #================================================================== - # Finally failed. - #================================================================== - - testb %dl, %dl - jnz a20_done_fail - /* We cannot disable it, so consider there is no A20 gate. */ - call assign_base_pointer /* BP points to base_addr */ - movb $A20_NONE, %cs:(A20Type - base_addr)(%bp) - -a20_done_fail: - incw %dx # set ZF=0 for failure - -a20_done: - pushfw - /* print "done!" to show that a return was executed */ - testb %dh, %dh - jz 1f - call assign_base_pointer /* BP points to base_addr */ - leaw (A20DbgMsgEnd - base_addr)(%bp), %si /* CS:SI is string */ - call a20_print_string -1: - popfw -// popal - movl %cs:(A20_old_eax - base_addr)(%bp), %eax - movl %cs:(A20_old_ebx - base_addr)(%bp), %ebx - movl %cs:(A20_old_ecx - base_addr)(%bp), %ecx - movl %cs:(A20_old_edx - base_addr)(%bp), %edx - movl %cs:(A20_old_esi - base_addr)(%bp), %esi - movl %cs:(A20_old_edi - base_addr)(%bp), %edi - pushw %cs:(A20ReturnAddress - base_addr)(%bp) /* return address */ - movl %cs:(A20_old_ebp - base_addr)(%bp), %ebp /* restore EBP */ - ret - - -////////////////////////////////////////////////////////////////////////////// -// -// ///////////////////////////////////////////////////////// -// // -// // Subroutines begin here -// // -// ///////////////////////////////////////////////////////// -// -////////////////////////////////////////////////////////////////////////////// - - - ###################################################################### - ## This routine tests if A20 status matches the desired. - ###################################################################### - -a20_test_match: -1: - call a20_test - pushw %ax - sete %al /* save ZF to AL */ - testb %dl, %dl - sete %ah /* save ZF to AH */ - cmpb %al, %ah - popw %ax - ADDR32 loopnz 1b /* dec ECX */ - /* ZF=1(means equal) for match */ - ret - - ###################################################################### - ## This routine tests if A20 is enabled (ZF = 0). This routine - ## must not destroy any register contents. - ###################################################################### - -a20_test: - - /******************************************************************/ - /* Don't call a20_debug_print! The A20_tmp_ variables are shared! */ - /******************************************************************/ - - pushl %ebp - call assign_base_pointer /* BP points to base_addr */ - /* save original EBP */ - popl %cs:(A20_tmp_ebp - base_addr)(%bp) - - /* save a20_test return address */ - popw %cs:(A20_tmp_ReturnAddress - base_addr)(%bp) - - movl %eax, %cs:(A20_tmp_eax - base_addr)(%bp) - movl %ebx, %cs:(A20_tmp_ebx - base_addr)(%bp) - movl %ecx, %cs:(A20_tmp_ecx - base_addr)(%bp) - movl %edx, %cs:(A20_tmp_edx - base_addr)(%bp) - movl %esi, %cs:(A20_tmp_esi - base_addr)(%bp) - movl %edi, %cs:(A20_tmp_edi - base_addr)(%bp) - movw %ds, %cs:(A20_tmp_ds - base_addr)(%bp) - movw %es, %cs:(A20_tmp_es - base_addr)(%bp) - - //pushl %eax - //pushw %cx - //pushw %ds - //pushw %es - //pushw %si - //pushw %di - - pushfw /* save old IF, DF */ - -#if DISABLE_CPU_CACHE - - /* disable CPU cache for the test to work reliably. */ - - cli - movl %cr0, %eax - - pushl %eax /* save old cr0 */ - - orl $0x60000000, %eax /* set CD and NW */ - movl %eax, %cr0 - jmp 1f -1: - movl %cr0, %eax - testl $0x60000000, %eax /* check if we can use wbinvd. */ - jz 1f /* CPU has no wbinvd instruction. */ - wbinvd - andl $0xDFFFFFFF, %eax /* clear NW */ - movl %eax, %cr0 - jmp 1f -1: -#endif - sti - xorw %ax, %ax - movw %ax, %ds /* DS=0 */ - decw %ax - movw %ax, %es /* ES=0xFFFF */ - - movw $(0xFFF0 / 4), %cx - xorw %si, %si - movw $0x0010, %di - cld - repz cmpsl - jne 1f /* A20 is known to be enabled */ - - /* A20 status unknown */ - - movl 0x200, %eax - pushl %eax /* save old int 0x80 vector */ - - movw $32, %cx # Loop count - //cli /* safe to touch int 0x80 vector */ -2: - pause - incl %eax - movl %eax, 0x200 - call delay # Serialize, and fix delay - pause - cmpl %es:0x210, %eax - loopz 2b - - popl %eax /* restore int 0x80 vector */ - movl %eax, 0x200 -1: - //sti - /* ZF=0(means not equal) for A20 on, ZF=1(means equal) for A20 off. */ - -#if DISABLE_CPU_CACHE - cli - popl %eax /* restore cr0 */ - movl %eax, %cr0 - jmp 1f -1: -#endif - - lahf /* Load Flags into AH Register. */ - /* AH = SF:ZF:xx:AF:xx:PF:xx:CF */ - - popfw /* restore IF, DF */ - sahf /* update ZF */ - - //popw %di - //popw %si - //popw %es - //popw %ds - //popw %cx - //popl %eax - call assign_base_pointer /* BP points to base_addr */ - movl %cs:(A20_tmp_eax - base_addr)(%bp), %eax - movl %cs:(A20_tmp_ebx - base_addr)(%bp), %ebx - movl %cs:(A20_tmp_ecx - base_addr)(%bp), %ecx - movl %cs:(A20_tmp_edx - base_addr)(%bp), %edx - movl %cs:(A20_tmp_esi - base_addr)(%bp), %esi - movl %cs:(A20_tmp_edi - base_addr)(%bp), %edi - movw %cs:(A20_tmp_ds - base_addr)(%bp), %ds - movw %cs:(A20_tmp_es - base_addr)(%bp), %es - pushw %cs:(A20_tmp_ReturnAddress - base_addr)(%bp) - movl %cs:(A20_tmp_ebp - base_addr)(%bp), %ebp /* restore EBP */ - ret - -//slow_out: -// outb %al, %dx # Fall through - -delay: - //pushw %ax - //movb $0x80, %al /* try to write only a known value to port */ - //aam //outb %al, $IO_DELAY_PORT - //aam //outb %al, $IO_DELAY_PORT - //popw %ax - pushw %cx - movw $8, %cx -1: - pause - loop 1b - popw %cx - ret - - ###################################################################### - ## - ## Print A20Tries, A20Type - ## - ###################################################################### - -a20_debug_print: - testb %dh, %dh /* debug mode? */ - jnz 1f /* yes, continue */ - ret -1: - //pushal - call assign_base_pointer /* BP points to base_addr */ - movl %eax, %cs:(A20_tmp_eax - base_addr)(%bp) - movl %ebx, %cs:(A20_tmp_ebx - base_addr)(%bp) - movl %ecx, %cs:(A20_tmp_ecx - base_addr)(%bp) - movl %edx, %cs:(A20_tmp_edx - base_addr)(%bp) - movl %esi, %cs:(A20_tmp_esi - base_addr)(%bp) - movl %edi, %cs:(A20_tmp_edi - base_addr)(%bp) - movw %ds, %cs:(A20_tmp_ds - base_addr)(%bp) - movw %es, %cs:(A20_tmp_es - base_addr)(%bp) - movw %fs, %cs:(A20_tmp_fs - base_addr)(%bp) - movw %gs, %cs:(A20_tmp_gs - base_addr)(%bp) - - movb %cs:(A20Tries - base_addr)(%bp), %al /* A20Tries */ - call a20_hex - movw %ax, %cs:(A20DbgMsgTryHex - base_addr)(%bp) /* A20Tries */ - - movb %cs:(A20Type - base_addr)(%bp), %al /* A20Type */ - call a20_hex - movw %ax, %cs:(A20DbgMsgTryHex - base_addr + 2)(%bp) /* A20Type */ - - leaw (A20DbgMsgTry - base_addr)(%bp), %si /* CS:SI is string */ - call a20_print_string - call assign_base_pointer /* BP points to base_addr */ - movl %cs:(A20_tmp_eax - base_addr)(%bp), %eax - movl %cs:(A20_tmp_ebx - base_addr)(%bp), %ebx - movl %cs:(A20_tmp_ecx - base_addr)(%bp), %ecx - movl %cs:(A20_tmp_edx - base_addr)(%bp), %edx - movl %cs:(A20_tmp_esi - base_addr)(%bp), %esi - movl %cs:(A20_tmp_edi - base_addr)(%bp), %edi - movw %cs:(A20_tmp_ds - base_addr)(%bp), %ds - movw %cs:(A20_tmp_es - base_addr)(%bp), %es - movw %cs:(A20_tmp_fs - base_addr)(%bp), %fs - movw %cs:(A20_tmp_gs - base_addr)(%bp), %gs - //popal - ret - - /************************************************/ - /* print ASCIZ string CS:SI (modifies AX BX SI) */ - /************************************************/ -3: - xorw %bx, %bx /* video page 0 */ - movb $0x0e, %ah /* print char in AL */ - int $0x10 /* via TTY mode */ - -a20_print_string: - - lodsb %cs:(%si), %al /* get token */ - cmpb $0, %al /* end of string? */ - jne 3b - ret - - /****************************************/ - /* convert AL to hex ascii number in AX */ - /****************************************/ - -a20_hex: - movb %al, %ah - shrb $4, %al - andb $0x0F, %ah - orw $0x3030, %ax - - /* least significant digit in AH */ - cmpb $0x39, %ah - jbe 1f - addb $7, %ah -1: - /* most significant digit in AL */ - cmpb $0x39, %al - jbe 1f - addb $7, %al -1: - ret - - ###################################################################### - ## - ## Routine to empty the 8042 KBC controller. Return ZF=0 on failure. - ## - ###################################################################### - -empty_8042: - pushl %ecx - movl $10000, %ecx # 100000 is too big -4: - call delay - - inb $0x64, %al # read 8042 status from port 64h - testb $1, %al # is output buffer(data FROM keyboard) full? - jnz 1f # yes, read it and discard - testb $2, %al # is input buffer(data TO keyboard) empty? - jnz 2f # no, wait until time out - jmp 3f # both input buffer and output buffer are empty - # success and return with ZF=1 -1: - call delay # ZF=0, DELAY should not touch flags!! - inb $0x60, %al # read output buffer and discard input - # data/status from 8042 -2: - ADDR32 loop 4b # ZF=0 - # timed out and failure, return with ZF=0 -3: - popl %ecx - ret - - /* a20 debug message. 25 backspaces to wipe out the previous - * "A20 Debug: XXXX trying..." message. - */ -A20DbgMsgTry: - .ascii "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bA20 Debug: " -A20DbgMsgTryHex: - .string "XXXX trying..." // null terminated - - /* a20 done message. 9 backspaces to wipe out the previous - * "trying..." message. - */ -A20DbgMsgEnd: - .string "\b\b\b\b\b\b\b\b\bdone! " // null terminated - - .align 2 - -A20List: - .word a20_dunno - base_addr - .word a20_none - base_addr - .word a20_bios - base_addr - .word a20_kbc - base_addr - .word a20_fast - base_addr -A20Type: - .word A20_DUNNO // default = unknown -A20Tries: - .word 0 // Times until giving up on A20 - - /* Just in case INT 15 might have destroyed the stack... */ -A20Flags: - .word 0 // save original Flags here -A20ReturnAddress: - .word 0 // save original return address here -A20_tmp_ReturnAddress: - .word 0 // save a20_test return address here - - .align 4 - -A20_old_ebp: .long 0 -A20_old_eax: .long 0 -A20_old_ebx: .long 0 -A20_old_ecx: .long 0 -A20_old_edx: .long 0 -A20_old_esi: .long 0 -A20_old_edi: .long 0 -A20_tmp_ebp: .long 0 -A20_tmp_eax: .long 0 -A20_tmp_ebx: .long 0 -A20_tmp_ecx: .long 0 -A20_tmp_edx: .long 0 -A20_tmp_esi: .long 0 -A20_tmp_edi: .long 0 -A20_tmp_ds: .word 0 -A20_tmp_es: .word 0 -A20_tmp_fs: .word 0 -A20_tmp_gs: .word 0 - - diff --git a/stage2/asm.S b/stage2/asm.S index d0ce5c5c..8d5aa831 100644 --- a/stage2/asm.S +++ b/stage2/asm.S @@ -31,7 +31,7 @@ Aside from that, you can include as many other registers as you like. ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg -{ 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } +{ 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } */ #define ASM_FILE @@ -39,8 +39,18 @@ #include "filesys.h" #include "shared.h" +//#define ABS(x) ((x) - EXT_C(main) + 0x8200) +#define ABS(x) (x) -# define ABS(x) ((x) - EXT_C(main) + 0x8200) +#if defined(__i386__) + #define extent long +#else + #define extent quad +#endif + +#VARIABLE(变量名称) //变量的地址在此 +# .extent 0 +# .extent ABS(EXT_C(变量名称)) //变量的地址不在此处,是一种映射关系 .file "asm.S" @@ -57,43 +67,42 @@ _start: ENTRY(main) - .code16 - + .code64 /* If BP=0x07C0, it indicates boot from pxe or no-emulation cdrom */ /* * Guarantee that "main" is loaded at 0x0:0x8200 in stage2 and * at 0x0:0x2200 in stage1.5. */ - ljmp $0, $ABS(codestart) + + jmp real_codestart - . = EXT_C(main) + 0x5 + . = EXT_C(main) + 0x5 //0x8205 - /* control byte: pxe, DUCE, tune - * bit 0 = 1: disable pxe - * bit 1 = 1: disable keyboard intervention in boot process - * bit 2 = 1: disable the "unconditional command-line entrance" feature - * bit 3 = 1: disable geometry tune - * bit 4 = 1: disable startup cdrom drive look-up. - * bit 5 = 1: enable HLT instruction for checkkey idle loop. + /* control byte: pxe, DUCE, tune //控制字节 + * bit 0 = 1: disable pxe //禁用PXE + * bit 1 = 1: disable keyboard intervention in boot process //禁用键盘干预引导过程中 + * bit 2 = 1: disable the "unconditional command-line entrance" feature //禁用“无条件命令行入口”功能 + * bit 3 = 1: 默认http网起模式(0/1=tftp/http) + * bit 4 = 1: disable startup cdrom drive look-up. //禁止启动光盘驱动器查找。 + * bit 5 = 1: enable HLT instruction for checkkey idle loop. //使能HLT指令,当执行checkkey空闲循环时。 + * bit 6 = 1: enable debug = 3. //启动时进入调试模式 + * bit 7 = 1: 将HTTP文件读取到指定内存 */ .byte 0 - . = EXT_C(main) + 0x6 + . = EXT_C(main) + 0x6 //0x8206 uefi未使用 - .byte COMPAT_VERSION_MAJOR, COMPAT_VERSION_MINOR + .byte 0, 0 - . = EXT_C(main) + 0x8 + . = EXT_C(main) + 0x8 //0x8208 -VARIABLE(install_partition) +VARIABLE(install_partition) //unsigned int 引导分区 0xffff=0分区; 0x3ffff=3分区; 0x0ffffff=整个磁盘 .long 0x00FFFFFF -#define preset_menu 0x307FFC -#define use_preset_menu 0x307FF8 + . = EXT_C(main) + 0xC //0x820c - . = EXT_C(main) + 0xC - -VARIABLE(saved_entryno) +VARIABLE(saved_entryno) //int /* Note: GRUB for DOS uses this for the commandline preset_menu. * A preset_menu can be embedded in the commandline of GRUB.EXE. * This new preset_menu overrides the built-in preset_menu. @@ -105,17099 +114,678 @@ VARIABLE(saved_entryno) * Do NOT change this variable to other value than 0. */ /* Some external utilities use this to locate the preset_menu. */ - .long ABS(preset_menu_old) - //.long preset_menu /* it is now at a fixed address 0x307FFC */ + .long 0 - . = EXT_C(main) + 0x10 + . = EXT_C(main) + 0x10 //0x8210 -VARIABLE(stage2_id) +VARIABLE(stage2_id) //stage2 id 00 .byte STAGE2_ID -VARIABLE(force_lba) - /* only bit 0 is now used for force_lba. */ - /* bit 1=1 means we are booting as a Linux kernel. */ - /* bit 2=0 enable single-key-selection feature. */ - .byte 0x04 +VARIABLE(force_lba) //0x8211 uefi未使用 + .byte 0 -VARIABLE(version_string) - .string VERSION +VARIABLE(version_string) //0x8212 + .string VERSION //0.97\0(hd0,0) -VARIABLE(config_file) - .string "/menu.lst" +VARIABLE(config_file) //0x821e 配置文件 最长72字节 + .string "/efi/grub/menu.lst" - . = EXT_C(main) + 0x34 + . = EXT_C(main) + 0x60 - .word 0x14C /* CPU type for i386 and compatibles */ - .word 1 /* there is 1 section */ - - . = EXT_C(main) + 0x44 - - .word 0x00 /* size of optional header */ - .word 3 /* flags: "no relocation" and "valid executable" */ - .word 0x722E /* section name for resources */ - .word 0x7273 - .word 0x63 - - /* Utilities may use this to locate the bss starting address, - * where the "bootlace" signature is placed and preset-menu - * follows. - */ +VARIABLE(hotkey_func) //int* //0x8260 外置热键功能 + .long 0 + .long 0 - . = EXT_C(main) + 0x6C #; bss starting address + . = EXT_C(main) + 0x68 //0x8268 + +VARIABLE(min_con_mem_start) //0x8268 最低常规内存起始(字节) int + .long 0 +VARIABLE(min_con_mem_size) //0x826c 最低常规内存尺寸(字节) int + .long 0 -preset_menu_old: -#if defined(HAVE_USCORE_USCORE_BSS_START_SYMBOL) - .long __bss_start - 0x300000 -#elif defined(HAVE_USCORE_EDATA_SYMBOL) - .long _edata - 0x300000 -#elif defined(HAVE_EDATA_SYMBOL) - .long edata - 0x300000 + . = EXT_C(main) + 0x70 //0x8270 uefi未使用 + .word 0 + +#if defined(__i386__) + .byte 32 //0x8272 bootia32.efi引导 #else -#error no bss starting address + .byte 64 // bootx64.efi引导 (BIOS是0) #endif - . = EXT_C(main) + 0x70 - -/* the real mode code continues... */ -codestart: - jmp real_codestart - . = EXT_C(main) + 0x73 -VARIABLE(debug_msg) +VARIABLE(debug_msg) //byte .byte 2 /* internal variables follow */ - . = EXT_C(main) + 0x74 -VARIABLE(menu_num_ctrl) - .long 0x2000 - #include "grub4dos_int_ver.h" - #ifdef GRUB4DOS_INT_VER - .long GRUB4DOS_INT_VER - #else - .long 0 - #endif - #undef GRUB4DOS_INT_VER -VARIABLE(hotkey_func) - .long 0 - . = EXT_C(main) + 0x80 + . = EXT_C(main) + 0x74 //0x8274 +VARIABLE(menu_num_ctrl) //unsigned char menu_num_ctrl[4] 4字节 + .long 0x2000 //2000/2001/2d01 位0: 00/01/02=不显示自动菜单/显示自动菜单_引导标题/显示自动菜单_所有标题 + // 位1: 20/2d=自动菜单标号后显示' '/自动菜单标号后显示'-' + // 位2: 返回当前菜单标号 + //由于传统菜单使用"write 0x8274 0x2001",是4字节,改变了0x8276,0x8277的值,所以使用这2字节时,要判断是否有影响. + //0x8276返回当前菜单项号 +#include "grub4dos_int_ver.h" +#ifdef GRUB4DOS_INT_VER + .long GRUB4DOS_INT_VER //0x8278 GRUB4DOS编译的日期十进制数. 2010-12-30日编译的是: 20121230=0x133068e +#else + .long 0 +#endif +#undef GRUB4DOS_INT_VER + +VARIABLE(grub_timeout) //0x827c 倒计时 int + .long -1 + + . = EXT_C(main) + 0x80 //0x8280 -VARIABLE(boot_drive) +VARIABLE(boot_drive) //引导驱动器 int .long 0xFFFFFFFF /* can be setup by external programs. */ -VARIABLE(pxe_yip) +//VARIABLE(use_config_file) //int uefi未使用 .long 0 -VARIABLE(pxe_sip) + +//VARIABLE(configfile_opened) //int uefi未使用 .long 0 -VARIABLE(pxe_gip) + +VARIABLE(saved_pxe_ip) //int .long 0 - . = EXT_C(main) + 0x90 + . = EXT_C(main) + 0x90 //0x8290 -VARIABLE(filesize) +VARIABLE(filesize) //文件尺寸 long long .long 0, 0 -VARIABLE(saved_mem_upper) /* maximum contiguous memory in KB starting at 1M and below 4G */ +VARIABLE(use_preset_menu) //0x8298 使用预置菜单 int 原0x307FF8 .long 0 -VARIABLE(saved_partition) +VARIABLE(saved_partition) //0x829c int 根分区 .long 0 - . = EXT_C(main) + 0xA0 + . = EXT_C(main) + 0xA0 //0x82a0 -VARIABLE(saved_drive) +VARIABLE(saved_drive) //根驱动器 int .long 0 -VARIABLE(no_decompression) +VARIABLE(no_decompression) //0x82a4 int 不解压缩 0/1=开启/关闭压缩文件支持 .long 0 -VARIABLE(part_start) +VARIABLE(part_start) //0x82a8 分区开始 long long .long 0, 0 - . = EXT_C(main) + 0xB0 + . = EXT_C(main) + 0xB0 //0x82b0 -VARIABLE(part_length) +VARIABLE(part_length) //分区长度 long long .long 0, 0 -VARIABLE(fb_status) +VARIABLE(fb_status) //0x82b8 FB状态 int .long 0 -VARIABLE(is64bit) +VARIABLE(is64bit) //0x82bc 64位支持 int .long 0 - . = EXT_C(main) + 0xC0 - -VARIABLE(saved_mem_higher) /* maximum contiguous memory in KB starting at 4G */ - .long 0, 0 + . = EXT_C(main) + 0xC0 //0x82c0 + +VARIABLE(linux_text_len) //int + .long 0 -VARIABLE(cdrom_drive) - .long 0xFFFFFFFF /* default is the invalid drive number */ +VARIABLE(cursor_state) //0x82c4 鼠标状态 int + .long 0 //bit 0=1 show cursor,bit 1=1 show splashimage 位0=1显示光标,位1=1显示图像 + +VARIABLE(menu_cfg) //0x82c8(原0x8308) char menu_cfg[2] 2字节, 实际占用4字节 + .long 0x1110 -VARIABLE(ram_drive) +VARIABLE(ram_drive) //0x82cc RAM驱动器 int .long 0x7F /* default is a floppy */ - . = EXT_C(main) + 0xD0 - -VARIABLE(rd_base) - .long 0, 0 - -VARIABLE(rd_size) - .long 0, 1 /* default is 4G */ + . = EXT_C(main) + 0xD0 //0x82d0 - . = EXT_C(main) + 0xE0 +VARIABLE(rd_base) //RD基地址 long long + .long 0x10000, 0 - /* mem alloc array structure +VARIABLE(rd_size) //0x82d8 RD尺寸 long long + .long 0x80000, 0 /* default is 4G */ - long // mem block starting address(16 byte align) - // bit0=0 for free mem, 1 for used mem - // bit 2:1 =0 for program code - // =1 for environment - // =2 for extra data - // =3 reserved - // bit 3=reserved - long // process id. - // 0 - 255 for kernel, others for user program - */ -VARIABLE(mem_alloc_array_start) - .long 0x800000 /* at 8M */ + . = EXT_C(main) + 0xE0 //0x82e0 -VARIABLE(mem_alloc_array_end) - .long 0xA00000 /* at 10M */ +VARIABLE(return_value) //int 返回值 + .long 0 -VARIABLE(page_map_start) - .long 0xA00000 /* at 10M */ +//VARIABLE(QUOTE_CHAR) //int uefi未使用 + .long 0 -VARIABLE(page_map_end) - .long 0xE00000 /* at 14M */ +VARIABLE(linux_bzimage_tmp_addr) //char * + .long LINUX_TMP_MEMORY + .long 0 + . = EXT_C(main) + 0xF0 //0x82f0 - . = EXT_C(main) + 0xF0 +VARIABLE(linux_data_tmp_addr) //char * + .long 0, 0 -VARIABLE(free_mem_start) /* unused mem starting address. */ - .long SYSTEM_RESERVED_MEMORY /* may increase later. */ +VARIABLE(linux_data_real_addr) //char * + .long 0, 0 -VARIABLE(free_mem_end) /* unused mem ending address */ - .long 0 /* 0 for 4G(i.e., unlimited) */ + . = EXT_C(main) + 0x100 //0x8300 + +VARIABLE(addr_system_functions) //0x8300 系统功能地址 + .extent ABS(EXT_C(system_functions)) -VARIABLE(saved_mmap_addr) /* system memory map starting addess */ - .long ABS(EXT_C(end_of_low_16bit_code)) +#if defined(__i386__) + .long 0 //使变量指针始终为0x8308 +#endif -VARIABLE(saved_mmap_length) /* system memory map length */ +VARIABLE(addr_system_variables) //0x8308 系统变量地址(原0x8304) + .extent ABS(EXT_C(system_variables)) +#if defined(__i386__) .long 0 - - . = EXT_C(main) + 0x100 - -VARIABLE(addr_system_functions) - .long ABS(EXT_C(system_functions)) - -VARIABLE(addr_system_variables) - .long ABS(EXT_C(system_variables)) -VARIABLE(menu_cfg) /*char menu_cfg[]*/ - .long 0x1110 -VARIABLE(iso_types)/*char iso_types*/ +#endif + + . = EXT_C(main) + 0x110 //0x8310 + +VARIABLE(iso_types) //byte 原0x830c .byte 0xff - . = EXT_C(main) + 0x110 -VARIABLE(addr_saved_dir) - .long ABS(EXT_C(saved_dir)) +VARIABLE(menu_tab) //0x8311 菜单标签 byte + .byte 0 +/* +位2: 0/1=显示按键帮助/不显示按键帮助 04 +位3: 0/1=侧边对齐/中心对齐 08 +位4: 0/1=高亮项目背景短/满 10 +位5: 0/1=英文/中文 20 +位6: 0/1=左对齐/右对齐 40 +位7: 0/1=打印版本信息/不打印版本信息 80 +*/ + +VARIABLE(menu_tab_ext) //0x8312 菜单标签 byte + .byte 0 +/* +位0: 1=已在图形模式 01 +位1: 1=已加载背景图像 02 +位2: 1=已加载字库 04 +*/ + + .byte 0 //0x8313 未使用 -VARIABLE(errnum) +VARIABLE(errnum) //0x8314 错误号 grub_error_t 64位是8字节? .long 0 -VARIABLE(current_drive) +VARIABLE(current_drive) //0x8318 当前驱动器 int .long 0xFFFFFFFF -VARIABLE(current_partition) +VARIABLE(current_partition) //0x831c 当前分区 int .long 0 - . = EXT_C(main) + 0x120 + . = EXT_C(main) + 0x120 //0x8320 -VARIABLE(filemax) +VARIABLE(filemax) //文件最大 long long .long 0, 0 -VARIABLE(filepos) +VARIABLE(filepos) //0x8328 文件指针 long long .long 0, 0 - . = EXT_C(main) + 0x130 + . = EXT_C(main) + 0x130 //0x8330 -VARIABLE(debug) - /* 0 for silent, 1 for normal, 2..MAX_UINT for verbose. - * if debug == MAX_UINT or debug < 0, then filesystem debug mode is on. +VARIABLE(debug) //调试 int + /* 0 for silent, 1 for normal, 2..MAX_UINT for verbose. //0=沉默,1=正常,2=冗长MAX_UINT。 MAX_UINT 是 0x7FFFFFFF + * if debug == MAX_UINT or debug < 0, then filesystem debug mode is on. //如果调试=MAX_UINT或调试<0,那么文件系统调试模式开。 * (MAX_UINT is 0x7FFFFFFF) */ - .long 0 - -VARIABLE(current_slice) - .long 0 - -VARIABLE(dos_drive_geometry) - # byte 0=DOS boot drive: 0 for floppy, 0x80 for harddrive. - # byte 1=max head number for DOS boot drive=(number of heads - 1). - # byte 2=sectors per track for DOS boot drive. - # byte 3=0(reserved). - .long 0 + .long 1 -VARIABLE(dos_part_start) - # partition start sector number(or hidden sectors) for DOS boot drive. +VARIABLE(current_slice) //0x8334 当前片 int .long 0 + +VARIABLE(saved_pxe_mac) //0x8338 unsigned char saved_pxe_mac[6]; + .byte 0, 0, 0, 0, 0, 0 + + .byte 0, 0 //未使用 - . = EXT_C(main) + 0x140 + . = EXT_C(main) + 0x140 //0x8340 -VARIABLE(buf_track) +VARIABLE(buf_track) //缓存跟踪 long long .long -1 - .long 0 /* buf_track will grow to 64-bit */ -VARIABLE(buf_drive) + .long 0 +VARIABLE(buf_drive) //缓存驱动器 int .long -1 - .long 0 /* padding */ +VARIABLE(current_x_resolution) //0x834c 当前水平像素 int + .long 0 - . = EXT_C(main) + 0x150 - -VARIABLE(usb_count_error) //bit 7: 0 = usb_count; 1 = usb_error - .byte 0 -VARIABLE(usb_drive_num) - .byte 0,0,0,0 -VARIABLE(usb_md_address) - .word 0 -VARIABLE(count_ms) - .word 0 -VARIABLE(beep_frequency) - .word 0 - - . = EXT_C(main) + 0x160 + . = EXT_C(main) + 0x150 //0x8350 + +VARIABLE(ext_timer) //0x8350 外部定时器 int* + .long 0 + .long 0 + .long 0 //未使用 + .long 0 //未使用 -real_codestart: - - cli - cld - - xorw %ax, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %ss - movl $STACKOFF, %esp - - sti /* added 2008-08-04 */ - - /* save DX at 0x8206, overwriting the unused version numbers. */ - movw %dx, ABS(EXT_C(install_partition)) - 2 - - # it is time to do this after DX has been saved. - pushal - movw $0x0003, %ax /* set display mode: 80*25 color text */ - int $0x10 # this might destroy our DX - popal - - /* check for fb structure */ - cmpl $0x46424246, (0x21b4) - jnz 1f - movw %ax, (0x21b4) //destroy it to prevent repeated fb recognition - movl (0x21ae), %eax - movb (0x21ad), %al - movl %eax, ABS(EXT_C(fb_status)) - cmpb $0,%ah - jnz 1f - /* it is the floppy (fd0) */ - testb $0x01,0x0410 - jnz 1f - /* no floppy in BDA, so we set floppy count to 1. */ - orb $0x01,0x0410 /* diskette set as present */ - andb $0x3F,0x0410 /* clear bit 6-7 */ - -// movb $(FB_DRIVE),%dl -1: - movb 0x0410, %al - movb %al, ABS(EXT_C(floppies_orig)) - movb 0x0475, %al - movb %al, ABS(EXT_C(harddrives_orig)) - - //movb $((int13_handler_end - int13_handler + 0x3ff) / 0x400), ABS(int13_handler) - - movb $1, %cl // CX != 0, indicating our int13 handler not present + . = EXT_C(main) + 0x160 //0x8360 - movl 0x54, %eax - movl %eax, ABS(EXT_C(ROM_int15)) - movl 0x4C, %eax - movl %eax, ABS(EXT_C(ROM_int13)) - movl %eax, ABS(EXT_C(ROM_int13_dup)) - cmpl $0xC0000000, %eax - jnb 1f - cmpl $0x5A000000, %eax // cmpl $0x9A000000, %eax - jb 1f - andl $0x3FFFFF, %eax -// cmpl $0x100, %eax - cmpl $(int13_handler_entry - int13_handler), %eax - jnz 1f - movw 0x413, %ax /* Memory size in Kb */ - shlw $6, %ax /* Memory size in paragragh */ - cmpw 0x4E, %ax /* 0000:004E=current int 13 segment */ - jne 1f /* not hooked */ - - movw %ax, %ds /* DS=current int13 code segment */ - - /* check our int13 signature "$INT13SFGRUB4DOS" */ -// cmpl $0x544E4924, 0x103 /* $INT */ - cmpl $0x544E4924, (int13_handler_entry - int13_handler + 3) /* $INT */ - jnz 2f -// cmpl $0x46533331, 0x107 /* 13SF */ - cmpl $0x46533331, (int13_handler_entry - int13_handler + 7) /* 13SF */ - jnz 2f -// cmpl $0x42555247, 0x10B /* GRUB */ - cmpl $0x42555247, (int13_handler_entry - int13_handler + 0xb) /* GRUB */ - jnz 2f -// cmpl $0x534F4434, 0x10F /* 4DOS */ - cmpl $0x534F4434, (int13_handler_entry - int13_handler + 0xf) /* 4DOS */ - jnz 2f - - movl (EXT_C(ROM_int13) - int13_handler), %eax /* 0x1C=ROM int 13 */ - cmpl $0x5A000000, %eax // cmpl $0x9A000000, %eax - jb 2f /* not our handler */ - - movl (EXT_C(ROM_int15) - int13_handler), %eax /* 0x0C=ROM int 15 */ - cmpl $0x5A000000, %eax // cmpl $0x9A000000, %eax - jb 2f /* not our handler */ +VARIABLE(disk_data) //磁盘数据指针 grub_disk_data * + .long 0, 0 - /* restore old emu data, except the first byte of handler size. */ -// movw $(0x140 - 1), %cx - mov $(restore_old_emu - int13_handler - 1), %cx - movw $1, %si /* DS=current int13 code segment */ - movw $ABS(int13_handler + 1), %di /* ES=0 */ - repz movsb -#ifdef CDROM_INIT - /* calculate the new max_cdrom_id. */ - movw $2, %si - lodsw /* AL=atapi_dev_count, AH=min_cdrom_id */ - addb %ah, %al - decw %ax /* AL=max_cdrom_id */ - movb %al, %cs:ABS(max_cdrom_id) /* CS=0 */ -#endif - /* initialize bios_drive_map with hooked_drive_map_1 */ -#if MAP_NUM_16 - movw $(DRIVE_MAP_SIZE * DRIVE_MAP_SLOT_SIZE / 4), %cx - movw $ABS(EXT_C(hooked_drive_map_1)), %si /* CS=0 */ -#else - movw $(DRIVE_MAP_SIZE * DRIVE_MAP_SLOT_SIZE / 2), %cx - movw $ABS(EXT_C(hooked_drive_map)), %si /* CS=0 */ -#endif - movw $ABS(EXT_C(bios_drive_map)), %di /* ES=0 */ - cs repz movsw +VARIABLE(partition_info) //0x8368 分区信息指针 grub_part_data * + .long 0, 0 - movw $(0x3000 - 0x2800)/8, %cx - movw $0x2800, %si -3: - cmpl $0x47415246, (%si) /* FRAGMENT */ - je 3f - addw $8, %si - loop 3b - jmp 2f -3: - cmpl $16, 0xfc //16 FRAGMENT - jne 3f - -#if MAP_NUM_16 - pushw %si - // BIOS-hooked_drive_map_2 -> G4D-hooked_drive_map_2 - movw $(DRIVE_MAP_SIZE * DRIVE_MAP_SLOT_SIZE / 4), %cx - pushw %cx - subw $((DRIVE_MAP_SIZE / 2 + 1) * DRIVE_MAP_SLOT_SIZE), %si - pushw %si - movw $ABS(EXT_C(hooked_drive_map_2)), %di /* ES=0 */ - repz movsw - //BIOS_hooked_drive_map_2 -> G4D-bios_drive_map_8 - popw %si - popw %cx - movw $ABS(EXT_C(bios_drive_map) + ((DRIVE_MAP_SIZE / 2) * DRIVE_MAP_SLOT_SIZE)), %di /* ES=0 */ - repz movsw - popw %si -#endif -3: - addw $8, %si - movw $ABS(EXT_C(hooked_fragment_map)), %di - movw $FRAGMENT_MAP_SLOT_SIZE/2, %cx - repz movsw - - /* Now CX = 0, indicating our int13 handler is present. */ -2: - xorw %ax, %ax - movw %ax, %ds /* DS=0 */ -1: - jcxz 1f /* our int13 handler is present, skip */ - /* clear highest 2 bits of byte at 0x410. */ - andb $0x3F, 0x0410 /* clear bit 6-7 */ - cmpw $0x07C0, %bp /* boot from pxe or cdrom? */ - je 3f /* yes, directly mask off floppy. */ - /* check fbinst boot */ - movl ABS(EXT_C(fb_status)), %ecx - jecxz 2f /* did not boot by fbinst, continue */ - cmpb $0, %ch /* fbinst boot drive is floppy? */ - jz 1f /* yes, skip */ -2: - /* check DOS boot of grub.exe */ - movl ABS(EXT_C(dos_drive_geometry)), %ecx - jecxz 2f /* did not boot off DOS, continue */ - cmpb $0, %cl /* DOS boot drive is floppy? */ - jz 1f /* yes, skip */ -2: - /* check saved DX register */ - movw ABS(EXT_C(install_partition)) - 2, %cx - cmpb $0, %cl /* BIOS boot drive is floppy? */ - jz 1f /* yes, skip */ -3: - /* did not boot from floppy. clear lowest bit of byte at 0x410. */ - andb $0xFE, 0x0410 /* clear bit 0 */ -1: - /* check the BIOS type (currently only for Bochs) */ - movw $0xF000, %ax - movw %ax, %es /* ES=0xF000 */ - movw $0xFF00, %di - movw $ABS(bochs_copygrght_string), %si - movw $0x22, %cx - repz cmpsw - setz ABS(EXT_C(bios_id)) /* 1 for bochs, 0 for unknown. */ - xorw %ax, %ax - movw %ax, %es /* ES=0 */ - -// pushw %dx /* DL=boot drive */ - - xorw %ax, %ax - movw %ax, %ds - movw %ax, %es - - sti - - /* check the DUCE indicator */ + . = EXT_C(main) + 0x170 //0x8370 - movl 0x5FC, %eax - movl %eax, %ecx - testb $0x0C, %al - jz 1f - orb $0x0C, %al - cmpl $0x4543554C, %eax - jne 1f - andb $0x0C, %cl /* bit2=DUCE, bit3=chs-no-tune */ - orb %cl, ABS(EXT_C(main)) + 5 /* at 0x8205 */ -1: - movw $1, %bx /* BL=1, BH=0 */ - - testb $0x02, ABS(EXT_C(main)) + 5 /* disable keyboard intervention? */ - jnz 4f /* yes */ - - movl 0x46c, %eax /* initial tick */ - addl $5, %eax /* wait 0.27 seconds */ - pushl %eax - -2: - /* checkkey 'c' */ - - pushw %bx - movb $0x01, %ah /* checkkey */ - int $0x16 - popw %bx - - jz 1f /* no keypress */ - - /* getkey */ - - pushw %bx - movb $0x00, %ah /* getkey */ - int $0x16 - popw %bx - - cmpw $KEY_IC, %ax /* insert char */ - jne 3f - orb $1, %bh /* DEBUG_KEY pressed */ - jmp 2b /* get next key */ -3: - orb $0x20, %al - cmpb $0x73, %al /* is "S"? */ - jne 3f - orb $2, %bh /* Single Sector for Buggy BIOS */ -3: - cmpb $0x63, %al /* is "C"? */ - jne 2b /* no, get next key */ - - /* "C" is pressed. */ - - testb $0x04, ABS(EXT_C(main)) + 5 /* at 0x8205, bit2=DUCE */ - jnz 2b - - /* Bypass all config files */ - movb $0, %bl - jmp 2b -1: - - popl %eax - pushl %eax - movl 0x46c, %ecx /* current tick */ - cmpl %eax, %ecx - jnb 1f - subl $5, %eax - cmpl %eax, %ecx - jnb 2b - cmpl $5, %ecx - jb 2b -1: - popl %eax -4: - movb %bh, ABS(EXT_C(debug_boot)) - - testb %bl, %bl - jnz 1f - movl $0, ABS(EXT_C(use_config_file)) -1: -// popw %dx /* DL=boot drive */ - -// movzbl %dl, %eax -// movl %eax, ABS(EXT_C(boot_drive)) - - xorw %ax, %ax - movw %ax, %ds - movw %ax, %es - - testb $0x02, ABS(EXT_C(main)) + 5 /* disable keyboard intervention? */ - jnz 4f /* yes */ - - //pushw %bx - - /* clear keyboard buffer */ -2: - movb $0x01, %ah /* checkkey */ - int $0x16 - - jz 1f /* no keypress */ - - movb $0x00, %ah /* getkey */ - int $0x16 - jmp 2b -1: - - //popw %bx - -4: +VARIABLE(floppies_orig) //软盘数 byte + .byte 0 +VARIABLE(harddrives_orig) //硬盘数 byte + .byte 0 +VARIABLE(cdrom_orig) //光盘数 byte + .byte 0 - /* Oops! I forgot to enable A20. Thanks to zw2312914. */ + .byte 0 //未使用 + .long 0 //未使用 + +VARIABLE(g4e_data) //0x8378 固定数据区 char * + .long 0, 0 - movw $0x00ff, %cx # try so many times on failure - movw $0x0101, %dx # DL=1(enable A20), DH=1(debug on) - - cli /* yes, keep interrupt off when controlling A20 */ - call enable_disable_a20 # EAX, CX modified - sti - - jz 1f /* enabled A20 with success */ + . = EXT_C(main) + 0x180 //0x8380 + +VARIABLE(preset_menu) //0x8380 预置菜单 char * 原0x307FFC + .long 0, 0 - /* A20 control failed. Notify the user. */ - pushw $ABS(bootup_a20_failure) # the format string - call realmode_printf - //addw $2, %sp # adjust the stack pointer, but not required for now. - jmp hard_stop +VARIABLE(menu_mem) //0x8388 菜单 char * + .long 0, 0 -bootup_a20_failure: - .ascii "\r\ngrub4dos: A20 failure. Please report with error code(if any in the above line).\r\n\0" + . = EXT_C(main) + 0x190 //0x8390 -1: - movw %ds:0x046c, %dx - xorl %ecx, %ecx -1: - movw %ds:0x046c, %ax - cmpw %dx, %ax - je 1b -1: - cmpw %ds:0x046c, %ax - jne 2f - pushw %dx - pushw %ax - movw $0xcf8, %dx - inw %dx, %ax - popw %ax - popw %dx - incl %ecx - cmpl $0, %ecx - jmp 1b -2: - xorl %edx, %edx - movl %ecx, %eax - movl $0x37, %ecx - divl %ecx - movw %ax, ABS(EXT_C(count_ms)) +VARIABLE(efi_pxe_buf) //char * 2023-11-24 + .long 0, 0 + .long 0 + .long 0 + .long 0 + .long 0 + + . = EXT_C(main) + 0x200 //0x8400 以上预留 - xorb %bh, %bh - movb $0, %bl - movw $0x1003, %ax - int $0x10 +//ENTRY(disk_fragment_map) .space FRAGMENT_MAP_SLOT_SIZE //映射碎片插槽 800 +VARIABLE(disk_fragment_map) //映射碎片插槽 char * + .long 0, 0 +// . = EXT_C(main) + 0xa00 //0x8c00 + +//ENTRY(disk_drive_map) .space [DRIVE_MAP_SIZE + 1] * DRIVE_MAP_SLOT_SIZE //磁盘驱动器映射插槽 70*9=3c0 - /* transition to protected mode */ - call EXT_C(real_to_prot) +real_codestart: + .align 8 +#if defined(__i386__) +//kern/i386/efi/startup.S .code32 - /* enable preset_menu */ - movl $1, use_preset_menu - - /* if force_cdrom_as_boot_device==0, we are running by configfile, so we skip preset menu check */ - cmpl $0, ABS(EXT_C(force_cdrom_as_boot_device)) - je 1f /* skip all */ - - /* before clearing the bss, we move preset_menu to 0x800 */ - -#if 0 - movl preset_menu, %eax - -#if defined(HAVE_USCORE_USCORE_BSS_START_SYMBOL) - cmpl $__bss_start - 0x300000, %eax -#elif defined(HAVE_USCORE_EDATA_SYMBOL) - cmpl $_edata - 0x300000, %eax -#elif defined(HAVE_EDATA_SYMBOL) - cmpl $edata - 0x300000, %eax -#else -#error no bss starting address -#endif - jnz 4f /* use old bootp for diskless */ -#endif - - xorl %eax, %eax - cmpb %al, ABS(EXT_C(config_file)) /* AL == 0 */ - jnz 2f - movl ABS(EXT_C(saved_entryno)), %ebx - testl %ebx, %ebx - jnz 3f /* use menu embedded in commnad-line of grub.exe */ -2: - /* use builtin preset_menu */ - - /* set the starting address of the preset_menu */ - -#if defined(HAVE_USCORE_USCORE_BSS_START_SYMBOL) - movl $__bss_start - 0x300000, %esi -#elif defined(HAVE_USCORE_EDATA_SYMBOL) - movl $_edata - 0x300000, %esi -#elif defined(HAVE_EDATA_SYMBOL) - movl $edata - 0x300000, %esi + movl 4(%esp), %eax + movl %eax, EXT_C(grub_efi_image_handle) + movl 8(%esp), %eax + movl %eax, EXT_C(grub_efi_system_table) + call EXT_C(grub_init) + #else -#error no bss starting address -#endif - - cld - addl $16, %esi /* skip 4 bytes of B0 02 1A CE */ - /* skip 4 bytes of reserved */ - /* skip 4 bytes of reserved */ - /* skip 4 bytes of zeroes */ - /* check LZMA */ - cmpb $0xE0, (%esi) - ja 5f /* not lzma */ - movl 1(%esi), %ecx - jecxz 5f /* not lzma */ - cmpl $0x1000, %ecx - jb 5f /* unaccepted lzma */ - movl $0x80000000, %eax - xorl %edx, %edx /* dividend=EDX:EAX */ - divl %ecx /* divisor=ECX */ - /* result: EAX=quotient, EDX=remainder */ - testl %edx, %edx - jnz 5f /* unaccepted lzma */ - cmpl %edx, 9(%esi) /* EDX=0 */ - jnz 5f /* unaccepted lzma */ - /* now it is LZMA */ - movl $0x10000, %ecx /* move 256KB of the menu ... */ - movl $0x110000, %edi /* ... to address 1M+64K */ - repz movsl - movl $0x110000, preset_menu /* use new menu at 1M+64K */ - jmp 4f -5: - movl $0x400, %ecx /* move 4KB of the menu ... */ - movl $0x800, %edi /* ... to 0x800 */ - repz movsl - -3: - movl $0x0800, preset_menu /* use new menu at 0x800 */ -4: - -// /* if force_cdrom_as_boot_device==0, we are running by configfile, so we do not clear bss */ -// cmpl $0, ABS(EXT_C(force_cdrom_as_boot_device)) -// je 1f +//------------------------------------------------------------------ +//kern/x86_64/efi/startup.S + .code64 + movq %rcx, EXT_C(grub_efi_image_handle)(%rip) //映像处理 + movq %rdx, EXT_C(grub_efi_system_table)(%rip) //系统表 + + andq $~0xf, %rsp + call EXT_C(grub_init) + // Doesn't return. +//----------------------------------------------------------------------- +//kern/x86_64/efi/callwrap.S +ENTRY(efi_wrap_0) + subq $40, %rsp + call *%rdi + addq $40, %rsp + ret + +ENTRY(efi_wrap_1) + subq $40, %rsp + mov %rsi, %rcx + call *%rdi + addq $40, %rsp + ret + +ENTRY(efi_wrap_2) + subq $40, %rsp + mov %rsi, %rcx + call *%rdi + addq $40, %rsp + ret + +ENTRY(efi_wrap_3) + subq $40, %rsp + mov %rcx, %r8 + mov %rsi, %rcx + call *%rdi + addq $40, %rsp + ret + +ENTRY(efi_wrap_4) + subq $40, %rsp + mov %r8, %r9 + mov %rcx, %r8 + mov %rsi, %rcx + call *%rdi + addq $40, %rsp + ret + +ENTRY(efi_wrap_5) + subq $40, %rsp + mov %r9, 32(%rsp) + mov %r8, %r9 + mov %rcx, %r8 + mov %rsi, %rcx + call *%rdi + addq $40, %rsp + ret + +ENTRY(efi_wrap_6) + subq $56, %rsp + mov 56+8(%rsp), %rax + mov %rax, 40(%rsp) + mov %r9, 32(%rsp) + mov %r8, %r9 + mov %rcx, %r8 + mov %rsi, %rcx + call *%rdi + addq $56, %rsp + ret + +ENTRY(efi_wrap_7) + subq $88, %rsp + mov 88+16(%rsp), %rax + mov %rax, 48(%rsp) + mov 88+8(%rsp), %rax + mov %rax, 40(%rsp) + mov %r9, 32(%rsp) + mov %r8, %r9 + mov %rcx, %r8 + mov %rsi, %rcx + call *%rdi + addq $88, %rsp + ret + +ENTRY(efi_wrap_10) + subq $88, %rsp + mov 88+40(%rsp), %rax + mov %rax, 72(%rsp) + mov 88+32(%rsp), %rax + mov %rax, 64(%rsp) + mov 88+24(%rsp), %rax + mov %rax, 56(%rsp) + mov 88+16(%rsp), %rax + mov %rax, 48(%rsp) + mov 88+8(%rsp), %rax + mov %rax, 40(%rsp) + mov %r9, 32(%rsp) + mov %r8, %r9 + mov %rcx, %r8 + mov %rsi, %rcx + call *%rdi + addq $88, %rsp + ret +#endif +//--------------------------------------------------------------------------------------- + .code64 + .align 8 +//VARIABLE(pxenv) //ipxe +VARIABLE(pxe_tftp_open) //PXENV_TFTP_OPEN_t + .word 0 # Status 状态 + .long 0 # ServerIPAddress 服务器IP地址 + .long 0 # GatewayIPAddress 网关IP地址 + .space 128 # FileName[128]; 文件名 + .word 0 # TFTPPort TFTP端口 + .word 0 # PacketSize 包尺寸 +/* +//boot.c + .align 8 +VARIABLE(mbi) //multiboot_info + .space (22 * 4) +*/ - /* before clearing bss, move 32-bit code to above 3M. */ - /* This need A20 to be enabled. */ +/****************************************************************************/ +/************************* 32-bit functions follow **************************/ +/****************************************************************************/ - movl $ABS(EXT_C(end_of_low_16bit_code)), %esi - leal 0x300000(%esi), %edi +// .space 0x300000 /* !!!! insert 3M !!!! */ -#if defined(HAVE_USCORE_USCORE_BSS_START_SYMBOL) - movl $__bss_start, %ecx -#elif defined(HAVE_USCORE_EDATA_SYMBOL) - movl $_edata, %ecx -#elif defined(HAVE_EDATA_SYMBOL) - movl $edata, %ecx -#else -#error no bss starting address -#endif - subl %edi, %ecx - shrl $2, %ecx - cld - repz movsl +/* get_code_end() : return the address of the end of the code + * This is here so that it can be replaced by asmstub.c. + */ - /* clean out the bss */ +/* + * The C code for a grub4dos executable may have defines as follows: + * -// /* set %edi to the bss starting address */ -//#if defined(HAVE_USCORE_USCORE_BSS_START_SYMBOL) -// movl $__bss_start, %edi -//#elif defined(HAVE_USCORE_EDATA_SYMBOL) -// movl $_edata, %edi -//#elif defined(HAVE_EDATA_SYMBOL) -// movl $edata, %edi -//#else -//#error no bss starting address -//#endif +#define sprintf ((int (*)(char *, const char *, ...))((*(int **)0x8300)[0])) +#define printf(...) sprintf(NULL, __VA_ARGS__) +#define putstr ((void (*)(const char *))((*(int **)0x8300)[1])) +#define putchar ((void (*)(int))((*(int **)0x8300)[2])) +#define get_cmdline ((int (*)(char *))((*(int **)0x8300)[3])) +#define getxy ((int (*)(void))((*(int **)0x8300)[4])) +#define gotoxy ((void (*)(int, int))((*(int **)0x8300)[5])) +#define cls ((void (*)(void))((*(int **)0x8300)[6])) +#define setcursor ((int (*)(int))((*(int **)0x8300)[7])) +#define nul_terminate ((int (*)(char *))((*(int **)0x8300)[8])) +#define safe_parse_maxint ((int (*)(char **, unsigned long long *))((*(int **)0x8300)[9])) +#define substring ((int (*)(const char *, const char *, int))((*(int **)0x8300)[10])) +#define strstr ((char *(*)(const char *, const char *))((*(int **)0x8300)[11])) +#define strlen ((int (*)(const char *))((*(int **)0x8300)[12])) +#define strtok ((char *(*)(char *, const char *))((*(int **)0x8300)[13])) +#define strncat ((int (*)(char *, const char *, int))((*(int **)0x8300)[14])) +#define strcmp ((int (*)(const char *, const char *))((*(int **)0x8300)[15])) +#define strcpy ((char *(*)(char *, const char *))((*(int **)0x8300)[16])) +#define tolower ((int (*)(int))((*(int **)0x8300)[17])) +#define isspace ((int (*)(int))((*(int **)0x8300)[18])) +#define getkey ((int (*)(void))((*(int **)0x8300)[19])) +#define checkkey ((int (*)(void))((*(int **)0x8300)[20])) +#define sleep ((unsigned int (*)(unsigned int))((*(int **)0x8300)[21])) +#define memcmp ((int (*)(const char *, const char *, int))((*(int **)0x8300)[22])) +#define memmove ((void *(*)(void *, const void *, int))((*(int **)0x8300)[23])) +#define memset ((void *(*)(void *, int, int))((*(int **)0x8300)[24])) +//#define mem64 ((int (*)(int, unsigned long long, unsigned long long, unsigned long long))((*(int **)0x8300)[74])) +#define open ((int (*)(char *))((*(int **)0x8300)[26])) +#define read ((unsigned long (*)(unsigned long long, unsigned long long, unsigned long))((*(int **)0x8300)[27])) +#define close ((void (*)(void))((*(int **)0x8300)[28])) +#define grub_memalign ((void * (*)(grub_size_t, grub_size_t))((*(int **)0x8300)[48])) +#define grub_zalloc ((void *(*)(unsigned long))((*(int **)0x8300)[49])) +#define grub_malloc ((void *(*)(unsigned long))((*(int **)0x8300)[50])) - /* set %ecx to the bss end */ -#if defined(HAVE_END_SYMBOL) - movl $end, %ecx -#elif defined(HAVE_USCORE_END_SYMBOL) - movl $_end, %ecx +http://grubutils.googlecode.com/svn/trunk/src/include/grub4dos.h + * + */ + +//i386 32位系统编译在此处可以使用 long, 但是不能使用 quad,为了简化批处理, 统一使用 extent. +VARIABLE(system_functions) //IMG(0x8300) + .extent ABS(EXT_C(grub_sprintf)) //0 + .extent ABS(EXT_C(grub_putstr)) //1 +//VARIABLE(grub_putchar) +// .extent ABS(EXT_C(_putchar)) + .extent ABS(EXT_C(grub_putchar)) //2 + .extent ABS(EXT_C(get_cmdline_obsolete)) //3 + .extent ABS(EXT_C(getxy)) //4 + .extent ABS(EXT_C(gotoxy)) //5 + .extent ABS(EXT_C(cls)) //6 + .extent ABS(EXT_C(wee_skip_to)) //7 was obsolete setcursor + .extent ABS(EXT_C(nul_terminate)) //8 + .extent ABS(EXT_C(safe_parse_maxint_with_suffix)) //9 + .extent ABS(EXT_C(substring)) //10 + .extent ABS(EXT_C(grub_strstr)) //11 + .extent ABS(EXT_C(grub_strlen)) //12 + .extent ABS(EXT_C(grub_strtok)) //13 + .extent ABS(EXT_C(grub_strncat)) //14 + .extent ABS(EXT_C(grub_strcmp)) //15 + .extent ABS(EXT_C(grub_strcpy)) //16 + .extent ABS(EXT_C(grub_efidisk_readwrite)) //17 + .extent ABS(EXT_C(blockio_read_write)) //18 + .extent ABS(EXT_C(getkey)) //19 + .extent ABS(EXT_C(checkkey)) //20 + .extent 0 //21 原ABS(EXT_C(pxe_call)) 现在未使用 + .extent ABS(EXT_C(grub_memcmp)) //22 + .extent ABS(EXT_C(grub_memmove)) //23 + .extent ABS(EXT_C(grub_memset)) //24 + .extent ABS(EXT_C(get_partition_info)) //25 grub_part_data * + .extent ABS(EXT_C(grub_open)) //26 + .extent ABS(EXT_C(grub_read)) //27 + .extent ABS(EXT_C(grub_close)) //28 + .extent ABS(EXT_C(get_device_by_drive)) //29 grub_disk_data * + .extent ABS(EXT_C(tftp_write)) //30 int + VARIABLE(disk_read_hook) + .extent 0 //31 + .extent ABS(EXT_C(devread)) //32 + .extent 0 //33 原ABS(EXT_C(devwrite)) 现在未使用 + .extent ABS(EXT_C(next_partition)) //34 + .extent ABS(EXT_C(open_device)) //35 + .extent ABS(EXT_C(real_open_partition)) //36 + .extent ABS(EXT_C(set_device)) //37 + .extent ABS(EXT_C(run_line)) //38 int + .extent ABS(EXT_C(vdisk_install)) //39 grub_efi_status_t + .extent 0 //40 reserved + .extent ABS(EXT_C(parse_string)) //41 + .extent ABS(EXT_C(hexdump)) //42 + .extent ABS(EXT_C(skip_to)) //43 + .extent ABS(EXT_C(builtin_cmd)) //44 + .extent ABS(EXT_C(get_datetime)) //45 + .extent ABS(EXT_C(find_command)) //46 + .extent 0 //47 reserved g4d是get_mmap_entry + .extent ABS(EXT_C(grub_memalign)) //48 void * + .extent ABS(EXT_C(grub_zalloc)) //49 void * + .extent ABS(EXT_C(grub_malloc)) //50 void * + .extent ABS(EXT_C(grub_free)) //51 void + .extent 0 //52 原list_partitions 现在未使用 + .extent 0 //53 原ABS(EXT_C(realmode_run)) realmode_run reserved for wee 现在未使用 + .extent 0 //54 未使用 + .extent 0 //55 未使用 + .extent 0 //56 未使用 + .extent 0 //57 未使用 + .extent 0 //58 未使用 + .extent 0 //59 未使用 + .extent 0 //60 未使用 + ////////////////////////////////////////////61 + .extent ABS(EXT_C(dir)) //61 + .extent ABS(EXT_C(print_a_completion)) //62 + .extent ABS(EXT_C(print_completions)) //63 + .extent 0 //64 + .extent ABS(EXT_C(probe_bpb)) //65 + .extent ABS(EXT_C(probe_mbr)) //66 + .extent ABS(EXT_C(unicode_to_utf8)) //67 + .extent ABS(EXT_C(rawread)) //68 + .extent ABS(EXT_C(rawwrite)) //69 + .extent ABS(EXT_C(setcursor)) //70 + .extent ABS(EXT_C(grub_tolower)) //71 + .extent ABS(EXT_C(grub_isspace)) //72 + .extent ABS(EXT_C(grub_sleep)) //73 + .extent 0 //74 原ABS(EXT_C(mem64)) 现在未使用 + .extent ABS(EXT_C(envi_cmd)) //75 + .extent ABS(EXT_C(strncmpx)) //76 +#ifdef SUPPORT_GRAPHICS + .extent ABS(EXT_C(rectangle)) //77 #else -#error no bss ending address + .extent 0 #endif - - /* compute the bss length */ - subl %edi, %ecx - shrl $2, %ecx - - /* zero %eax */ - xorl %eax, %eax - - /* set the direction */ - cld - - /* clean out */ - rep stosl - - /* initialize IDT */ - - movl $0x300000, %edi - movl $0x100, %ecx - xorl %ebx, %ebx -2: - movl $ABS(default_iret), %eax - cmpb $0xFE, %cl // int 0x02 nmi - jne 3f - movl $ABS(int2_nmi), %eax - jmp 5f -3: - cmpb $0xF8, %cl - jg 5f // int 0x00 - 0x07 - cmpb $0xF1, %cl - jl 3f // int 0x10 - 0xFF - cmpb $8, %bl - jne 4f - movl $ABS(irq_0), %eax // int 0x08 - jmp 5f -4: - movl $(irq_2 - irq_1), %eax // int 0x09 - 0x0F - subl $0x09, %ebx - mull %ebx - addl $0x09, %ebx - addl $ABS(irq_1), %eax - jmp 5f -3: - cmpb $0x90, %cl - jg 5f // int 0x10 - 0x6F - cmpb $0x88, %cl - jl 3f // int 0x78 - 0xFF - movl $(irq_9 - irq_8), %eax // int 0x70 - 0x77 - subl $0x70, %ebx - mull %ebx - addl $0x70, %ebx - addl $ABS(irq_8), %eax - //jmp 5f -3: -5: - stosw - shrl $16, %eax - movl $(0x8E000000 + 40), %edx - xchgl %eax, %edx - stosl - xchgl %eax, %edx - stosw - incl %ebx - loop 2b - -1: - call EXT_C(prot_to_real) - - .code16 - - call EXT_C(real_to_prot) - - .code32 - - sti - - /* - * Call the start of main body of C code, which does some - * of it's own initialization before transferring to "cmain". - */ - call EXT_C(init_bios_info) - call EXT_C(cmain) - + .extent ABS(EXT_C(get_cmdline)) //78 /* - * This call is special... it never returns... in fact it should simply - * hang at this point! - */ - -ENTRY(stop) - call EXT_C(prot_to_real) - - /* - * This next part is sort of evil. It takes advantage of the - * byte ordering on the x86 to work in either 16-bit or 32-bit - * mode, so think about it before changing it. - */ - - /* No external program ever calls HARD_STOP. HARD_STOP is only called - * by the asm.S itself, and all calls are from real mode. So we - * could(and should) use .code16 here clearly. - */ - - .code16 - -hard_stop: - sti - //hlt - call conditional_hlt - jmp hard_stop - -conditional_hlt: -//DS should already be 0, but ... - pushw $0 - popw %ds // just in case DS changed by buggy BIOS - testb $0x20, 0x8205 // Enable HLT? - jz 1f // No. Skip the HLT instruction. - hlt // Yes. Execute the HLT instruction. -1: - ret // on return, DS=0 - - .code32 - -VARIABLE(force_cdrom_as_boot_device) - .long 1 -VARIABLE(use_config_file) - .long 1 -VARIABLE(configfile_opened) - .long 0 - -/* If preset_menu == __bss_start, the new menu at end of pre_stage2 will be used. */ - -#if 0 -VARIABLE(preset_menu) -#if defined(PRESET_MENU_STRING) -#if defined(HAVE_USCORE_USCORE_BSS_START_SYMBOL) - .long __bss_start - 0x300000 -#elif defined(HAVE_USCORE_EDATA_SYMBOL) - .long _edata - 0x300000 -#elif defined(HAVE_EDATA_SYMBOL) - .long edata - 0x300000 -#else /* ! HAVE_EDATA_SYMBOL */ -#error no bss starting address -#endif /* ! HAVE_EDATA_SYMBOL */ -#else /* ! PRESET_MENU_STRING */ - .long 0 -#endif /* PRESET_MENU_STRING */ -#endif - -VARIABLE(debug_boot) - .long 0 - -#if 0 - /* real mode print string */ - -/* prints string DS:SI (modifies AX BX SI) */ - -print_message: - - .code16 - -1: - sti /* for hardware interrupt or watchdog */ - cld - lodsb (%si), %al /* get token */ - xorw %bx, %bx /* video page 0 */ - movb $0x0e, %ah /* print it */ - int $0x10 /* via TTY mode */ - cmpb $0, %al /* end of string? */ - jne 1b /* until done */ - ret - -reset_disk_string: - .ascii "Reseting the boot drive... \0" -reset_disk_success_string: - .ascii "Success.\r\n\0" -reset_disk_failure_string: - .ascii "Failure!\r\n\0" -#endif - -bochs_copygrght_string: - .ascii "(c) 2002 MandrakeSoft S.A. Written by Kevin Lawton & the Bochs team.\0" -ENTRY(bios_id) - .long 0 /* 1 for bochs, 0 for unknown. */ - - .code32 - - -#ifdef FSYS_PXE -/* unsigned long pxe_scan(void) - * - * Scan pxe runtime. + * The C code for a grub4dos executable may have defines as follows: * - * Return 0 on failure. Return the pxe_entry pointer on success. - */ -ENTRY(pxe_scan) - - .code32 - pushl %ebx - pushl %ebp /* save this in case int1A would change it! */ - pushl %esi /* save this in case int1A would change it! */ - pushl %edi /* save this in case int1A would change it! */ - - call EXT_C(prot_to_real) - .code16 - - sti /* for hardware interrupt or watchdog */ - movw $0x5650, %ax - int $0x1A - xorl %ecx, %ecx //initialize it for "failure" - cmpw $0x564E, %ax - jnz 1f - cmpl $0x4E455850, %es:(%bx) // PXEN(V+) - jnz 1f - cmpw $0x201, %es:6(%bx) // API version - jb 1f - lesw %es:0x28(%bx), %bx // !PXE structure - cmpl $0x45585021, %es:(%bx) // !PXE - jnz 1f - movw %es, %cx - shll $4, %ecx - movzwl %bx, %ebx - addl %ebx, %ecx -1: - - call EXT_C(real_to_prot) - .code32 - - sti - - /* EAX=0 */ - testl %ecx, %ecx - jz 3f // failure - - movl 0x10(%ecx), %eax /* PXE API entry point, segoff16 */ - movl 0x2A(%ecx), %edx - cmpl 0x32(%ecx), %edx - ja 1f - movl 0x32(%ecx), %edx - movzwl 0x36(%ecx), %ebx - jmp 2f -1: - movzwl 0x2E(%ecx), %ebx -2: - addl %ebx, %edx - addl $1023, %edx - shrl $10, %edx - movw %dx, EXT_C(pxe_freemem) - - /* calculate base mem */ - - /* first, the low mem size */ - movzwl 0x413, %esi - shll $10, %esi - - movl $0xA0000, %ebx - - movl 0x22(%ecx), %edx - cmpl %esi, %edx - jb 4f - cmpl %ebx, %edx - jnb 4f - movl %edx, %ebx -4: - movl 0x2A(%ecx), %edx - cmpl %esi, %edx - jb 4f - cmpl %ebx, %edx - jnb 4f - movl %edx, %ebx -4: - movl 0x32(%ecx), %edx - cmpl %esi, %edx - jb 4f - cmpl %ebx, %edx - jnb 4f - movl %edx, %ebx -4: - movl 0x3A(%ecx), %edx - cmpl %esi, %edx - jb 4f - cmpl %ebx, %edx - jnb 4f - movl %edx, %ebx -4: - movl 0x42(%ecx), %edx - cmpl %esi, %edx - jb 4f - cmpl %ebx, %edx - jnb 4f - movl %edx, %ebx -4: - movl 0x4A(%ecx), %edx - cmpl %esi, %edx - jb 4f - cmpl %ebx, %edx - jnb 4f - movl %edx, %ebx -4: - movl 0x52(%ecx), %edx - cmpl %esi, %edx - jb 4f - cmpl %ebx, %edx - jnb 4f - movl %edx, %ebx -4: - shrl $10, %ebx - movw %bx, EXT_C(pxe_basemem) - -3: - movl %eax, EXT_C(pxe_entry) - - popl %edi - popl %esi - popl %ebp - popl %ebx - ret - -/* int pxe_call(int func,void* data) - * - * PXE function call - */ -ENTRY(pxe_call) - - .code32 - - pushl %ebp - movl %esp, %ebp - pushl %esi - pushl %edi - pushl %ebx - - movl 8(%ebp), %ecx - movl 12(%ebp), %edx - movl %edx, %eax - andl $0xF, %eax - shrl $4, %edx - shll $16, %edx - addl %eax, %edx - movl EXT_C(pxe_entry), %ebx - - call EXT_C(prot_to_real) - .code16 - - sti /* for hardware interrupt or watchdog */ - pushl %ebx - pushl %edx - pushw %cx - movw %sp, %bx - lcall *%ss:6(%bx) - cld - addw $10, %sp - movw %ax, %cx - - call EXT_C(real_to_prot) - .code32 - - sti - - movzwl %cx, %eax - - popl %ebx - popl %edi - popl %esi - popl %ebp - ret - -/* this was originally defined in fsys_pxe.c, but should be in low memory. - * -static PXENV_TFTP_OPEN_t pxe_tftp_open; - * - * So define it here. - * -typedef struct { - PXENV_STATUS Status; - IP4 ServerIPAddress; - IP4 GatewayIPAddress; - UINT8 FileName[128]; - UDP_PORT TFTPPort; - UINT16 PacketSize; -} PACKED PXENV_TFTP_OPEN_t; -typedef unsigned short UINT16; -typedef UINT16 PXENV_STATUS; -typedef unsigned long UINT32; -typedef UINT32 IP4; -typedef unsigned char UINT8; -typedef UINT16 UDP_PORT; - * - */ - - .align 2 -VARIABLE(pxenv) -VARIABLE(pxe_tftp_open) - .word 0 # Status - .long 0 # ServerIPAddress - .long 0 # GatewayIPAddress - .space 128 # FileName[128]; - .word 0 # TFTPPort - .word 0 # PacketSize - -#if PXE_FAST_READ - -/* int pxe_fast_read(void* data,int num) - * - * Read multiple packets - */ -ENTRY(pxe_fast_read) - - .code32 - - pushl %ebp - movl %esp, %ebp - pushl %esi - pushl %edi - pushl %ebx - - movl 8(%ebp), %edx - movl 12(%ebp), %esi /* num */ - movl EXT_C(pxe_blksize), %edi - movl %edx, %eax - andl $0xF, %eax - shrl $4, %edx - shll $16, %edx - addl %eax, %edx - movl EXT_C(pxe_entry), %ebx - - call EXT_C(prot_to_real) - .code16 - - sti /* for hardware interrupt or watchdog */ - movw %si, %cx /* num */ -1: - pushw %cx /* blocks to read */ - pushw %di /* block size */ - pushl %ebx /* pxe_entry */ - pushl %edx /* data pointer */ - pushw $0x22 // PXENV_TFTP_READ - movw %sp, %bp - lesw 2(%bp), %si /* ES:SI=data pointer */ - - movw %di, %es:4(%si) /* block size */ - lcall *6(%bp) - movw %sp, %bp - lesw 2(%bp), %si /* ES:SI=data pointer */ - popw %dx // PXENV_TFTP_READ - popl %edx /* data pointer */ - popl %ebx /* pxe_entry */ - popw %di /* block size */ - popw %cx /* blocks to read */ - cld - - cmpw $0, %es:(%si) - jnz 2f - movw %es:4(%si), %bp -// cmpw $512, %dx -// jb 2f -// cmpw %di, %dx -// ja 2f -// je 3f -// cmpl EXT_C(filemax), %edx -// jae 3f -// movl %edx, EXT_C(pxe_blksize) -// movl %edx, %edi -//3: - addw %bp, %es:6(%si) - cmpw %di, %bp - jb 2f - loop 1b - -2: - //addw $10, %sp - movw %ax, %cx - - call EXT_C(real_to_prot) - .code32 - - sti - - movzwl %cx, %eax - - popl %ebx - popl %edi - popl %esi - popl %ebp - ret -#endif /* PXE_FAST_READ */ -#endif /* FSYS_PXE */ - -/* - * stop_floppy() - * - * Stops the floppy drive from spinning, so that other software is - * jumped to with a known state. - */ -ENTRY(stop_floppy) - - .code32 - - pushal - call EXT_C(prot_to_real) - .code16 - sti #; added 2006-11-30 - xorb %dl, %dl -#if 1 - int $0x13 -#else - call safe_int13 -#endif - call EXT_C(real_to_prot) - .code32 - sti - - popal - ret - -/* - * boot_int18() - */ -ENTRY(boot_int18) - - .code32 - - call EXT_C(prot_to_real) - - .code16 - int $0x18 - ljmp $0xFFFF, $0x0000 - -/* - * grub_reboot() - * - * Reboot the system. At the moment, rely on BIOS. - */ -ENTRY(grub_reboot) - - .code32 - - call EXT_C(prot_to_real) - - .code16 - - /* cold boot */ - - //sti /* needn't enable interrupt here. comment it out */ - - movw $0x0472, %di - movw %ax, (%di) - ljmp $0xFFFF, $0x0000 - -/* - * grub_halt(int skip_flags) - * - * Halt the system, using APM or ACPI if possible. If NO_APM is true, don't use - * APM even if it is available. - */ - -ENTRY(grub_halt) - .code32 - - cli - pushl %ebp - movl %esp, %ebp - movl 8(%ebp), %eax /* get the argument: skip_flags */ - - /* first, try APM BIOS call. */ - testl $1, %eax /* bit 0=1 for --no-apm */ - jnz 1f - call try_apm -1: - /* second, try ACPI. */ - testl $2, %eax /* bit 1=1 for --no-acpi */ - jnz 1f - call acpi_soft_off -1: - /* halt failed. */ - xorl %eax, %eax /* return 0 for false */ - - pushl %eax /* EAX=0 */ - popfl /* cld, cli, ... */ - - movl $74, EXT_C(errnum) /* set errnum to ERR_HALT(=74) */ - popl %ebp - ret - -acpi_soft_off: /* contributor: zw2312914(bbs.znpc.net) */ - - .code32 - - pushal - - /* find RSDP in 0xE0000-0xFFFFF. it should be there in most cases. */ - movl $0xE0000, %eax - movl $(0x20000/0x10), %ecx - call find_rsdp - jnz 3f /* rsdp found */ - - /* try the 1st 1KB of EBDA */ - movzwl 0x40E, %eax /* EBDA segment */ - testl %eax, %eax /* segment should >= 0x8000 */ - jns 1f /* no EBDA, fail */ - shll $4, %eax /* EAX=physical address */ - movl $(1024/16), %ecx - call find_rsdp - jz 1f /* fail */ -3: - /* locate rsdt, ignoring xsdt table for simplicity. */ - movl 16(%eax), %esi /* physical address of RSDT */ - cmpl $0x54445352, (%esi) /* 'RSDT' */ - jnz 1f /* fail, ignoring xsdt */ - movl 4(%esi), %ecx /* RSDT length */ - subl $0x24, %ecx - jbe 1f /* fail */ - shrl $2, %ecx - addl $0x24, %esi - -4://find_facp: - cld - lodsl - cmpl $0x50434146, (%eax) /* 'FACP' */ - jz 5f /* found, exit loop */ - loop 4b /* try next DWORD */ - jmp 1f /* fail */ - -5://facp_found: - movl %eax, %ebx /* fadt address */ - cmpl $0, 64(%ebx) /* PM1a_CNT_BLK port must be true */ - jz 1f /* fail */ - - movl $1, %edi /* pass EDI = 1 for enable ACPI */ - call write_smi_port /* this call running at here , purpose of the delay is sufficient */ - jz 1f /* fail, don't transform */ - - movl 40(%ebx), %edi /* physical address of DSDT */ - cmpl $0x54445344, (%edi) /* 'DSDT' */ - jnz 12f /* if fail, disable_acpi */ - movl 4(%edi), %eax /* DSDT length */ - subl $40, %eax - jbe 12f /* if fail, disable_acpi */ - addl $36, %edi - -6://locate_S5: - cmpl $0x5F35535F, (%edi) /* '_S5_' */ - jnz 7f - cmpb $0x08, -1(%edi) /* NameOp */ - jz 8f - cmpb $0x08, -2(%edi) /* NameOp with RootChar prefix '\' */ - jnz 7f - -8://locate_next: - #; DefPackage := PackageOp PkgLength NumElements PackageElementList - #; PackageOp := 0x12 - #; NumElements := ByteData - #; PackageElementList := Nothing | - #; PackageElement := DataRefObject | NameString - #; PkgLength := PkgLeadByte | - #; | - #; | - #; - #; PkgLeadByte := - #; - #; - #; Note: The high 2 bits of the first byte reveal how many follow bytes - #; are in the PkgLength. If the PkgLength has only one byte, bit 0 - #; through 5 are used to encode the package length (in other words, - #; values 0-63). If the package length value is more than 63, more than - #; one byte must be used for the encoding in which case bit 4 and 5 of - #; the PkgLeadByte are reserved and must be zero. If the multiple bytes - #; encoding is used, bits 0-3 of the PkgLeadByte become the least - #; significant 4 bits of the resulting package length value. The next - #; ByteData will become the next least significant 8 bits of the - #; resulting value and so on, up to 3 ByteData bytes. Thus, the maximum - #; package length is 2**28. - - cmpb $0x12, 4(%edi) /* PackageOp */ - jnz 7f - cmpb $4, 5(%edi) /* PkgLeadByte, the minimum must be 4 for \S5_ object */ - jb 7f - movb 6(%edi), %dl /* NumElements */ - - cmpb $4, %dl /* Complete _S5_ object should contain 4 NumElements, - but some BIOSes reduced to 2 . - because 2 reserved NumElements be ignored */ - ja 7f - cmpb $0, %dl - ja 8f /* find succeeded */ - -7://loop_continue: - incl %edi - decl %eax - jnz 6b - jmp 12f /* if fail, disable_acpi */ - -8://get_slp_typx: - leal 7(%edi), %edi - call data_analyze - incl %edi - call data_analyze /* slp_typ_a in %cl, slp_typ_b in %ch */ - andl $0x0707, %ecx /* slp_typX only have 3 bit */ - shll $2, %ecx /* the description of slp_typX in pm1_cnt_blk Description see below */ - -/* The following will enter G2 state (ie acpi soft off)*/ -/* AT here, %ebx = FADT address, %cx = slp_typX(a and b), other regsiters is free */ - -/* Thanks for MR.rockrock99 and MR.xianglang reports their different and special hardware response mechanism */ - -9://is_keep_SCI: - testl $0x4, 8(%ebp) /* check for --force-sci */ - jnz 10f /* if --force-sic is true, don't disable acpi */ - xorl %edi, %edi /* pass EDI = 0 for disable SCI */ - call write_smi_port /* faster close SCI for MR.xianglang's Pc */ - jz 1f /* fail, don't transform */ - -10://read_pm1_cnt_group: - xorl %esi, %esi - movl 64(%ebx), %edx /* PM1a_CNT_BLK port */ - inw %dx, %ax - call wait_io_delay - call test_pm1b_port /* when pm1b_cnt_blk value is true, will use slp_typ_b port */ - jz 11f - xchgl %eax, %esi - inw %dx, %ax - call wait_io_delay - -11://write_pm1_cnt_group: - orl %esi, %eax /* PM1_cnt_group state is pm1a OR pm1b */ - movl 64(%ebx), %edx /* PM1a_CNT_BLK port */ - call write_pm1_cnt_group - call test_pm1b_port /* when pm1b_cnt_blk value is true, will use slp_typ_b port */ - jz 12f - xchgb %ch, %cl - call write_pm1_cnt_group - -12://disable_acpi: /* acpi soft off failed. disable acpi if possible!!! */ - xorl %edi, %edi - call write_smi_port /* pass EDI = 0 for disable ACPI */ - -1://acpi_fail: - popal - ret - -find_rsdp: - /* will change EAX, ECX, EDX, ESI */ -1: - cmpl $0x20445352, (%eax) /* 'RSD ' */ - jnz 3f - cmpl $0x20525450, 4(%eax) /* 'PTR ' */ - jnz 3f - - /* checksum for rsdp version 0 */ - xorl %edx, %edx - xorl %esi, %esi -2: - addb (%eax, %esi), %dl - incl %esi - cmpl $20, %esi - jnz 2b - jz 4f -3: - leal 16(%eax), %eax - loop 1b -4: - testl %ecx, %ecx /* success with ZF=0, failure with ZF=1 */ - ret - -test_pm1b_port: - movl 68(%ebx), %edx /* PM1b_CNT_BLK port */ - testl %edx, %edx - ret - -data_analyze: - cmpb $0x0A, (%edi) /* ByteData Prefix */ - jnz 1f - incl %edi -1: - movb (%edi), %cl - xchgb %cl, %ch - ret - -wait_io_delay: /* NOTE: we have not save %edi, and %edi will be set to zero */ - movl $0x1FFFFF, %edi -1: - nop - decl %edi - jnz 1b - ret - -write_smi_port: - /* input: %edi = 0 for disable acpi, %edi = 1 for enable acpi */ - movl 48(%ebx), %edx /* SMI_CMD port */ - testl %edx, %edx /* must be non-zero */ - jz 2f - movw 52(%ebx), %ax /* AH for ACPI_DISABLE, AL for ACPI_ENABLE */ - testl %edi, %edi - jnz 1f - xchgb %ah, %al -1: - testb %al, %al /* must be non-zero */ - jz 2f - outb %al, %dx - call wait_io_delay - testl %eax, %eax -2: - ret - -write_pm1_cnt_group: - /* PM1 Control Registers Fixed Hardware Feature Control Bits - Bit Name Description - --- ---- ------------------------------------------------------ - 0 SCI_EN Selects the power management event to be either an SCI - or SMI interrupt for the following events. When this - bit is set, then power management events will generate - an SCI interrupt. When this bit is reset power - management events will generate an SMI interrupt. It - is the responsibility of the hardware to set or reset - this bit. OSPM always preserves this bit position. - 1 BM_RLD When set, this bit allows the generation of a bus - master request to cause any processor in the C3 state - to transition to the C0 state. When this bit is reset, - the generation of a bus master request does not affect - any processor in the C3 state. - 2 GBL_RLS This write-only bit is used by the ACPI software to - raise an event to the BIOS software, that is, - generates an SMI to pass execution control to the BIOS - for IA-PC platforms. BIOS software has a corresponding - enable and status bit to control its ability to - receive ACPI events (for example, BIOS_EN and - BIOS_STS). The GBL_RLS bit is set by OSPM to indicate - a release of the Global Lock and the setting of the - pending bit in the FACS memory structure. - 3-8 Reserved These bits are reserved by OSPM. - 9 Ignore Software ignores this bit field. - 10-12 SLP_TYPx Defines the type of sleeping state the system enters - when the SLP_EN bit is set to one. This 3-bit field - defines the type of hardware sleep state the system - enters when the SLP_EN bit is set. The \_Sx object - contains 3-bit binary values associated with the - respective sleeping state(as described by the object). - OSPM takes the two values from the \_Sx object and - programs each value into the respective SLP_TYPx - field. - 13 SLP_EN This is a write-only bit and reads to it always return - a zero. Setting this bit causes the system to sequence - into the sleeping state associated with the SLP_TYPx - fields programmed with the values from the \_Sx - object. - 14-15 Reserved This field always returns zero. */ - - andw $0x63F9, %ax /* reserved and ignored bits must use read back value, clear others */ - orb %cl, %ah /* set new slp_typX from \S5 object */ - bts $13, %ax /* set slp_en bit */ - outw %ax, %dx - call wait_io_delay - ret - -try_apm: - - call EXT_C(prot_to_real) - - .code16 - - pushw %ds - pushw %es - pushal - - sti - - /* detect APM */ - movw $0x5300, %ax - xorw %bx, %bx - int $0x15 - jc 1f /* APM fail */ - /* don't check %bx for buggy BIOSes... */ - - /* connect real mode interface of APM */ - movw $0x5301, %ax - xorw %bx, %bx - int $0x15 - jc 1f /* APM fail */ - - /* set APM protocol level - 1.1 or bust. (this covers APM 1.2 also) */ - movw $0x530E, %ax - xorw %bx, %bx - movw $0x0101, %cx - int $0x15 - jc 1f - - /* turn off system by APM 1.1+ */ - movw $0x5307, %ax - movw $1, %bx - movw $3, %cx - int $0x15 - -1: - popal - popw %es - popw %ds - - call EXT_C(real_to_prot) - - .code32 - sti - - ret /* APM code end */ - - /* end of halt code */ - -//////////////////////////////////////////////////////////////////////////// - -/* - * int tpm_init (void) - * return non-zero for success and zero for failure. - */ -ENTRY(tpm_init) - - .code32 - - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - - call EXT_C(prot_to_real) /* enter real mode */ - - .code16 - - sti - - movw $0xBB00, %ax - int $0x1A - testl %eax, %eax - jnz 1f /* failure */ - cmpl $0x41504354, %ebx /* "TCPA" */ - jnz 1f /* failure */ - cmpw $0x102, %cx /* TCG BIOS version 1.2 */ - jb 1f /* failure */ - movw %ax, %es /* ES=0 */ - movw $0xBB07, %ax /* eax hi word=0 */ - movl $0x00000200, %ecx /* buffer size to hash */ - movl $0x00000008, %edx /* PCR index for the hashed result */ - xorl %esi, %esi /* place 0 into the event field */ - movl $0x00007C00, %edi /* ES:DI point to data buffer to hash */ - int $0x1A - - testl %eax, %eax -1: - setz %dl - - call EXT_C(real_to_prot) - .code32 - - sti - - movzbl %dl, %eax - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - -/* Catch CPU exceptions 0 - 7 - * 0 Divide - * 1 Debug - * 2 NMI - * 3 Break point - * 4 Overflow - * 5 Bound - * 6 Invalid Instruction - * 7 no coprocessor - */ - -set_fault_recovery_handler: - - .code16 - - pushfw - pushw %ds - pushw %es - pushaw - - /* backup int 00 - 07 */ - - xorw %ax, %ax - movw %ax, %ds - movw %ax, %es - xorw %si, %si - movw $ABS(int_00_07_vectors), %di - movw $16, %cx - cld - repz movsw - - /* set to new vector */ - - xorw %ax, %ax - movw %ax, %ds - movw %ax, %es - xorw %si, %si - movw $ABS(int_00_07_vectors), %di - - pushl %eax - - xorw %di, %di - movl $ABS(fault_recovery_handler), %eax /* 0000:fault_recovery_handler */ - movw $8, %cx - cld - repz stosl - - popl %eax - - popaw - popw %es - popw %ds - popfw - ret - -unset_fault_recovery_handler: - - .code16 - - pushfw - pushw %ds - pushw %es - pushaw - - /* restore int 00 - 07 */ - - xorw %ax, %ax - movw %ax, %ds - movw %ax, %es - xorw %di, %di - movw $ABS(int_00_07_vectors), %si - movw $16, %cx - cld - repz movsw - - popaw - popw %es - popw %ds - popfw - ret - - .align 4 - -int_00_07_vectors: - .space 32 - -original_registers: - .space 48 - -safe_int13: - - .code16 - - /* setup our fault recovery handler */ - - call set_fault_recovery_handler - - /* backup old registers. Note: CS=0 */ - - movw %ds, %cs:ABS(original_registers) - movw %es, %cs:ABS(original_registers) + 4 - movw %ss, %cs:ABS(original_registers) + 8 - movl %esp, %cs:ABS(original_registers) + 12 - movl %eax, %cs:ABS(original_registers) + 16 - movl %ebx, %cs:ABS(original_registers) + 20 - movl %ecx, %cs:ABS(original_registers) + 24 - movl %edx, %cs:ABS(original_registers) + 28 - movl %esi, %cs:ABS(original_registers) + 32 - movl %edi, %cs:ABS(original_registers) + 36 - movl %ebp, %cs:ABS(original_registers) + 40 - - pushw %bp - pushw %ax - movw %sp, %bp - movw 4(%bp), %ax - movw %ax, %cs:ABS(original_registers) + 44 #; return IP - popw %ax - popw %bp - - int $0x13 - - call unset_fault_recovery_handler - - ret - -fault_recovery_handler: - - .code16 - - /* restore old registers. Note: CS=0 */ - - movw %cs:ABS(original_registers), %ds - movw %cs:ABS(original_registers) + 4, %es - movw %cs:ABS(original_registers) + 8, %ss - movl %cs:ABS(original_registers) + 12, %esp - movl %cs:ABS(original_registers) + 16, %eax - movl %cs:ABS(original_registers) + 20, %ebx - movl %cs:ABS(original_registers) + 24, %ecx - movl %cs:ABS(original_registers) + 28, %edx - movl %cs:ABS(original_registers) + 32, %esi - movl %cs:ABS(original_registers) + 36, %edi - movl %cs:ABS(original_registers) + 40, %ebp - - /* stack is available, so we can push and pop. */ - - pushw %bp - pushw %ax - movw %sp, %bp - movw %cs:ABS(original_registers) + 44, %ax #; return IP - movw %ax, 4(%bp) - popw %ax - popw %bp - - pushl $1 #; CF=1 indicating error - popfl #; CLD, CLI, and many more... - - call unset_fault_recovery_handler - - ret - - /* never come here. */ - - iret - -#if 0 -/* - * Translate a key code to another. - * - * Note: This implementation cannot handle more than one length - * scancodes (such as Right Ctrl). - */ - -int15_handler: - - .code16 - - /* if non-carrier, ignore it */ - jnc 1f - /* check if AH=4F */ - cmpb $0x4F, %ah - jne 1f - - /* E0 and E1 are special */ - cmpb $0xE1, %al - je 4f - cmpb $0xE0, %al - /* this flag is actually the machine code (je or jmp) */ -int15_skip_flag: - je 4f - - pushw %bp - movw %sp, %bp - - pushw %bx - pushw %dx - pushw %ds - pushw %si - - /* save bits 0-6 of %al in %dl */ - movw %ax, %dx - andb $0x7f, %dl - /* save the highest bit in %bl */ - movb %al, %bl - xorb %dl, %bl - /* set %ds to 0 */ - xorw %ax, %ax - movw %ax, %ds - /* set %si to the key map */ - movw $ABS(EXT_C(bios_key_map)), %si - - /* find the key code from the key map */ -2: - lodsw - /* check if this is the end */ - testw %ax, %ax - jz 3f - /* check if this matches the key code */ - cmpb %al, %dl - jne 2b - /* if so, perform the mapping */ - movb %ah, %dl -3: - /* restore %ax */ - movw %dx, %ax - orb %bl, %al - /* make sure that CF is set */ - orw $1, 6(%bp) - /* restore other registers */ - popw %si - popw %ds - popw %dx - popw %bx - popw %bp - iret - -4: - /* tricky: jmp (0x74) <-> je (0xeb) */ - xorb $(0x74 ^ 0xeb), ABS(int15_skip_flag) -1: - /* just cascade to the original */ - /* ljmp */ - .byte 0xea -int15_offset: .word 0 -int15_segment: .word 0 - - .align 4 -ENTRY(bios_key_map) - .space (KEY_MAP_SIZE + 1) * 2 -#endif - - -/* - * Map a drive to another drive or a disk image file. - */ - - .code16 - - .align 4 - -ENTRY(bios_drive_map) - .space (DRIVE_MAP_SIZE + 1) * DRIVE_MAP_SLOT_SIZE - - /* align it this way so that int13_handler can be used as a segment - * base address. The `cdrom' command requires this. - */ - .align 16 - -int13_handler: - - /* memory size in K that int13 handler uses. */ -#ifdef CDROM_INIT - .byte ((int13_handler_end - int13_handler + 0x3ff) / 0x400) -#else - .byte ((cdrom_start - int13_handler + 0x3ff) / 0x400) -#endif - /* 1-byte space reserved. */ - - . = int13_handler + 0x2 - -ENTRY(atapi_dev_count) .byte 0 -ENTRY(min_cdrom_id) .byte 0xE0 - - . = int13_handler + 0x4 - - /* Signature */ - .ascii "G4DS" # Please don't use this signature any longer. - # This field might be used for other purposes. - # Use signature at offset 0x103 instead. - - . = int13_handler + 0x08 - - /* Version number */ - .word 1 - - . = int13_handler + 0x0A - -VARIABLE(floppies_orig) - .byte 0 /* original value at 0040:0010 */ - - . = int13_handler + 0x0B - -VARIABLE(harddrives_orig) - .byte 0 /* original value at 0040:0075 */ - - . = int13_handler + 0x0C - -VARIABLE(ROM_int15) - .long 0 /* original int15 vector */ - - . = int13_handler + 0x10 - - /* 12-byte space reserved. */ - - . = int13_handler + 0x1C - -VARIABLE(ROM_int13) - .long 0 /* original int13 vector */ - - . = int13_handler + 0x20 /* drive map table begins at 0x20 */ - -#if MAP_NUM_16 -ENTRY(hooked_drive_map_1) - .space (DRIVE_MAP_SIZE / 2 + 1) * DRIVE_MAP_SLOT_SIZE -#else -ENTRY(hooked_drive_map) - .space (DRIVE_MAP_SIZE + 1) * DRIVE_MAP_SLOT_SIZE - /* 8-byte space reserved. */ -#endif - - . = int13_handler + 0xFC - .long 16 - - . = int13_handler + 0x100 /* real int13 handler entry at 0x100 */ - -int13_handler_entry: - jmp 1f - - . = int13_handler + 0x103 - - /*******************************************************************/ - /* ----------------- SafeMBRHook structure begin ----------------- */ - - .ascii "$INT13SF" /* Win9x use this! Don't touch! */ - - .ascii "GRUB4DOS" /* 8-byte Vender ID */ - - . = int13_handler + 0x113 - -VARIABLE(ROM_int13_dup) /* Win9x Safe-MBR-Hook structure requires this! */ - - .long 0 - - . = int13_handler + 0x117 - -VARIABLE(safe_mbr_hook) - - /* 2012-12-13: set to 0 according to sha0: - * http://reboot.pro/topic/17881-g4d-safe-hook-flags/ - * http://www.osronline.com/ddkx/w98ddk/storage_5l6g.htm - * - * 2013-01-12: sometimes 0 causes Win98 boot failure, so restore - * the original value of 1. See also: - * http://www.osronline.com/ddkx/w98ddk/storage_5o6r.htm - * which says: - * - * Safe MBR Hook - * - * To create a safe MBR hook for translation, you can either write - * an MBR hooker and a corresponding VSD or just write an MBR hooker - * that sets the smhflgs member to 1. In either case, the MBR hooker - * must have a SafeMBRHook structure at the beginning of its hook - * routine, as described in About Vendor-Supplied Drivers. - * - * You do not have to write a VSD if the MBR hooker only has - * functionality that the Windows 95 IDE driver already supports. In - * this case, the MBR hooker can set the smhflgs member to 1 on its - * own so that Windows 95 can take over in protect mode. - * - * If the MBR hooker has functionality that is not already supported - * by Windows 95, for example, encryption, you must write a VSD or - * leave your MBR hooker marked as unsafe. If you write a VSD to - * support the extra functionality in protect mode, the VSD is - * responsible for setting the smhflgs member to 1 to indicate to - * Windows 95 that it is safe to take over in protect mode. - * - * Built on Friday, April 11, 2003 - */ - .long 0x00000001 /* safe MBR hook flag */ - - /* ----------------- SafeMBRHook structure end ----------------- */ - /*******************************************************************/ - - /* But Win9x may expect additional data after SafeMBRHook structure. - * This is undocumented, and mysterious. If this area is not what - * Win9x expected, Win9x could hang. - */ - - . = int13_handler + 0x11B - -VARIABLE(int13_scheme) - - /* bit 0 controls how we access sectors in protected mode. - * bit0=0: use pushf and far call for ROM int13 service. - * bit0=1: use the `int $0x13' instruction. - */ - .long 0x00000001 - - . = int13_handler + 0x120 - -VARIABLE(saved_pxe_ip) - - .long 0 - - . = int13_handler + 0x124 - -VARIABLE(saved_pxe_mac) - - .byte 0, 0, 0, 0, 0, 0 - - /* space reserved. */ - - . = int13_handler + 0x140 - -restore_old_emu: - - /* GDT used by int13_handler RAM disk (32-bit protected mode, PAE - * paging, and 64-bit long mode). - * Linear address will be set by set_int13_handler routine. - * int13_handler does not have to modify it. - */ - .align 16 -MyGDT: -//gdt: -/* 0*/ .word 0 /* NULL entry. Can be used at will. */ -gdtdesc: /* 6 bytes used for gdt descriptor. */ - .word MyGDTEnd - MyGDT - 1 /* GDT limit */ - /* The gdt linear base address will be adjusted by set_int13_handler, - * but not touched outside int13_handler. */ - .long ABS(MyGDT) /* GDT linear address */ - -/* 8*/ PM_DS16 = (. - MyGDT) /* adjusted base = int13_handler */ - .long 0x0000FFFF, 0x00009300 /* 16-bit data 64K limit */ -/*16*/ PM_DS32 = (. - MyGDT) - .long 0x0000FFFF, 0x00CF9300 /* 32-bit data 4GB limit */ - - /* The 16-bit code segment base will be adjusted by set_int13_handler, - * but not touched outside int13_handler. */ -/*24*/ PM_CS16 = (. - MyGDT) /* adjusted base = int13_handler */ - .long 0x0000FFFF, 0x00009B00 /* 16-bit code 64K limit */ -/*32*/ LM_CS64 = (. - MyGDT) - .long 0x0000FFFF, 0x00AF9B00 /* 64-bit code 4GB limit */ - - /* This gdt entry is not used by int13_handler, but used outside. */ -/*40*/ PM_CS32 = (. - MyGDT) - .long 0x0000FFFF, 0x00CF9B00 /* 32-bit code 4GB limit */ -MyGDTEnd: - -OldGDT: - /* The int13_handler only uses it as a temp space for the OldGDT - * variable. Only the last 6 bytes are used by OldGDT, and the - * starting 2 bytes are not used by OldGDT. */ - //.word 0 -int13_is64bit: - .byte 0 // bit0 1=support PAE. bit1 1=support AMD64 long mode. -int13_need_64_bit: -int13_prev_DL: // used in 64-bit code - .byte 0 -OldGDTdesc: - .word 0 - .long 0 - - .align 4 -int13_prev_CR0: - .long 0 -int13_prev_CR3: -old_cr3: - .long 0 -int13_prev_CR4: -old_cr4: - .long 0 -int13_prev_PML4T_entry: - .long 0, 0 -int13_prev_PDPT_entry: - .long 0, 0 -int13_prev_PDT_entry: - .long 0, 0 - .long 0, 0 - .long 0, 0 - -//DS_seg: .word 0 -//ES_seg: .word 0 -//FS_seg: .word 0 -//GS_seg: .word 0 -//SP_off: .word 0 -//SS_seg: .word 0 -//DX_reg: .word 0 -//DI_reg: .word 0 - -data_addr_above_1M: - .long 0 - .long 0 -data_addr_below_1M: - .long 0 -// .long 0 - - .align 4 - -int13_old_cs_ip: .long 0 -int13_old_eax: .long 0 -int13_old_ebx: .long 0 -int13_old_ecx: .long 0 -int13_old_edx: .long 0 -int13_old_esi: .long 0 -int13_old_edi: .long 0 -int13_old_esp: .long 0 -int13_old_ebp: .long 0 -int13_old_ds: .word 0 -int13_old_es: .word 0 -int13_old_flags: .word 0 -int13_new_bp: .word 0 - - -/* cache 1 big 2048-byte sector at edd30_disk_buffer */ - - .align 4 -int13_cdrom_edi: - .long 0 -int13_cdrom_ebx: - .long 0 -int13_cdrom_cx: - .word 0 -int13_cdrom_bx: - .word 0 -int13_cdrom_es: - .word 0 - -last_read_cd_drive: - .byte 0 #; a value < 0x80 normally invalidate the cache - - .align 4 -last_read_sector: /* set it to 0xFFFFFFFFFFFFFFFF to invalidate the cache */ - .long 0xFFFFFFFF #; lo dword. for a valid cache, lowest 2 bits=0 - .long 0xFFFFFFFF #; hi dword - -tmp_dap: - .long 0 - .long 0 - .long 0 - .long 0 - -#if 0 -1: - /* backup far return address */ - popl %cs:(int13_old_cs_ip - int13_handler) - - /* build new stack: flags */ - popw %cs:(int13_handler_end - 2 - int13_handler) - - /* backup old stack */ - movw %sp, %cs:(int13_old_sp - int13_handler) - movw %ss, %cs:(int13_old_ss - int13_handler) - - /* build new stack pointer */ - movw $(int13_handler_end - 2 - int13_handler), %cs:(int13_new_sp - int13_handler) - movw %cs, %cs:(int13_new_ss - int13_handler) - - /* switch to new stack */ - lssw %cs:(int13_new_sp - int13_handler), %sp - - //pushfw /* flags already on stack */ - pushw %cs - call 1f - - /* restore old stack */ - lssw %cs:(int13_old_sp - int13_handler), %sp - - /* transfer control to caller */ - ljmp *%cs:(int13_old_cs_ip - int13_handler) - - //iret /* never reach here */ - - .align 4 - -int13_old_cs_ip: .long 0 -int13_old_sp: .word 0 -int13_old_ss: .word 0 -int13_new_sp: .word 0 -int13_new_ss: .word 0 - -#endif - -1: - - /* backup far return address */ - popl %cs:(int13_old_cs_ip - int13_handler) - - /* backup old flags */ - popw %cs:(int13_old_flags - int13_handler) - -#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - cld - movl %eax, %cs:(int13_old_eax - int13_handler) - movl %ebx, %cs:(int13_old_ebx - int13_handler) - movl %ecx, %cs:(int13_old_ecx - int13_handler) - movl %edx, %cs:(int13_old_edx - int13_handler) - movl %esi, %cs:(int13_old_esi - int13_handler) - movl %edi, %cs:(int13_old_edi - int13_handler) - movl %esp, %cs:(int13_old_esp - int13_handler) - movl %ebp, %cs:(int13_old_ebp - int13_handler) - movw %ds, %cs:(int13_old_ds - int13_handler) - movw %es, %cs:(int13_old_es - int13_handler) - -// # this check is not too useful, so comment out to save space -// cmpb $0x1a, %ah /* PS/2 low level format ESDI drive!!!! */ -// je error_01_disable /* disabled in any case */ -#ifdef CDROM_INIT - cmpb $0, %cs:(EXT_C(atapi_dev_count) - int13_handler) - jz 1f /* no cdrom */ - cmpb %cs:(EXT_C(min_cdrom_id) - int13_handler), %dl - jb 1f /* not cdrom drive */ - cmpb %cs:(max_cdrom_id - int13_handler), %dl - jbe edd30_for_cdrom -1: -#endif -/****************************************************************************/ - /* find the drive number from the drive map */ -#if MAP_NUM_16 - movw $(EXT_C(hooked_drive_map_1) - int13_handler - DRIVE_MAP_SLOT_SIZE), %bp -#else - movw $(EXT_C(hooked_drive_map) - int13_handler - DRIVE_MAP_SLOT_SIZE), %bp -#endif -1: - addw $DRIVE_MAP_SLOT_SIZE, %bp -#if MAP_NUM_16 - cmpw $EXT_C(hooked_drive_map_1) - int13_handler + DRIVE_MAP_SIZE * DRIVE_MAP_SLOT_SIZE / 2, %bp - jne 2f - movw $(EXT_C(hooked_drive_map_2) - int13_handler), %bp -2: - cmpw $EXT_C(hooked_drive_map_2) - int13_handler + DRIVE_MAP_SIZE * DRIVE_MAP_SLOT_SIZE / 2, %bp - je 2f -#endif - - movw %bp, %cs:(int13_new_bp - int13_handler) - movl %cs:(%bp), %eax /* FROM, TO, Hmax, Smax */ - - /* check if this is the end */ - testl %eax, %eax - jnz 3f /* not end, continue */ - - movl %cs:12(%bp), %eax /* StartLBA_Hi */ - testl %eax, %eax - jnz 3f /* not end, continue */ - - movl %cs:8(%bp), %eax /* StartLBA_Lo */ - testl %eax, %eax - jnz 3f /* not end, continue */ - - movl %cs:20(%bp), %eax /* S_count_Hi */ - testl %eax, %eax - jnz 3f /* not end, continue */ - - movl %cs:16(%bp), %eax /* S_count_Lo */ - testl %eax, %eax - jz 2f /* map whole drive to itself signals the end */ -3: - /* Now this is a valid drive map slot */ - cmpb %cs:(%bp), %dl /* check if this matches the drive number */ - jne 1b /* no, continue to check the next map */ - - /* yes, found the map corresponding to drive DL */ - -// movw %cs:2(%bp), %ax /* AL=Hmax, AH=Smax */ - - /* bit 1-5 already cleared for in-situ */ - //andb $0xC1, %ah /* clear bit 5 - bit 1 */ - - testb $0x80, %cs:7(%bp) /* TO_S */ - jnz 1f /* in-situ */ - - /* non-zero StartLBA signals emulation */ - - cmpl $0, %cs:12(%bp) /* StartLBA_Hi */ - jnz drive_emulation - cmpl $0, %cs:8(%bp) /* StartLBA_Lo */ - jnz drive_emulation - - /* StartLBA == 0 */ - - /* if FROM and TO are both cdrom, this is a whole drive map. */ - testw $0x4000, %cs:4(%bp) /* TO_C bit 14=(TO is cdrom) */ - jz 3f /* not cdrom */ - testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ - jz 3f /* not cdrom */ -#ifdef CDROM_INIT - movb %cs:1(%bp), %dl /* DL changed(!!) to TO_drive */ - cmpb $0, %cs:(EXT_C(atapi_dev_count) - int13_handler) - jz 2f /* no cdrom, so it is a bios drive map. */ - cmpb %cs:(EXT_C(min_cdrom_id) - int13_handler), %dl /* TO_drive */ - jb 2f /* not cdrom, so it is a bios drive map. */ - cmpb %cs:(max_cdrom_id - int13_handler), %dl /* TO_drive */ - ja 2f /* not cdrom, so it is a bios drive map. */ - jmp edd30_for_cdrom -#endif -3: - - /* S_count being not 1 signals emulation */ - - movl %cs:20(%bp), %eax /* S_count_Hi */ - testl %eax, %eax - jnz drive_emulation - movl %cs:16(%bp), %eax /* S_count_Lo */ - shrl $1, %eax - jnz drive_emulation - - /* now StartLBA=0 and sector count=1(for whole disk) */ - - /* if sectors per track > 1, this is force geometry screw. */ - - movw %cs:2(%bp), %ax /* AL=Hmax, AH=Smax */ - testb $62, %ah /* Sectors > 1 means force geom, this -- */ - jnz drive_emulation /* -- also leads to drive emulation */ - - /* ignore geom and directly map a whole drive */ - -1: - /* bit 7 of the TO_S is for in-situ primary partition(alter MBR) */ - - /* bits of AH: - * 7 bit set means readonly/fakewrite - * 6 bit set means disable LBA - * 5 - 1 bits already cleared(=0) - * 0 bit cleared means disable CHS - * So, if AH!=1, it is a restricted disk access; - * and if AH=1, it is a normal disk access. - */ -// cmpb $1, %ah - testb $0xc0, %ah - je 1f - call restricted_map -1: - /* map a whole drive, normal access */ - - /* but if --in-situ was used, we should avoid writing the MBR! */ - testb $0x80, %cs:7(%bp) /* TO_S */ - jz 1f /* not in-situ, allow write */ - testb $0x40, %cs:7(%bp) /* TO_S. bit 6 here means safe-boot */ - jz 1f /* unsafe-boot, allow write */ - movw %cs:(int13_old_eax - int13_handler), %ax - cmpb $0x03, %ah /* is it CHS write? */ - jne 3f - - /* check if it is a write to MBR, i.e., C/H/S=0/0/1 */ - cmpw $0x0001, %cx /* C=0, S=1 */ - jne 1f - cmpb $0x00, %dh /* H=0 */ - jne 1f - - /* deny the write and end the int 13 call */ - call readonly_fakewrite /* NO RETURN!! */ -3: - cmpb $0x43, %ah /* is it LBA write? */ - jne 1f /* no, continue the normal access */ - - /* check if it is a write to MBR, i.e., LBA=0 */ - - xorl %eax, %eax - orl 12(%si), %eax /* LBA_hi */ - orl 8(%si), %eax /* LBA_lo */ - je readonly_fakewrite /* deny the write and end */ - -1: - movb %cs:1(%bp), %dl /* Let DL access TO instead of FROM */ -2: - /* might map to itself, i.e., actually not mapped */ - - movl %cs:(int13_old_eax - int13_handler), %eax - movl %cs:(int13_old_ebp - int13_handler), %ebp /* BP changed!! */ - - call backup_int13 - - pushw %cs:(int13_old_flags - int13_handler) - popfw - - int $0x13 - - /* save the returned CF flag to int13_old_flags */ - - jnc 1f - orb $1, %cs:(int13_old_flags - int13_handler) - jmp 2f -1: - andb $0xFE, %cs:(int13_old_flags - int13_handler) -2: - call restore_int13 - - /* restore BP!! */ - movw %cs:(int13_new_bp - int13_handler), %bp - xchgw %ax, %cs:(int13_old_eax - int13_handler) - /* old AX changed!! */ - - /* check int13/AH=4Bh for cdrom */ - testw $0x4000, %cs:4(%bp) /* TO_C bit 14=(TO is cdrom) */ - jz 1f /* not cdrom */ - testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ - jz 1f /* not cdrom */ - cmpb $0x4B, %ah - jne 1f - cmpb $0x01, %al - ja 1f - /* this is int13 function 0x4B00 or 0x4B01 */ - /* restore DS:SI, just in case they were changed by buggy int13 */ - movw %cs:(int13_old_esi - int13_handler), %si - movw %cs:(int13_old_ds - int13_handler), %ds - cmpb $0x13, (%si) /* packet size */ - jne 1f - testb $0x0F, 1(%si) /* boot type(0=no emu) */ - jne 1f - movb %cs:1(%bp), %dl /* just in case DL was changed by a buggy int13 */ - cmpb %dl, 2(%si) - jne 1f - movb %cs:(%bp), %dl /* restore DL back to the FROM drive */ - movb %dl, 2(%si) - jmp 3f /* return */ -1: - - -#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - pushw %cs:(int13_old_flags - int13_handler) - popfw - - /* check if should restore(reversely map) the drive number */ - jc 1f /* restore DL on error */ - - /* alter MBR after read */ - - testb $0x80, %cs:7(%bp) /* TO_S */ - jz 2f - - cmpb $0x02, %ah - je 4f /* alter MBR */ - cmpb $0x42, %ah - je 4f /* alter MBR */ -2: - cmpb $0x08, %ah /* int13 AH=08h, read drive parameters */ - jne 2f - - /* DL==number of drives, should not restore */ - xorw %ax, %ax - movw %ax, %ds - movb 0x475, %dl /* DL=number of hard drives */ - testb $0x80, %cs:(int13_old_edx - int13_handler) /* harddrive? */ - jnz 3f /* yes, jump */ - //movw $0x10, %bx /* for floppy, refer to function 0x48 */ - movb 0x410, %al - rorb $1, %al - cbw - shlb $1, %al - shrb $6, %al - incw %ax - andb %ah, %al - movb %al, %dl /* DL=number of floppy drives */ - //lesw 0x0078, %di /* point to int 1E floppy parameters */ - jmp 3f -2: - cmpb $0x15, %ah /* read drive type */ - jne 2f - testb $0x80, %cs:(int13_old_edx - int13_handler) /* harddrive? */ - jnz 3f /* yes, do not restore DL */ - /* restore DL for floppy int13 AH=15h call */ - jmp 1f -4: - call modify_in_situ - movl %cs:(int13_old_ebx - int13_handler), %ebx - movl %cs:(int13_old_ecx - int13_handler), %ecx - movl %cs:(int13_old_edx - int13_handler), %edx - movl %cs:(int13_old_edi - int13_handler), %edi - movw %cs:(int13_old_es - int13_handler), %es -2: - movw %cs:(%bp), %ax /* get the drive mapping */ - /* try to restore DL if possible */ - cmpb %al, %ah /* check if the mapping was performed */ - je 3f /* not performed, so need not restore DL */ - cmpb %dl, %ah - jne 3f /* DL changed by int13, so do not restore */ -1: - movb %cs:(int13_old_edx - int13_handler), %dl /* restore DL back to the FROM drive */ -3: - /* return */ - - /* BX, CX, DX, ES, DI are output registers and should not touch. */ - - pushw %cs:(int13_old_flags - int13_handler) - popfw - - movl %cs:(int13_old_esi - int13_handler), %esi - movw %cs:(int13_old_ds - int13_handler), %ds - movl %cs:(int13_old_eax - int13_handler), %eax - movl %cs:(int13_old_ebp - int13_handler), %ebp - movw %cs:(int13_old_esp - int13_handler), %sp - ljmp *%cs:(int13_old_cs_ip - int13_handler) - -/****************************************************************************/ -restricted_map: - movw %cs:(int13_old_eax - int13_handler), %ax - - /* CHS read functions */ - cmpb $0x02, %ah /* read sectors */ - je 2f - cmpb $0x04, %ah /* verify sectors, also a read operation */ -// # these checks are not too useful, so comment out to save space -// je 2f -// cmpb $0x0a, %ah /* read long sectors */ -// je 2f -// cmpb $0x0c, %ah /* seek to cylinder */ -// je 2f -// cmpb $0x21, %ah /* PS/1 PS/2 - read multiple disk sectors */ - jne 1f -2: - movb %cs:3(%bp), %ah /* AH=Smax */ - testb $63, %ah /* check if Sectors=0, i.e., disable CHS */ - jz error_01_disable - ret -1: - /* CHS write functions */ - cmpb $0x03, %ah /* CHS write sectors */ - je 2f - cmpb $0x05, %ah /* PC/XT/AT/EISA format tracks */ -// # these checks are not too useful, so comment out to save space -// je 2f -// cmpb $0x06, %ah /* PC/XT format tracks with bad sectors */ -// je 2f -// cmpb $0x07, %ah /* PC/XT format multiple cylinders */ -// je 2f -// cmpb $0x0b, %ah /* PC/XT/AT/EISA write sectors with ECC */ -// je 2f -// cmpb $0x0f, %ah /* PC/XT/PS/1 write sector buffer */ -// je 2f -// cmpb $0x22, %ah /* PS/1 PS/2 - write multiple disk sectors */ - jne 1f -2: - movb %cs:3(%bp), %ah /* AH=Smax */ - testb $63, %ah /* check if Sectors=0, i.e., disable CHS */ - jz error_01_disable - testb $0x80, %ah /* readonly access? */ - jnz readonly_fakewrite - ret -1: - /* LBA read functions */ - cmpb $0x41, %ah /* Extensions - INSTALLATION CHECK */ - je 2f - cmpb $0x42, %ah /* Extensions - EXTENDED READ */ - je 2f - cmpb $0x44, %ah /* Extensions - verify sectors */ - je 2f -// # these checks are not too useful, so comment out to save space -// cmpb $0x45, %ah /* Extensions - LOCK/UNLOCK DRIVE */ -// je 2f -// cmpb $0x46, %ah /* Extensions - EJECT MEDIA */ -// je 2f -// cmpb $0x47, %ah /* Extensions - EXTENDED SEEK */ -// je 2f - cmpb $0x48, %ah /* Extensions - GET DRIVE PARAMETERS */ -// # these checks are not too useful, so comment out to save space -// je 2f -// cmpb $0x49, %ah /* Extensions - detect media change */ -// je 2f -// cmpb $0x4a, %ah /* CDROM - INITIATE DISK EMULATION */ -// je 2f -// cmpb $0x4b, %ah /* CDROM - TERMINATE DISK EMULATION */ -// je 2f -// cmpb $0x4c, %ah /* CDROM - INITIATE DISK EMULATION AND BOOT */ -// je 2f -// cmpb $0x4d, %ah /* CDROM - RETURN BOOT CATALOG */ -// je 2f -// cmpb $0x4e, %ah /* Extensions - SET HARDWARE CONFIGURATION */ - jne 1f -2: - movb %cs:3(%bp), %ah /* AH=Smax */ - testb $64, %ah /* disable LBA? */ - jnz error_01_disable - ret -1: - /* LBA write functions */ - cmpb $0x43, %ah /* Extensions - EXTENDED WRITE */ - jne 1f -2: - movb %cs:3(%bp), %ah /* AH=Smax */ - testb $64, %ah /* disable LBA? */ - jnz error_01_disable - testb $0x80, %ah /* readonly access? */ - jnz readonly_fakewrite -1: - /* no restrictions, return and continue */ - ret - -error_01_disable: - /* function not supported, or the input CHS is invalid */ - movl %cs:(int13_old_eax - int13_handler), %eax - movb $0x01, %ah /* invalid function call */ -1: - pushw %cs:(int13_old_flags - int13_handler) - popfw - stc /* error */ - jmp 1f - -readonly_fakewrite: - testb $0x40, %cs:7(%bp) /* bit 6 of TO_S */ - movl %cs:(int13_old_eax - int13_handler), %eax - movb $0x03, %ah /* write protection */ - jz 1b /* read only */ - xorb %ah, %ah /* fake write */ - pushw %cs:(int13_old_flags - int13_handler) - popfw - clc /* write succeeded */ -1: - movl %cs:(int13_old_esi - int13_handler), %esi - movw %cs:(int13_old_ds - int13_handler), %ds - movl %cs:(int13_old_ebp - int13_handler), %ebp - movw %cs:(int13_old_esp - int13_handler), %sp - ljmp *%cs:(int13_old_cs_ip - int13_handler) - - -/****************************************************************************/ -drive_emulation: - movw %cs:2(%bp), %ax /* AL=Hmax, AH=Smax */ - testb $63, %ah /* disable CHS? */ - jz 2f /* yes, call restricted map */ - testb $0xc0, %ah /* readonly or disable LBA? */ - jz 1f -2: - call restricted_map -1: - movw %cs:(int13_old_eax - int13_handler), %ax - - testb %ah, %ah /* reset disk system, always succeed */ - jnz 1f - /*clc*/ /* CF already cleared by TEST */ - jmp int13_return -/****************************************************************************/ -1: - cmpb $0x01, %ah /* get status, always succeed */ - jnz 1f - xorb %ah, %ah - jmp int13_return -/****************************************************************************/ -1: - cmpb $0x04, %ah /* verify sectors, always succeed */ - jnz 1f - xorb %ah, %ah - jmp int13_return -/****************************************************************************/ -// # this check is not too useful, so comment out to save space -//1: -// cmpb $0x09, %ah /* INITIALIZE CONTROLLER WITH DRIVE PARAMETERS */ -// jnz 1f -// testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ -// jnz error_01_invalid /* CDROM */ -// xorb %ah, %ah -// jmp int13_return -/****************************************************************************/ -// # this check is not too useful, so comment out to save space -//1: -// cmpb $0x0c, %ah /* SEEK TO CYLINDER */ -// jnz 1f -// testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ -// jnz error_01_invalid /* CDROM */ -// xorb %ah, %ah -// jmp int13_return -/****************************************************************************/ -// # this check is not too useful, so comment out to save space -//1: -// cmpb $0x0d, %ah /* reset hard disks */ -// jnz 1f -// testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ -// jnz error_01_invalid /* CDROM */ -// xorb %ah, %ah -// jmp int13_return -/****************************************************************************/ -// # this check is not too useful, so comment out to save space -//1: -// cmpb $0x10, %ah /* check if drive ready */ -// jnz 1f -// testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ -// jnz error_01_invalid /* CDROM */ -// xorb %ah, %ah -// jmp int13_return -/****************************************************************************/ -// # this check is not too useful, so comment out to save space -//1: -// cmpb $0x11, %ah /* recalibrate drive */ -// jnz 1f -// testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ -// jnz error_01_invalid /* CDROM */ -// xorb %ah, %ah -// jmp int13_return -/****************************************************************************/ -// # this check is not too useful, so comment out to save space -//1: -// cmpb $0x14, %ah /* CONTROLLER INTERNAL DIAGNOSTIC */ -// jnz 1f -// testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ -// jnz error_01_invalid /* CDROM */ -// xorb %ah, %ah -// jmp int13_return -/****************************************************************************/ -1: - cmpb $0x05, %ah /* format track */ - jnz 1f - testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ - jnz error_01_invalid /* CDROM */ - - /* CH=cylinder number (bits 8,9 in high bits of CL) - * CL=high bits of cylinder number (bits 7,6) - * DH=head number - * DL=drive number - */ - - xorb %ah, %ah /* do nothing but return success */ - jmp int13_return -/****************************************************************************/ -1: - cmpb $0x08, %ah /* get drive parameters */ - jnz 1f - testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ - jnz error_01_invalid /* CDROM */ - pushw %ds - xorw %ax, %ax - movw %ax, %ds - testb %dl, %dl /* hard drive? */ - movb 0x475, %dl /* DL=number of hard drives */ - js 2f /* yes, jump */ - movw $0x10, %bx /* for floppy, refer to function 0x48 */ - movb 0x410, %al - rorb $1, %al - cbw - shlb $1, %al - shrb $6, %al - incw %ax - andb %ah, %al - xchgw %ax, %dx /* DL=number of floppy drives */ - lesw 0x0078, %di /* point to int1E floppy parameters */ -2: - popw %ds - movw %cs:2(%bp), %ax /* AL=Hmax, AH=Smax */ - movb %al, %dh /* max head number */ - andb $63, %ah - movb %ah, %cl /* max sector number */ - - /* max cylinder number */ - - pushl %edx - pushl %ecx - movzbl %dh, %eax - movzbl %cl, %ecx - incl %eax - mull %ecx /* EDX=0, EAX=sectors per cylinder */ - xchgl %eax, %ecx - - movl %cs:16(%bp), %eax /* S_count_Lo */ - cmpl $4, %eax - ja 2f - cmpl $0, %cs:8(%bp) /* StartLBA_Lo */ - jnz 2f - /* map whole drive, use TO_C instead. */ - movw %cs:4(%bp), %ax /* TO_C */ - jmp 3f -2: - decl %eax - //xorl %edx, %edx - divl %ecx /* EAX=max cylinder number */ -3: - popl %ecx - popl %edx - - movb %al, %ch /* low 8 bits of cylinder */ - shlb $6, %ah /* high 2 bits of cylinder */ - orb %ah, %cl - - xorw %ax, %ax - jmp int13_return -/****************************************************************************/ -1: - cmpb $0x15, %ah /* get disk type */ - jnz 1f - testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ - jnz error_01_invalid /* CDROM */ - testb %dl, %dl /* hard drive? */ - js 2f /* yes, jump */ - movb $0x02, %ah /* floppy (or other removable drive) with change-line support */ - clc - jmp int13_return -2: - movb $0x03, %ah /* hard disk */ - - /* CX:DX=total number of sectors */ - movw %cs:16(%bp), %dx /* lo word of S_count_Lo */ - movw %cs:18(%bp), %cx /* hi word of S_count_Lo */ - clc - jmp int13_return -/****************************************************************************/ - # lbacache requires this. See http://reboot.pro/14924/ -1: - # FLOPPY DISK - DETECT DISK CHANGE (XT 1986/1/10 or later,XT286,AT,PS) - - cmpb $0x16, %ah - jnz 1f -// testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ -// jnz error_01_invalid /* CDROM */ - xorb %ah, %ah /* AH=0 means disk not changed */ - jmp int13_return -/****************************************************************************/ -// # this check is not too useful, so comment out to save space -//1: -// cmpb $0x17, %ah /* set floppy type for format */ -// jnz 1f -// testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ -// jnz error_01_invalid /* CDROM */ -// movb $0x03, %al /* 1.44M drive, 1.44M floppy */ -// xorb %ah, %ah -// jmp int13_return -/****************************************************************************/ -// # this check is not too useful, so comment out to save space -//1: -// cmpb $0x18, %ah /* set media type for format */ -// jnz 1f -// testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ -// jnz error_01_invalid /* CDROM */ -// testb %dl, %dl /* hard drive? */ -// js error_01_invalid -// pushw %ax -// xorw %ax, %ax -// movw %ax, %es -// movw $0x0078, %di -// movl %es:(%di), %eax -// movw %ax, %di -// shrl $0x10, %eax -// movw %ax, %es -// popw %ax -// xorb %ah, %ah -// jmp int13_return -/****************************************************************************/ -1: - /* Now AH is neither 0 nor 1 */ - - testb $0xfc, %ah /* CHS read/write sectors */ - jnz 1f - - /* so AH is either 2(for read) or 3(for write) */ - - testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ - jnz error_01_invalid /* CDROM */ - - cmpw $0x0301, %ax /* is it write 1 sector? */ - jne 2f - cmpw $0x0001, %cx /* write to cylinder 0, sector 1? */ - jne 2f - cmpb $0x01, %dh /* write to head 0 or 1? */ - ja 2f - /* cmpw $0xaa55, %es:0x1fe(%bx) - je 2f */ - testb %dl, %dl - js 3f /* protect hard disk head 0 and 1 */ - testb %dh, %dh /* write to floppy head 0? */ - jne 2f /* no, write permitted */ -3: - testb $0x40, %cs:7(%bp) /* TO_S, bit 6=fake write(safeboot) */ - jnz readonly_fakewrite /* fake the write */ -2: - cmpb $0x7F, %al /* check if sectors exceed 127 */ - ja error_01_invalid - testb %al, %al /* read 0 sectors not allowed */ - jz error_01_invalid - testb $63, %cl /* beginning sector number 0 is invalid */ - jz error_01_invalid - movb %cs:3(%bp), %ah /* AH=Smax */ - andb $63, %ah - pushw %cx - andb $63, %cl - cmpb %ah, %cl /* CL should not > max sector number */ - popw %cx - ja error_01_invalid - movb %cs:2(%bp), %ah /* AH=Hmax */ - cmpb %ah, %dh /* DH should not > max head number */ - ja error_01_invalid - - movw %cs, %si /* use SI as temp var, instead of AX */ - movw %si, %ds /* DS=CS */ - - movw $(EBIOS_disk_address_packet - int13_handler), %si - movw $0x0010, (%si) /* Disk Address Packet length */ - movb %al, 2(%si) /* number of sectors to transfer */ - movw %bx, 4(%si) /* offset */ - movw %es, 6(%si) /* segment */ - xorl %eax, %eax /* EAX=0 */ - movb %ah, 3(%si) /* sectors_hi_reserved */ - movl %eax, 12(%si) /* zero out hi 32 bits */ - movb %ch, %al /* cylinder number lo 8 bits */ - movb %cl, %ah /* CL holds higher 2 bits */ - shrb $6, %ah /* AH lower holds the 2 bits */ - /* EAX=cylinder number, <1024 */ - pushl %ebx /* save EBX */ - - xorl %ebx, %ebx /* EBX=0 */ - movb %cs:2(%bp), %bl /* BL=Hmax */ - incw %bx /* EBX=total heads, <=256 */ - - pushl %edx - mull %ebx /* EDX=0, EAX=tracks before this cylinder */ - popl %edx - - xorw %bx, %bx /* EBX=0 */ - movb %dh, %bl /* EBX=head number */ - addl %ebx, %eax /* EAX=tracks before this head */ - movb %cs:3(%bp), %bl /* Max sector number */ - andb $63, %bl /* EBX=sectors per track */ - - pushl %edx - mull %ebx /* EDX=0, EAX=sectors before this head */ - popl %edx - - movb %cl, %bl /* sector number */ - andb $63, %bl - decb %bl - addl %ebx, %eax /* EAX=lo 32 bits of logical sector number */ - movl %eax, 8(%si) - - popl %ebx /* restore EBX */ - -disk_address_packet_ready: - - /* DS=CS */ - - /* start-sector-number(LBA) in DAP is still for FROM_DRIVE */ - -/****************************************************************************/ - /* - * check if the request exceeds the boundary of the emulated disk. - * - * input: DS:SI - * output: CF=0, success, all sectors transferred - * CF=1, failure, no sectors transferred - * EAX changed - * - */ - cmpl $0, %cs:20(%bp) /* S_count_Hi */ - ja 2f - cmpl $1, %cs:16(%bp) /* S_count_Lo */ - ja 2f - cmpl $0, %cs:12(%bp) /* StartLBA_Hi */ - jne 2f - cmpl $0, %cs:8(%bp) /* StartLBA_Lo */ - je 4f /* map whole drive, no restrictions */ -2: - movl %cs:20(%bp), %eax /* S_count_Hi */ - cmpl %eax, 12(%si) /* requested StartLBA_Hi */ - ja 3f - jb 2f - movl %cs:16(%bp), %eax /* S_count_Lo */ - cmpl %eax, 8(%si) /* requested StartLBA_Lo */ - jnb 3f -2: - pushl %ebx - subl 8(%si), %eax - movl %cs:20(%bp), %ebx /* S_count_Hi */ - sbbl 12(%si), %ebx /* EBX:EAX available sectors */ - testl %ebx, %ebx /* CF=0 */ - popl %ebx - jnz 4f - pushl %ebx - movzwl 2(%si), %ebx /* requested sectors */ - cmpl %ebx, %eax - popl %ebx -// jnb 4f -//3: -// stc -4: -/****************************************************************************/ - - jc 3f /* no sectors to transfer, fail */ - -// To_count(0) To_count(1) To_count(2) To_count(3) -// ੤੤੤ -//To_start(0) To_start(1) To_start(2) To_start(3) -// Form_len -// -// 0 Form_statr - - pushaw - movw 2(%si), %ax - movw %ax, %cs:(old_form_len - int13_handler) - movw 4(%si), %ax - movw %ax, %cs:(old_form_offset - int13_handler) - movl 8(%si), %eax - movl %eax, %cs:(old_form_statr_lo - int13_handler) - movl 12(%si), %eax - movl %eax, %cs:(old_form_statr_hi - int13_handler) - movw $0, %cs:(next_fragment_len - int13_handler) - xorw %di, %di - testw $0x400, %cs:4(%bp) - je no_sp - movw $(EXT_C(hooked_fragment_map) - int13_handler), %bp - -2: - cmpb $0, %cs:(%bp) - je no_sp - cmpb %dl, %cs:2(%bp) - je 2f - movzbw %cs:(%bp), %ax - addw %ax, %bp - loop 2b -2: - movw %bp, %cs:(next_fragment_base - int13_handler) - movl 8(%si), %eax //Form_statr_Lo 0000 - movl 12(%si), %ebx //Form_statr_Hi 0000 - xorl %ecx, %ecx - xorl %edx, %edx -2: - addl %cs:12(%bp,%di), %ecx //To_count(0i) + To_count(i+1) - adcl %cs:16(%bp,%di), %edx - call compare_64 //Form_statr <> To_count(0i) - jb 2f - addw $16, %di -// cmpw $(16*DRIVE_MAP_FRAGMENT), %di -// jb 2b - jmp 2b -2: - addl %cs:12(%bp,%di), %eax //Form_statr + To_count(i) - adcl %cs:16(%bp,%di), %ebx - addl %cs:4(%bp,%di), %eax //Form_statr + To_count(i) + To_start(i) - adcl %cs:8(%bp,%di), %ebx - subl %ecx, %eax //Form_statr + To_count(i) + To_start(i) - To_count(0i) - sbbl %edx, %ebx - - subl 8(%si), %ecx //To_count(0i) - Form_statr - sbbl 12(%si), %edx - movl %eax, 8(%si) //Form_statr - To_count(0i-1) + To_start(i) - movl %ebx, 12(%si) - movzwl 2(%si), %eax //Form_len - xorl %ebx, %ebx - call compare_64 //Form_len <> To_count(0i) - Form_statr - jbe 2f - - movw %cx, 2(%si) //To_count(0i) - Form_statr - subw %cx, %ax //Form_len - (To_count(0i) - Form_statr) - movw %ax, %cs:(next_fragment_len - int13_handler) - addw $16, %di - movw %di, %cs:(next_fragment_offset - int13_handler) -2: - popaw - jmp 2f - - -no_sp: - popaw - - /* adjust start-sector-number(LBA) to access TO_DRIVE */ - movl %cs:8(%bp), %eax /* StartLBA_Lo */ - addl %eax, 8(%si) - movl %cs:12(%bp), %eax /* StartLBA_Hi */ - adcl %eax, 12(%si) - -2: - /* set drive number(TO_DRIVE) and function number(EBIOS) */ - movb %cs:1(%bp), %dl /* DL=TO_DRIVE */ - movb %cs:(int13_old_eax - int13_handler + 1), %ah - /* 0x02=read, 0x03=write */ - orb $0x40, %ah /* 0x42=EXT_read, 0x43=EXT_write */ - - call real_int13_service - - jc 3f /* failure */ - -2: - pushaw - movw %cs:(next_fragment_len - int13_handler), %cx - orw %cx, %cx - je 2f - - movw %cs:(next_fragment_base - int13_handler), %bp - movw $0, %cs:(next_fragment_len - int13_handler) - movw %cs:(next_fragment_offset - int13_handler), %di - movl %cs:4(%bp,%di), %eax - movl %eax, 8(%si) - movl %cs:8(%bp,%di), %eax - movl %eax, 12(%si) - movw 4(%si), %ax - movw 2(%si), %bx - shlw $9, %bx - addw %bx, %ax - movw %ax, 4(%si) - movw %cs:12(%bp,%di), %ax - cmpw %ax, %cx - jbe 4f - - subw %ax, %cx - movw %cx, %cs:(next_fragment_len - int13_handler) - addw $16, %di - movw %di, %cs:(next_fragment_offset - int13_handler) - xchgw %ax, %cx -4: - movw %cx, 2(%si) - popaw - call real_int13_service - jc 3f /* failure */ - jmp 2b - -2: - popaw - testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ - jnz 4f /* CDROM */ - - movw $(EBIOS_disk_address_packet - int13_handler), %si - movw %cs, %ax - movw %ax, %ds - - /* restore original start-sector-number(in the DAP) */ -// movl %cs:8(%bp), %eax /* StartLBA_Lo */ -// subl %eax, 8(%si) -// movl %cs:12(%bp), %eax /* StartLBA_Hi */ -// sbbl %eax, 12(%si) - - movw %cs:(old_form_len - int13_handler), %ax - movw %ax, 2(%si) - movw %cs:(old_form_offset - int13_handler), %ax - movw %ax, 4(%si) - movl %cs:(old_form_statr_lo - int13_handler), %eax - movl %eax, 8(%si) - movl %cs:(old_form_statr_hi - int13_handler), %eax - movl %eax, 12(%si) - - call modify_boot_sectors -4: - movb %cs:(int13_old_eax - int13_handler), %al - xorb %ah, %ah - jmp 4f /* success */ - -3: - movw $0x400, %ax /* no sectors transferred */ - /* write back sectors transferred to original DAP for LBA access */ - cmpb $0x40, %cs:(int13_old_eax - int13_handler + 1) - jb 4f /* CF=1, function 02 or 03, not an LBA call */ - - movw %cs:(int13_old_esi - int13_handler), %si - movw %cs:(int13_old_ds - int13_handler), %ds - - /* DS:SI -> original DAP */ - movb %al, 2(%si) - stc /* failure */ -4: - movl %cs:(int13_old_edx - int13_handler), %edx - movl %cs:(int13_old_ebx - int13_handler), %ebx - movl %cs:(int13_old_ecx - int13_handler), %ecx - movl %cs:(int13_old_edi - int13_handler), %edi - movw %cs:(int13_old_es - int13_handler), %es - jmp int13_return - -old_form_statr_lo: - .long 0 -old_form_statr_hi: - .long 0 -old_form_len: - .word 0 -old_form_offset: - .word 0 -next_fragment_base: - .word 0 -next_fragment_offset: - .word 0 -next_fragment_len: - .word 0 - -//input: ebx=A_hi, eax=A_lo, edx=B_hi, ecx=B_lo -compare_64: - cmpl %edx, %ebx //A_hi <> B_hi - jne compare_64_end //A_hi != B_hi, end - //A_hi = B_hi - cmpl %ecx, %eax //A_lo <> B_lo -compare_64_end: - ret -/****************************************************************************/ -1: - cmpb $0x41, %ah /* EBIOS installation check */ - jnz 1f - cmpw $0x55aa, %bx - jnz error_01_invalid -// testb %dl, %dl -// jns error_01_invalid - movw $0xaa55, %bx - movb $0x21, %ah /* major version 2.1(EDD-1.1) */ - movw $0x01, %cx /* support functions 42h,43h,44h,47h,48h */ - clc - jmp int13_return -/****************************************************************************/ -1: - cmpb $0x42, %ah /* EBIOS read sectors */ - jz 2f - cmpb $0x43, %ah /* EBIOS write sectors */ - jnz 1f - -// testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ -// jz 2f -// -// /* CDROM */ -// movb $0x03, %ah /* write protection */ -// stc /* error */ -// jmp int13_return -2: - /* get old SI, disk address packet */ - movw %cs:(int13_old_esi - int13_handler), %si - movl (%si), %eax /* packet length, sectors, etc. */ - testb %ah, %ah - jnz error_01_invalid - testb $0xf0, %al - jz error_01_invalid - shrl $16, %eax - testw $0xff80, %ax - jnz error_01_invalid - testb %al, %al - jz error_01_invalid - - /* copy disk address packet to EBIOS_disk_address_packet */ - - pushw %es - pushw %cx - pushw %di - - movw %cs, %ax - movw %ax, %es /* ES=CS */ - - movw $(EBIOS_disk_address_packet - int13_handler), %di - movw $8, %cx /* will copy only 16 bytes! */ - cld - repz movsw - - popw %di - popw %cx - popw %es - - /* set DS:SI */ - - movw %cs, %ax - movw %ax, %ds /* DS=CS */ - movw $(EBIOS_disk_address_packet - int13_handler), %si - - testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ - jz 2f - shlb $2, 2(%si) - movl 8(%si), %eax - shldl $2, %eax, 12(%si) - shll $2, 8(%si) -2: - //movw 4(%si), %bx - //movw 6(%si), %es - lesw 4(%si), %bx - jmp disk_address_packet_ready - -/****************************************************************************/ -1: - cmpb $0x44, %ah /* EBIOS verify sectors */ - jnz 1f - xorb %ah, %ah - clc - jmp int13_return -/****************************************************************************/ -// # this check is not too useful, so comment out to save space -//1: -// cmpb $0x47, %ah /* EBIOS seek */ -// jnz 1f -// xorb %ah, %ah -// clc -// jmp int13_return -/****************************************************************************/ -1: - cmpb $0x48, %ah /* EBIOS GET DRIVE PARAMETERS */ - jnz 1f - - testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ - jz 2f /* normal disks */ - - /* CDROM */ - /* get old SI, extended drive parameter table */ - movw %cs:(int13_old_esi - int13_handler), %si - cmpw $26, (%si) - jb error_01_invalid - - movw $26, (%si) /* buffer length */ - movw $0x00, 2(%si) # no flags - movw $0x800, 24(%si) # bytes per sect=2048 - xorl %eax, %eax - decw %ax - movl %eax, 4(%si) # cylinders=0xFFFF - movb $0, %ah - movl %eax, 8(%si) # heads=0xFF - movb $15, %al - movl %eax, 12(%si) # sectors per track=15 - xorw %ax, %ax # CF cleared - movl %eax, 20(%si) # total sectors hi dword=0 -// xorw %ax, %ax # CF cleared - decl %eax # EAX=0xFFFFFFFF - movl %eax, 16(%si) # total sectors lo dword - # CF is cleared - - xorw %ax, %ax /* success, CF cleared */ - jmp int13_return -2: - /* get old SI, extended drive parameter table */ - movw %cs:(int13_old_esi - int13_handler), %si - movw $26, (%si) /* buffer length */ - movw $2, 2(%si) /* info */ - xorl %eax, %eax - movl %eax, 8(%si) /* total heads */ - movl %eax, 12(%si) /* sectors per track */ - movl %eax, 16(%si) /* total sectors */ - movl %eax, 20(%si) /* total sectors hi */ - pushl %ebx - xorl %ebx, %ebx - movw %cs:2(%bp), %ax /* AL=Hmax, AH=Smax */ - andb $63, %ah - movb %ah, 12(%si) /* sectors per track */ - movb %ah, %bl - xorb %ah, %ah - incw %ax /* total heads=Hmax+1 */ - movw %ax, 8(%si) /* total heads */ - pushl %edx - mulw %bx /* DX:AX=product, DX=0 */ - movw %ax, %bx /* BX=sectors per cylinder */ - movl %cs:20(%bp), %edx /* S_count_Hi */ - movl %edx, 20(%si) /* total sectors hi */ - movl %cs:16(%bp), %eax /* S_count_Lo */ - movl %eax, 16(%si) /* total sectors lo */ - /*xorl %edx, %edx*/ /* EDX:EAX=64bit total sectors */ - testw %bx, %bx - jz 2f - divl %ebx /* EAX=quotient, EDX=residue */ -2: - testl %edx, %edx - popl %edx - popl %ebx - jz 2f - incl %eax -2: - movl %eax, 4(%si) /* total cylinders */ - movw $512, 24(%si) /* bytes per sector */ - xorb %ah, %ah - /*clc*/ /* signal success, CF already cleared by XOR */ - jmp int13_return - -/****************************************************************************/ -1: - cmpw $0x4B01, %ax /* CDROM GET DISK EMULATION STATUS */ - jnz 1f - - testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ - jz error_01_invalid /* normal disks have no 0x4B01 function */ - - /* CDROM */ - pushw %es - pushw %di - movw %cs:(int13_old_esi - int13_handler), %di /* old SI */ - pushw %ds - popw %es - movw $0x0013, %ax /* packet size=13h, boot type=0 (no-emu) */ - cld - stosw - movb %dl, %al /* drive=DL, controller=0 */ - stosw - - pushl %cs:EXT_C(lba_cd_boot) - int13_handler - popw %ax - stosw - popw %ax - stosw /* LBA for no-emu image */ - - xorw %ax, %ax - stosw /* device specification */ - stosw /* user buffer segment */ - stosw /* load segment */ - movb $4, %al - stosw /* sector count=4 */ - /* CHS makes no sense for no-emu */ - popw %di - popw %es - xorb %ah, %ah /* success, CF cleared */ - jmp int13_return - -/****************************************************************************/ -1: -/****************************************************************************/ -error_01_invalid: - movb $0x01, %ah /* unsupported function call */ - stc /* signal error */ - -int13_return: - movw %ax, %cs:(int13_old_eax - int13_handler) /* status */ - jnc 1f - orb $1, %cs:(int13_old_flags - int13_handler) - jmp 2f -1: - andb $0xFE, %cs:(int13_old_flags - int13_handler) -2: - pushw %cs:(int13_old_flags - int13_handler) - popfw - - movl %cs:(int13_old_eax - int13_handler), %eax - movl %cs:(int13_old_esi - int13_handler), %esi - movw %cs:(int13_old_ds - int13_handler), %ds - movl %cs:(int13_old_ebp - int13_handler), %ebp - movw %cs:(int13_old_esp - int13_handler), %sp - ljmp *%cs:(int13_old_cs_ip - int13_handler) - -/****************************************************************************/ -real_int13_service: - - /* AH = 0x42 or 0x43 */ - - /* save return address to memory */ - popw %cs:(int13_ret_IP - int13_handler) - /* save AX to memory */ - movw %ax, %cs:(int13_reg_AX - int13_handler) - - cmpb $0xff, %dl /* mem drive */ - jne normal_disk_drive - - testw $0x4000, %cs:4(%bp) /* TO_C bit 14=(TO is cdrom) */ - jnz normal_disk_drive - - /* handle memdrive */ - - sti /* for hardware interrupt or watchdog */ - cmpb $0x42, %ah - je 3f - cmpb $0x43, %ah - je 3f - stc - jmp *%cs:(int13_ret_IP - int13_handler) //ret - /* DS:SI points to disk address packet */ - /* 2(%si), byte, sectors(1-127) */ - /* 4(%si), word, offset */ - /* 6(%si), word, segment */ - /* 8(%si), qword, lba */ -3: - /* AH = 0x42 or 0x43 */ - movzwl 4(%si), %ebx #; BX=offset, EBX_high_word=0 - movzwl 6(%si), %edi #; DI=segment - shll $4, %edi #; EDI=linear base address of segment - addl %ebx, %edi #; EDI=linear address of BUFFER(below 1M) - - movl 12(%si), %ebx #; EBX=LBA of MEMDRIVE SECTOR hi - movl 8(%si), %ecx #; ECX=LBA of MEMDRIVE SECTOR lo - shldl $9, %ecx, %ebx - shll $9, %ecx #; EBX:ECX=linear address of SECTOR(above 1M) - //xorl %edx, %edx - movl %edi, %cs:(data_addr_below_1M - int13_handler) - //movl %edx, %cs:(data_addr_below_1M - int13_handler + 4) - movl %ecx, %cs:(data_addr_above_1M - int13_handler) - movl %ebx, %cs:(data_addr_above_1M - int13_handler + 4) - testl %ebx, %ebx - setnz %dl - movzbl 2(%si), %ebx # sectors to read/write - shll $9, %ebx # bytes to read/write - decl %ebx - addl %ecx, %ebx - setc %dh - orb %dh, %dl - movb %dl, %cs:(int13_need_64_bit - int13_handler) - - /* if RAM disk is at above 4G, the int15/ah=87h call will fail. */ - - # int15/ah=87h is buggy on many BIOSes. You should use the default RAW. - cmpl $0, %cs:(EXT_C(memdisk_raw) - int13_handler) - je int15_87 /* do not use raw mode, but use BIOS. */ - - # win9x vm86-mode int15/ah=87h will also fail in accessing more than 4G - # memory. Hope someone would develop a driver for win9x in the future. - smsw %bx - testb $1, %bl - jnz int15_87 /* vm86/protected mode also need int15_87 */ - - /* raw mode as in memdisk, contributed by Bean */ - - /* switch to protected mode myself */ - /* ebx destroy */ - - /* EDI=linear address of BUFFER(below 1M) */ - /* ECX=linear address of SECTOR(above 1M), lower 32 bits */ - movzbl 2(%si), %ebx # sectors to read/write - shll $9, %ebx # bytes to read/write - movl %ebx, %edx # bytes to read/write - addl %edi, %ebx # point to the byte after the buffer - decl %ebx # point to the last byte of the source - orl %edi, %ebx # to see if the buffer is inside an even mega - addl %ecx, %edx # point to the byte after the sectors - decl %edx # point to the last byte of the sectors - orl %ecx, %edx # to see if the sectors is inside an even mega - orl %ebx, %edx # to see if both are in even megas - andl $0x100000, %edx # zero means both are in even megas, DX=0 - setz %dl # we think of it as if A20 were on - jz 3f # no need to enable A20. DX=1. - - /* DX=0 */ - movw $0x00ff, %cx # try so many times on failure - incw %dx # DL=1(enable A20), DH=0(debug off) - - cli /* yes, keep interrupt off when controlling A20 */ - call enable_disable_a20 # EAX, CX modified - sti - - setc %dl # CF=1 means A20 was originally enabled. - jz 3f /* enabled A20 with success */ - - /* A20 control failed. Notify the user. */ - movw $(a20_failure - int13_handler), %si - xorw %bx, %bx -5: - lodsb - cmpb $0x20, %al - jb 5f - movb $0x0e, %ah /* print it */ - int $0x10 /* via TTY mode */ - jmp 5b -5: - stc - jmp *%cs:(int13_ret_IP - int13_handler) //ret - -a20_failure: - .ascii "\r\ngrub4dos: A20 failure.\r\n\0" - -3: - /* EDI=linear address of BUFFER(below 1M) */ - xorl %ebx, %ebx - movw $(EBIOS_disk_address_packet - int13_handler), %si - movw %cs, %bx - movw %bx, %ds - - // GDT is initialized by set_int13_handler - //shll $4, %ebx - //addl $(MyGDT - int13_handler), %ebx - //movl %ebx, %cs:MyGDT - int13_handler + 4 - - movzbl 2(%si), %ecx #; ECX=number of sectors to transfer - shll $7, %ecx /* 128 dwords per sector */ - cld - - sgdtl %cs:(OldGDTdesc - int13_handler) - lgdt %cs:(gdtdesc - int13_handler) - testb $0xFF, %cs:(int13_need_64_bit - int13_handler) # need 64 bit? - jnz move_block_using_64_bit # yes - //jmp move_block_using_64_bit /* only test 64-bit code */ - - /*********************************/ - /* normal 32-bit(4GB) block move */ - /*********************************/ - - /* EDI=linear address of BUFFER(below 1M) */ - - //movl %cs:(data_addr_below_1M - int13_handler), %edi - movl %cs:(data_addr_above_1M - int13_handler), %esi - testb $1, %cs:(int13_reg_AX - int13_handler + 1) # AH - jz 3f # read - xchgl %esi, %edi -3: - #; ESI changed!! - movl %cr0, %eax - //andl $0x7FFFFFFF, %eax - orb $1, %al // set CR0.PE(bit0) - - cli - movl %eax, %cr0 /* Switch to protected mode */ - - movw $(PM_DS32), %bx /* Switch to 4G data segment */ - movw %bx, %ds - movw %bx, %es - - addr32 rep movsl /* ESI, EDI changed! */ - - /* Don't switch back to 64K limit for DS and ES. Keeping 4G limit - * would hurt nothing(in principle). There are softwares which run - * initially with DS and ES able to access 4G memory. They call - * int13 and expect on return the DS and ES could still access 4G - * memory. So we should not forcibly set the limit to a lower value - * of 64K. -- tinybit - */ -#if 0 - movw $(PM_DS16), %bx // 64KB data segment limit - movw %bx, %ds - movw %bx, %es -#endif - - //movl %cr0, %eax /* EAX not touched */ - andb $0xFE, %al // reset CR0.PE(bit0) - movl %eax, %cr0 // back to real mode - - /* no problem if we skip this and save some bytes of code. */ -#if 0 - movw %cs, %bx - movw %bx, %ds - movw %bx, %es -#endif - -move_block_finished: - lgdtl %cs:(OldGDTdesc - int13_handler) - - sti - - cmpl $0, (EXT_C(a20_keep_on) - int13_handler) - jne 1f /* Keep A20 on. This should hurt nothing. */ - - /* Disable A20 if necessary ! */ - testw %dx, %dx /* 0=orig A20 off, 1=orig A20 on */ - jnz 1f /* should not turn off A20 */ - - movw $0x0004, %cx # try so many times on failure - //xorw %dx, %dx # DL=0(disable A20), DH=0(debug off) - cli /* yes, keep interrupt off when controlling A20 */ - call enable_disable_a20 - sti - -1: - clc - jmp *%cs:(int13_ret_IP - int13_handler) //ret - -move_block_using_64_bit: - -#if 1 /* Yes, you may comment out the 64-bit code on a 32-bit platform. */ - - /* EDI=linear address of BUFFER(below 1M) */ - - /* DS=CS */ - - //movw %cs, /*%cs:*/(CS_seg - int13_handler) - //movw %es, /*%cs:*/(ES_seg - int13_handler) - //movw %fs, /*%cs:*/(FS_seg - int13_handler) - //movw %gs, /*%cs:*/(GS_seg - int13_handler) - //movw %ss, /*%cs:*/(SS_seg - int13_handler) - //movw %sp, /*%cs:*/(SP_off - int13_handler) - //movw %di, /*%cs:*/(DI_reg - int13_handler) - - ////sidtl %cs:OldIDT - int13_handler - movb %dl, /*%cs:*/(int13_prev_DL - int13_handler) /* save DL */ - movl %cr3, %eax - movl %eax, /*%cs:*/(int13_prev_CR3 - int13_handler) /* save CR3 */ - movl %cr4, %eax - movl %eax, /*%cs:*/(int13_prev_CR4 - int13_handler) /* save CR4 */ - - /* EDI=linear address of BUFFER(below 1M) */ - - /* if BUF_ADDR >= 16K, we build page tables at 4K, 8K and 12K; */ - /* otherwise, we build page tables at 84K, 88K and 92K. */ - /* in either case, the page tables will not overlap the buffer, */ - /* because the buffer length is <= 64K as for each int13 call. */ - xorl %ebx, %ebx - movb $0x01, %bh /* BX=0x0100 */ - cmpl $0x4000, %edi - jnb 3f - movb $0x15, %bh /* BX=0x1500 */ -3: - //movw %bx, /*%cs:*/(DS_seg - int13_handler) /* for page tables */ - movw %bx, %ds /* DS:0000 = PML4 base */ - /* DS changed!! DS != CS */ - - shll $4, %ebx /* EBX=0x1000 or 0x15000 */ - - movw %cs, %ax - movw %ax, %es - /* ES changed!! ES=CS */ - - movw $(int13_prev_PML4T_entry - int13_handler), %di - // DI = offset to backup variables - /* DI changed!! */ - xorw %si, %si - - //cld - cli - /* backup PML4 table and build it */ - /* lo of entry 0 */ - movsl - movl %ebx, %eax - addw $0x1007, %ax /* EAX=EAX+0x1007, CF=0 */ - movl %eax, -4(%si) //movl %eax, 0 - - /* hi of entry 0 */ - movsl - movl $0, -4(%si) //movl $0, 4 - - /* backup PDP table and build it */ - /* lo of entry 0 */ - movw $0x1000, %si - addw %si, %ax //CF=0, so the same as addl $0x1000, %eax - //EAX = (addr of PD | 7) - movsl - movl %eax, -4(%si) //movl %eax, 0x1000 - - /* hi of entry 0 */ - movsl - movl $0, -4(%si) //movl $0, 0x1004 - - /* backup PD table and build it */ - /* entry 0 is identity mapping, 2M page size */ - /* lo of entry 0 */ - movw $0x2000, %si - movsl - movl $0x00000087, -4(%si) //movl $0x00000087, 0x2000 - /* hi of entry 0 */ - movsl - movl $0, -4(%si) //movl $0, 0x2004 - - /* load linear address of the disk block into EDX:EAX */ - movl %cs:(data_addr_above_1M - int13_handler), %eax - movl %cs:(data_addr_above_1M - int13_handler + 4), %edx - - andl $0xFFE00000, %eax # align to 2M boundary - orb $0x87, %al - /* entry 1 is mapping to the first half 2M page of the disk block. */ - /* lo of entry 1 */ - movsl - movl %eax, -4(%si) //movl %edx, 0x2008 - /* hi of entry 1 */ - movsl - movl %edx, -4(%si) //movl %ebx, 0x200C - - addl $0x00200000, %eax - adcl $0, %edx - /* entry 2 is mapping to the last half 2M page of the disk block. */ - /* lo of entry 2 */ - movsl - movl %eax, -4(%si) //movl %edx, 0x2010 - /* hi of entry 2 */ - movsl - movl %edx, -4(%si) //movl %ebx, 0x2014 - - /* virtual linear address of disk block */ - movl %cs:(data_addr_above_1M - int13_handler), %esi - andl $0x001FFFFF, %esi - addl $0x00200000, %esi - movl %cs:(data_addr_below_1M - int13_handler), %edi - - testb $1, %cs:(int13_reg_AX - int13_handler + 1) # AH - jz 3f # read - xchgl %esi, %edi -3: - - /* prepare to enter paging or 64-bit mode */ - movl %cr4, %eax - orb $0x30, %al # 0x80=PGE, 0x20=PAE, 0x10=PSE - movl %eax, %cr4 - - /* EBX = address of PML4T, EBX+0x1000 = address of PDPT */ - - testb $2, %cs:(int13_is64bit - int13_handler) - jz int13_paemove // use PAE if AMD64 is not supported - //jmp int13_paemove // only test PAE code - - .code16 -//int13_lm64move: - movl %ebx, %cr3 // CR3 = address of PML4T - - movl %ecx, %ebx # save ECX into EBX - /* rdmsr will change EDX:EAX */ - movl $0xC0000080, %ecx # specify EFER MSR - rdmsr # enable long mode(EFER.LME=1) - orb $0x1, %ah - wrmsr - movl %ebx, %ecx # restore ECX from EBX - - xorl %ebx, %ebx - movw %cs, %bx - shll $4, %ebx // EBX=linear address of int13_handler - - movl %cr0, %eax # Activate long mode by enabling - orl $0x80000001, %eax # paging and protection simultaneously - movl %eax, %cr0 # skipping protected mode entirely - - .byte 0x66, 0xEA # 32-bit long jmp -int13_lm64move_lm64_start_addr: - /* linear address of start_64_bit, adjusted by set_int13_handler */ - .long (int13_lm64move_lm64_start - int13_handler) - .word LM_CS64 # 64-bit code 4GB limit - - .code64 -int13_lm64move_lm64_start: - /* DS, ES is not used in 64-bit */ - - shrl $1, %ecx /* we will move 2 dwords at a time */ - - /* only use 32-bit virtual adresses ESI, EDI */ - addr32 rep movsq /* ESI, EDI changed! */ - - /* switch to 16-bit compatibility mode then back to real mode */ - ljmp *(int13_lm64move_cm16_addr - int13_handler)(%ebx) - // EBX=linear address of int13_handler -int13_lm64move_cm16_addr: - .long (int13_lm64move_cm16 - int13_handler) - .word PM_CS16 # 16-bit code 64K limit - - .code16 -int13_paemove: - // DS:0x1000=PDPTE. The lowest byte of PDPTE was set to 7 by code above. For PAE paging, only bit 0 must be 1, bit1-2 must be 0. - movb $1, 0x1000 - addl $0x1000, %ebx // EBX = linear address of PDPT - movl %ebx, %cr3 // CR3 = linear address of PDPT - - movl %cr0, %eax - orl $0x80000001, %eax - movl %eax, %cr0 // protected mode with PAE paging - ljmp $(PM_CS16), $(int13_paemove_pm_start - int13_handler) -int13_paemove_pm_start: - movw $PM_DS32, %bx /* Switch to 4G data segment */ - movw %bx, %ds - movw %bx, %es - - /* use 32-bit virtual adresses ESI, EDI */ - addr32 rep movsl /* ESI, EDI changed! */ - - movl %cr0, %eax - andl $0x7FFFFFFF, %eax # disable paging - movl %eax, %cr0 - - subl $0x1000, %ebx // EBX=linear address of PML4E - jmp int13_pgmove_exit_pm - - .code16 -int13_lm64move_cm16: - /* now in 16-bit compatability mode */ - movl %cr0, %eax - andl $0x7FFFFFFF, %eax # disable paging, leaving long mode - movl %eax, %cr0 - /* now in 16-bit flat protected mode */ - /* rdmsr will change EDX:EAX */ - movl $0xC0000080, %ecx # specify EFER MSR - rdmsr - andb $0xFE, %ah # disable long mode(EFER.LME=0) - wrmsr - movl %cr3, %ebx // EBX=linear address of PML4E -// jmp int13_pgmove_exit_pm - -int13_pgmove_exit_pm: // shared by PAE and long mode block move - movw $(PM_DS16), %ax // int13_handler data segment - movw %ax, %ds // DS limit=64KB base=int13_handler - //movw %ax, %es // ES limit=64KB base=int13_handler - - movl (int13_prev_CR4 - int13_handler), %eax - movl %eax, %cr4 - movl (int13_prev_CR3 - int13_handler), %eax - movl %eax, %cr3 - - /* Switching to 4GB limit for DS and ES would hurt nothing(in - * principle). There are softwares which run initially with DS and - * ES able to access 4G memory. They call int13 and expect on return - * the DS and ES could still access 4G memory. So we should not - * forcibly set the limit to a lower value of 64K. -- tinybit - */ - movw $(PM_DS32), %ax // 4G data segment - movw %ax, %ds // DS limit=4GB base=0 - movw %ax, %es // ES limit=4GB base=0 - - movl %cr0, %eax - andb $0xFE, %al // reset CR0.PE(bit0) - movl %eax, %cr0 // back to real mode - ljmp $0, $(int13_pgmove_to_rm - int13_handler) -int13_pgmove_to_rm_cs = . - 2 // segment will be set by set_int13_handler -int13_pgmove_to_rm: - movw %cs, %ax - movw %ax, %ds // DS=int13_handler segment - shrl $4, %ebx - movw %bx, %es // ES=PML4T, PDPT, PD segment - - /* restore page tables */ - movw $(int13_prev_PML4T_entry - int13_handler), %si - xorw %di, %di - //cld - movsl - movsl - movw $0x1000, %di - movsl - movsl - movw $0x2000, %di - movsl - movsl - movsl - movsl - movsl - movsl - - // no need to restore ES - //movw /*%cs:*/(ES_seg - int13_handler), %es - - /* restore DL and clear DH */ - movzbw (int13_prev_DL - int13_handler), %dx - -#endif /* end of 64-bit code */ - jmp move_block_finished - -int15_87: - /* EDI=linear address of BUFFER(below 1M) */ - /* ECX=linear address of SECTOR(above 1M) */ - - negb %dl /* need_64_bit? */ - jc 6f /* Yes. Cannot handle. Failure. */ - xchgl %eax, %edi /* movl %edi, %eax */ - testb $1, %cs:(int13_reg_AX - int13_handler + 1) # AH - jnz 3f # write - xchgl %eax, %ecx # read -3: - /* Data transfer: (%eax) -> (%ecx), number of sectors 2(%si) */ - - movb 2(%si), %bl /* number of sectors to be moved */ - pushw %cs - popw %es - movw $(GDT_data - int13_handler), %si /* SI changed!! */ - movw %ax, %es:0x12(%si) #; source physical address low 16 bits - shrl $16, %eax - movb %al, %es:0x14(%si) #; source physical address bit 16-23 - movb %ah, %es:0x17(%si) #; source physical address bit 24-32 - movw %cx, %es:0x1a(%si) #; dest physical address low 16 bits - shrl $16, %ecx - movb %cl, %es:0x1c(%si) #; dest physical address bit 16-23 - movb %ch, %es:0x1f(%si) #; dest physical address bit 24-32 - - xorw %cx, %cx /* ECX is 0 */ - movl %ecx, %es:(%si) - movl %ecx, %es:0x04(%si) - movl %ecx, %es:0x08(%si) - movl %ecx, %es:0x0c(%si) - movl %ecx, %es:0x20(%si) - movl %ecx, %es:0x24(%si) - movl %ecx, %es:0x28(%si) - movl %ecx, %es:0x2c(%si) - movb %bl, %ch /* CX=number of words to be moved */ - movb $0x87, %ah /* access extended memory */ - - pushw %ax - smsw %ax - testb $1, %al - popw %ax - jnz 4f /* protected mode */ - - /* real mode */ - pushfw - lcall %cs:*(EXT_C(ROM_int15) - int13_handler) - - jmp 6f -4: - /* protected mode */ - int $0x15 -6: - jmp *%cs:(int13_ret_IP - int13_handler) //ret - -/****************************************************************************/ -normal_disk_drive: - - /* handle normal disk drive */ - - /* AH = 0x42 or 0x43 */ - pushw %ax - smsw %ax - testb $1, %al - popw %ax - jz 3f // real mode - - /* protected mode(Windows 98, EMM386) */ - - pushw %si /* save SI */ - pushl %eax /* save EAX */ - pushl %ebx /* save EBX */ - - /* set SI to the drive map */ -#if MAP_NUM_16 - movw $(EXT_C(hooked_drive_map_1) - int13_handler), %si -#else - movw $(EXT_C(hooked_drive_map) - int13_handler), %si -#endif - /* find the drive number from the drive map */ - cld - subw $DRIVE_MAP_SLOT_SIZE - 4, %si -2: - addw $DRIVE_MAP_SLOT_SIZE - 4, %si - -#if MAP_NUM_16 - cmpw $EXT_C(hooked_drive_map_1) - int13_handler + DRIVE_MAP_SIZE * DRIVE_MAP_SLOT_SIZE / 2, %si - jne 4f - movw $(EXT_C(hooked_drive_map_2) - int13_handler), %si -4: - cmpw $EXT_C(hooked_drive_map_2) - int13_handler + DRIVE_MAP_SIZE * DRIVE_MAP_SLOT_SIZE / 2, %si - je 2f -#endif - - lodsl %cs:(%si), %eax - testl %eax, %eax /* end of map table? */ - movl %eax, %ebx /* save the map to EBX */ - jz 2f /* yes, no map found */ - cmpb %dl, %ah /* found the map? */ - jne 2b /* no, check the next slot */ - - /* drive is mapped. check if map a whole drive */ - shrl $16, %eax - testb $62, %ah - jnz 2b /* no, check the next slot */ - movl %cs:8(%si), %eax /* StartLBA_Hi */ - testl %eax, %eax - jnz 2b /* no, check the next slot */ - movl %cs:4(%si), %eax /* StartLBA_Lo */ - testl %eax, %eax - jnz 2b /* no, check the next slot */ - movl %cs:16(%si), %eax /* S_count_Hi */ - testl %eax, %eax - jnz 2b /* no, check the next slot */ - movl %cs:12(%si), %eax /* S_count_Lo */ - shrl $1, %eax - jnz 2b /* no, check the next slot */ -2: - testl %ebx, %ebx /* mapped or not mapped ? */ - jz 2f /* not mapped, do nothing */ - movb %bl, %dl /* use the mapped FROM_DRIVE for win 98 */ -2: - movb %cs:(%bp), %al /* AL=FROM_DRIVE */ - testb %al, %al /* hard drive emulation? */ - jns 2f /* floppy, jump */ - cmpb %al, %dl - jb 2f - incb %dl -2: - popl %ebx - popl %eax - popw %si - - /* fall through to real mode... */ - -3: - - /* in real mode DOS, call original real mode int13 */ - /* DS:SI points to disk address packet */ - /* 2(%si), byte, sectors(1-127) */ - /* 4(%si), word, offset */ - /* 6(%si), word, segment */ - /* 8(%si), qword, lba */ - - testw $0x4000, %cs:4(%bp) /* TO_C bit 14=(TO is cdrom) */ - jz 1f - - /* LBA supported, CHS not applicable for CDROM */ - - movw %es, %cs:(int13_cdrom_es - int13_handler) - movw %cx, %cs:(int13_cdrom_cx - int13_handler) - movl %ebx, %cs:(int13_cdrom_ebx - int13_handler) - movl %edi, %cs:(int13_cdrom_edi - int13_handler) - - movzbw 2(%si), %cx /* sectors to transfer */ - movl 8(%si), %edi /* start sector number(LBA) */ - movl 12(%si), %ebx -3: - /* read 1 small sector at LBA=EDI to edd30_disk_buffer */ - - /* if we have previously read it, we can skip this step now. */ - cmpb %dl, %cs:last_read_cd_drive - int13_handler - jne 2f - cmpl %ebx, %cs:last_read_sector - int13_handler + 4 - jne 2f - movl %edi, %eax - andb $0xFC, %al - cmpl %eax, %cs:last_read_sector - int13_handler #; // + 4 - je 4f -2: - movl (%si), %eax - movl %eax, %cs:(tmp_dap - int13_handler) - movl 4(%si), %eax - movl %eax, %cs:(tmp_dap - int13_handler + 4) - movl 8(%si), %eax - movl %eax, %cs:(tmp_dap - int13_handler + 8) - movl 12(%si), %eax - movl %eax, %cs:(tmp_dap - int13_handler + 12) - - movl %edi, 8(%si) - movl %ebx, 12(%si) - shrdl $2, %ebx, 8(%si) /* turn LBA small to LBA big */ - shrl $2, 12(%si) - - movb $1, 2(%si) /* read 1 big sector */ - - //pushw %es - movw %bx, %cs:(int13_cdrom_bx - int13_handler) - movw %cs, %ax - movw %ax, %es - movw %ax, 6(%si) /* set the buffer segment */ - movw $edd30_disk_buffer - int13_handler, %bx - movw %bx, 4(%si) /* set the buffer offset */ - movw %cs:(int13_reg_AX - int13_handler), %ax -#ifdef CDROM_INIT - /* check if DL is for anyone of (cd?)'s */ - cmpb $0, %cs:(EXT_C(atapi_dev_count) - int13_handler) - jz 2f /* no cdX'es */ - cmpb %cs:(EXT_C(min_cdrom_id) - int13_handler), %dl - jb 2f /* not cdX */ - cmpb %cs:(max_cdrom_id - int13_handler), %dl - ja 2f /* not cdX */ - /* read 1 cdrom sector using our builtin cdrom driver. */ - movb $1, %cs:(force_int13 - int13_handler) -2: -#endif - call int13_with_retry /* read a big 2048-byte sector */ -#ifdef CDROM_INIT - movb $0, %cs:(force_int13 - int13_handler) -#endif - movw %cs:(int13_cdrom_bx - int13_handler), %bx - //popw %es - jc 3f /* failed */ - - movl %cs:(tmp_dap - int13_handler), %eax - movl %eax, (%si) - movl %cs:(tmp_dap - int13_handler + 4), %eax - movl %eax, 4(%si) - movl %cs:(tmp_dap - int13_handler + 8), %eax - movl %eax, 8(%si) - movl %cs:(tmp_dap - int13_handler + 12), %eax - movl %eax, 12(%si) - - pushw %di - andw $0xFFFC, %di - movl %edi, %cs:last_read_sector - int13_handler - popw %di - movl %ebx, %cs:last_read_sector - int13_handler + 4 - movb %dl, %cs:last_read_cd_drive - int13_handler -4: - pushw %cx - pushw %bx - pushw %di - - /* calculate the buffer ES:BX */ - //movw %di, %ax - subw 8(%si), %di /* sectors already read */ - shlw $5, %di /* paragraghs */ - addw 6(%si), %di /* segment */ - movw 4(%si), %bx /* offset */ - movw %bx, %ax - shrw $4, %ax /* turn to paragraghs */ - andw $0x000F, %bx - addw %di, %ax /* segment */ - movw %ax, %es - - movw %bx, %di - popw %ax /* AX=old DI */ - pushw %ax - - andb $3, %al - shlw $9, %ax /* offset in edd30_disk_buffer */ - - addw $edd30_disk_buffer - int13_handler, %ax - - xchgw %ax, %si - - /* move 512 bytes */ - movw $0x100, %cx - cld - cs repz movsw - - xchgw %ax, %si - - popw %di - popw %bx - - incl %edi /* next sector */ - jnz 2f - incl %ebx -2: - - popw %cx - decw %cx - jnz 3b -// loop 3b - - movw %cs:(int13_cdrom_es - int13_handler), %es - movw %cs:(int13_cdrom_cx - int13_handler), %cx - movl %cs:(int13_cdrom_ebx - int13_handler), %ebx - movl %cs:(int13_cdrom_edi - int13_handler), %edi - clc - jmp *%cs:(int13_ret_IP - int13_handler) //ret -3: - movw %cs:(int13_cdrom_es - int13_handler), %es - movw %cs:(int13_cdrom_cx - int13_handler), %cx - movl %cs:(int13_cdrom_ebx - int13_handler), %ebx - movl %cs:(int13_cdrom_edi - int13_handler), %edi - stc - jmp *%cs:(int13_ret_IP - int13_handler) //ret - -1: - #;jmp 1f /* just check if CHS translation code works */ - testw $0x8000, %cs:4(%bp) /* TO_C bit 15=LBA support */ -#if 0 - jnz int13_with_retry /* LBA mode */ -#else - jz 1f /* CHS only, so skip the LBA access */ - movw %es, %cs:(int13_tmp_es_bx - int13_handler + 2) - movw %bx, %cs:(int13_tmp_es_bx - int13_handler) - movw 4(%si), %bx - shrw $4, %bx - addw %bx, 6(%si) - andw $0x000F, 4(%si) - cmpb $0x80, 2(%si) - jb 2f /* 0x7F sectors or less is ok */ - ja 3f /* 0x81 sectors or more is bad */ - - /* now 0x80 sectors requested. */ - - testw $0x2000, %cs:4(%bp) /* TO_C bit 13=(FROM is cdrom) */ - jz 3f /* not CDROM, fail out. */ - /* virtual cdrom function call could request 64K data each time */ - /* transfer 0x80 sectors = twice 0x40 sectors */ - movb $0x40, 2(%si) /* transfer the first 32K */ - //movw 4(%si), %bx - //movw 6(%si), %es - lesw 4(%si), %bx - call int13_with_retry - jc 4f - movb $0x40, 2(%si) - addw $0x800, 6(%si) /* step to next 32K of the buffer */ - //movw 4(%si), %bx - //movw 6(%si), %es - lesw 4(%si), %bx - pushl %eax - xorl %eax, %eax - movb $0x40, %al - addl %eax, 8(%si) /* adjust start_LBA */ - movb $0, %al - adcl %eax, 12(%si) - popl %eax - call int13_with_retry - /* we ignore this step and keep start_LBA in a modified state. This is - * because only modify_boot_sectors need start_LBA and we are accessing - * the virtual cdrom, so we will not call modify_boot_sectors. - */ - //pushfw - //pushl %eax - //xorl %eax, %eax - //movb $0x40, %al - //subl %eax, 8(%si) /* adjust start_LBA */ - //movb $0, %al - //sbbl %eax, 12(%si) - //popl %eax - //popfw -4: - movb $0x80, 2(%si) /* restore its original value */ - lesw %cs:(int13_tmp_es_bx - int13_handler), %bx - movw %bx, 4(%si) /* restore its original value */ - movw %es, 6(%si) /* restore its original value */ - jmp *%cs:(int13_ret_IP - int13_handler) //ret - -2: - //movw 4(%si), %bx - //movw 6(%si), %es - lesw 4(%si), %bx - call int13_with_retry - lesw %cs:(int13_tmp_es_bx - int13_handler), %bx - movw %bx, 4(%si) /* restore its original value */ - movw %es, 6(%si) /* restore its original value */ - jnc 4f - testw $0x1000, %cs:4(%bp) /* TO_C bit 12=BIFURCATE */ - jz 1f /* not bifurcate, use CHS access once more. */ - stc /* bifurcate, error out. */ -4: - jmp *%cs:(int13_ret_IP - int13_handler) //ret - -3: - movb $1, %ah - stc - jmp *%cs:(int13_ret_IP - int13_handler) //ret - - .align 4 -int13_tmp_es_bx: .long 0 - -1: -#endif - /* CHS mode */ - - /* byte at SI+2: number of sectors to access */ - /* 8 bytes at SI+8: StartLBA */ - - /* CHS mode cannot access large addresses */ - cmpl $0, 12(%si) - jnz 1f - - pushl %edx - pushl %ebx - movw %cs:4(%bp), %ax /* TO_C */ - andw $0x3FF, %ax /* get lo 10 bits */ - incw %ax /* cylinders */ - pushw %ax - movzbw %cs:6(%bp), %ax /* TO_H */ - incw %ax /* heads */ - movzbw %cs:7(%bp), %bx /* TO_S */ - andb $0x3F, %bl - mulw %bx /* DX=0, AX=heads*sectors */ - popw %bx /* cylinders */ - mulw %bx /* DX:AX=total sectors in drive */ - pushw %dx - pushw %ax - movzbl 2(%si), %eax /* number of sectors to access */ - addl 8(%si), %eax /* last sector number + 1 */ - popl %edx /* total sectors in drive */ - cmpl %edx, %eax - popl %ebx - popl %edx - jnb 1f - - /* all requested sectors can be accessed by CHS */ - - /* we will access one sector at a time */ - - movzbw 2(%si), %cx /* sectors to transfer */ - movl 8(%si), %edi /* start sector number(LBA) */ -3: - /* translate LBA to CHS */ - - //pushw %cx - movw %cx, %cs:(int13_chs_cx - int13_handler) - - /* get sectors per cylinder */ - - //pushw %dx - movw %dx, %cs:(int13_chs_dx - int13_handler) - - pushl %edi /* lba */ - movzbw %cs:6(%bp), %ax /* TO_H */ - incw %ax /* heads */ - movzbw %cs:7(%bp), %bx /* TO_S */ - andb $0x3F, %bl - mulw %bx /* DX=0, AX=sectors per cylinder */ - popw %cx /* lba_lo */ - xchgw %ax, %cx /* CX=sectors per cylinder, AX=lba_lo */ - popw %dx /* DX:AX=lba */ - - divw %cx /* AX=cylinder number, DX=rem */ - xchgw %ax, %dx /* DX=cylinder number, AX=rem */ - - movb %dl, %ch /* CH=lo 8 bits of cylinder */ - - divb %bl /* AL=head number, AH=sector number - 1 */ - movb %ah, %cl - incw %cx /* CL=sector number */ - shlb $6, %dh /* hi 2 bits of cylinder */ - orb %dh, %cl - - movw %cs:(int13_chs_dx - int13_handler), %dx /* DL=drive number */ - //popw %dx /* DL=drive number */ - //pushw %dx - - movb %al, %dh /* DH=head number */ - - //pushl %edi - movl %edi, %cs:(int13_chs_edi - int13_handler) - - //movw %di, %ax - subw 8(%si), %di /* sectors already read */ - shlw $5, %di /* paragraghs */ - addw 6(%si), %di /* segment */ - movw 4(%si), %bx /* offset */ - movw %bx, %ax - shrw $4, %ax /* turn to paragraghs */ - andw $0x000F, %bx - addw %di, %ax /* segment */ - movw %ax, %es - - movb %cs:(int13_old_eax - int13_handler + 1), %ah - /* 0x42/0x02=read, 0x43/0x03=write */ - andb $0x03, %ah /* AH=0x02 or 0x03 */ - movb $0x01, %al /* number of sectors to read/write */ - - call int13_with_retry - - movl %cs:(int13_chs_edi - int13_handler), %edi - movw %cs:(int13_chs_dx - int13_handler), %dx - //popl %edi - //popw %dx - - incl %edi /* next sector */ - - movw %cs:(int13_chs_cx - int13_handler), %cx - //popw %cx - jc 1f - loop 3b - - jmp *%cs:(int13_ret_IP - int13_handler) //ret -1: - stc - jmp *%cs:(int13_ret_IP - int13_handler) //ret - - .align 2 -int13_ret_IP: - .word 0 -int13_reg_AX: - .word 0 -int13_chs_cx: - .word 0 -int13_chs_dx: - .word 0 - - .align 4 -int13_chs_edi: - .long 0 - -/****************************************************************************/ -int13_with_retry: - - /* save return address to memory */ - popw %cs:(int13_retry_IP - int13_handler) -// /* backup the last DWORD in the buffer */ -// pushl %es:0x1FC(%bx) -// popl %cs:(sector_last_dword - int13_handler) - - /* retry count should be an odd number initially */ - movb $5, %cs:(retry_count - int13_handler) -#ifdef CDROM_INIT - cmpb $0, %cs:(force_int13 - int13_handler) - jnz 3f /* we should use current int 13 instead of ROM_int13 */ -#endif - call backup_int13 -3: - movb %ah, %cs:(int13_retry_ah - int13_handler) - call int13_simple - - jnc 3f /* success */ - -// /* if the last dword changed, consider it is success */ -// -// pushl %eax -// movl %es:0x1FC(%bx), %eax -// cmpl %eax, %cs:(sector_last_dword - int13_handler) -// popl %eax -// -// jne 3f /* success */ - - decb %cs:(retry_count - int13_handler) - jz 2f /* finally failed */ - - /* reset disk and try again */ - movb $0, %cs:(int13_retry_ah - int13_handler) - call int13_simple - -// testb $1, %cs:(int13_old_eax - int13_handler + 1) -// /* 0x42/0x02=read, 0x43/0x03=write */ -// jnz 3b /* it is write */ -// -// /* touch the last dword of the buffer */ -// notl %es:0x1FC(%bx) -// notl %cs:(sector_last_dword - int13_handler) - - jmp 3b /* try again, ignoring the reset failure */ -2: - stc /* failure */ - jmp 2f -3: - clc /* success */ -2: - pushfw -#ifdef CDROM_INIT - cmpb $0, %cs:(force_int13 - int13_handler) - jnz 2f /* we have not touched the int 13 vector */ -#endif - call restore_int13 -2: - popfw - jmp *%cs:(int13_retry_IP - int13_handler) //ret - -backup_int13: - - /* backup the current int 13 to tmp_int13, then install ROM_int13 */ - cli - pushw %ds - pushl %eax - xorw %ax, %ax - movw %ax, %ds - movl 0x4C, %eax /* current int 13 vector */ - movl %eax, %cs:(tmp_int13 - int13_handler) - movl %cs:(EXT_C(ROM_int13) - int13_handler), %eax - movl %eax, 0x4C - popl %eax - popw %ds - ret - -restore_int13: - - /* restore the current int 13 from tmp_int13 */ - cli - pushw %ds - pushl %eax - xorw %ax, %ax - movw %ax, %ds - movl %cs:(tmp_int13 - int13_handler), %eax - movl %eax, 0x4C - popl %eax - popw %ds - ret - -retry_count: - .byte 5 - -int13_retry_ah: - .byte 0 -#ifdef CDROM_INIT -force_int13: - .byte 0 -#endif - .align 2 -int13_retry_IP: - .word 0 -int13_retry_ds: - .word 0 -int13_retry_es: - .word 0 - - .align 4 -int13_retry_eax: - .long 0 -int13_retry_ebx: - .long 0 -int13_retry_ecx: - .long 0 -int13_retry_edx: - .long 0 -int13_retry_esi: - .long 0 -int13_retry_edi: - .long 0 -int13_retry_ebp: - .long 0 -tmp_int13: - .long 0 -//sector_last_dword: -// .long 0 - -/****************************************************************************/ -int13_simple: - - /* input: CF=0 reset disk */ - - /* save return address to memory */ - popw %cs:(int13_simple_IP - int13_handler) - - movl %eax, %cs:(int13_retry_eax - int13_handler) - movl %ebx, %cs:(int13_retry_ebx - int13_handler) - movl %ecx, %cs:(int13_retry_ecx - int13_handler) - movl %edx, %cs:(int13_retry_edx - int13_handler) - movl %esi, %cs:(int13_retry_esi - int13_handler) - movl %edi, %cs:(int13_retry_edi - int13_handler) - movl %ebp, %cs:(int13_retry_ebp - int13_handler) - movw %ds, %cs:(int13_retry_ds - int13_handler) - movw %es, %cs:(int13_retry_es - int13_handler) - - //sti -#ifdef CDROM_INIT - cmpb $0, %cs:(force_int13 - int13_handler) - jz 3f - /* read 1 cdrom sector using our builtin cdrom driver. */ - - /* backup old variables to bak variables */ - movl %cs:(int13_old_eax - int13_handler), %eax - movl %eax, %cs:(int13_bak_eax - int13_handler) - movl %cs:(int13_old_ebx - int13_handler), %eax - movl %eax, %cs:(int13_bak_ebx - int13_handler) - movl %cs:(int13_old_ecx - int13_handler), %eax - movl %eax, %cs:(int13_bak_ecx - int13_handler) - movl %cs:(int13_old_edx - int13_handler), %eax - movl %eax, %cs:(int13_bak_edx - int13_handler) - movl %cs:(int13_old_esi - int13_handler), %eax - movl %eax, %cs:(int13_bak_esi - int13_handler) - movl %cs:(int13_old_edi - int13_handler), %eax - movl %eax, %cs:(int13_bak_edi - int13_handler) - movl %cs:(int13_old_ebp - int13_handler), %eax - movl %eax, %cs:(int13_bak_ebp - int13_handler) - movw %cs:(int13_old_ds - int13_handler), %ax - movw %ax, %cs:(int13_bak_ds - int13_handler) - movw %cs:(int13_old_es - int13_handler), %ax - movw %ax, %cs:(int13_bak_es - int13_handler) - movw %cs:(int13_old_flags - int13_handler), %ax - movw %ax, %cs:(int13_bak_flags - int13_handler) - movl %cs:(int13_old_cs_ip - int13_handler), %eax - movl %eax, %cs:(int13_bak_cs_ip - int13_handler) - - /* setup old variables for use by edd30_for_cdrom */ - - /* edd30_for_cdrom far return address */ - movw %cs, %cs:(int13_old_cs_ip + 2 - int13_handler) - movw $(2f - int13_handler), %cs:(int13_old_cs_ip - int13_handler) - /* edd30_for_cdrom flags */ - pushfw - popw %cs:(int13_old_flags - int13_handler) - movw %cs:(int13_retry_es - int13_handler), %ax - movw %ax, %cs:(int13_old_es - int13_handler) - movw %cs:(int13_retry_ds - int13_handler), %ax - movw %ax, %cs:(int13_old_ds - int13_handler) - movl %cs:(int13_retry_ebp - int13_handler), %eax - movl %eax, %cs:(int13_old_ebp - int13_handler) - movl %cs:(int13_retry_edi - int13_handler), %eax - movl %eax, %cs:(int13_old_edi - int13_handler) - movl %cs:(int13_retry_esi - int13_handler), %eax - movl %eax, %cs:(int13_old_esi - int13_handler) - movl %cs:(int13_retry_edx - int13_handler), %eax - movl %eax, %cs:(int13_old_edx - int13_handler) - movl %cs:(int13_retry_ecx - int13_handler), %eax - movl %eax, %cs:(int13_old_ecx - int13_handler) - movl %cs:(int13_retry_ebx - int13_handler), %eax - movl %eax, %cs:(int13_old_ebx - int13_handler) - movl %cs:(int13_retry_eax - int13_handler), %eax - movl %eax, %cs:(int13_old_eax - int13_handler) - - movb %cs:(int13_retry_ah - int13_handler), %ah - jmp edd30_for_cdrom /* will return at 2f */ -2: - /* restore old variables from bak variables */ - movl %cs:(int13_bak_eax - int13_handler), %eax - movl %eax, %cs:(int13_old_eax - int13_handler) - movl %cs:(int13_bak_ebx - int13_handler), %eax - movl %eax, %cs:(int13_old_ebx - int13_handler) - movl %cs:(int13_bak_ecx - int13_handler), %eax - movl %eax, %cs:(int13_old_ecx - int13_handler) - movl %cs:(int13_bak_edx - int13_handler), %eax - movl %eax, %cs:(int13_old_edx - int13_handler) - movl %cs:(int13_bak_esi - int13_handler), %eax - movl %eax, %cs:(int13_old_esi - int13_handler) - movl %cs:(int13_bak_edi - int13_handler), %eax - movl %eax, %cs:(int13_old_edi - int13_handler) - movl %cs:(int13_bak_ebp - int13_handler), %eax - movl %eax, %cs:(int13_old_ebp - int13_handler) - movw %cs:(int13_bak_ds - int13_handler), %ax - movw %ax, %cs:(int13_old_ds - int13_handler) - movw %cs:(int13_bak_es - int13_handler), %ax - movw %ax, %cs:(int13_old_es - int13_handler) - movw %cs:(int13_bak_flags - int13_handler), %ax - movw %ax, %cs:(int13_old_flags - int13_handler) - movl %cs:(int13_bak_cs_ip - int13_handler), %eax - movl %eax, %cs:(int13_old_cs_ip - int13_handler) - /* eax changed but no problem */ - - jmp 2f -#endif -3: - movb %cs:(int13_retry_ah - int13_handler), %ah - xorb %al, %al //Correction write mapping device fail in real machine 2017.05.10 yaya - int $0x13 -2: - movw %cs:(int13_retry_ds - int13_handler), %ds - movw %cs:(int13_retry_es - int13_handler), %es - movl %cs:(int13_retry_eax - int13_handler), %eax - movl %cs:(int13_retry_ebx - int13_handler), %ebx - movl %cs:(int13_retry_ecx - int13_handler), %ecx - movl %cs:(int13_retry_edx - int13_handler), %edx - movl %cs:(int13_retry_esi - int13_handler), %esi - movl %cs:(int13_retry_edi - int13_handler), %edi - movl %cs:(int13_retry_ebp - int13_handler), %ebp - - jmp *%cs:(int13_simple_IP - int13_handler) //ret - - .align 2 -int13_simple_IP: - .word 0 - - .align 4 -int13_bak_cs_ip: .long 0 -int13_bak_eax: .long 0 -int13_bak_ebx: .long 0 -int13_bak_ecx: .long 0 -int13_bak_edx: .long 0 -int13_bak_esi: .long 0 -int13_bak_edi: .long 0 -int13_bak_ebp: .long 0 -int13_bak_ds: .word 0 -int13_bak_es: .word 0 -int13_bak_flags: .word 0 - -/****************************************************************************/ -modify_boot_sectors: - - movw %cs:(int13_old_eax - int13_handler), %ax -// /* check CHS read */ -// cmpb $0x02, %ah /* is it read? */ -// jne 3f -// cmpw $0x0001, %cx /* read from cylinder 0, sector 1? */ -// je 5f -//3: - /* check LBA read */ - //cmpb $0x42, %ah /* is it extended read? */ - testb $0x01, %ah /* is it extended read? */ - jne 4f /* no, do nothing. */ - cmpl $0, 12(%si) /* read from LBA_high=0? */ - jne 4f /* no, do nothing. */ - - movb $0, %dh /* simulate CHS read of head 0 */ - cmpl $0, 8(%si) /* read from LBA_low=0? */ - je 3f /* yes, continue. */ - - movzbl %cs:3(%bp), %eax /* AL=Smax */ - andb $63, %al /* EAX=sectors per track */ - movb $1, %dh /* simulate CHS read of head 1 */ - cmpl %eax, 8(%si) /* read from LBA_low=sectors per track? */ - jne 4f /* no, exit. */ -3: - //movw 4(%si), %bx /* simulate CHS read buffer offset */ - //movw 6(%si), %es /* simulate CHS read buffer segment */ - lesw 4(%si), %bx - -5: - /* CHS mode read from cylinder 0, sector 1 */ - -#; testb %dl, %dl /* The TO_DRIVE is hard drive? */ -#; jns 4f /* no, do nothing */ - cmpw $0xaa55, %es:0x1fe(%bx) /* is it a valid boot sector? */ - jne 4f /* no, skip */ - movl %cs:16(%bp), %eax /* S_count_Lo */ - shrl $1, %eax /* map a whole drive? */ - jz 4f /* yes, nothing need to change */ - movl %cs:8(%bp), %eax /* StartLBA_Lo */ - testl %eax, %eax /* geometry translation only? */ - jz 4f /* yes, needn't change */ - movl %cs:(%bp), %eax /* FROM_DRIVE, TO_DRIVE, H, S */ - - testb %al, %al /* The FROM_DRIVE is hard drive? */ - jns modify_floppy /* no, goto floppy boot record modification */ - - testb %dh, %dh /* read from head 0? */ - jnz modify_HD_DOS /* no, goto HD DOS boot record modification */ - - /* we have read an MBR, and we need to modify the partition table */ - - /* the partition table could be an extended partition table. if so, - * we need to turn it to be a primary partition table. - */ - - /* if all start_sectors are not sectors_per_track, then it is not - * an extended partition table. - */ - - /* first, the MS magic number should be non-zero */ - cmpl $0, %es:0x1b8(%bx) - jne 5f - movb %al, %es:0x1b8(%bx) /* let it be the FROM_DRIVE */ -5: - shrl $16, %eax /* AL=Hmax, AH=Smax */ - andb $63, %ah /* AH=Smax */ -// cmpb $1, %ah -// jbe 4f /* do not modify partition table when disable CHS mode */ - - /* an extended partition table should have an entry with - * StartSector=Smax. - */ - movzbl %ah, %eax - movw $0x1c6, %si /* SI=0x1c6 */ - cmpl %eax, %es:(%bx, %si) - jz 5f - addw $16, %si /* SI=0x1d6 */ - cmpl %eax, %es:(%bx, %si) - jz 5f - addw $16, %si /* SI=0x1e6 */ - cmpl %eax, %es:(%bx, %si) - jz 5f - addw $16, %si /* SI=0x1f6 */ - cmpl %eax, %es:(%bx, %si) - jnz 4f /* not an extended partition table */ -5: - /* check if it is a primary partition table */ - - /* now the StartSector=Smax. if it is a primary partition table entry, - * it must have C/H/S=0/1/1. - */ - - movl %es:-8(%bx, %si), %eax - shrl $8, %eax /* hi word:cylinder/sector, lo word:head */ - cmpl $0x000101, %eax /* 0x00=C, 0x01=S, 0x01=H */ - je 4f /* primary partition table, nothing to do */ - - /* now we are sure this is an extended partition table */ - - /* compose a master boot record routine */ - - cld -#if 1 - movw %bx, %di - movb $0xFA, %al /* cli */ - stosb - movl $0xD08EC033, %eax /* xor AX,AX; mov SS,AX */ - stosl - movl $0xFB7C00BC, %eax /* mov SP,7C00 ; sti */ - stosl - movl $0x07501F50, %eax /* push AX; pop DS; push AX; pop ES */ - stosl - movl $0x7C1CBEFC, %eax /* cld; mov SI,7C1C */ - stosl - movl $0x50061CBF, %eax /* mov DI,061C ; push AX */ - stosl - movl $0x01E4B957, %eax /* push DI ; mov CX, 01E4 */ - stosl - movl $0x1ECBA4F3, %eax /* repz movsb; retf; push DS */ - stosl - movl $0x537C00BB, %eax /* mov BX,7C00 ; push BX */ - stosl - movl $0x520180BA, %eax /* mov DX,0180 ; push DX */ - stosl - movl $0x530201B8, %eax /* mov AX,0201 ; push BX */ - stosl - movl $0x5F13CD41, %eax /* inc CX; int 13; pop DI */ - stosl - movl $0x5607BEBE, %eax /* mov SI,07BE ; push SI */ - stosl - movl $0xCBFA5A5D, %eax /* pop BP; pop DX; cli; retf */ - stosl -#endif - - /* empty all other entries except this one by 2 steps: */ - - /* step 1. move this entry onto the first one (overwrite it) */ - movl %es:-8(%bx, %si), %eax - movl %eax, %es:0x1be(%bx) - movl %es:-4(%bx, %si), %eax - movl %eax, %es:0x1c2(%bx) - movl %es:(%bx, %si), %eax - movl %eax, %es:0x1c6(%bx) - movl %es:4(%bx, %si), %eax - movl %eax, %es:0x1ca(%bx) - -#if 1 - /* step 2. empty the last 3 entries */ - xorw %ax, %ax - movw %bx, %di - addw $0x1ce, %di - movw $24, %cx - repz stosw /* DI=BX+0x1fe */ -#else - xorw %ax, %ax - movw %bx, %di - addw $0x1d1, %di - stosw /* DI=BX+0x1d3 */ - addw $2, %di /* DI=BX+0x1d5 */ - stosb /* DI=BX+0x1d6 */ - addw $0x28, %di /* DI=BX+0x1fe */ -#endif - - /* modify the start_CHS of the first entry */ - subw $0x40, %di /* DI=BX+0x1be */ - movb $0x80, %al /* set boot indicator */ - stosb /* DI=BX+0x1bf */ - movb $0x01, %al /* AX=1 */ - stosb /* DI=BX+0x1c0, H=0x01 */ - stosw /* DI=BX+0x1c2, S=0x01, C=0x00 */ - -#if 0 - movb $0x0B, %al - stosb /* DI=BX+0x1c3 */ -#else - /* modify the end_CHS of the first entry */ - incw %di /* DI=BX+0x1c3 */ -#endif - - /* get total sectors */ - movl %es:7(%di), %eax /* DI+7=BX+0x1ca */ - - /* calculate the end sector number */ - addl %es:3(%di), %eax /* DI+3=BX+0x1c6 */ - //decl %eax - - pushl %eax /* EAX-1=end sector number */ - movzwl %cs:2(%bp), %eax /* Hmax, Smax */ - andb $63, %ah - movzbl %ah, %ecx - mulb %cl - addw %cx, %ax /* EAX=sectors per cylinder */ - pushl %eax /* EAX=sectors per cylinder */ - movw $1024, %cx - mull %ecx /* EAX=CHS addressible total sectors */ - /* EDX=0 */ - popl %edx /* EDX=sectors per cylinder */ - popl %ecx /* ECX-1=end sector number */ - cmpl %eax, %ecx - jb 5f - - /* assign max end sector number */ - movl %eax, %ecx - //subl $0x3EC1, %ecx /* XXX: 0x3EC1=255*63 */ -5: - pushl %ecx /* ECX-1=end sector number */ - movl %edx, %ecx /* ECX=sectors per cylinder */ - xorl %edx, %edx - popl %eax /* EAX-1=end sector number */ - decl %eax - - divl %ecx /* EAX=cylinder number */ - /* EDX=sector number in the last cylinder */ - /* EAX hi=0, EDX hi=0 */ - xchgw %ax, %cx /* CX=cylinder number */ - xchgw %ax, %dx /* AX=sector number in the last cylinder */ - movb %cs:3(%bp), %dl /* DL=Smax */ - andb $63, %dl - divb %dl /* AL=head number, AH=sector number - 1 */ - stosb /* DI=BX+0x1c4 */ - movb %ah, %al - incw %ax /* AL=sector number */ - movb %cl, %ah /* cylinder lo 8 bits */ - shlb $6, %ch /* cylinder hi 2 bits */ - orb %ch, %al - //movb $0, %ah /* XXX: let cylinder lo 8 bits=0 */ - stosw /* DI=BX+0x1c6 */ - -4: - /* end partition table modification */ - /* needn't restore registers */ - ret - -/****************************************************************************/ -modify_floppy: - - /* AL=FROM_DRIVE is the floppy drive number. */ - - cmpb $0x00, %dh /* read from head 0? */ - jne 4b - - testw $0x0800, %cs:4(%bp) /* TO_C bit 11=bootsector has known filesystem */ - jz 4b /* unknown boot sector */ - - pushl %ecx - pushw %si - - /* FAT12/FAT16/NTFS drive number is at offset 0x24. */ - movw $0x24, %si - - xorl %ecx, %ecx - - /* check if it is FAT32. */ - - /* FAT32 should have 0 root_dir_entries and total_sectors_short. */ - cmpl %ecx, %es:0x11(%bx) - jne 5f /* not FAT32 */ - - /* FAT32 should have 0 sectors_per_fat. */ - cmpw %cx, %es:0x16(%bx) - jne 5f /* not FAT32 */ - - /* FAT32 should have non-zero total_sectors_long. */ - cmpl %ecx, %es:0x20(%bx) - je 5f /* not FAT32 */ - - /* FAT32 should have non-zero sectors_per_fat32. */ - cmpl %ecx, %es:0x24(%bx) - je 5f /* not FAT32 */ - - /* Now it is FAT32, and the drive number is at offset 0x40. */ - movw $0x40, %si -5: - movb %al, %es:(%bx, %si) /* modify the boot drive number. */ - - movl %ecx, %es:0x1c(%bx) /* let number of hidden sectors=0 */ - /*movb $0xf0, %es:0x15(%bx)*/ /* set floppy media descriptor */ - - popw %si - popl %ecx - - jmp 4b - -/****************************************************************************/ -modify_HD_DOS: - - cmpb $0x01, %dh /* read from head 1? */ - jne 4b - movl %cs:8(%bp), %eax /* StartLBA_Lo */ - testl %eax, %eax - jz 4b - cmpl %eax, %es:0x1c(%bx) /* Number of hidden sectors */ - jbe 4b - subl %eax, %es:0x1c(%bx) - xorl %eax, %eax - cmpl %eax, %es:0x1c(%bx) - jne 4b - movb %cs:3(%bp), %al /* AL=Smax */ - andb $63, %al - movb %al, %es:0x1c(%bx) - //cmpl %eax, %es:0x1c(%bx) /* Number of hidden sectors */ - //jnb 4b - //movl %eax, %es:0x1c(%bx) - jmp 4b - -/****************************************************************************/ -modify_in_situ: - - movb %al, %cs:(int13_in_situ_sectors - int13_handler) - - cld - - /* if FROM is not harddrive, do nothing. */ - testb $0x80, %cs:(%bp) /* FROM drive */ - jz 4f - - cmpb $0x02, %ah /* is it CHS read? */ - jne 3f - - /* AL=sectors read */ - - /* translate CHS to LBA */ - - movw %dx, %di /* save DX to DI */ - movw %cx, %si /* save CX to SI */ - - movb %cs:7(%bp), %al /* TO_S */ - andb $63, %al - movzbw %al, %dx - mulb %cs:6(%bp) /* TO_H */ - addw %dx, %ax /* AX=sectors_per_cylinder */ - - /* get current cylinder number */ - - shrb $6, %cl - xchgb %cl, %ch - - mulw %cx /* DX:AX=sectors */ - - pushw %dx - pushw %ax - - /* restore DX */ - - movw %di, %dx - - /* get current head number */ - - movb %cs:7(%bp), %al /* TO_S */ - andb $63, %al - mulb %dh /* AX=sectors */ - - popl %edx - - movzwl %ax, %eax - addl %edx, %eax - - movw %si, %cx /* restore CX */ - andb $0x3F, %cl - decw %cx - movzbl %cl, %ecx - addl %ecx, %eax /* EAX=start sector number */ - movzbl %cs:(int13_in_situ_sectors - int13_handler), %ecx - jmp 6f - -3: - cmpb $0x42, %ah /* is it LBA read? */ - jne 4f - cmpl $0, 12(%si) /* read from LBA_high=0? */ - jne 4f - movl 8(%si), %eax /* start sector number */ - movzbl 2(%si), %ecx /* sectors read */ - //movw 4(%si), %bx /* simulate CHS read buffer offset */ - //movw 6(%si), %es /* simulate CHS read buffer segment */ - lesw 4(%si), %bx -6: -#; testb %dl, %dl /* The TO_DRIVE is hard drive? */ -#; jns 4f /* no, do nothing */ - /* ECX=sectors read */ - cmpl $0, %eax /* start sector number 0 is for MBR */ - je 5f - - /* if EAX <= startLBA_Lo < EAX + ECX, then the boot sector is read. */ - - cmpl %cs:8(%bp), %eax /* startLBA_Lo */ - ja 4f /* boot sector was not read */ - addl %eax, %ecx - cmpl %cs:8(%bp), %ecx - jbe 4f /* boot sector was not read */ - - movl %cs:8(%bp), %ecx - subl %eax, %ecx /* sectors between ES:BX and boot record */ - - /* modify hidden sectors of the partition boot record */ - cmpb $0x07, %cs:4(%bp) /* NTFS */ - je 3f - cmpb $0x0C, %cs:4(%bp) /* FAT32(LBA) */ - je 3f - cmpb $0x0E, %cs:4(%bp) /* FAT12/16 */ - je 3f - cmpb $0x83, %cs:4(%bp) /* EXT2 */ - jne 4f -3: - movw %es, %ax - shlw $5, %cx /* 1 sector is 32 paragraphs */ - addw %cx, %ax - movw %ax, %es - cmpw $0xaa55, %es:0x1fe(%bx) - jne 4f - movl %cs:8(%bp), %eax /* startLBA_Lo */ - movl %eax, %es:0x1c(%bx) - - jmp 4f -5: - /* Modify partition table. Note that there are 4 partition entries. - * The first one is called entry 0, and the last is entry 3. */ - - cmpw $0xaa55, %es:0x1fe(%bx) - jne 4f - - /* first, the MS magic number should be non-zero */ - cmpl $0, %es:0x1b8(%bx) - jne 5f - movb %cs:(%bp), %al /* FROM drive */ - movb %al, %es:0x1b8(%bx) /* let it be the FROM_DRIVE */ -5: - leaw 0x1be(%bx), %di /* DI=BX+0x1be */ - - movw %di, %si - - /* if the first entry is empty, we simply put our new entry on it. */ - - //cmpb $0, %es:4(%si) /* consider partition type 00 as empty */ - //jz 5f - testb $63, %es:2(%si) /* invalid start sector number of 0 */ - jz 5f - testb $63, %es:6(%si) /* invalid end sector number of 0 */ - jz 5f - cmpl $0, %es:8(%si) /* invalid start LBA of 0 */ - jz 5f - cmpl $0, %es:12(%si) /* invalid sector count of 0 */ - jz 5f - - /* Now that the first entry is not empty, we should find an empty one - * in entries 1, 2, 3(the last 3 partition entries). */ - -7: - addw $0x10, %si /* SI=BX+0x1ce or BX+0x1de or BX+0x1ee */ - - //cmpb $0, %es:4(%si) /* consider partition type 00 as empty */ - //jz 7f - testb $63, %es:2(%si) /* invalid start sector number of 0 */ - jz 7f - testb $63, %es:6(%si) /* invalid end sector number of 0 */ - jz 7f - cmpl $0, %es:8(%si) /* invalid start LBA of 0 */ - jz 7f - cmpl $0, %es:12(%si) /* invalid sector count of 0 */ - jz 7f - - leaw 0x1ee(%bx), %bx - cmpw %bx, %si - leaw -0x1ee(%bx), %bx - jb 7b /* try next entry */ - - /* Now SI=BX+0x1ee points to the last entry */ - -7: - /* SI points to empty entry(or the last entry), we move old entry 0 - * onto this one. - */ - - movl %es:(%di), %eax - movl %eax, %es:(%si) - movl %es:4(%di), %eax - movl %eax, %es:4(%si) - movl %es:8(%di), %eax - movl %eax, %es:8(%si) - movl %es:12(%di), %eax - movl %eax, %es:12(%si) - -5: - /* build our new entry 0 */ - - /* DI=BX+0x1be */ - - movl %cs:8(%bp), %eax /* startLBA_Lo */ - - call lba_to_chs - - movb $0x80, %al /* set boot indicator */ - //movb $0x00, %al /* clear boot indicator */ - stosl /* DI=BX+0x1c2 */ - - movl %cs:16(%bp), %eax - addl %cs:8(%bp), %eax - decl %eax /* endLBA */ - - call lba_to_chs - - /* if in situ, TO_C holds the partition type: - * 0x07(NTFS), 0x0C(FAT32), 0x0E(FAT12/16), 0x83(EXT2/3) - */ - movb %cs:4(%bp), %al /* TO_C */ - stosl /* DI=BX+0x1c6 */ - - /* modify start sector and sector count */ - - movl %cs:8(%bp), %eax - stosl /* DI=BX+0x1ca */ - movl %cs:16(%bp), %eax - stosl /* DI=BX+0x1ce */ - - /* bit 8 of TO_C means clearing other partition entries. */ - testb $1, %cs:5(%bp) /* TO_C hi word for in_situ_flags */ - jz 3f - - /* empty the last 3 entries */ - xorw %ax, %ax - movw %bx, %di - addw $0x1ce, %di - movw $24, %cx - repz stosw /* DI=BX+0x1fe */ - ret -3: -#if 1 - /* clear other boot indicators in the last 3 entries */ - - movb $0, %al /* DI=BX+0x1ce */ - stosb /* DI=BX+0x1cf */ - - leaw 0x1de(%bx), %di /* DI=BX+0x1de */ - stosb /* DI=BX+0x1df */ - - leaw 0x1ee(%bx), %di /* DI=BX+0x1ee */ - stosb /* DI=BX+0x1ef */ -#endif - -//#if 0 -// /* hide entry 3 (test only) */ -// orb $0x10, %es:0x1f2(%bx) -//#endif - -#if 0 - /* move extended partition entries to last */ - - cmpb $0x0F, %es:0x1f2(%bx) - je 4f /* entry 3 is extended, do nothing */ - - cmpb $0x05, %es:0x1f2(%bx) - je 4f /* entry 3 is extended, do nothing */ - - cmpb $0x0F, %es:0x1e2(%bx) - je 7f /* entry 2 is extended */ - - cmpb $0x05, %es:0x1e2(%bx) - je 7f /* entry 2 is extended */ - - /* both entry 2 and entry 3 are not extended */ - - cmpb $0x0F, %es:0x1d2(%bx) - je 8f /* entry 1 is extended */ - - cmpb $0x05, %es:0x1d2(%bx) - jne 4f /* all entries 1, 2, 3 are not extended, do nothing */ -8: - /* entry 1 is extended, but entry 2 and entry 3 are not extended. - * so exchange entry 1 and entry 3. */ - - xchgl %eax, %es:0x1ce(%bx) - xchgl %eax, %es:0x1ee(%bx) - xchgl %eax, %es:0x1ce(%bx) - - xchgl %eax, %es:0x1d2(%bx) - xchgl %eax, %es:0x1f2(%bx) - xchgl %eax, %es:0x1d2(%bx) - - xchgl %eax, %es:0x1d6(%bx) - xchgl %eax, %es:0x1f6(%bx) - xchgl %eax, %es:0x1d6(%bx) - - xchgl %eax, %es:0x1da(%bx) - xchgl %eax, %es:0x1fa(%bx) - xchgl %eax, %es:0x1da(%bx) - - jmp 4f - -7: - /* entry 2 is extended, but entry 3 is not. if entry 1 is extended, - * we exchange entry 1 and 3, else, we exchange entry 2 and 3. */ - */ - - cmpb $0x0F, %es:0x1d2(%bx) - je 8b /* entry 1 is extended */ - - cmpb $0x05, %es:0x1d2(%bx) - je 8b /* entry 1 is extended */ - - /* exchange entry 2 and 3 */ - xchgl %eax, %es:0x1de(%bx) - xchgl %eax, %es:0x1ee(%bx) - xchgl %eax, %es:0x1de(%bx) - - xchgl %eax, %es:0x1e2(%bx) - xchgl %eax, %es:0x1f2(%bx) - xchgl %eax, %es:0x1e2(%bx) - - xchgl %eax, %es:0x1e6(%bx) - xchgl %eax, %es:0x1f6(%bx) - xchgl %eax, %es:0x1e6(%bx) - - xchgl %eax, %es:0x1ea(%bx) - xchgl %eax, %es:0x1fa(%bx) - xchgl %eax, %es:0x1ea(%bx) -#endif - -// /* empty the last 3 entries */ -// xorw %ax, %ax -// movw %bx, %di -// addw $0x1ce, %di -// movw $24, %cx -// repz stosw /* DI=BX+0x1fe */ - -4: - /* end partition table and BPB modification */ - ret - -int13_in_situ_sectors: - .byte 0 - -/****************************************************************************/ - -lba_to_chs: - - /* input: - * - * EAX: LBA - * - * output: - * - * EAX: CHS - * - * - * - */ - - pushl %eax /* EAX=end sector number */ - movzwl %cs:6(%bp), %eax /* TO_H, TO_S */ - andb $63, %ah - movzbl %ah, %ecx - mulb %cl - addw %cx, %ax /* EAX=sectors per cylinder */ - pushl %eax /* EAX=sectors per cylinder */ - movw $1024, %cx - mull %ecx /* EAX=CHS addressible total sectors */ - /* EDX=0 */ - popl %edx /* EDX=sectors per cylinder */ - popl %ecx /* ECX=end sector number */ - decl %eax - cmpl %eax, %ecx - jb 5f - - /* assign max end sector number */ - movl %eax, %ecx - //subl $0x3EC1, %ecx /* XXX: 0x3EC1=255*63 */ -5: - pushl %ecx /* ECX=end sector number */ - movl %edx, %ecx /* ECX=sectors per cylinder */ - xorl %edx, %edx - popl %eax /* EAX=end sector number */ - - divl %ecx /* EAX=cylinder number */ - /* EDX=sector number in the last cylinder */ - /* EAX hi=0, EDX hi=0 */ - xchgw %ax, %cx /* CX=cylinder number */ - xchgw %ax, %dx /* AX=sector number in the last cylinder */ - movb %cs:7(%bp), %dl /* TO_S */ - andb $63, %dl - divb %dl /* AL=head number, AH=sector number - 1 */ - //stosb /* DI=BX+0x1c4 */ - - xchgb %ah, %al /* AH=head number, AL=sector number - 1 */ - - pushw %ax - - //movb %ah, %al - incw %ax /* AL=sector number */ - movb %cl, %ah /* cylinder lo 8 bits */ - shlb $6, %ch /* cylinder hi 2 bits */ - orb %ch, %al - //movb $0, %ah /* XXX: let cylinder lo 8 bits=0 */ - //stosw /* DI=BX+0x1c6 */ - shll $16, %eax - - popw %ax - - ret - -/****************************************************************************/ -#ifdef CDROM_INIT -max_cdrom_id: .byte 0xE0 -#endif - .align 4 -ENTRY(e820cycles) - .long -1 /* no limit. set to 0 if int15 will unhook */ -ENTRY(int15nolow) - .long 0 /* set to 1 if int15 will not handle low memory */ -ENTRY(memdisk_raw) - .long 1 /* set to 0 if accessing memdrives using int15/87h */ -ENTRY(a20_keep_on) - .long 1 /* set to 0 if a20 should be auto-off */ -ENTRY(lba_cd_boot) - .long 0 /* LBA of no-emu boot image, in 2048-byte sectors */ - -minimum_mem_lo_in_map: - .long 0 /* min ram drive base below 16M */ -ENTRY(minimum_mem_hi_in_map) - .long 0 /* min ram drive base above 16M */ -#if (repair_memory_holes) -ENTRY(prime_end) - .long 0,0 -ENTRY(new_end) - .long 0,0 -#endif -#if 0 -int15_e820_saved_ebx: - .long 0 -int15_e820_range0_addr: - .long 0, 0 -int15_e820_range0_length: - .long ((int13_handler_end - int13_handler + 0x3ff)&(-0x400)), 0 -int15_e820_range0_type: - .long 2 -#endif - -/****************************************************************************/ -int15_e820_handler: - - /* Comments are mostly gotten from Ralf Brown's Interrupt List. */ - - cmpw $0xe820, %ax //cmpl $0x0000e820, %eax - jne 1f - - /* Newer BIOSes - GET SYSTEM MEMORY MAP */ - - //AX = E820h - //EAX = 0000E820h - //EDX = 534D4150h ('SMAP') - //EBX = continuation value or 00000000h to start at beginning of map - //ECX = size of buffer for result, in bytes (should be >= 20 bytes) - //ES:DI -> buffer for result - - //Return: - //CF clear if successful - //EAX = 534D4150h ('SMAP') - //ES:DI buffer filled - //EBX = next offset from which to copy or 00000000h if all done - //ECX = actual length returned in bytes - //CF set on error - //AH = error code (86h) - - /* Notes: Originally introduced with the Phoenix BIOS v4.0, this - * function is now supported by most newer BIOSes, since various - * versions of Windows call it to find out about the system memory. - * A maximum of 20 bytes will be transferred at one time, even if ECX - * is higher; some BIOSes (e.g. Award Modular BIOS v4.50PG) ignore the - * value of ECX on entry, and always copy 20 bytes. Some BIOSes expect - * the high word of EAX to be clear on entry, i.e. EAX=0000E820h. If - * this function is not supported, an application should fall back to - * AX=E802h, AX=E801h, and then AH=88h. The BIOS is permitted to return - * a nonzero continuation value in EBX and indicate that the end of the - * list has already been reached by returning with CF set on the next - * iteration. This function will return base memory and ISA/PCI memory - * contiguous with base memory as normal memory ranges; it will - * indicate chipset-defined address holes which are not in use and - * motherboard memory-mapped devices, and all occurrences of the system - * BIOS as reserved; standard PC address ranges will not be reported - */ - -//Format of Phoenix BIOS system memory map address range descriptor: -// -//Offset Size Description -//------ ----- ---------------------- -// 00h QWORD base address -// 08h QWORD length in bytes -// 10h DWORD type of address range - -//Values for System Memory Map address type: -//01h memory, available to OS -//02h reserved, not available (e.g. system ROM, memory-mapped device) -//03h ACPI Reclaim Memory (usable by OS after reading ACPI tables) -//04h ACPI NVS Memory (OS is required to save this memory between NVS sessions) -//other not defined yet -- treat as Reserved - - cmpl $0x534D4150, %edx /* "SMAP" */ - jne 99f /* not a valid e820 call. But could be another */ - /* unknown call. So pass through to original BIOS. */ - - cmpl $20, %ecx - jb 2f /* treat this as error: invalid call. */ - -#if (repair_memory_holes) - orl %ebx, %ebx - jne 3f - movl %ebx, %cs:(prime_end - int13_handler) - movl %ebx, %cs:(prime_end + 4 - int13_handler) - movl %ebx, %cs:(new_end - int13_handler) - movl %ebx, %cs:(new_end + 4 - int13_handler) -#endif -3: -#if 0 - cmpl $1, %ebx - jb 8f /* EBX = 0 : start at beginning */ - ja 3f /* input EBX > 1 : invalid */ - /* input EBX = 1 : continue */ - movl %cs:(int15_e820_saved_ebx - int13_handler), %ebx - test %ebx, %ebx - jz 9f /* BIOS ranges ended */ -8: -#endif - //pushfw - //lcall %cs:*(EXT_C(ROM_int15) - int13_handler) - call safe_ROM_int15 - - jc 3f /* it signals end of a cycle of the e820 calls */ - cmpl $0x534D4150, %eax /* "SMAP" */ - jne 3f /* unknown failure. Also end the cycle for safety. */ -#if 0 - movl %ebx, %cs:(int15_e820_saved_ebx - int13_handler) - movl $1, %ebx -#endif - ##################################################################### - pushal - ##################################################################### - - xorl %eax, %eax - cdq /* let EDX=0 */ - movw %cs, %ax - shll $4, %eax - - /* EDX:EAX=linear address of int13_handler */ - -#if 1 - /* get 0x413 memory size */ - pushw %ds - movw %dx, %ds /* DS = 0 */ - movzwl 0x413, %ebx - shll $10, %ebx - jz 5f /* invalid mem size */ - cmpl %ebx, %eax - jbe 5f - xchgl %eax, %ebx /* movl %ebx, %eax */ -5: - popw %ds -#endif - - pushl %eax /* available low mem size in bytes */ - - movl %es:16(%di), %eax /* Type: 1 = usable memory. */ - decl %eax /* is it usable? */ - jz 5f /* yes, modify usable mem range */ -#if (!repair_memory_holes) - /* it is reserved memory. only modify low mem range at this moment. */ - cmpl %edx, %cs:(EXT_C(int15nolow) - int13_handler) /* EDX=0 */ - jnz 4f /* int15 will not handle low mem */ - cmpl %edx, %es:4(%di) /* BaseAddrHigh */ - jnz 4f /* not low mem */ - cmpl %edx, %es:12(%di) /* LengthHigh */ - jnz 4f /* not low mem */ - movl %es:(%di), %eax /* BaseAddrLow */ - addl %es:8(%di), %eax /* LengthLow, EAX=EndAddrLow */ - jc 4f - cmpl $0xA0000, %eax /* EndAddrLow */ - jne 4f /* not a top range, will not touch */ - - /* Yes, modify this range */ - popl %eax /* available low mem size in bytes */ - pushl %eax /* available low mem size in bytes */ - movl %eax, %es:(%di) - movl $0xA0000, %es:8(%di) - subl %eax, %es:8(%di) - jmp 4f /* done modifying reserved low mem range */ -#else - andb $0xfe, %cs:(prime_end - int13_handler) - movl %es:4(%di), %edx - cmpl %edx, %cs:(prime_end + 4 - int13_handler) //0 - jne 4f - movl %es:(%di), %eax - cmpl %eax, %cs:(prime_end - int13_handler) - jne 4f - - subl %cs:(new_end - int13_handler), %eax - sbbl %cs:(new_end + 4 - int13_handler), %edx - addl %eax, %es:8(%di) - adcl %edx, %es:12(%di) - - movl %cs:(new_end - int13_handler), %eax - movl %cs:(new_end + 4 - int13_handler), %edx - movl %eax, %es:(%di) - movl %edx, %es:4(%di) - jmp 4f -#endif -5: - /* it is usable memory. */ - - /* check if overlapping with int13_handler and memdrives. */ - -#if MAP_NUM_16 - movw $(EXT_C(hooked_drive_map_1)-int13_handler-DRIVE_MAP_SLOT_SIZE), %si -#else - movw $(EXT_C(hooked_drive_map)-int13_handler-DRIVE_MAP_SLOT_SIZE), %si -#endif - -#if (!repair_memory_holes) - movw $(DRIVE_MAP_SIZE + 1), %cx -#else - movw $(DRIVE_MAP_SIZE + 1), %bp -#endif - popl %eax /* available low mem size in bytes */ - pushl %eax /* available low mem size in bytes */ - -#if (!repair_memory_holes) - cmpl %edx, %cs:(EXT_C(int15nolow) - int13_handler) /* EDX=0 */ -#else - cmpl $0, %cs:(EXT_C(int15nolow) - int13_handler) -#endif - jz 7f /* int15 will handle low mem */ - jmp 5f /* this "jmp" instruction can be omitted. */ -6: -#if MAP_NUM_16 - cmpw $EXT_C(hooked_drive_map_1) - int13_handler + DRIVE_MAP_SIZE * DRIVE_MAP_SLOT_SIZE / 2, %si //hooked_drive_map_1 end - jne 8f - movw $(EXT_C(hooked_drive_map_2) - int13_handler), %si -8: -#endif - /* the code should not change SI, DI and CX! */ - cmpb $0xff, %cs:1(%si) - jne 5f /* not memdrive */ - testb $0x40, %cs:5(%si) /* TO_C bit 14=(TO is cdrom) */ - jnz 5f /* not memdrive */ - movl %cs:12(%si), %edx /* start_sector hi */ - movl %cs:8(%si), %eax /* start_sector lo */ - shldl $9, %eax, %edx - shll $9, %eax /* EDX:EAX=start_address of mem drive*/ -7: - subl %es:(%di), %eax - sbbl %es:4(%di), %edx /* EDX:EAX=new length */ - jb 5f /* start_address is below the base */ - ja 7f - /* now EDX=0 */ - testl %eax, %eax /* EAX also be zero? ZF holds it! */ - jne 7f - /* Change memory address type from 1 (usable) to 2 (reserved). Note - * that original value is long integer of 1 (all higher 3 bytes = 0). - * So only the lowest byte needs to be incremented. */ - incb %es:16(%di) /* memory address type */ - jmp 5f -7: - subl %es:8(%di), %eax - sbbl %es:12(%di), %edx /* EDX:EAX=difference */ - jnb 5f /* new length is too big */ -#if (!repair_memory_holes) - addl %eax, %es:8(%di) - adcl %edx, %es:12(%di) /* apply new length */ -#else - movl %es:8(%di), %ebx - movl %es:12(%di), %ecx - addl %ebx, %eax - adcl %ecx, %edx - movl %eax, %es:8(%di) - movl %edx, %es:12(%di) - addl %es:(%di), %eax - adcl %es:4(%di), %edx - movl %eax, %cs:(new_end - int13_handler) - movl %edx, %cs:(new_end + 4 - int13_handler) - - testb $1, %cs:(prime_end - int13_handler) - jne 5f - addl %es:(%di), %ebx - adcl %es:4(%di), %ecx - movl %ebx, %cs:(prime_end - int13_handler) - movl %ecx, %cs:(prime_end + 4 - int13_handler) - orb $1, %cs:(prime_end - int13_handler) -#endif -5: - /* try next slot */ - addw $DRIVE_MAP_SLOT_SIZE, %si -#if (!repair_memory_holes) - loop 6b -#else - dec %bp - jne 6b -#endif - /* done modifying usable mem range */ -4: - popl %eax /* available low mem size in bytes */ - ##################################################################### - popal - ##################################################################### - testl %ebx, %ebx - jnz 5f - call dec_e820cycles -5: - clc - lret $2 -#if 0 -9: - pushfw - pushw %si - pushw %di - cld - movw $(int15_e820_range0_addr - int13_handler), %si - movw $(20/2), %cx - rep movsw %cs:(%si), %es:(%di) - movl $20, %ecx /* number of byte */ - xorl %ebx, %ebx /* no continuation */ - movl %edx, %eax /* "SMAP" */ - popw %di - popw %si - popfw - clc - lret $2 -#endif -3: - call dec_e820cycles -2: - movb $0x86, %ah /* function not supported */ - stc - lret $2 -#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -1: - cmpw $0xe801, %ax //cmpl $0x0000e801, %eax - je 1f - cmpw $0xe881, %ax //cmpl $0x0000e881, %eax - je 1f - cmpw $0xda88, %ax - je 1f -// cmpb $0xc7, %ah -// je 1f - cmpb $0x8a, %ah - je 1f - cmpb $0x88, %ah - je 1f -99: - ljmp %cs:*(EXT_C(ROM_int15) - int13_handler) -#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -1: - - pushal - - /* find minimum mem ever used in the drive map slots */ - - movl %cs:(EXT_C(minimum_mem_hi_in_map) - int13_handler), %eax - /* set %si to the drive map */ -#if MAP_NUM_16 - movw $(EXT_C(hooked_drive_map_1) - int13_handler), %si -#else - movw $(EXT_C(hooked_drive_map) - int13_handler), %si -#endif - movw $(DRIVE_MAP_SIZE), %cx -6: -#if MAP_NUM_16 - cmpw $EXT_C(hooked_drive_map_1) - int13_handler + DRIVE_MAP_SIZE * DRIVE_MAP_SLOT_SIZE / 2, %si //hooked_drive_map_1 end - jne 8f - movw $(EXT_C(hooked_drive_map_2) - int13_handler), %si -8: -#endif - cmpb $0xff, %cs:1(%si) - jne 5f - testb $0x40, %cs:5(%si) /* TO_C bit 14=(TO is cdrom) */ - jnz 5f - - cmpl $0, %cs:12(%si) - jnz 5f // too big, address exceeding 2048G! - - movl %cs:8(%si), %ebx /* StartLBA_Lo */ - testl $0xFF800000, %ebx - jnz 5f // too big, address exceeding 4G! - - shll $9, %ebx /* convert to address in bytes */ - - /* hi mem */ - cmpl %ebx, %eax - jbe 5f - movl %ebx, %eax -5: - /* try next slot */ - addw $DRIVE_MAP_SLOT_SIZE, %si - loop 6b - - subl $0x100000, %eax - shrl $10, %eax - movl %eax, %cs:(minimum_mem_lo_in_map - int13_handler) - popal - -#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -1: - cmpw $0xe801, %ax //cmpl $0x0000e801, %eax - jne 1f - - /* Phoenix BIOS v4.0 - GET MEMORY SIZE FOR >64M CONFIGURATIONS */ - - //AX = E801h - - //Return: - //CF clear if successful - //AX = extended memory between 1M and 16M, in K (max 3C00h = 15MB) - //BX = extended memory above 16M, in 64K blocks - //CX = configured memory 1M to 16M, in K - //DX = configured memory above 16M, in 64K blocks - //CF set on error - - /* Notes: Supported by the A03 level (6/14/94) and later XPS P90 - * BIOSes, as well as the Compaq Contura, 3/8/93 DESKPRO/i, and - * 7/26/93 LTE Lite 386 ROM BIOS. Supported by AMI BIOSes dated - * 8/23/94 or later. On some systems, the BIOS returns AX=BX=0000h; - * in this case, use CX and DX instead of AX and BX. This interface - * is used by Windows NT 3.1, OS/2 v2.11/2.20, and is used as a - * fall-back by newer versions if AX=E820h is not supported. This - * function is not used by MS-DOS 6.0 HIMEM.SYS when an EISA machine - * (for example with parameter /EISA) (see also MEM F000h:FFD9h), or - * no Compaq machine was detected, or parameter /NOABOVE16 was given. - */ - - /* between 16M and 4G, we modify BX, DX */ -4: - movl %cs:(minimum_mem_lo_in_map - int13_handler), %ebx - subl $0x3c00, %ebx /* 16M */ - shrl $6, %ebx /* AX=mem above 16M in 64K blocks */ - movw %bx, %dx - - /* between 1M and 16M, we modify AX, CX */ - - movw $0x3c00, %ax - movw %ax, %cx - - clc - lret $2 - -#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -1: - cmpw $0xe881, %ax //cmpl $0x0000e881, %eax - jne 1f - - /* Phoenix BIOS v4.0 - GET MEMORY SIZE FOR >64M CONFIGURATIONS (32-bit) */ - - //AX = E881h - - //Return: - //CF clear if successful - //EAX = extended memory between 1M and 16M, in K (max 3C00h = 15MB) - //EBX = extended memory above 16M, in 64K blocks - //ECX = configured memory 1M to 16M, in K - //EDX = configured memory above 16M, in 64K blocks - //CF set on error - - /* Notes: Supported by AMI BIOSes dated 8/23/94 or later. This - * interface is used by Windows NT 3.1, OS/2 v2.11/2.20, and is used - * as a fall-back by newer versions if AX=E820h is not supported - */ - - //movl $0x3c00, %eax /* 1-16M mem in K (0x3c00 = 15MB) */ - //movl $0x0300, %ebx /* mem above 16M in 64K blocks */ - - jmp 4b -#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -1: - cmpw $0xda88, %ax - jne 1f - - /* AMI PCI BIOS - GET EXTENDED MEMORY SIZE */ - - //AX = DA88h - - //Return: - //CF clear (successful) - //AX = 0000h - //CL:BX = extended memory size in KBytes - - /* 63M = 3f00000 Bytes = 0xfc00 K */ - //movw $0xfc00, %bx - -#; pushfw -#; lcall %cs:*(EXT_C(ROM_int15) - int13_handler) -#; -#; jc 3f - - pushl %eax - - movl %cs:(minimum_mem_lo_in_map - int13_handler), %eax - xchgw %ax, %bx - shrl $16, %eax - movb %al, %cl - - popl %eax - - xorw %ax, %ax - clc - lret $2 -#;3: -#; stc -#; lret $2 - -#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -#if 0 - /* comment out this function because it uses DS register on call and - * thus it cannot call safe_ROM_int15 - */ -1: - cmpb $0xC7, %ah - jne 1f - - /* SYSTEM - later PS/2s - RETURN MEMORY-MAP INFORMATION */ - - //AH = C7h - //DS:SI -> user supplied memory map table - - //Return: - //CF set on error - //CF clear if successful - - /* Notes: Call AH=C0h and examine bit 4 of feature byte 2 to check if - * this function is supported. IBM classifies this function as - * optional. Windows95 OSR2 reportedly does not support this function - * even though INT 15/AH=C0h indicates that it is available (observed - * on several different systems) - */ - -//Format of memory-map table structure: -// -//Offset Size Description -//------ ----- -------------------------------------------------------------- -// 00h WORD length of table (excluding this word) -// 02h DWORD local memory between 1M and 16M, in 1K blocks -// 06h DWORD local memory between 16M and 4G, in 1K blocks -// 0Ah DWORD system memory between 1M and 16M, in 1K blocks -// 0Eh DWORD system memory between 16M and 4G, in 1K blocks -// 12h DWORD cacheable memory between 1M and 16M, in 1K blocks -// 16h DWORD cacheable memory between 16M and 4G, in 1K blocks -// 1Ah DWORD 1K blocks before start of non-system memory between 1M and 16M -// 1Eh DWORD 1K blocks before start of non-system memory between 16M and 4G -// 22h WORD start segment of largest free block from C0000h-DFFFFh -// 24h WORD size of largest free block -// 26h DWORD reserved - - //movw $0x0028, (%si) - pushw %ds - pushw %si - - pushfw - lcall %cs:*(EXT_C(ROM_int15) - int13_handler) - - popw %si - popw %ds - - jc 3f - - pushl %eax - - /* between 16M and 4G */ - - movl %cs:(minimum_mem_hi_in_map - int13_handler), %eax - cmpl $-1, %eax /* 4G - 1 */ - je 5f - subl $0x1000000, %eax /* 16M */ - shrl $10, %eax /* AX=mem above 16M in 1K blocks */ - movl %eax, 0x0e(%si) - movl %eax, 0x1e(%si) -5: - - /* between 1M and 16M */ - - movl %cs:(minimum_mem_lo_in_map - int13_handler), %eax - cmpl $0x1000000, %eax /* 16M */ - je 5f - subl $0x0100000, %eax /* 1M */ - shrl $10, %eax /* AX=1-16M mem in K */ - movl %eax, 0x0a(%si) - movl %eax, 0x1a(%si) -5: - - popl %eax - - clc - lret $2 -3: - stc - lret $2 -#endif -#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -1: - cmpb $0x8a, %ah - jne 1f - - /* Phoenix BIOS v4.0 - GET BIG MEMORY SIZE */ - - //AH = 8Ah - - //Return: - //DX:AX = extended memory size in K - //movw $0xfc00, %ax - -#; pushfw -#; lcall %cs:*(EXT_C(ROM_int15) - int13_handler) -#; -#; jc 3f - - movl %cs:(minimum_mem_lo_in_map - int13_handler), %edx - movw %dx, %ax - shrl $16, %edx - - clc - lret $2 -#;3: -#; stc -#; lret $2 - -#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -1: - cmpb $0x88, %ah - jne 1f - - /* SYSTEM - GET EXTENDED MEMORY SIZE (286+) */ - - //AH = 88h - - //Return: - //CF clear on success(Not all BIOSes correctly return the carry flag) - //AX = number of contiguous KB starting at absolute address 100000h - //CF set on error - //AH = status - // 80h invalid command (PC,PCjr) - // 86h unsupported function (XT,PS30) - //movw $0xfc00, %ax - -#; pushfw -#; lcall %cs:*(EXT_C(ROM_int15) - int13_handler) -#; -#; jc 3f - - movl %cs:(minimum_mem_lo_in_map - int13_handler), %eax - cmpl $0x10000, %eax - jb 5f - movw $0xFFFF, %ax -5: - clc - lret $2 -#;3: -#; stc -#; lret $2 - -1: - ljmp %cs:*(EXT_C(ROM_int15) - int13_handler) - -safe_ROM_int15: - - pushw %ds - pushw $0 - popw %ds /* DS = 0 */ - pushl 0x54 /* backup original int 15 vector */ - pushl %cs:(EXT_C(ROM_int15) - int13_handler) - popl 0x54 /* install ROM_int15 */ - pushw %ds /* DS = 0 */ - int $0x15 - popw %ds /* DS = 0 */ - popl 0x54 /* restore original int 15 vector */ - popw %ds - ret - -dec_e820cycles: - /* if e820cycles = -1, do nothing, else decrement */ - pushal - movl %cs:(EXT_C(e820cycles) - int13_handler), %ecx - incl %ecx - jz 1f - decl %ecx - jz 2f - decl %ecx - jnz 3f -2: - /* unhook int15 */ - pushw %ds - movw %cx, %ds /* DS = 0 */ - pushl %cs:(EXT_C(ROM_int15) - int13_handler) - popl 0x54 /* install ROM_int15 */ - popw %ds -3: - movl %ecx, %cs:(EXT_C(e820cycles) - int13_handler) -1: - popal - ret - -#;============================================================================ - -/****************************************************************************/ - -#include "a20.inc" - -/****************************************************************************/ - - .align 16 - -GDT_data: /* used by int15/ah=87h */ - -/*00*/ .long 0, 0 /* unused descriptor, must be 0 */ -/*08*/ .long 0, 0 /* GDT descriptor, must be 0 */ - - /* source descriptor */ -/*10*/ .word 0xffff /* segment limit, 64K */ -/*12*/ .byte 0, 0, 0 /* physical address(low 24 bits) */ -/*15*/ .byte 0x93 /* access rights, 93h=readable/writable */ -/*16*/ .byte 0 /* low 4 bits are high 4 bits of segment limit(here - should be 0). high 4 bits are flags, also should - be set to 0 for this function call */ -/*17*/ .byte 0 /* physical address(high 8 bits) */ - - /* destination descriptor */ -/*18*/ .word 0xffff /* segment limit, 64K */ -/*1A*/ .byte 0, 0, 0 /* physical address(low 24 bits) */ -/*1D*/ .byte 0x93 /* access rights, 93h=readable/writable */ -/*1E*/ .byte 0 /* low 4 bits are high 4 bits of segment limit(here - should be 0). high 4 bits are flags, also should - be set to 0 for this function call */ -/*1F*/ .byte 0 /* physical address(high 8 bits) */ - -/*20*/ .long 0, 0 /* code segment descriptor, must be 0 */ -/*28*/ .long 0, 0 /* stack segment descriptor, must be 0 */ -/*30*/ - - - - .align 16 - -/* EBIOS_disk_address_packet should be at the end of the handler because some - * buggy BIOSes could destroy the memory that immediately follows. - */ -EBIOS_disk_address_packet: - .byte 0x10 /* packet size, 16 or more */ - .byte 0 /* reserved, must be 0 */ - .byte 0 /* number of sectors, must be from 1 to 127 */ - .byte 0 /* reserved, must be 0 */ - .word 0 /* displacement of memory address */ - .word 0 /* segment of memory address */ - .long 0 /* 64bit, start logical sector number */ - .long 0 - -edd30_disk_buffer: .space 0x800 - -#if MAP_NUM_16 -ENTRY(hooked_drive_map_2) - .space (DRIVE_MAP_SIZE / 2 + 1) * DRIVE_MAP_SLOT_SIZE -#endif - - .ascii "FRAGMENT" - -ENTRY(hooked_fragment_map) .space FRAGMENT_MAP_SLOT_SIZE - - .ascii "int13end" - -cdrom_start: -#ifdef CDROM_INIT -/* EDD30 code imported from edd30.asm of Smart Boot Manager. */ - -/* -#; asmsyntax=nasm -#; -#; CD-ROM Boot Extension v 1.1 for Smart Boot Manager -#; -#; Copyright (C) 2000, Christopher Li . -#; Copyright (C) 2000, James Su -#; -#; This is free software, you can redistribute it and/or modify it -#; under the terms of the GNU General Public License version 2 or above. -#; -#; The ATAPI driver is based on the source code of atadrv written by -#; Hale Landis , Thanks him a lot! -#; -#; Without his great program, we could not implement the CD-ROM Boot feature -#; so quickly. -#; -*/ - - -//#define EDD_3_0 - -#define sane_check -#define check_extra_fail - -//#define CB_DATA 0 //; data reg in/out pio_base_addr1+0 -//#define CB_FR 1 //; feature reg out pio_base_addr1+1 -//#define CB_SC 2 //; sector count in/out pio_base_addr1+2 -//#define CB_SN 3 //; sector number in/out pio_base_addr1+3 -//#define CB_CL 4 //; cylinder low in/out pio_base_addr1+4 -//#define CB_CH 5 //; cylinder high in/out pio_base_addr1+5 -//#define CB_DH 6 //; device head in/out pio_base_addr1+6 -//#define CB_STAT 7 //; primary status in pio_base_addr1+7 -//#define CB_CMD 7 //; command out pio_base_addr1+7 -//#define CB_DC 8 //; device control out pio_base_addr2+6 -//#define CB_ASTAT 8 //; alternate status in pio_base_addr2+6 -//#define CB_DC_SRST 0x04 //; soft reset -#define CB_STAT_BSY 0x80 //; busy -#define CB_STAT_RDY 0x40 //; ready -#define CB_STAT_SKC 0x10 //; seek complete - -#define CB_STAT_DRQ 0x08 //; data request -#define CB_STAT_ERR 0x01 //; error - -#define CB_SC_P_TAG 0xf8 //; ATAPI tag (mask) -#define CB_SC_P_REL 0x04 //; ATAPI release -#define CB_SC_P_IO 0x02 //; ATAPI I/O -#define CB_SC_P_CD 0x01 //; ATAPI C/D - -#define FAILBIT8 0x0100 //; SC( CD/IO bits) wrong at end of cmd -#define FAILBIT6 0x0040 //; byte count wrong at data packet xfer time -#define FAILBIT5 0x0020 //; SC (IO bit) wrong at data packet xfer time -#define FAILBIT4 0x0010 //; SC (CD bit) wrong at data packet xfer time -#define FAILBIT3 0x0008 //; byte count wrong at cmd packet xfer time -#define FAILBIT2 0x0004 //; SC wrong at cmd packet xfer time -#define FAILBIT0 0x0001 //; slow setting BSY=1 or DRQ=1 after AO cmd - -#define CB_DC_HD15 0x08 //; bit should always be set to one -#define CB_DC_NIEN 0x02 //; disable interrupts -#define cmd_DC CB_DC_HD15 -#define cmd_DC_ni CB_DC_HD15 | CB_DC_NIEN - -/****************************************************************************/ - -__reg_select_dev: -#; ax = dev -#; simple version of the select dev - addb $0x0A, %al #; AL= 0x0A or 0x0B - shlb $4, %al #; AL= 0xA0 or 0xB0 - movw reg_addr - int13_handler + (6 * 2), %dx #; CB_DH = drive select - outb %al, %dx - - call delay400ns - ret - - -reg_select_dev: -#; input: ax = bx = dev -#; set_timeout first -// movw %ax, %bx - cmpb $2, (reg_dev_info - int13_handler)(%bx) # REG_CONFIG_TYPE_ATA - jb __reg_select_dev # not ATA - - /* The device is ATA */ - -// pushw %bx - - call reg_poll_busy # change AL, DX - -#if 0 - orw %ax, %ax - jnz 1f # return if,{or ax,ax},nz -#else - ja 1f # timeout, failure -#endif - - movw %bx, %ax - call __reg_select_dev # change AL, DX - -#ifndef USE_ATA - call reg_poll_busy # change AL, DX -#if 0 - jmp 1f -#else -#if 0 - orw %ax, %ax - jz 1f -#else - jna 1f -#endif -#endif -#else //; USE_ATA -3: - movw reg_addr - int13_handler + (7 * 2), %dx #; CB_STAT - inb %dx, %al - - cmpb $2, (reg_dev_info - int13_handler)(%bx) # REG_CONFIG_TYPE_ATA - jne 4f - andb $(CB_STAT_BSY | CB_STAT_RDY | CB_STAT_SKC), %al - # return if,{cmp al,CB_STAT_RDY|CB_STAT_SKC},e - cmpb $(CB_STAT_RDY | CB_STAT_SKC), %al - je 1f - jmp 3b -4: - # return if,{test al,CB_STAT_BSY},z - testb $CB_STAT_BSY, %al - jz 1f - jmp 3b -#endif //; USE_ATA - - - call __reg_select_dev -1: -// popw %bx - ret - - -select_atapi: - cmpw %cs:(atapi_cur_dev - int13_handler), %ax # device serial number - jne select_atapi_force - //clc #; CF already cleared - ret - - -select_atapi_force: -#; input: ax = device serial number -#; return: cf =0 success, cf =1 failed - pushaw - pushw %es - - pushw %cs - popw %es - - cmpb %cs:(EXT_C(atapi_dev_count) - int13_handler), %al - cmc - jb 2f - - movw %ax, %cs:(atapi_cur_dev - int13_handler) # device serial number - - movw $atapi_dev_base - int13_handler, %si # array of ATAPI reg pointer and dev - shlw $2, %ax # each element of array has 4 bytes - addw %ax, %si - movw %cs:(%si), %bx # BX is the reg pointer of the current device - - call reg_setup_base_addr # fill the 10-word reg_addr area - # change no registers - - movw %cs:2(%si), %bx # BX is the dev number of the current device - movw %bx, %ax - - call set_timeout # set timeout for reg_select_dev - # change no registers - - call reg_select_dev - - addb $0x0A, %bl #; BL= 0x0A or 0x0B - shlb $4, %bl #; BL= 0xA0 or 0xB0 - movb %bl, %cs:(reg_cur_dev - int13_handler) - - clc -2: - pop %es - popaw - ret - - -read_atapi: -#;input: es:di -> buffer, cx = sector count, edx = lba address -#;return: cf =0 success, cx = number of bytes actually read - pushaw - orw %cx, %cx - jz 3f - -1: - pushw %cx - pushl %edx - - call clear_atapi_buffer - movb $0x28, atapi_cmd_buffer - int13_handler - - bswapl %edx - movl %edx, atapi_cmd_buffer - int13_handler + 2 - movb $1, atapi_cmd_buffer - int13_handler + 8 - - # invoke reg_packet,byte, 0, es, di, REG_ATAPI_MAX_BYTES - pushw $0x8000 #; REG_ATAPI_MAX_BYTES - pushw %di - pushw %es - pushw $0 - call reg_packet - addw $8, %sp - - orw %ax, %ax - jnz 2f - cmpw $0x800, %cx #; CDSECTOR_SIZE - jne 2f - popl %edx - incl %edx - addw %cx, %di - popw %cx - loop 1b - - clc - jmp 4f - -2: - popl %edx - popw %cx - -3: - stc -4: - popaw - ret - - -read_bios_time: -#; return EAX as the long time - pushw %ds - xorw %ax, %ax - movw %ax, %ds - movl 0x46c, %eax - popw %ds - ret - - -edd30_read_cdrom: -#;return cf=0 success, cf=1 fail, ah = fail code -#;will change all registers, including ES!! - - call test_atapi_ready - movb $0xAA, %ah # error code if CF=1 - jc 4f - - movw %ds, %ax # save DS - - # get DS for the disk address packet - movw %cs:(int13_old_ds - int13_handler), %ds - movw 2(%si), %cx # struc_int13ext.blk_count - movw 4(%si), %di # struc_int13ext.buf_addr_off - movw 6(%si), %bx # struc_int13ext.buf_addr_seg - movl 8(%si), %edx # struc_int13ext.blk_num_low1 - cmpb $16, (%si) # valid packet size is 16 - - movw %ax, %ds # restore DS - - setne %ah # AH=1 for invalid function call - stc # error out if ... - jne 4f # ... invalid packet size - - movw %bx, %es # ES changed!! - - call read_atapi - - movb $0x0C, %ah # error code if CF=1 -4: -// /* debug print AX and FLAGS */ -// pushfw -// pushw %ax -// pushw $read_cdrom_ah_flags - int13_handler # the format string -// call realmode_printf -// popw %ax -// popw %ax -// popfw - ret - -//read_cdrom_ah_flags: -// .ascii "edd30_read_cdrom: AX=%X, FLAGS=%X\r\n\0" - - -reg_reset: -#; call after reg_probe_exist - pushaw - -#; mov_ax 0 -#; call __reg_select_dev - -#if 0 - /* The ATA software reset mechanism, SRST, (bit 2 in the Device Control - * Register) cannot be used for ATAPI Device, because resets issued by - * the ATAPI driver would also reset any attached hard disk and vice - * versa. To solve this, ATAPI defines an ATAPI Soft Reset command - * using a reserved ATA opcode which could be decoded by the interface - * controller hardware. - */ - - movb $cmd_DC, %al - orb $0x04, %al #; CB_DC_SRST = soft reset - - movw reg_addr - int13_handler + (8 * 2), %dx #; CB_DC - outb %al, %dx - - call delay400ns -#endif - -#if 0 - movb $0x08, %al #; ATAPI Soft Reset - movw reg_addr - int13_handler + (7 * 2), %dx #; CB_CMD - outb %al, %dx - - call delay400ns -#endif - -#if 1 - /* set features (0xEF to command port) */ - /* set transfer mode (0x03 in feature register) */ - /* mode value in Sector Count register (0 for PIO default mode) */ - - movb $0, %al #; PIO default transfer mode - movw reg_addr - int13_handler + (2 * 2), %dx #; CB_SC = interrupt reason register - outb %al, %dx - - call delay400ns - - movb $0x03, %al #; 0x03 = set transfer mode based on value in sector count register - movw reg_addr - int13_handler + (1 * 2), %dx #; CB_FR = Feature Register - outb %al, %dx - - call delay400ns - - movb $0xEF, %al #; Set Features Command - movw reg_addr - int13_handler + (7 * 2), %dx #; CB_CMD - outb %al, %dx - - call delay400ns -#endif - -#if 1 - movb $0x08, %al #; ATAPI Soft Reset - movw reg_addr - int13_handler + (7 * 2), %dx #; CB_CMD - outb %al, %dx - - call delay400ns -#endif - -#; Test only: do a hard reset and see if it works -#if 1 - /* The ATA software reset mechanism, SRST, (bit 2 in the Device Control - * Register) cannot be used for ATAPI Device, because resets issued by - * the ATAPI driver would also reset any attached hard disk and vice - * versa. To solve this, ATAPI defines an ATAPI Soft Reset command - * using a reserved ATA opcode which could be decoded by the interface - * controller hardware. - */ - - movb $cmd_DC, %al - orb $0x04, %al #; CB_DC_SRST = soft reset - - movw reg_addr - int13_handler + (8 * 2), %dx #; CB_DC - outb %al, %dx - - call delay400ns -#endif - - movb $cmd_DC, %al - movw reg_addr - int13_handler + (8 * 2), %dx #; CB_DC - outb %al, %dx - - call delay400ns - - call set_timeout - - cmpb $0, reg_dev_info - int13_handler - je 1f #; master not exist - - call sub_atapi_delay - - call reg_poll_busy - -1: - cmpb $0, reg_dev_info - int13_handler + 1 - je 1f #; slave not exist - - call sub_atapi_delay - - //call reg_poll_busy #; added recently for test - - //jmp 1f #; added recently for test - -2: - movw $1, %ax - - call __reg_select_dev - - movw reg_addr - int13_handler + (2 * 2), %dx #; CB_SC = interrupt reason register - inb %dx, %al - movb %al, %ah - - movw reg_addr - int13_handler + (3 * 2), %dx #; CB_SN = reserved for SAM TAG byte - inb %dx, %al - - cmpw $0x0101, %ax - je 1f - - call check_timeout - jna 2b -1: - popaw - ret - - -test_atapi_ready: -#; return: cf =0 ready, cf =1 not ready - pushaw - movw $2, %cx - -1: - pushw %cx - - call clear_atapi_buffer - - #; TEST UNIT READY Command - #; - #; The TEST UNIT READY command provides a means to check if the Device - #; is ready. This is not a request for a self-test. If the Device would - #; accept an appropriate medium-access command without returning CHECK - #; CONDITION status, this command shall return a GOOD status. If the - #; Device cannot become operational or is in a state such that a Host - #; Computer action(e.g. START/STOP UNIT command with LoEj = 0 and Start - #; = 1) is required to make the unit ready, the ATAPI CD-ROM Drive - #; shall return CHECK CONDITION status with a sense key of NOT READY. - #; - #; Byte - #; 0 Operation code (00h) - #; 1 Reserved - #; 2 Reserved - #; 3 Reserved - #; 4 Reserved - #; 5 Reserved - #; 6 Reserved - #; 7 Reserved - #; 8 Reserved - #; 9 Reserved - #; 10 Reserved - #; 11 Reserved - #; - #; Using the TEST UNIT READY Command - #; - #; The TEST UNIT READY command is useful in that it allows a Host - #; Computer to poll a Device until it is ready without the need to - #; allocate space for returned data. It is especially useful to check - #; cartridge status. ATAPI CD-ROM Drives are expected to respond - #; promptly to indicate the current status of the device. - - # invoke reg_packet,byte,0,cs, atapi_tmp_buffer, 128 - pushw $128 - pushw $atapi_tmp_buffer - int13_handler - pushw %cs - pushw $0 - call reg_packet - addw $8, %sp - -// /* debug print AX */ -// pushw %ax -// pushw $test_atapi_ax - int13_handler # the format string -// call realmode_printf -// popw %ax -// popw %ax - - orw %ax, %ax - jnz 2f - - call get_atapi_sense - -// /* debug print AL, FLAGS */ -// pushfw -// pushw %ax -// pushw $test_atapi_al_flags - int13_handler # the format string -// call realmode_printf -// popw %ax -// popw %ax -// popfw - - jc 2f - orb %al, %al - jnz 2f - - popw %cx - clc - popaw - ret -2: - call start_stop_unit #; start unit - - popw %cx - loop 1b #; try again - - stc - popaw - ret - -//test_atapi_ax: -// .ascii "test_atapi_ax: AX=%X\r\n\0" - -//test_atapi_al_flags: -// .ascii "test_atapi_al_flags: AX=%X, FLAGS=%X\r\n\0" - - -start_stop_unit: -#; return: cf =0 ready, cf =1 not ready - pushaw - movw $1, %cx - -1: - pushw %cx - - call clear_atapi_buffer - - #; START/STOP UNIT Command - #; - #; The START/STOP UNIT command requests that the ATAPI CD-ROM Drive - #; enable or disable media access operations. - #; - #; | bit bit bit bit bit bit bit bit - #; Byte | 7 6 5 4 3 2 1 0 - #; -----+-------------------------------------------------------------- - #; 0 | Operation code (1Bh) - #; -----+-------------------------------------------------------+------ - #; 1 | Reserved | Immed - #; -----+-------------------------------------------------------+------ - #; 2 | Reserved - #; -----+-------------------------------------------------------------- - #; 3 | Reserved - #; -----+-----------------------------------------------+-------+------ - #; 4 | Reserved | LoEj | Start - #; -----+-----------------------------------------------+-------+------ - #; 5 | - #; -----+-------------------------------------------------------------- - #; 6 | Reserved - #; -----+-------------------------------------------------------------- - #; 7 | Reserved - #; -----+-------------------------------------------------------------- - #; 8 | Reserved - #; -----+-------------------------------------------------------------- - #; 9 | Reserved - #; -----+-------------------------------------------------------------- - #; 10 | Reserved - #; -----+-------------------------------------------------------------- - #; 11 | Reserved - #; -----+-------------------------------------------------------------- - - movb $0x1B, atapi_cmd_buffer - int13_handler - movb $0x01, atapi_cmd_buffer - int13_handler + 4 #; start unit - - # invoke reg_packet,byte,0,cs, atapi_tmp_buffer, 128 - pushw $128 - pushw $atapi_tmp_buffer - int13_handler - pushw %cs - pushw $0 - call reg_packet - addw $8, %sp - - orw %ax, %ax - jnz 2f - -// call get_atapi_sense -// -// jc 2f -// orb %al, %al -// jnz 2f - - popw %cx - clc - popaw - ret -2: - popw %cx - loop 1b - - stc - popaw - ret - - - - -reg_setup_base_addr: -#; input: bx = base addr pointer - pushw %ax - pushw %di - cld # store upward - movw $reg_addr - int13_handler, %di # points to 10-word space - movw %cs:(%bx), %ax # get base address - # store 8 ports(command block registers) - -#if 0 - pushw 18(%di) - pushw 16(%di) - pushw 14(%di) - pushw 12(%di) - pushw 10(%di) - pushw 8(%di) - pushw 6(%di) - pushw 4(%di) - pushw 2(%di) - pushw (%di) - pushw 2(%bx) - pushw %ax - pushw $reg_addresses - int13_handler # the format string - call realmode_printf - addw $26, %sp # adjust the stack pointer -#endif - - stosw - incw %ax - stosw - incw %ax - stosw - incw %ax - stosw - incw %ax - stosw - incw %ax - stosw - incw %ax - stosw - incw %ax - stosw - - movw %cs:2(%bx), %ax # get base address - stosw # store 2 ports(control block registers) - incw %ax - stosw - popw %di - popw %ax - ret - -#if 0 -reg_addresses: - .ascii "reg_addresses: Data=%X, Ctrl=%X, di: %X, %X, %X, %X, %X, %X, %X, %X, %X, %X\r\n\0" -#endif - -set_timeout: - pushl %eax - call read_bios_time - addl $(5 * 18), %eax #; 20 seconds - # not 20 seconds, but 5 seconds - #; FIXME: Midnight overflow - # Midnight overflow is handled in check_timeout - movl %eax, %cs:(time_out - int13_handler) - popl %eax - ret - - -check_timeout: -#; you need to setup the timeout first - pushl %eax - pushl %ebx - pushl %edx - call read_bios_time - movl time_out - int13_handler, %ebx - movl %ebx, %edx - subl $(5 * 18), %ebx # the time when we set_timeout - cmpl %ebx, %eax - jnb 1f - /* the next day */ - addl $0x001800B0, %eax /* 24 hours = 0x1800B0 ticks */ -1: - cmpl %edx, %eax - popl %edx - popl %ebx - popl %eax - ret - - -clear_atapi_buffer: - pushaw - pushw %es - pushw %cs - popw %es - cld - movw $atapi_tmp_buffer - int13_handler, %di - movw $128, %cx # but note the buffer is 256-byte long! - xorb %al, %al - rep stosb # added the lost rep prefix - movw $atapi_cmd_buffer - int13_handler, %di - movw $16, %cx - rep stosb # added the lost rep prefix - popw %es - popaw - ret - - -reg_packet: -#;proc reg_packet,withlocal,dir,packet_seg,packet_off,packet_len -#; input: -#; return ax = 0 noerror, ah = error code al= error bit -#; cx = len - pushaw - - movw %sp, %bp - - call set_timeout - movb $0, _pre_fail_bit7_ - int13_handler - -#; outbytes CB_DC,cmd_DC_ni,CB_FR,0,CB_SC,0,CB_SN,0, - # outbytes CB_DC,cmd_DC,CB_FR,0,CB_SC,0,CB_SN,0, - movb $cmd_DC, %al - movw reg_addr - int13_handler + (8 * 2), %dx #; CB_DC - outb %al, %dx - - call delay400ns #; added recently - - call sub_atapi_delay #; added recently - - movb $0, %al - movw reg_addr - int13_handler + (1 * 2), %dx #; CB_FR = Feature Register - outb %al, %dx - - movb $0, %al - movw reg_addr - int13_handler + (2 * 2), %dx #; CB_SC = interrupt reason register - outb %al, %dx - - movb $0, %al - movw reg_addr - int13_handler + (3 * 2), %dx #; CB_SN = reserved for SAM TAG byte - outb %al, %dx - - - # outbytes CB_CL,[.packet_len],CB_CH,[.packet_len+1] - movb 24(%bp), %al #; packet_len low byte - movw reg_addr - int13_handler + (4 * 2), %dx #; CB_CL = byte count low - outb %al, %dx - - movb 25(%bp), %al #; packet_len high byte - movw reg_addr - int13_handler + (5 * 2), %dx #; CB_CH = byte count high - outb %al, %dx - - # outbyte CB_DH,[reg_cur_dev] - movb reg_cur_dev - int13_handler, %al - movw reg_addr - int13_handler + (6 * 2), %dx #; CB_DH = drive select - outb %al, %dx - - # outbyte CB_CMD,CMD_PACKET - movb $0xA0, %al #; CMD_PACKET - movw reg_addr - int13_handler + (7 * 2), %dx #; CB_CMD - outb %al, %dx - - call delay400ns - - call sub_atapi_delay - - subw %bx, %bx #; clear error number - - # while {inbyte CB_ASTAT},{test al,CB_STAT_BSY|CB_STAT_ERR|CB_STAT_DRQ},z -3: - # inbyte CB_ASTAT - movw reg_addr - int13_handler + (8 * 2), %dx #; CB_ASTAT=8, CB_STAT=7 - inb %dx, %al - - testb $(CB_STAT_BSY | CB_STAT_DRQ | CB_STAT_ERR), %al - jnz 3f - - orb $FAILBIT0, %bl #; error - call check_timeout - jna 3b -3: - # endwhile - - # while {inbyte CB_ASTAT},{test al, CB_STAT_BSY}, nz -3: - # inbyte CB_ASTAT - movw reg_addr - int13_handler + (8 * 2), %dx #; CB_ASTAT=8, CB_STAT=7 - inb %dx, %al - - testb $CB_STAT_BSY, %al - jz 3f - - call check_timeout - jna 3b - movw $-1, 18(%bp) - movb $51, %bh #; error -3: - # endwhile - - cmpb $0, %bh - jnz 2f #; error - - # inbyte CB_STAT,[.status] - movw reg_addr - int13_handler + (7 * 2), %dx #; CB_STAT - inb %dx, %al - movb %al, _status_ - int13_handler - - # inbyte CB_SC, [.reason] - movw reg_addr - int13_handler + (2 * 2), %dx #; CB_SC = interrupt reason register - inb %dx, %al - movb %al, _reason_ - int13_handler - - # inbyte CB_CL, [.bcnt] - movw reg_addr - int13_handler + (4 * 2), %dx #; CB_CL = byte count low - inb %dx, %al - movb %al, _bcnt_ - int13_handler - - # inbyte CB_CH, [.bcnt+1] - movw reg_addr - int13_handler + (5 * 2), %dx #; CB_CH = byte count high - inb %dx, %al - movb %al, _bcnt_ - int13_handler + 1 - - movb _status_ - int13_handler, %al - andb $(CB_STAT_BSY | CB_STAT_DRQ), %al - cmpb $CB_STAT_DRQ, %al - jz 3f - movb $52, %bh #; error - - jmp 2f -3: - -#ifdef sane_check - movb _reason_ - int13_handler, %al - testb $(CB_SC_P_TAG | CB_SC_P_REL | CB_SC_P_IO), %al - jnz 3f - testb $CB_SC_P_CD, %al - jnz 4f -3: - orb $FAILBIT2, %bl #; error -4: - movw _bcnt_ - int13_handler, %ax - cmpw 24(%bp), %ax - jz 3f - orb $FAILBIT3, %bl #; error - -3: - -#endif //; sane_check - - movw $atapi_cmd_buffer - int13_handler, %si -#if 0 - movw $12, %cx #; cmd_buff_len is 12 - shrw $1, %cx -#else - movw $6, %cx #; cmd_buff_len is 12 -#endif - movw reg_addr - int13_handler + (0 * 2), %dx #; CB_DATA = 16-bit data port - cld - repz outsw - - call delay400ns - - subw %cx, %cx -3: - # while - - call sub_atapi_delay -4: - # while {inbyte CB_ASTAT},{test al,CB_STAT_BSY},nz - # inbyte CB_ASTAT - movw reg_addr - int13_handler + (8 * 2), %dx #; CB_ASTAT=8, CB_STAT=7 - inb %dx, %al - - testb $CB_STAT_BSY, %al - jz 4f - call check_timeout - jna 4b - movb $54, %bh #; error - jmp 2f - # endwhile -4: - - #; Data transfer loop - #; read the primary state register - - # inbyte CB_STAT,[.status] - movw reg_addr - int13_handler + (7 * 2), %dx #; CB_STAT - inb %dx, %al - movb %al, _status_ - int13_handler - - # inbyte CB_SC, [.reason] - movw reg_addr - int13_handler + (2 * 2), %dx #; CB_SC = interrupt reason register - inb %dx, %al - movb %al, _reason_ - int13_handler - - # inbyte CB_CL, [.bcnt] - movw reg_addr - int13_handler + (4 * 2), %dx #; CB_CL = byte count low - inb %dx, %al - movb %al, _bcnt_ - int13_handler - - # inbyte CB_CH, [.bcnt+1] - movw reg_addr - int13_handler + (5 * 2), %dx #; CB_CH = byte count high - inb %dx, %al - movb %al, _bcnt_ - int13_handler + 1 - - testb $(CB_STAT_BSY | CB_STAT_DRQ), _status_ - int13_handler - jnz 4f - orb $0x80, 18(%bp) #; NON_DATA - jmp 2f -4: - movb _status_ - int13_handler, %al - andb $(CB_STAT_BSY | CB_STAT_DRQ), %al - cmpb $CB_STAT_DRQ, %al - jz 4f - movb $55, %bh #; error - jmp 2f -4: - -#ifdef sane_check - testb $(CB_SC_P_TAG | CB_SC_P_REL | CB_SC_P_CD), _reason_ - int13_handler - jz 4f - orb $FAILBIT4, %bl #; error -4: - testb $CB_SC_P_IO, _reason_ - int13_handler - jz 4f - cmpb $0, 18(%bp) - jz 4f - orb $FAILBIT5, %bl #; error -4: -#endif //; sane_check - - #; do the slow data transfer - - call sub_atapi_delay - - movw _bcnt_ - int13_handler, %ax - orw %ax, %ax - jnz 4f - movb $60, %bh #; error - orb $0x80, 18(%bp) #; NON_DATA - jmp 2f -4: - -#ifdef sane_check - cmpw $0x8000, %ax #; REG_ATAPI_MAX_BYTES - jna 4f - orb $FAILBIT6, %bl #; error -4: -#endif //; sane_check - movb _pre_fail_bit7_ - int13_handler, %dl - orb %dl, %bl #; error - testb $1, %al - setnz _pre_fail_bit7_ - int13_handler - - movw %cx, %dx - addw %ax, %dx - cmpw 24(%bp), %dx - jna 4f - movb $59, %bh #; error - orb $0x80, 18(%bp) #; NON_DATA - jmp 2f -4: - - pushw %dx - movw %ax, %cx - incw %cx - shrw $1, %cx - movw reg_addr - int13_handler + (0 * 2), %dx #; CB_DATA = 16-bit data port - cld - cmpb $0, 18(%bp) - jz 4f - pushw %ds - movw 20(%bp), %ds #; packet_seg - movw 22(%bp), %si #; packet_off - repz outsw - popw %ds - jmp 5f -4: - pushw %es - movw 20(%bp), %es #; packet_seg - movw 22(%bp), %di #; packet_off - repz insw - popw %es -5: - popw %cx - - addw %ax, 22(%bp) #; packet_off - call delay400ns - jmp 3b - # endwhile -3: - testb $0x80, 18(%bp) #; NON_DATA - jnz 3f - call sub_atapi_delay - - call check_timeout # !!added recently!! - jna 3f - - movb $57, %bh #; error: time is out - jmp 2f -3: - - # inbyte CB_STAT, #; [.status] - movw reg_addr - int13_handler + (7 * 2), %dx #; CB_STAT - inb %dx, %al - - testb $(CB_STAT_BSY | CB_STAT_DRQ | CB_STAT_ERR), %al - jz 1f - - movb $58, %bh #; error - jmp 2f -1: - # inbyte CB_SC, [.reason] - movw reg_addr - int13_handler + (2 * 2), %dx #; CB_SC = interrupt reason register - inb %dx, %al - movb %al, _reason_ - int13_handler -2: - -#ifdef check_extra_fail - movb _reason_ - int13_handler, %al - testb $(CB_SC_P_TAG | CB_SC_P_REL), %al - jnz 1f - testb $CB_SC_P_IO, %al - jz 1f - testb $CB_SC_P_CD, %al - jnz 2f -1: - orw $FAILBIT8, %bx #; error -2: -#endif //; check_extra_fail - -#; outbyte CB_DC,cmd_DC - - movw %bx, 14(%bp) # __AX #; error - movw %cx, 12(%bp) # __CX - - popaw - ret - -# local status,1,reason,1,bcnt,2,pre_fail_bit7,1 -_status_: .byte 0 -_reason_: .byte 0 -_bcnt_: .byte 0, 0 -_pre_fail_bit7_: .byte 0 -# //; end of function reg_packet - - -delay400ns: - - pushw %cx - movw $0x0040, %cx -1: - pause - loop 1b - popw %cx - ret - - # inbyte CB_ASTAT - movw reg_addr - int13_handler + (8 * 2), %dx #; CB_ASTAT=8, CB_STAT=7 - inb %dx, %al - inb %dx, %al - inb %dx, %al - inb %dx, %al - ret - - -sub_atapi_delay: -#; delay a few clicks - cmpl $0, EXT_C(slow_atapi_device) - int13_handler - jz 1f - - # delay 1 millisecond - - pushl %ecx - //pushfw - - //sti #; sti should already be done by the caller - - movl delay_repeat_num - int13_handler, %ecx # loops per millisecond -2: - call read_bios_time - cmpw %ax, %ax # for more accurate timing - addr32 loope 2b - - //popfw - popl %ecx - -1: - ret - - -reg_poll_busy: -#; need to setup the timeout first -#;return ax=0 ok -#; ax = 1 timeout - -1: - movw reg_addr - int13_handler + (7 * 2), %dx #; CB_STAT - inb %dx, %al - - andb $0x80, %al # CB_STAT_BSY - jz 1f - call check_timeout - jna 1b - # timeout -1: - ret - - -get_atapi_sense: -#; return: cf =0 success, al = sense key, bl = asc, bh = ascq -#; cf =1 failed - - call clear_atapi_buffer - - #; REQUEST SENSE Command - #; - #; The REQUEST SENSE command requests that the ATAPI CD-ROM Drive - #; transfer sense data to the Host Computer. - #; - #; Byte - #; 0 Operation code (03h) - #; 1 Reserved - #; 2 Reserved - #; 3 Reserved - #; 4 Allocation Length - #; 5 Reserved - #; 6 Reserved - #; 7 Reserved - #; 8 Reserved - #; 9 Reserved - #; 10 Reserved - #; 11 Reserved - - movb $0x03, atapi_cmd_buffer - int13_handler - movb $32, atapi_cmd_buffer - int13_handler + 4 - - # invoke reg_packet,byte,0,cs, atapi_tmp_buffer, 128 - pushw $128 - pushw $atapi_tmp_buffer - int13_handler - pushw %cs - pushw $0 - call reg_packet - addw $8, %sp - - orw %ax, %ax - jnz 1f - - movb atapi_tmp_buffer - int13_handler, %al - /* bit 7 is `Valid' bit, and should be 1 - * bit 0-6 is the error code and can be 70h or 71h - */ - andb $0x7f, %al - cmpb $0x70, %al - je 2f - cmpb $0x71, %al - jne 1f -2: - movb atapi_tmp_buffer - int13_handler + 2, %al #; get sense key - andb $0x0f, %al #; low 4 bits are sense key - xorw %bx, %bx - cmpb $0x06, atapi_tmp_buffer - int13_handler + 7 #; additional sense length - jb 3f - movw atapi_tmp_buffer - int13_handler + 12, %bx -3: - clc - ret -1: - stc - ret - - -edd30_for_cdrom: -// ; Stack layout: -// ; +10 INT flags -// ; +8 INT CS -// ; +6 INT IP -// ; +2 EAX -// ; BP+0 BP -// ; -2 ax -// ; -4 cx -// ; -6 dx -// ; -8 bx -// ; -10 sp -// ; -12 bp -// ; -14 si -// ; -16 di -// ; -18 ds -// ; -20 es -// ; -24 edx - - /* will read these variables: - * int13_old_eax - * int13_old_ebx - * int13_old_ecx - * int13_old_edx - * int13_old_esi - * int13_old_edi - * int13_old_ebp - * int13_old_ds - * int13_old_es - * int13_old_flags - * int13_old_cs_ip - * will write these variables: - * int13_old_eax - * int13_old_ebx - * int13_old_ecx - * int13_old_flags - */ - - sti - - cld - - pushw %cs - popw %ds - - movzbw %dl, %ax - subb %cs:(EXT_C(min_cdrom_id) - int13_handler), %al - call select_atapi #; select_atapi_force - movw %cs:(int13_old_eax - int13_handler), %ax - - jnc 1f - movb $0xAA, %ah - jmp 2f //fail_out -1: - cmpb $0, %ah - je 6f //reset - cmpb $1, %ah - je 7f //get_last_stat - cmpb $0x41, %ah - je 8f //install_check - cmpb $0x42, %ah - je 9f //ext_read - cmpb $0x43, %ah - je 10f //ext_write - cmpb $0x44, %ah /* verify sectors */ - je 5f //success_out - cmpb $0x47, %ah /* extended seek */ - je 5f //success_out - cmpb $0x48, %ah - je 11f //get_drv_param - cmpb $0x4B, %ah - jne 3f //invalid_cmd - - //stop_disk_emu: - cmpb $1, %al /* only 0x4B01 supported */ - jne 3f //invalid_cmd - - movw %si, %di - movw %cs:(int13_old_ds - int13_handler), %es - movw $0x0013, %ax /* packet size=13h, boot type=0 (no-emu) */ - cld - stosw - //movb %dl, %al /* drive=DL, controller=0 */ - movb %cs:(int13_old_edx - int13_handler), %al /* drive=DL, controller=0 */ - stosw - xorw %ax, %ax - stosw - stosw /* LBA for no-emu image=0 */ - stosw /* device specification */ - stosw /* user buffer segment */ - stosw /* load segment */ - movb $4, %al - stosw /* sector count=4 */ - /* CHS makes no sense for no-emu */ - jmp 5f //success_out - -11: //get_drv_param: - movw %cs:(int13_old_ds - int13_handler), %ds - cmpw $26, (%si) - jb 3f //invalid_cmd - - movw $26, (%si) -// movw $0x74, 2(%si) #; struc_extparam.flags: removable, lock, chg line - movw $0x00, 2(%si) # none, tinybit 2007-11-15 - movw $0x800, 24(%si) # bytes per sect=2048 - xorl %eax, %eax - decw %ax - movl %eax, 4(%si) # cylinders=0xFFFF - movb $0, %ah - movl %eax, 8(%si) # heads=0xFF - movb $15, %al - movl %eax, 12(%si) # sectors per track=15 - movl %eax, 20(%si) # total sectors hi dword=0 - xorw %ax, %ax # CF cleared - decl %eax # EAX=0xFFFFFFFF - movl %eax, 16(%si) # total sectors lo dword - # CF is cleared - jmp 5f //success_out - -10: //ext_write: - movb $0x03, %ah # error code of write-protection - jmp 2f //fail_out - -9: //ext_read: - call edd30_read_cdrom - jnc 5f //success_out - jmp 2f //fail_out - -8: //install_check: - cmpw $0x55AA, %bx # added by tinybit 2007-11-15 - jne 3f //invalid_cmd - - movw $0xAA55, %cs:(int13_old_ebx - int13_handler) #; bx=0xaa55 - movb $0x21, %ah # ah=0x21 edd-1.1 - movb $0x01, %cs:(int13_old_ecx - int13_handler) # cx=0x01, ext disk access ok -- tinybit 2007-11-15 - jmp 4f //success_out_no_ah - -7: //get_last_stat: - movb %cs:(int13_last_stat - int13_handler), %ah - jmp 4f //success_out_no_ah - -6: //reset: - call reg_reset - movw %cs:(atapi_cur_dev - int13_handler), %ax # device serial number - call select_atapi_force - -5: //success_out: - xorb %ah, %ah - -4: //success_out_no_ah: - andb $0xFE, %cs:(int13_old_flags - int13_handler) - jmp 1f - -3: //invalid_cmd: - movb $0x01, %ah - -2: //fail_out: - orb $1, %cs:(int13_old_flags - int13_handler) // set CF=1 for ERROR - -1: - /* set error code AH */ - movb %ah, %cs:(int13_last_stat - int13_handler) - movb %ah, %cs:(int13_old_eax + 1 - int13_handler) - - movl %cs:(int13_old_eax - int13_handler), %eax - movl %cs:(int13_old_ebx - int13_handler), %ebx - movl %cs:(int13_old_ecx - int13_handler), %ecx - movl %cs:(int13_old_edx - int13_handler), %edx - movl %cs:(int13_old_esi - int13_handler), %esi - movl %cs:(int13_old_edi - int13_handler), %edi - movl %cs:(int13_old_ebp - int13_handler), %ebp - movw %cs:(int13_old_ds - int13_handler), %ds - movw %cs:(int13_old_es - int13_handler), %es - - /* restore old flags */ - pushw %cs:(int13_old_flags - int13_handler) - popfw - /* transfer control to caller */ - ljmp *%cs:(int13_old_cs_ip - int13_handler) - -#;============================================================================ - -int13_last_stat: .byte 0 #; the error code in AH - -start_of_atapi_data: - -atapi_cur_dev: .word 0 #; device serial number -reg_cur_dev: .byte 0 #; 0xA0 for master, 0xB0 for slave -time_out: .long 0 -reg_dev_info: .byte 0, 0 - - -atapi_dev_base: .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - -atapi_dev_base_bak: .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - .word 0, 0 #; base pointer, device - -reg_addr: .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -atapi_cmd_buffer: .space 16 -atapi_tmp_buffer: .space 256 -//atapi_devinfo: .space 32 # SIZE_OF_ATAPI_DEVINFO -delay_repeat_num: .long 0 # loops per millisecond - -end_of_atapi_data: - -ENTRY(slow_atapi_device) - .long 0 - - .align 16 - - #;******************************************************************* - #; ATA Registers Layout - #;******************************************************************* - #; - #; Address Read Write - #; --------- --------------------- ----------------------------- - #; A N 0 0 0 16-bit data port for both read and write - #; ------------------------------------------------------------------ - #; A N 0 0 1 ATAPI/ATA Error(Read) ATAPI/ATA Feature(Write) - #; ------------------------------------------------------------------ - #; A N 0 1 0 ATAPI Interrupt Reason(Read) / ATA Sector Count - #; ------------------------------------------------------------------ - #; A N 0 1 1 Reserved for SAM TAG Byte / ATA Sector Number - #; ------------------------------------------------------------------ - #; A N 1 0 0 ATAPI Byte Count LSB(R/W) / ATA Cylinder Low(R/W) - #; ------------------------------------------------------------------ - #; A N 1 0 1 ATAPI Byte Count MSB(R/W) / ATA Cylinder High(R/W) - #; ------------------------------------------------------------------ - #; A N 1 1 0 ATAPI Drive Select(R/W) / ATA Drive/Head Select(R/W) - #; ------------------------------------------------------------------ - #; A N 1 1 1 ATAPI/ATA Status(Read) ATA Command(Write) - #; ------------------------------------------------------------------ - #; N A 1 1 0 Alternate Status(Read) Device Control(Write) - #; ------------------------------------------------------------------ - -reg_base_addr: - .word 0x01f0, 0x03f6 - .word 0x0170, 0x0376 - .word 0x00f0, 0x02f6 - #;.word 0x0070, 0x0276 //port 70 and 71 is for CMOS - .word 0x0180, 0x0386 - .word 0x6b00, 0x6f00 - .word 0x7300, 0x7700 -ENTRY(reg_base_addr_append) - .word 0, 0 - .word 0, 0 // ending null - -#endif //CDROM_INIT -#;============================================================================ - -/* void realmode_printf(const char *format, ...) - * - * input: format is offset in CS segment - * - * Usage example: - * - * pushw IntegerN - * ... ... ... ... - * pushw Integer2 - * pushw Integer1 - * pushw $format_string - int13_handler - * call realmode_printf - * addw $(2*(N+1)), %sp - * - * where int13_handle should be the base of the CS segment, - * and format_string like this: - * - * format_string: - * .string "Int1=%x, Int2=%x, ..., IntN=%x\r\n" - * - * Currently only %d, %x and %X are implemented. - */ - -realmode_printf: - pushaw - movw %sp, %bp - # bp+18: format - # bp+20: variables - addw $18, %bp - movw (%bp), %si # points to format string - addw $2, %bp # (%bp) is the first variable -1: - cs lodsb - testb %al, %al - jz 1f - cmpb $'%', %al - jne 2f - - #; %d, %u, %x, %X, %4x, %4X - xorw %cx, %cx -7: - cs lodsb - testb %al, %al - jz 1f - movw $10, %bx # base 10 - cmpb $'d', %al - jz 4f - cmpb $'u', %al - jz 4f - cmpb $'x', %al - jz 3f - cmpb $'X', %al - jz 3f - cmpb $'4', %al - jne 1b # unkown directive, continue - movw $4, %cx - jmp 7b -3: - /* print hexa number */ - movw $16, %bx # base 16 -4: - /* print decimal or hexa number */ - pushl %edi - - movl $1, %edi - movw (%bp), %ax -5: - xorw %dx, %dx - divw %bx # AX=quo, DX=rem - shll $4, %edi - orw %dx, %di - jcxz 7f - loop 5b -7: - testw %ax, %ax # end? - jnz 5b - - /* print the digits in EDI */ - xorw %bx, %bx /* video page 0 */ -5: - movw %di, %ax # get digit in AL - shrl $4, %edi - jz 7f - andb $0x0f, %al - cmpb $9, %al - jbe 6f - addb $7, %al # A, B, C, D, E, F -6: - addb $0x30, %al - movb $0x0e, %ah /* print it */ - int $0x10 /* via TTY mode */ - jmp 5b -7: - popl %edi - - addw $2, %bp # (%bp) is the next variable - jmp 1b # continue -2: - /* print char in AL */ - xorw %bx, %bx /* video page 0 */ - movb $0x0e, %ah /* print it */ - int $0x10 /* via TTY mode */ - jmp 1b # continue -1: - popaw - ret - - -#;============================================================================ - - -/* Don't insert code or data here! Buggy BIOSes could overwrite this area! */ - -// .align 16 - -// .space 0x1000 /* 4KB stack */ - -int13_handler_end: - - /* Total size of int13_handler should better not exceed 12KB. */ - -// . = . - (int13_handler_end - int13_handler)/0x3001 - - // this is used to check the current size of the handler code - //. = . - (int13_handler_end - int13_handler)/0x2F01 - -#;============================================================================ -ENTRY(defer) - - .code32 - - pushl %ebp - movl %esp, %ebp - pushl %ebx - pushl %ecx - pushl %edx - - movl 8(%ebp), %ebx - movw EXT_C(count_ms), %dx - - call EXT_C(prot_to_real) - .code16 - - movw %bx, %ax -2: - movw %dx, %cx -3: - cmpw %cs:0x046C, %ax - jmp 1f -1: - pushw %dx - pushw %ax - movw $0xcf8, %dx - inw %dx, %ax - popw %ax - popw %dx - decw %cx - cmpw $0, %cx - jne 3b - decw %ax - jne 2b - - call EXT_C(real_to_prot) - .code32 - - popl %edx - popl %ecx - popl %ebx - popl %ebp - ret - -/* unsigned long - * init_usb() : return number of usb devices. - */ - -ENTRY(init_usb) - - .code32 - - pushl %ebp - pushl %ebx - - call EXT_C(prot_to_real) /* enter real mode */ - - .code16 - - sti /* enable interrupt for USB */ - - cld - - /* set CS base to be USB2DRI */ - .byte 0xEA - .word ABS(1f) - .word 0 -1: - pushaw - pushw %es - pushw %ds - - pushw %cs - popw %ds - pushw %cs - popw %es - - //Load the usb driver - movw $ABS(USB2DRI), %ax - shrw $4, %ax - movw %ax, ABS(2f+2) - lcall *ABS(2f) - - popw %ds - popw %es - popaw - - ljmp $0, $ABS(1f) -2: - .word 0 - .word 0 -1: - - call EXT_C(real_to_prot) - .code32 - - sti - popl %ebx - popl %ebp - ret - -/* ******************** USB2DRI start ****************************** */ - .align 32 -#define cd 1 -ENTRY(USB2DRI) -USB2DRI: - .code16 - - jmp Initialization - - .ascii "USB2DRI " -ENTRY(usb_delay) - .byte 0 -map_num: - .byte 0 -bios_dl: - .byte 0 -fd_num: - .byte 0 -hd_num: - .byte 0 -max_dev: - .byte 0 -ENTRY(max_dri) - .byte 0 -Count_1ms: - .word 0 -ENTRY(One_transfer) - .word 0x4000 -bus_device_function: - .word 0 -Register_pci: - .long 0 -old_int13: - .long 0 - - . = USB2DRI + 0x20 - - - -qh: - .fill 0x90,1,0x00 //QH,qTD - -//qTD1 db 40h dup(0) - -//QH0 db 40h dup(0) -// db 10h dup(0) - -cbw_qq: -dCBWSignature: - .long 0x43425355 -dCBWTag: - .long 0x12345678 -dCBWDataTransferLength: - .long 0 -bmCBWFlags: - .byte 0 -bCBWLUN: - .byte 0 -bCBWCBLength: - .byte 0x0c -CBWCB: - .long 0 - .long 0 - .long 0 - .long 0 - .byte 0 - -csw_qq: - .fill 0x20,1,0x00 - -//---------------------------------------------------------------------------- - -GDT: - - .word 0, 0 - .byte 0, 0, 0, 0 - - -LimitL: - .word 0xffff -BaseL: - .word 0 -BaseM: - .byte 0 -Attributes: - .byte 0x92 -LimitH: - .byte 0 -BaseH: - .byte 0 - -aaaa: -#define GDTLen aaaa - GDT - - -VGDTR: - .word GDTLen - 1 -Base: - .long 0 - - -//---------------------------------------------------------------------------- - .ascii "DEV" - -Dev: -DevID: - .byte 0 -ConProperty: - .byte 0 -ConAddress: - .byte 0 -ConSize: - .word 0 -InProperty: - .byte 0 -InAddress: - .byte 0 -InSize: - .word 0 -OutProperty: - .byte 0 -OutAddress: - .byte 0 -OutSize: - .word 0 -MaxLUN: - .byte 0 -Port_Num_Reg: - .byte 0 -HUB_id: - .byte 0 - -bbbb: -#define DevLen (bbbb - Dev) - - .fill (DevLen*7),1,0x00 - -//---------------------------------------------------------------------------- - .ascii "DRI" - -Dri: -Number: - .byte 0 -DriID: - .byte 0 -DriLUN: - .byte 0 -#if cd -DriType: - .byte 0 -#endif -SectorSize: - .word 0 -Capacity: - .long 0 -StartSector: - .long 0 - -cccc: -#define DriveLen (cccc - Dri) - - .fill (DriveLen*3),1,0x00 - -//---------------------------------------------------------------------------- - .align 8 - -Get_device: - .byte 0x80,06,00,01,00,00,0x12,00 -Get_Configuration: - .byte 0x80,06,00,02,00,00,0x20,00 -Get_lun: - .byte 0xa1,0xfe,00,00,00,00,01,00 -Set_Configuration: - .byte 00,0x09,01,00,00,00,00,00 -Set_device_Address: - .byte 00,05,00,00,00,00,00,00 -Clear_endpoint: - .byte 02,01,00,00,00,00,00,00 -Bulk_Reset: - .byte 0x21,0xff,00,00,00,00,00,00 -Get_Hub: - .byte 0xa0,06,00,0x29,00,00,0x10,00 -Set_HubPort_Power: - .byte 0x23,03,0x08,00,00,00,00,00 -Get_HubPort_Status: - .byte 0xa3,00,00,00,00,00,04,00 -Clear_HubPort_Conne: - .byte 0x23,01,0x10,00,00,00,00,00 -Set_HubPort_Reset: - .byte 0x23,03,04,00,00,00,00,00 -Clear_HubPort_Reset: - .byte 0x23,01,0x14,00,00,00,00,00 - -_id: - .byte 1 -_lun: - .byte 0 -#if cd -_type: - .byte 0 -Media_types: - .byte 0 -cd_num: - .byte 0xf8 -#endif -AsyncListAddr: - .long 0 -qTD1: - .word 0 -qTD1_Linear: - .long 0 -ds_Linear: - .long 0 -Sector_Size: - .word 0 -Disk_sector: - .long 0 -Start_sector: - .long 0 -Status: - .byte 0 -Read_write_repeat_Number: - .byte 0 -Stack_sp: - .word 0 -Stack_ss: - .word 0 -Ability_Register_Size: - .word 0 -_eax: - .long 0 -_bx: - .word 0 -_cl: - .byte 0 -_es: - .word 0 -Direction1: - .byte 0 -R_W_Mark: - .byte 0 -Save_ah: - .byte 0 -Return: - .byte 0 -TSize: - .long 0 -TOffset: - .word 0 -TSection: - .word 0 -Single_size: - .word 0 - -Entry_int13: - call Find_drive_info - jnb 1f - testb $1, %cs:(map_num - USB2DRI) - je 2f - cmpb $0x80, %dl - jb 2f - incb %dl -2: - ljmp *%cs:(old_int13 - USB2DRI) -1: - cld - pushal // eax ecx edx ebx esp ebp esi edi cf - movw %sp, %bp //bp+ 1c 18 14 10 0c 08 04 00 24 - pushw %ds - pushw %es - pushw %fs - pushw $0 - popw %fs - //ss=ds=0 es=2000 cs=9e00 fs=0000 - cmpb $00, %ah - je int13_00_04_16_17_18_44_47 - cmpb $01, %ah - je int13_01 - cmpb $02, %ah - je int13_02_03 - cmpb $03, %ah - je int13_02_03 - cmpb $0x08, %ah - je int13_08 - cmpb $0x15, %ah - je int13_15 - cmpb $0x16, %ah - je int13_00_04_16_17_18_44_47 - cmpb $0x41, %ah - je int13_41 - cmpb $0x42, %ah - je int13_42_43 - cmpb $0x43, %ah - je int13_42_43 - cmpb $0x48, %ah - je int13_48 -#if cd - cmpw $0x4b01, %ax - je int13_4b01 -#endif -qtml: - movb $01, %ah - jmp 4f -int13_00_04_16_17_18_44_47: - xorb %ah, %ah -4: - testb $0x80, %dl - jne 1f - movb %ah, %fs:0x0441 - jmp 2f -1: - movb %ah, %fs:0x0474 -2: - andb $0xfe, 0x24(%bp) //cf=0 - movb %ah, 0x1d(%bp) //ah - orb %ah, %ah - je 3f - orb $01, 0x24(%bp) //cf=1 -3: - popw %fs - popw %es - popw %ds - popal - iret - - -int13_01: - testb $0x80, %dl - jne 1f - xchgb %fs:0x0441, %ah - jmp 2b -1: - xchgb %fs:0x0474, %ah - jmp 2b - - -int13_02_03: - movb %ah, %cs:(Save_ah - USB2DRI) - call chs_lba - cmpl %cs:(Disk_sector - USB2DRI), %eax - ja 2f - movb $01, %cl - cmpb $02, %cs:(Save_ah - USB2DRI) - je 1f - xorb %cl, %cl -1: - call Read_write_usb - jnb int13_00_04_16_17_18_44_47 -2: - jmp qtml - -int13_08: - pushw %dx - movw $0x3ec1, %cx - movw %cs:(Disk_sector - USB2DRI), %ax - movw %cs:(Disk_sector + 2 - USB2DRI), %dx - cmpw %cx, %dx - jae 1f - divw %cx - decw %ax - cmpw $0x03FF, %ax - jb 2f -1: - movw $0x03FF, %ax -2: - movw %ax, %cx - xchgb %ch, %cl - shlb $06, %cl - orb $0x3f, %cl - movb $0xfe, %dh - movb %fs:0x0475, %dl - movw %dx, 0x14(%bp) - movw %cx, 0x18(%bp) - movb $0x10, 0x10(%bp) - popw %dx - jmp int13_00_04_16_17_18_44_47 - -int13_15: - movb %al, %fs:0x0441 - movb $02, %ah - testb $0x80, %dl - je 1f - movb $03, %ah -1: - andb $0xfe,0x24(%bp) //cf=0 - movb %ah, 0x1d(%bp) //ah - jmp 3b - - -Find_drive_info: - pushal - pushw %ds - pushw %cs - popw %ds - movb (EXT_C(max_dri) - USB2DRI), %cl - movw $(Dri - USB2DRI), %si -1: - cmpb (Number - Dri)(%si), %dl - je 1f - decb %cl - orb %cl, %cl - je 2f - addw $DriveLen, %si - jmp 1b -1: - movb (DriID - Dri)(%si), %al - movb %al, (_id - USB2DRI) - movb (DriLUN - Dri)(%si), %al - movb %al, (_lun - USB2DRI) -#if cd - movb (DriType - Dri)(%si), %al - movb %al, (_type - USB2DRI) -#endif - movw (SectorSize - Dri)(%si), %ax - movw %ax, (Sector_Size - USB2DRI) - movl (Capacity - Dri)(%si), %eax - movl %eax, (Disk_sector - USB2DRI) - movl (StartSector - Dri)(%si), %eax - movl %eax, (Start_sector - USB2DRI) - clc -1: - popw %ds - popal - ret -2: - stc - jmp 1b - - -chs_lba: - movw %bx, %di - movzbw %al, %bx - - movb %cl, %al - andb $0x3f, %al - movzbl %al, %eax - pushl %eax - - xchgb %ch, %cl - andb $0xc0, %ch - rolb $02, %ch - - movl $0xff, %eax - movzwl %cx, %ecx - imull %ecx, %eax - movzbl %dh, %ecx - addl %ecx, %eax - movl $0x3f, %ecx - imull %ecx, %eax - popl %ecx - addl %ecx, %eax - decl %eax - - ret - - - - -int13_41: - cmpw $0x55aa, %bx - jne qtml - movw $0x2100, %ax //EDD-2.1 - notw %bx //bx=AA55 - movw $5, %cx - movw %bx, 0x10(%bp) - movw %cx, 0x18(%bp) - movw %ax, 0x1c(%bp) - andb $0xfe, 0x24(%bp) //cf=0 - jmp 3b - - -int13_42_43: - testl $0xffffffff, 12(%si) - jne qtml - movb %ah, %cs:(Save_ah - USB2DRI) - call Disk_package - movb $01, %cl - cmpb $0x42, %cs:(Save_ah - USB2DRI) - je 1f - xorb %cl, %cl -1: - call Read_write_usb - jnb int13_00_04_16_17_18_44_47 -2: - jmp qtml - - -Disk_package: - movw 02(%si), %bx - movw 04(%si), %di - movw 06(%si), %es - movl 0x08(%si), %eax - ret - -int13_48: - pushw %ds - popw %es - pushw %dx - movw %si, %di - xorb %al, %al - movw $0x1a, %cx - rep stosb - movb $0x1a, (%si) - movb $06, 02(%si) - movb $0x3f, 0x0c(%si) - movb $0xff, 0x08(%si) - movl $0x3ec1, %ecx - movl %cs:(Disk_sector - USB2DRI), %eax - movl %eax, 0x10(%si) - xorl %edx, %edx - divl %ecx - movl %eax, 04(%si) - movw %cs:(Sector_Size - USB2DRI), %ax - movw %ax, 0x18(%si) - popw %dx - jmp int13_00_04_16_17_18_44_47 -#if cd -int13_4b01: - movb $0x13, (%si) - movb %cs:(Media_types - USB2DRI), %al - movb %al, 1(%si) - movb %cs:(cd_num - USB2DRI), %al - movb %al, 2(%si) - movb $1, 3(%si) - movl %cs:(Start_sector - USB2DRI), %eax - movl %eax, 4(%si) - movw %cs:(bus_device_function - USB2DRI), %ax - movb %cs:(_lun - USB2DRI) ,%al - movw %ax, 8(%si) - movw $0, 0x0a(%si) - movw %cs:(Disk_sector - USB2DRI), %ax - movw %ax, 0x0c(%si) - movw %cs:(Disk_sector + 2 - USB2DRI), %ax - movw %ax, 0x0e(%si) - movw $0, 0x10(%si) - movb $0, 0x12(%si) - jmp int13_00_04_16_17_18_44_47 -#endif -//------------------------------------------------------------------------------------------ - - -Allow_A20: - call observe - orw %ax, %ax - jne 1f - mov $0x2401, %ax - int $0x15 - call observe - orw %ax, %ax - jne 1f - pushfl - cli - -2: - inb $0x64, %al - testb $02, %al - jne 2b - mov $0xd1, %al - outb %al, $0x64 -2: - inb $0x64, %al - testb $02, %al - jne 2b - movb $0xdf, %al - outb %al, $0x60 -2: - inb $0x64, %al - testb $02, %al - jne 2b - movb $0xff, %al - outb %al, $0x64 -2: - inb $0x64, %al - testb $02, %al - jne 2b - popfl -1: - ret - - - -observe: - pushw %bx - pushw %dx - pushw %gs - pushw $0xffff - popw %gs - pushfl - cli - movw %fs:0x0000, %ax - movw %gs:0x0010, %bx - notw %ax - movw %ax, %gs:0x0010 - movw %fs:0x0000, %dx - movw %bx, %gs:0x0010 - popfl - xorw %dx, %ax - popw %gs - popw %dx - popw %bx - ret - - - -Delay: - pushl %ecx - pushw %dx - movw (Count_1ms - USB2DRI), %dx -2: - movw %dx, %cx - -3: - cmpw %cs:0x046C, %ax - jmp 1f -1: - pushw %dx - pushw %ax - movw $0xcf8, %dx - inw %dx, %ax - popw %ax - popw %dx - decw %cx - cmpw $0, %cx - jne 3b - - decw %ax - jne 2b - popw %dx - popl %ecx - ret - - -Remove_qTD: - pushaw - xorw %ax, %ax - movw $0x20, %cx - rep stosw - popaw - ret - - -Control_transfer_hub: - movb %cl, 4(%si) -Control_transfer: - pushaw - - call Determine_device_address - - movw (qTD1 - USB2DRI), %di - movw $0x8e80, %ax - movw $8, %cx - movzwl %si, %edx - addl (ds_Linear - USB2DRI), %edx - call Con_mon - call Set_QH - - movw 6(%si), %cx - orw %cx, %cx - je 1f - movb $0, %ah - testb $0x80, (%si) - je 2f - movb $01, %ah -2: - movb $0x80, %al - orb $0x8c, %ah - orw $0x8000, %cx - movl $(Cache - USB2DRI), %edx - addl (ds_Linear - USB2DRI), %edx - call Con_mon - call Set_QH - cmpb $0, (Status - USB2DRI) - jne 2f -1: - movb $0x81, %ah - testb $0x80, (%si) - je 1f - movb $0x80, %ah -1: - movb $0x80, %al - orb $0x0c, %ah - movw $0x8000, %cx - xorl %edx, %edx - call Con_mon - call Set_QH -2: - popaw - ret - -Con_mon: - call Remove_qTD - movw %ax, 8(%di) - movw %cx, 0xa(%di) - movl %edx, 0xc(%di) - movl $0x1000, %eax - andl $0xfffff000, %edx - addl %eax, %edx - movl %edx, 0x10(%di) - movb $1,(%di) - movb $1,4(%di) - movw $0, %cx - ret - -Port_Reset: - movl $0x00001100, %eax - call Write_Register - movw $100, %ax - call Delay - - movl $0x00001000, %eax - call Write_Register - movw $200, %ax - call Delay - - movl $0x00001007, %eax - call Write_Register - - call Read_Register - ret - - -Determine_device_address: - movb (_id - USB2DRI), %bl - decb %bl - movb $DevLen, %al - mulb %bl - movw %ax, %bx - ret - - - -Set_QH: - pushw %si - pushw %di - addw $0x40, %di - movb $2, %dl - - leaw (ConAddress - USB2DRI)(%bx), %si - addw %cx, %si - movb (%si), %ch - andb $0x0f, %ch - shlb $04, %dl - orb %dl, %ch - movw 01(%si), %ax - orb %cl, %cl - jne 1f - orw $0x0800, %ax - orb $0x40, %ch -1: - orb $0x80, %ch - movb (DevID - USB2DRI)(%bx), %cl - andb $0x7f, %cl - movb %cl, 04(%di) - movb %ch, 05(%di) - movw %ax, 06(%di) - - movb $0x40, 0xb(%di) - - movl (qTD1_Linear - USB2DRI), %eax - movl %eax, 0x0c(%di) - movw (qTD1 - USB2DRI), %si - pushw %di - addw $0x10, %di - movw $0x20, %cx - rep movsw - popw %di - movb $00, (Status - USB2DRI) - - movl $0x80021, %eax - movw $0, %si - call Write_Register - movl $0x00100000, %ecx -1: - movw $04, %si - call Read_Register - testb $03, %al - jne 2f - loopl 1b - orb $2, (Status - USB2DRI) - jmp 1f -2: - movw $04, %si - call Write_Register - test $01, %al - jne 2f - orb $4, (Status - USB2DRI) - jmp 1f -2: - movl $0x00100000, %ecx -2: - testb $0x80, 0x18(%di) - je 2f - loopl 2b - orb $8, (Status - USB2DRI) -2: - testb $8, 7(%di) - je 1f - movw $20, %ax - call Delay -1: - pushw %ax - movl $0x80001, %eax - movw $0, %si - call Write_Register - popw %ax - cmpb $0, (Status - USB2DRI) - jne 6f - - movb 0x18(%di), %al - movb 0x19(%di), %ah - andb $0x0c, %ah - orb %ah, %ah - je 5f - testb $0x40, %al - jne 5f - testb $0x20, %al - jne 5f -3: - movzbl (usb_delay - USB2DRI), %ecx - orb %cl, %cl - je 1f - shll $14, %ecx -2: - loopl 2b -1: - popw %di - popw %si - ret -5: - orb $01, (Status - USB2DRI) -6: - jmp 3b - - -Bulk_transfer: - pushw %bx - movw (qTD1 - USB2DRI), %di - call Remove_qTD - - decb %al - je 1f - decb %al - je 2f - - movw $0x0d, %cx - movl $(csw_qq - USB2DRI), %eax - movb $01, (Direction1 - USB2DRI) - jmp 3f -1: - movw $0x1f, %cx - movl $(cbw_qq - USB2DRI), %eax - movb $0, (Direction1 - USB2DRI) -3: - movw %cs, %dx - movzwl %dx, %edx - shll $4, %edx - addl %eax, %edx - jmp 3f -2: - movb (bmCBWFlags - USB2DRI), %al - shrb $7, %al - movb %al, (Direction1 - USB2DRI) - movl (TOffset - USB2DRI), %edx - movw (Single_size - USB2DRI), %cx -3: - movb $01, (%di) - movb $01, 04(%di) - movb $0x80, 0x08(%di) - cmpw $0, %cx - je 1f - movl $0x1000, %eax - movl %edx, 0x0c(%di) - andl $0x0fffff000, %edx - addl %eax, %edx - movl %edx, 0x10(%di) - addl %eax, %edx - movl %edx, 0x14(%di) - addl %eax, %edx - movl %edx, 0x18(%di) - addl %eax, %edx - movl %edx, 0x1c(%di) -1: - leaw (InProperty - USB2DRI)(%bx), %si - movb (Direction1 - USB2DRI), %al - testb $01, %al - jne 1f - addw $4, %si -1: - testb $0x80, (%si) - je 1f - orw $0x8000, %cx -1: - orb $0x80, %al - orb $0x0c, %al - movb %al, 0x09(%di) - movw %cx, 0x0a(%di) - movw $4, %cx - testb $01, %al - jne 1f - - movb $0x81, 0x08(%di) - movw $8, %cx -1: - call Set_QH - cmpb $0, (Status - USB2DRI) - jne 1f - - addw $0x40, %di - andb $0x7f, (%si) - testb $0x80, 0x1b(%di) - je 1f - orb $0x80, (%si) -1: - popw %bx - ret - - -Reset_Recovery: - movw $(Bulk_Reset - USB2DRI), %si - call Control_transfer - - movw $(Clear_endpoint - USB2DRI), %si - movb (InAddress - USB2DRI)(%bx), %cl - call Control_transfer_hub - - mov $(Clear_endpoint - USB2DRI), %si - mov (OutAddress - USB2DRI)(%bx), %cl - call Control_transfer_hub - - andb $0x7f, (InProperty - USB2DRI)(%bx) - andb $0x7f, (OutProperty - USB2DRI)(%bx) - ret - - -SCSI_Command: - pushaw - - call Determine_device_address - movzwl (TOffset - USB2DRI), %eax - movzwl (TSection - USB2DRI), %edx - shll $04, %edx - addl %eax, %edx - movl %edx, (TOffset - USB2DRI) - movl (dCBWDataTransferLength - USB2DRI), %eax - movl %eax, (TSize - USB2DRI) - movw (One_transfer - USB2DRI), %ax - movw %ax, (Single_size - USB2DRI) - movb (_lun - USB2DRI), %al - movb %al, (bCBWLUN - USB2DRI) - - movb $01, %al - call Bulk_transfer - cmpb $0, (Status - USB2DRI) - jne 4f -1: - movl (TSize - USB2DRI), %eax - orl %eax, %eax - je 2f - movzwl (Single_size - USB2DRI), %ecx - cmpl %eax, %ecx - jbe 3f - movw %ax, (Single_size - USB2DRI) -3: - movb $02, %al - call Bulk_transfer - cmpb $0, (Status - USB2DRI) - jne 2f - - movzwl (Single_size - USB2DRI), %eax - addl %eax, (TOffset - USB2DRI) - subl %eax, (TSize - USB2DRI) - jmp 1b -2: - movb $03, %al - call Bulk_transfer - cmpb $0, (Status - USB2DRI) - je 3f - movw $(Clear_endpoint - USB2DRI), %si - movb (InAddress - USB2DRI)(%bx), %cl - call Control_transfer_hub - andb $0x7f, (InProperty - USB2DRI)(%bx) - movb $3, %al - call Bulk_transfer - cmpb $0, (Status - USB2DRI) - jne 4f -3: - movw $(csw_qq - USB2DRI), %si - cmpl $0x53425355, (%si) - jne 4f - cmpl $0x12345678, 04(%si) - jne 4f - cmpb $0, 0x0c(%si) - je 1f - cmpb $1, 0x0c(%si) - je 3f -4: - call Reset_Recovery -3: - movb $1, (Return - USB2DRI) - jmp 2f -1: - movb $0, (Return - USB2DRI) -2: - popaw - ret - - -Read_write_usb: - cli - movw %ss, %cs:(Stack_sp - USB2DRI) - movw %sp, %cs:(Stack_ss - USB2DRI) - pushw %cs - popw %ss - movw $(Stack - USB2DRI), %sp - sti - - pushal - pushw %ds - pushw %es - - pushw %cs - popw %ds - pushw %cs - popw %es - - call Remove_CBWCB - - popw %es - pushw %es - - movb $3, (Read_write_repeat_Number - USB2DRI) - movl %eax, (_eax - USB2DRI) - movw %bx, (_bx - USB2DRI) - movw %es, (_es - USB2DRI) - movb %cl, (_cl - USB2DRI) -5: - movb $0x80, (bmCBWFlags - USB2DRI) - movb $0x28, (CBWCB - USB2DRI) - orb %cl, %cl - jne 1f - movb $0, (bmCBWFlags - USB2DRI) - movb $0x2a, (CBWCB - USB2DRI) -1: - movb %al, (CBWCB - USB2DRI + 5) - movb %ah, (CBWCB - USB2DRI + 4) - shrl $0x10, %eax - movb %al, (CBWCB - USB2DRI + 3) - movb %ah, (CBWCB - USB2DRI + 2) - movb %bl, (CBWCB - USB2DRI + 8) - movb %bh, (CBWCB - USB2DRI + 7) - movw (Sector_Size - USB2DRI), %ax - mulw %bx - movw %dx, (dCBWDataTransferLength - USB2DRI + 2) - movw %ax, (dCBWDataTransferLength - USB2DRI) - movw %di, (TOffset - USB2DRI) - movw %es, (TSection - USB2DRI) - pushw %cs - popw %es - call Allow_A20 - movw $0x18, %si - call Read_Register - cmpl (AsyncListAddr - USB2DRI), %eax - je 1f - call init_QH_AsyncListAddr -1: - call SCSI_Command - cmpb $0, (Return - USB2DRI) - je 6f - movl (_eax - USB2DRI), %eax - movw (_bx - USB2DRI), %bx - movw (_es - USB2DRI), %es - movb (_cl - USB2DRI), %cl - - decb (Read_write_repeat_Number - USB2DRI) - cmpb $0, (Read_write_repeat_Number - USB2DRI) - jne 5b - - stc -3: - popw %es - popw %ds - popal - cli - movw %cs:(Stack_sp - USB2DRI), %ss - movw %cs:(Stack_ss - USB2DRI), %sp - sti - ret - -6: - clc - jmp 3b - - -Read_Base_address: - pushl %esi - movb $01, (R_W_Mark - USB2DRI) - jmp 1f - -Read_Register: - pushl %esi - movb $01, (R_W_Mark - USB2DRI) -2: - addw (Ability_Register_Size - USB2DRI), %si -1: - movzwl %si, %esi - call Protected_Mode - popl %esi - ret - - -Write_Register: - pushl %esi - movb $0, (R_W_Mark - USB2DRI) - jmp 2b - - -Protected_Mode: - pushw %es - pushfl - cli - pushw %ds - pushw %es - pushl %ecx - pushw %cs - lgdt %cs:(VGDTR - USB2DRI) - movl %cr0, %ecx - pushl %ecx - orb $01, %cl - movl %ecx, %cr0 - jmp 1f -1: - movw $0x08, %cx - movw %cx, %es - testb $01, (R_W_Mark - USB2DRI) - jne 1f - movl %eax, %es:(%si) - jmp 2f -1: - movl %es:(%si), %eax -2: - popl %ecx - andb $0xFE, %cl - movl %ecx, %cr0 - jmp 1f -1: - pushw $(1f - USB2DRI) - retf -1: - popl %ecx - popw %es - popw %ds - popfl - popw %es - ret - -Remove_CBWCB: - pushaw - movw $(dCBWDataTransferLength - USB2DRI), %di - xorw %ax, %ax - movw $12, %cx - repz stosw - movb $0xc, (bCBWCBLength - USB2DRI) - popaw - ret - -Port_Reset_hub: - movw $(Clear_HubPort_Conne - USB2DRI), %si - call Control_transfer_hub - mov $(Set_HubPort_Reset - USB2DRI), %si - call Control_transfer_hub - movw $200, %ax - call Delay - movw $(Clear_HubPort_Reset - USB2DRI), %si - call Control_transfer_hub - ret - -szsbdz: - movw $(Set_device_Address - USB2DRI), %si - movb (_id - USB2DRI), %al - movb %al, 2(%si) - call Control_transfer - movb %al, (DevID - USB2DRI)(%bx) - ret - -szpz: - movw $(Set_Configuration - USB2DRI), %si - call Control_transfer - movw $30, %ax - call Delay - ret - -init_QH_AsyncListAddr: - movl (qTD1_Linear - USB2DRI), %eax - addl $0x40, %eax - pushw %ax - orb $02, %al - movw (qTD1 - USB2DRI), %si - movl %eax, 0x40(%si) - popw %ax - movl %eax, (AsyncListAddr - USB2DRI) - movw $0x18, %si - call Write_Register - ret - - -Determine_delay_units: - xorw %ax, %ax - movw %ax, %fs - sti - movw %fs:0x046c, %dx - xorl %ecx, %ecx -1: - movw %fs:0x046c, %ax - cmpw %dx, %ax - je 1b -1: - cmpw %fs:0x046c, %ax - jne 2f - pushw %dx - pushw %ax - movw $0xcf8, %dx - inw %dx, %ax - popw %ax - popw %dx - incl %ecx - cmpl $0, %ecx - jmp 1b -2: - xorl %edx, %edx - movl %ecx, %eax - movl $0x37, %ecx - divl %ecx - movw %ax, (Count_1ms - USB2DRI) - ret - - -xh_hd: - call read_dri - decb %cl - je 1f - addw $0x200, %bx - incb %dl - jmp xh_hd -1: - ret - - -Check_bus: - xorl %edi, %edi - movw $0xB101, %ax - int $0x1A - cmpl $0x20494350, %edx - jne 1f - movw $0, %si - movw $0xB103, %ax - movl $0x000C0320, %ecx - int $0x1A - jb 1f - movw %bx, (bus_device_function - USB2DRI) - clc - ret -1: - stc - ret - - - -Stack: - .ascii " DATA " -Cache: -Ending: -//================================================================================================================= -#define mem_mbr 0 -#define mem_pbr mem_mbr + 0x1000 -#define mem_fd mem_mbr + 0x2000 -#define mem_hd mem_mbr + 0x2400 - -Disk_Info: - pushw %ds - pushw %es - pushw %cs:(Init_cs - USB2DRI) - popw %es - pushw %es - popw %ds - call Get_dri - movb %dl, %dh - orb %dl, %dl - je 1f - andb $0x3e, %fs:0x0410 - jmp bf_hd -1: - movb %fs:0x410, %cl - testb $1, %cl - jne 1f - xorb %cl, %cl - call set_410_1 -1: - shrb $6, %cl - incb %cl - cmpb $2, %cl - jbe 1f - movb $2, %cl -1: - movb %cl, %cs:(fd_num - USB2DRI) - xorb %dl, %dl - movw $mem_fd, %bx - call xh_hd -bf_hd: - movb $8, %cl - cmpb $8, %fs:0x0475 - ja 1f - movb %fs:0x0475, %cl -1: - movb %cl, %cs:(hd_num - USB2DRI) - cmpb $0, %cl - je 1f - movb $0x80, %dl - movw $mem_hd, %bx - call xh_hd - cmpb $0x80, %dh - jne 1f - movw $mem_hd, %di - call Check_PartitionTable - jnc 1f - orb $1, %cs:(map_num - USB2DRI) - call set_410_1 -1: - popw %es - popw %ds - ret - -host_initialization: - call Allow_A20 - - pushw $0x10 - pushw (bus_device_function - USB2DRI) - movb $02, %al - call Read_Write_Configuration - addw $04, %sp - movl %eax, (Register_pci - USB2DRI) - - movw %ds, %ax - movzwl %ax, %eax - shll $04, %eax - movl %eax, (ds_Linear - USB2DRI) - call Fill_descriptor - - call Define_qTD1 - - movw $0, %si - call Read_Base_address - movb %al, (Ability_Register_Size - USB2DRI) - - movw $04, %si - call Read_Base_address - andw $0x0F, %ax - movw %ax, (n_ports - USB2DRI) - - movl $02, %eax - movw $0, %si - call Write_Register -1: - movw $3, %ax - call Delay - - movw $0, %si - call Read_Register - testw $02, %ax - jne 1b - - movw $0x08, %si - call Read_Base_address - xorw %cx, %cx - movb %ah, %cl - jcxz 1f -2: - pushw %cx - pushw (bus_device_function - USB2DRI) - movb $1, %al - call Read_Write_Configuration - addw $4, %sp - cmpb $1, %al - je 2f - orb %ah, %ah - je 1f - addb %ah, %cl - jmp 2b -1: - jmp 3f -2: - movw %cx, %si - leaw 02(%si), %dx - - pushw %dx - pushw (bus_device_function - USB2DRI) - movb $01, %al - call Read_Write_Configuration - addw $04, %sp - - orw $0x100, %ax - pushw %ax - pushw %dx - pushw (bus_device_function - USB2DRI) - movb $03, %al - call Read_Write_Configuration - addw $06, %sp - - movw $0x01F4, %cx -2: - pushw %dx - pushw (bus_device_function - USB2DRI) - movb $01, %al - call Read_Write_Configuration - addw $04, %sp - testw $01, %ax - je 1f - movw $10, %ax - call Delay - loop 2b -1: - - leaw 04(%si), %dx - - pushw $00 - pushw %dx - pushw (bus_device_function - USB2DRI) - movb $03, %al - call Read_Write_Configuration - addw $06, %sp - -3: - call init_QH_AsyncListAddr - - movl $0x00080001, %eax - movw $0, %si - call Write_Register - - movl $3, %eax - movw $8, %si - call Write_Register - - movw (n_ports - USB2DRI), %cx - movw $0x44, %di - jmp 2f -3: - movl $0x00001000, %eax - movw %di, %si - call Write_Register - addw $04, %di - decw %cx -2: - cmpw $0, %cx - ja 3b - movw $100, %ax - call Delay -1: - - movl $0x00000001, %eax - movw $0x40, %si - call Write_Register - movw $500, %ax - call Delay - ret -//================================================================================================================= -n_ports: - .word 0 -Init_cs: - .word 0 -Config_Length: - .byte 0 -Num_Endpoint: - .byte 0 -usb_count: - .byte 0 -Interface_ok: - .byte 0 - - -Initialization: - pushw %ds - pushw %es - pushw %fs - pushal - - movw $0x8000, %cs:(Init_cs - USB2DRI) - - pushw %cs - popw %ds - pushw %cs - popw %es - - call Determine_delay_units - call Check_bus - movb $0x80,%fs:ABS(EXT_C(usb_count_error)) - jb 3f - call Disk_Info - call host_initialization - call Device_enumerate - movb $0x81,%fs:ABS(EXT_C(usb_count_error)) - cmpb $0, (usb_count - USB2DRI) - je 3f - call Drive_enumerate - movb $0x82, %fs:ABS(EXT_C(usb_count_error)) //usb_error - - movb (EXT_C(max_dri) - USB2DRI), %al - orb %al, %al - je 3f - movb %al, %fs:ABS(EXT_C(usb_count_error)) //usb_count - movw $(Number - USB2DRI), %si - movw $ABS(EXT_C(usb_drive_num)), %bx -1: - movb (%si), %ah - movb %ah, %fs:(%bx) - decb %al - je 1f - addw $DriveLen, %si - incw %bx - jmp 1b -1: - - movw %fs:0x0413, %ax - subw $3, %ax - movw %ax, %fs:0x0413 - shlw $6, %ax - pushw %ax - movzwl %ax, %eax - shll $4, %eax - movl %eax, (ds_Linear - USB2DRI) - call Define_qTD1 - call Fill_descriptor - popw %ax - - movw $(Ending - USB2DRI), %cx - xorw %si, %si - xorw %di, %di - movw %ax, %es - rep movsb - movw %ax, %ds - shrw $5, %ax - movw %ax, %fs:ABS(EXT_C(usb_md_address)) - call init_QH_AsyncListAddr - call Set_int13 - clc -4: - popal - popw %fs - popw %es - popw %ds - lret -3: - stc - jmp 4b - - - - - -Read_Write_Configuration: - pushw %bp - movw %sp, %bp - pushw %bx - pushl %ecx - pushw %di - movw 04(%bp), %bx - movw 06(%bp), %di - movw 0x08(%bp), %cx - decb %al - jne 1f - movw $0xB109, %ax - int $0x1A - jmp 2f -1: - decb %al - jne 1f - movw $0xB10A, %ax - int $0x1A - jmp 2f -1: - movw $0xB10C, %ax - int $0x1A -2: - movl %ecx, %eax - popw %di - popl %ecx - popw %bx - popw %bp - ret - - -Set_int13: - cli - movl %fs:0x004c, %ebx - movl %ebx, %ds:(old_int13 - USB2DRI) - - movw $(Entry_int13 - USB2DRI), %bx - movw %bx, %fs:0x004c - movw %ds, %fs:0x004e - sti - ret - - -Sector_comparison: - pushw %si - pushw %di - pushw %cx - movw $0x200, %cx -1: - repz cmpsb - je 2f - cmpw $0x01db, %cx - je 1b - cmpw $0x01bf, %cx - je 1b - cmpw $0x01e3, %cx - jne 3f - subw $3, %cx - addw $3, %si - addw $3, %di - jmp 1b -2: - clc -1: - popw %cx - popw %di - popw %si - ret -3: - stc - jmp 1b - - - - -Search_drive: - movb %fs:0x0475, %cl - orb $0x80, %cl - incb %fs:0x0475 - ret - - -read_hdd: - pushw %bx - movw $1, %bx - movb $1, %cl - call Read_write_usb - popw %bx - ret - - -read_int13: - pushw %ds - pushw %es - int $0x13 - popw %es - popw %ds - ret - - - -read_dri: - pushaw - movw $2, %si -1: - movw $0x0201, %ax - xorb %dh, %dh - movw $1, %cx - call read_int13 - jnb 1f - decw %si - je 1f - movb $0, %ah - call read_int13 - jmp 1b -1: - popaw - ret - - -Get_dri: - movb %fs:0x8280, %dl - cmpb $0x23, %dl - jne 1f - movb %fs:0x21af, %dl -1: - movb %dl, %cs:(bios_dl - USB2DRI) - ret - - -Check_PartitionTable: - pushaw - xorb %bl, %bl - leaw 0x1be(%di), %di - movw %di, %si - addw $0x40, %di -4: - cmpw %di, %si - jnb 3f /* partition table is OK */ - pushw %si - movw $4, %cx -2: - lodsl - negl %eax - jc 2f - loop 2b - popw %ax - incb %bl - cmpb $4, %bl - jb 4b /* empty entry, check next */ - jmp 5f /* Error: empty table */ -2: - /* non-empty entry */ - popw %si - lodsw - shlb $1, %al - jnz 5f - lodsw - andb $63, %al - jz 5f - lodsw - lodsw - andb $63, %al - jz 5f - lodsl - negl %eax - jnc 5f - lodsl - negl %eax - jc 4b - jmp 5f -3: - lodsw - cmpw $0xAA55, %ax - je 1f -5: - stc /* invalid partition table */ -1: - popaw - ret - - -Define_disk_No: - pushaw - pushw %ds - pushw %es - pushw (Init_cs - USB2DRI) - popw %es - pushw %es - popw %ds - - call Get_dri - movw %si, %bx -#if cd - cmpb $5, %cs:(_type - USB2DRI) - jne 1f - - cmpb $0x9f, %dl - jb 2f - movb %dl, %cs:(Number - USB2DRI)(%bx) - movb %dl, %cs:(cd_num - USB2DRI) - jmp 3f -2: - movb $0xf8, %cs:(Number - USB2DRI)(%bx) -3: - movl $0x11, %eax - movw $mem_mbr, %di - call read_hdd - jc cssq_err - cmpl $0x54204c45, 7(%di) - jne cssq_err - movl 0x47(%di), %eax - call read_hdd - cmpw $0xAA55, 0x1e(%di) - jne cssq_err - cmpw $0x88, 0x20(%di) - jne cssq_err - movb 0x21(%di), %al - movb %al, %cs:(Media_types - USB2DRI) - movw 0x22(%di), %ax - movw %ax, %cs:(Capacity - USB2DRI)(%bx) - movw 0x26(%di), %ax - movw %ax, %cs:(Capacity + 2 - USB2DRI)(%bx) - movl 0x28(%di), %eax - movl %eax, %cs:(StartSector - USB2DRI)(%bx) - jmp 5f -#endif -1: - xorl %eax, %eax - movw $mem_mbr, %di - call read_hdd - jc cssq_err - call Check_PartitionTable - jc 2f - - movw $4, %cx -1: - cmpb $0x80, 0x1be(%di) - je 1f - addw $0x10, %di - loop 1b - - movw $mem_mbr, %di - movw $4, %cx -1: - movl 0x1c6(%di), %eax - orl %eax, %eax - jne 1f - addw $0x10, %di - loop 1b - jmp 2f -1: - subw $mem_mbr, %di - shrw $4, %di - movw %di, %bp - movw $mem_pbr, %di - call read_hdd - jmp 1f -2: - movw $mem_mbr, %di - movl 0x1c(%di), %eax -1: - movl %eax, %cs:(StartSector - USB2DRI)(%bx) - - orb %dl, %dl - jne 2f - movb %cs:(fd_num - USB2DRI), %ch - cmpb $0, %ch - je 2f - xorb %cl, %cl - movw $mem_fd, %si -1: - movw $mem_mbr, %di - call Sector_comparison - jnc 3f - movw $mem_pbr, %di - call Sector_comparison - jc 4f - movw %bp, %fs:(0x8208+2) - movw %bp, %fs:(0x829c+2) - movw %bp, %fs:(0x831c+2) - jmp 3f -4: - decb %ch - je 2f - addw $0x200, %si - incb %cl - jmp 1b -2: - movb %cs:(hd_num - USB2DRI), %ch - cmpb $0, %ch - je 2f - movb $0x80, %cl - movw $mem_hd, %si - movw $mem_mbr, %di -1: - call Sector_comparison - jnc 3f - decb %ch - je 2f - addw $0x200, %si - incb %cl - jmp 1b -2: - call Search_drive -3: - testb $1, %cs:(map_num - USB2DRI) - je not_map - cmpb $0x80, %cl - jne not_map_80 - movb $0, %cs:(Number - USB2DRI)(%bx) - movb $0, %fs:0x8280 - movb $0, %fs:0x82a0 - movb $0, %fs:0x8318 - jmp 5f -not_map_80: - decb %cl -not_map: - movb %cl, %cs:(Number - USB2DRI)(%bx) -5: - testb $1, %cs:(map_num - USB2DRI) - je cssq_end_1 - decb %fs:(0x0475) -cssq_end_1: - clc -cssq_end_2: - popw %es - popw %ds - popaw - ret -cssq_err: - stc - jmp cssq_end_2 - - - -Drive_enumerate: - xorw %bx, %bx - xorw %si, %si - movb $0, (_lun - USB2DRI) - movb $0, (EXT_C(max_dri) - USB2DRI) - movzbw (max_dev - USB2DRI), %bp -0: - cmpb $0xf0, (MaxLUN - USB2DRI)(%bx) - jb 1f -5: - decw %bp - je 4f - addw $DevLen, %bx - jmp 0b -1: - movb (DevID - USB2DRI)(%bx), %al - movb %al, (_id - USB2DRI) -#if cd - call Remove_CBWCB - movb $0x80, (bmCBWFlags - USB2DRI) - movb $0x24, (dCBWDataTransferLength - USB2DRI) - movw $(Cache - USB2DRI), %ax - movw %ax, (TOffset - USB2DRI) - movw %ds, (TSection - USB2DRI) - movb $0x12, (CBWCB - USB2DRI) - movb $0x24, (CBWCB + 4 - USB2DRI) - call SCSI_Command - cmpb $0, (Return - USB2DRI) - jne 1f - movb (Cache - USB2DRI), %al - andb $0x1f, %al - cmpb $0x1f, %al - je 1f - movb %al, (_type - USB2DRI) -#endif - pushw %si -#if cd - movw $900, %si - cmpb $5, %al - je csdyd -#endif - movw $5, %si -csdyd: - call Remove_CBWCB - call SCSI_Command - cmpb $0, (Return - USB2DRI) - je 2f - decw %si - je 3f - movw $100, %ax - call Delay - jmp csdyd -3: - popw %si - jmp 1f - -2: - popw %si - call Remove_CBWCB - movb $0x80, (bmCBWFlags - USB2DRI) - movb $8, (dCBWDataTransferLength - USB2DRI) - movw $(Cache - USB2DRI), %ax - movw %ax, (TOffset - USB2DRI) - movw %ds, (TSection - USB2DRI) - movb $0x25, (CBWCB - USB2DRI) - call SCSI_Command - cmpb $0, (Return - USB2DRI) - jne 1f - - movl (Cache - USB2DRI), %eax - orl %eax, %eax - je 1f - xchgb %ah, %al - rorl $0x10, %eax - xchgb %ah, %al - movl %eax, (Capacity - USB2DRI)(%si) - - movw (Cache - USB2DRI + 6), %ax - xchgb %ah, %al - movw %ax, (SectorSize - USB2DRI)(%si) - movw %ax, (Sector_Size - USB2DRI) - - call Define_disk_No - jc 1f - - movb (_id - USB2DRI), %al - movb %al, (DriID - USB2DRI)(%si) - - movb (_lun - USB2DRI), %al - movb %al, (DriLUN - USB2DRI)(%si) -#if cd - movb (_type - USB2DRI), %al - movb %al, (DriType - USB2DRI)(%si) -#endif - incb (EXT_C(max_dri) - USB2DRI) - cmpb $4, (EXT_C(max_dri) - USB2DRI) - jae 4f - addw $DriveLen, %si -1: - movb (_lun - USB2DRI), %al - cmpb (MaxLUN - USB2DRI)(%bx), %al - jae 1f - incb (_lun - USB2DRI) - jmp 0b -1: - movb $0, (_lun - USB2DRI) - jmp 5b -4: - ret - -HUB_PORT: - .byte 0 -HUB__ID: - .byte 0 - -usb_probe: - pushw %cx - movb (DevID - USB2DRI)(%bx), %al - movb %al, (_id - USB2DRI) - movw $(Cache - USB2DRI), %di - - movw $(Get_Hub - USB2DRI), %si - call Control_transfer - movzbw 2(%di), %cx - movw %cx, (n_ports - USB2DRI) -2: - movw $(Set_HubPort_Power - USB2DRI), %si - call Control_transfer_hub - movw $200, %ax - call Delay - loop 2b - movw $200, %ax - call Delay - movw (n_ports - USB2DRI), %cx -2: - movw $(Get_HubPort_Status - USB2DRI), %si - call Control_transfer_hub - testw $1, (%di) - jne 4f -3: - decw %cx - jne 2b - jmp 1f -4: - call Port_Reset_hub - movw $(Get_HubPort_Status - USB2DRI), %si - call Control_transfer_hub - testw $2, (%di) - je 3b - testw $0x400,(%di) - je 3b - - movb %cl, (HUB_PORT - USB2DRI) - movb (_id - USB2DRI), %al - movb %al, (HUB__ID - USB2DRI) - pushw %bx - pushw (_id - USB2DRI) - call Fill_device_structure - popw (_id - USB2DRI) - popw %bx - - movw $(Cache - USB2DRI), %di - movb (_id - USB2DRI), %al - jmp 3b -1: - popw %cx - ret - - -Fill_device_structure: - pushw %cx - cmpb $8, (max_dev - USB2DRI) - jae jscl - movb (max_dev - USB2DRI), %dl - incb %dl - movb %dl, (_id - USB2DRI) - call Determine_device_address - - movb (HUB_PORT - USB2DRI), %al - orb %al, %al - je 1f - movb %al, (Port_Num_Reg - USB2DRI)(%bx) - movb (HUB__ID - USB2DRI), %al - movb %al, (HUB_id - USB2DRI)(%bx) - jmp 2f -1: - movw %si, (Port_Num_Reg - USB2DRI)(%bx) -2: - movw $(Cache - USB2DRI), %di - movw $(Get_device - USB2DRI), %si - movb $0x40, (ConSize - USB2DRI)(%bx) - call Control_transfer - cmpb $0, (Status - USB2DRI) - jne jscl - - call szsbdz - incb (max_dev - USB2DRI) - - pushw 4(%di) - movw $(Get_Configuration - USB2DRI), %si - call Control_transfer - popw %cx - cmpb $0, (Status - USB2DRI) - jne 5f - movb 2(%di), %al - movb %al, (Config_Length - USB2DRI) -pz_cl: - movb 5(%di), %al - movb %al, (Set_Configuration + 2 - USB2DRI) - cmpb $0, %cl - je pdlx - cmpb $9, %cl - je pdlx - call szpz - jmp 5f -pdlx: - movzbw (%di), %ax - subb %al, (Config_Length - USB2DRI) - je 5f - addw %ax, %di - movb 1(%di), %al - cmpb $5, %al - je dd_cl - cmpb $2, %al - je pz_cl - cmpb $4, %al - jne pdlx - movb $0, (Interface_ok - USB2DRI) -jk_cf: - cmpw $9, 5(%di) - je jk_cf_0 - cmpw $0x0608, 05(%di) - jne pdlx - cmpb $0x50, 07(%di) - jne pdlx -jk_cf_0: - movb $1, (Interface_ok - USB2DRI) - movb 4(%di), %al - movb %al, (Num_Endpoint - USB2DRI) - jmp pdlx -dd_cl: - cmpb $1, (Interface_ok - USB2DRI) - jne pdlx - movb 02(%di), %dl - movw 04(%di), %bp - movb 03(%di), %dh - cmpb $2, %dh - jne 3f - - testb $0x80, %dl - je 2f - - movb %dh, (InProperty - USB2DRI)(%bx) - movb %dl, (InAddress - USB2DRI)(%bx) - movw %bp, (InSize - USB2DRI)(%bx) - jmp 3f -2: - mov %dh, (OutProperty - USB2DRI)(%bx) - mov %dl, (OutAddress - USB2DRI)(%bx) - mov %bp, (OutSize - USB2DRI)(%bx) -3: - decb (Num_Endpoint - USB2DRI) - jne pdlx -4: - call szpz - cmpb $0, (OutProperty - USB2DRI)(%bx) - jne getlun - movb $0xff, (MaxLUN - USB2DRI)(%bx) - jmp jscl -getlun: - mov $(Get_lun - USB2DRI), %si - call Control_transfer - movb (Cache - USB2DRI), %al - movb %al, (MaxLUN - USB2DRI)(%bx) - incb (usb_count - USB2DRI) -jscl: - popw %cx - ret -5: - movb $0xf0, (MaxLUN - USB2DRI)(%bx) - jmp jscl - -Device_enumerate: - movw $0x44, %si - movw (n_ports - USB2DRI), %cx -1: - call Read_Register - testb $01, %al - jne 1f -2: - decw %cx - je 4f - addw $04, %si - jmp 1b -1: - testb $04, %ah - jne 1f - call Port_Reset - testb $04, %al - jne 3f -1: - movl $0x00003002, %eax - call Write_Register - movw $03, %ax - call Delay - jmp 2b -3: - pushw %si - movb $0, (HUB_PORT - USB2DRI) - call Fill_device_structure - popw %si - jmp 2b -4: - xorw %bx, %bx - movw $8, %cx -cl_jxq: - cmpb $0xff, (MaxLUN - USB2DRI)(%bx) - je cl_jxq_1 -cl_jxq_0: - addw $DevLen, %bx - decw %cx - jne cl_jxq - jmp cl_jxq_end -cl_jxq_1: - call usb_probe - jmp cl_jxq_0 -cl_jxq_end: - ret - - -Fill_descriptor: - movl $(GDT - USB2DRI), %eax - addl (ds_Linear - USB2DRI), %eax - movl %eax, (Base - USB2DRI) - - movl (Register_pci - USB2DRI), %eax - movw %ax, (BaseL - USB2DRI) - shrl $0x10, %eax - movb %al, (BaseM - USB2DRI) - movb %ah, (BaseH - USB2DRI) - ret - -Define_qTD1: - movl $(qh - USB2DRI), %eax - addl (ds_Linear - USB2DRI), %eax - testb $0x1f, %al - je 1f - andl $0xffffffe0, %eax - addl $0x20, %eax -1: - movl %eax, (qTD1_Linear - USB2DRI) - subl (ds_Linear - USB2DRI), %eax - movw %ax, (qTD1 - USB2DRI) - ret - -set_410_1: - orb $1, %fs:0x0410 - andb $0x3f, %fs:0x0410 - ret - - . = USB2DRI + 0x13c0 - -/* ******************** USB2DRI end ****************************** */ - - - -//#define CDROM_INIT -#ifdef CDROM_INIT - -/* unsigned long - * init_atapi() : return number of atapi cdrom devices. - */ - -ENTRY(init_atapi) - - .code32 - - pushl %ebp - pushl %ebx - - call EXT_C(prot_to_real) /* enter real mode */ - - .code16 - - sti /* enable interrupt for ATAPI */ - - cld - - /* set CS base to be int13_handler */ -#if 0 - ljmp $((ABS(int13_handler)) >> 4), $(1f - int13_handler) -#else - .byte 0xEA - .word 1f - int13_handler - .word (ABS(int13_handler)) >> 4 -#endif -1: - pushaw - pushw %es - pushw %ds - - pushw %cs - popw %ds - pushw %cs - popw %es - xorw %ax, %ax - - # initialize variables - - movw $(start_of_atapi_data - int13_handler), %di - movw $(end_of_atapi_data - start_of_atapi_data), %cx - repz stosb - - decw atapi_cur_dev - int13_handler # device serial number initialized to 0xFFFF - - #; begin init_timer - - call read_bios_time - movw %ax, %bx #; store initial timer in BX -1: - call read_bios_time - cmpw %ax, %bx #; timer just changed? - je 1b #; no, continue. - - /* now AX=BX+1 */ - - movw %ax, %bx #; store initial timer in BX - xorl %ecx, %ecx -1: - call read_bios_time - cmpw %ax, %bx #; timer changed? - addr32 loope 1b - - negl %ecx - - /* ECX loops=a tick=1/18.2second=1000/18.2(=54.9) milliseconds */ - - movl %ecx, %eax - xorl %edx, %edx - xorl %ecx, %ecx - movw $55, %cx # a tick is about 55 milliseconds - divl %ecx - - /* EAX=loops per millisecond */ - - movl %eax, delay_repeat_num - int13_handler - - #; end init_timer - - call init_atapi_cdroms - - //movw $-1, atapi_cur_dev - int13_handler # device serial number initialized to 0xFFFF - - popw %ds - popw %es - - movw %sp, %bp - movw %cx, 8(%bp) #; 8(%bp) is old BX on stack ! - popaw - - ljmp $0, $ABS(1f) -1: - - call EXT_C(real_to_prot) - .code32 - - sti - - movzwl %bx, %eax - - popl %ebx - popl %ebp - ret - -init_atapi_cdroms: - - .code16 - -#; return: CF=0 success, CX=number of cdroms -#; CF=1 failed, no cdrom found -#; push cs -#; pop es - - call reg_probe #; return cx = number of atapi devices - - orw %cx, %cx - jnz 1f - - call reg_probe #; return cx = number of atapi devices - - orw %cx, %cx - jnz 1f - - stc - ret - -1: -#if 1 - movw $atapi_dev_base - int13_handler, %si #; array of ATAPI reg pointer and dev - movw $atapi_dev_base_bak - int13_handler, %di #; for CDROMs - - cld - - pushw %si - pushw %di - - xorw %ax, %ax - xorw %bx, %bx -1: - call select_atapi_force #;input: ax = device serial number - #;return: cf=0 success, cf=1 failed - - - jc 2f - - call check_atapi_cdrom #;return: cf=0 is cdrom, cf=1 not cdrom - - jc 2f - - /* It is CDROM */ - - incw %bx #;count the cdroms - movsw #;store CDROM base pointer - movsw #;store CDROM device number - subw $4, %si - - # debug print the reg and dev - pushw %bx - - movw (%si), %bx # BX=reg group pointer - - pushw 2(%si) # CDROM device number - pushw 2(%bx) # base port of control block regs, i.e., device control port - pushw (%bx) # base port of command block regs, i.e., data port - pushw $cdrom_reg_dev - int13_handler # the format string - call realmode_printf - addw $8, %sp # adjust the stack pointer - - popw %bx - -2: - addw $4, %si - incw %ax #; try next ATAPI device - loop 1b - - popw %si #; points to atapi_dev_base_bak, which is for CDROMs - popw %di #; points to atapi_dev_base, which is for ATAPIs - - movw $64, %cx #; overwrite ATAPIs with CDROMs - repz movsb - - movb %bl, EXT_C(atapi_dev_count) - int13_handler - movb EXT_C(min_cdrom_id) - int13_handler, %cl - addb %bl, %cl - decw %cx - movb %cl, max_cdrom_id - int13_handler - movw %bx, %cx -#endif - - clc - ret - -cdrom_reg_dev: - .ascii "CDROM device found: Data=%X, Ctrl=%X, dev=%X(Note: 0=master, 1=slave)\r\n\0" - - -/* Called by init_atapi_cdroms - * Calls reg_setup_base_addr, reg_reset - */ -reg_probe: - - .code16 - -#; return cx = number of atapi devices - pushw %ax - pushw %bx - pushw %si - pushw %di - cld - movb $0, EXT_C(atapi_dev_count) - int13_handler # reset counter - movw $reg_base_addr - int13_handler, %bx # BX points to base address array - movw $atapi_dev_base - int13_handler, %di # will store base pointers and device numbers -1: - call reg_setup_base_addr # setup the base reg addresses(reg_addr) for reg base address BX - - #; begin reg_probe_exist - movb $cmd_DC, %al - movw reg_addr - int13_handler + (8 * 2), %dx #; CB_DC - outb %al, %dx - - movw $0, %ax - - call reg_probe_dev_exist - - movb %al, reg_dev_info - int13_handler # master device existence - movw $1, %ax - - call reg_probe_dev_exist - - movb %al, reg_dev_info - int13_handler + 1 # slave device existence - - #; end reg_probe_exist - - call reg_reset - - xor %si, %si # SI=0 for master -2: -// movw %si, %ax -// call reg_probe_dev_exist - - cmpb $0, (reg_dev_info - int13_handler)(%si) # check existence -// cmpb $0, %al # check existence - je 3f # device not exist, so skip - - /* The device exists, so do a further check for device type. */ - - movw %si, %ax - - #; begin reg_check_dev_type - - #; call after a reset - - call __reg_select_dev - - movw reg_addr - int13_handler + (2 * 2), %dx #; CB_SC = interrupt reason register - inb %dx, %al - movb %al, %ah - - movw reg_addr - int13_handler + (3 * 2), %dx #; CB_SN = reserved for SAM TAG byte - inb %dx, %al - - cmpw $0x0101, %ax # success? - movw $1, %ax # REG_CONFIG_TYPE_UNKN - jne 4f # No. The device type is unknown. - - movw reg_addr - int13_handler + (4 * 2), %dx #; CB_CL = byte count low - inb %dx, %al - movb %al, %ah - - movw reg_addr - int13_handler + (5 * 2), %dx #; CB_CH = byte count high - inb %dx, %al - - cmpw $0x14EB, %ax # Is ATAPI? - je 5f # yes. - - testb %al, %al # 0 is for ATA - movw $1, %ax # REG_CONFIG_TYPE_UNKN - jnz 4f - # AX=1 - - movw reg_addr - int13_handler + (7 * 2), %dx #; CB_STAT - inb %dx, %al - # AH=0 - //if AL==0, then AX=1=REG_CONFIG_TYPE_UNKN, else AX=2=REG_CONFIG_TYPE_ATA - testb %al, %al - setne %al - incw %ax - jmp 4f -5: - movw $3, %ax # REG_CONFIG_TYPE_ATAPI -4: - - #; end reg_check_dev_type - - - movb %al, (reg_dev_info - int13_handler)(%si) #; added (%si) recently - cmpb $3, %al # Is ATAPI? - jne 3f # no, ignore it. - - #; It is ATAPI, so add it to the list at atapi_dev_base - incb EXT_C(atapi_dev_count) - int13_handler # count it - movw %bx, %ax # store the pointer to the base reg pair - stosw - movw %si, %ax # store the device number(master/slave) - stosw - - # debug print the reg and dev - pushw %si - pushw 2(%bx) # base port of control block regs, i.e., device control port - pushw (%bx) # base port of command block regs, i.e., data port - pushw $atapi_reg_dev - int13_handler # the format string - call realmode_printf - addw $8, %sp # adjust the stack pointer -3: - incw %si # SI=1 for slave - cmpw $2, %si - jb 2b - - addw $4, %bx # try next group of base reg - #; incw %bx # try next group of base reg - #; incw %bx - cmpw $0, (%bx) # end? - jnz 1b # no, probe next reg group - - movzbw EXT_C(atapi_dev_count) - int13_handler, %cx - movw %cx, %bx - decw %bx - movb EXT_C(min_cdrom_id) - int13_handler, %al - addb %bl, %al - movb %al, max_cdrom_id - int13_handler - popw %di - popw %si - popw %bx - popw %ax - ret - -atapi_reg_dev: - .ascii "ATAPI device found: Data=%X, Ctrl=%X, dev=%X(Note: 0=master, 1=slave)\r\n\0" - - -check_atapi_cdrom: - - .code16 - -#;return: cf =0 is cdrom, cf =1 not cdrom - pushaw -#; push es -#; push cs -#; pop es -#; mov di, atapi_devinfo - call inquiry_atapi - jc 1f - clc - -#define ATATYPE_CDR 0x4 //#; Write-once device -#define ATATYPE_CD 0x5 //#; CD-ROM device - - cmpb $ATATYPE_CD, %al - je 1f - cmpb $ATATYPE_CDR, %al - je 1f - stc -1: -#; pop es - popaw - ret - - -inquiry_atapi: - - .code16 - -#;input: es:di -> atapi_devinfo -#;return: cf =0 success, al = device type, -#; cf =1 fail -#; save si, di, cx - call clear_atapi_buffer - movb $0x12, atapi_cmd_buffer - int13_handler - movb $128, atapi_cmd_buffer - int13_handler + 4 - - # invoke reg_packet,byte,0,cs, atapi_tmp_buffer, 128 - pushw $128 - pushw $atapi_tmp_buffer - int13_handler - pushw %cs - pushw $0 - call reg_packet - addw $8, %sp - - orw %ax, %ax - jnz 1f - - movb atapi_tmp_buffer - int13_handler, %al - testb $0xe0, %al - jnz 1f - - andb $0x1f, %al - -#if 0 - mov [es:di + struc_atapi_devinfo.dev_type], al - - mov ah, [atapi_tmp_buffer+7] - mov [es:di + struc_atapi_devinfo.dev_flags], ah - - add di, struc_atapi_devinfo.vender_id - mov si, atapi_tmp_buffer + 8 - mov cx, 24 - cld - rep movsb -#endif - clc - ret -1: - stc - ret - - -reg_probe_dev_exist: - - .code16 - -#; input ax=dev -#; return ax = 1: exist # <----- "ax=1" should be "al=1" - call __reg_select_dev - - # outbytes CB_SC,0x55,CB_SN,0xaa,CB_SC,0xaa,CB_SN,0x55,CB_SC,0x55 - movb $0x55, %al - movw reg_addr - int13_handler + (2 * 2), %dx #; CB_SC = interrupt reason register - outb %al, %dx - - movb $0xAA, %al - movw reg_addr - int13_handler + (3 * 2), %dx #; CB_SN = reserved for SAM TAG byte - outb %al, %dx - - movb $0xAA, %al - movw reg_addr - int13_handler + (2 * 2), %dx #; CB_SC = interrupt reason register - outb %al, %dx - - movb $0x55, %al - movw reg_addr - int13_handler + (3 * 2), %dx #; CB_SN = reserved for SAM TAG byte - outb %al, %dx - - movb $0x55, %al - movw reg_addr - int13_handler + (2 * 2), %dx #; CB_SC = interrupt reason register - outb %al, %dx - - movb $0xAA, %al - movw reg_addr - int13_handler + (3 * 2), %dx #; CB_SN = reserved for SAM TAG byte - outb %al, %dx - - movw reg_addr - int13_handler + (2 * 2), %dx #; CB_SC = interrupt reason register - inb %dx, %al - movb %al, %ah - - movw reg_addr - int13_handler + (3 * 2), %dx #; CB_SN = reserved for SAM TAG byte - inb %dx, %al - - cmpw $0x55AA, %ax - sete %al - ret - -#endif /* CDROM_INIT */ - - -/* - * chain_stage1(segment, offset, part_table_addr) - * - * This starts another stage1 loader, at segment:offset. - */ - -ENTRY(chain_stage1) - - .code32 - - /* no need to save anything, just use %esp */ - - /* store %ESI, presuming %ES is 0 */ - movl 0xc(%esp), %esi - - /* store new offset */ - movl 0x8(%esp), %eax - movl %eax, offset - - /* store new segment */ - movw 0x4(%esp), %ax - movw %ax, segment - - /* set up to pass boot drive */ - movb EXT_C(boot_drive), %dl - - call EXT_C(prot_to_real) - - .code16 - - //sti /* it is not bad keeping interrupt off */ - sti /* for hardware interrupt or watchdog */ - -#ifdef ABSOLUTE_WITHOUT_ASTERISK - DATA32 ADDR32 ljmp (offset) -#else - DATA32 ADDR32 ljmp *(offset) -#endif - - -/* - * These next two routines, "real_to_prot" and "prot_to_real" are structured - * in a very specific way. Be very careful when changing them. - * - * NOTE: Use of either one messes up %eax and %ebp. - */ - -ENTRY(real_to_prot) - - .code16 - - cli - - /* load the GDT register */ - xorw %ax, %ax - movw %ax, %ds - lgdt gdtdesc - - /* turn on protected mode */ - movl %cr0, %eax - andl $0x0000FFF3, %eax - orb $1, %al - movl %eax, %cr0 - - /* jump to relocation, flush prefetch queue, and reload %cs */ - ljmp $PROT_MODE_CSEG, $protcseg - - /* - * The ".code32" directive only works in GAS, the GNU assembler! - * This gets out of "16-bit" mode. - */ - - .code32 - -protcseg: - /* reload other segment registers */ - movw $PROT_MODE_DSEG, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - movw %ax, %ss - -#; /* put the return address in a known safe location */ -#; movl (%esp), %eax -#; movl %eax, STACKOFF - -#; /* get protected mode stack */ -#; movl protstack, %eax -#; movl %eax, %esp -#; movl %eax, %ebp - -#; /* get return address onto the right stack */ -#; movl STACKOFF, %eax -#; movl %eax, (%esp) - - lidt pmode_idtdesc - - /* zero %eax */ - xorl %eax, %eax - - /* return on the old (or initialized) stack! */ - .byte 0x66 # data32 /* YES!! only a 16-bit RET!! */ - ret - - -ENTRY(prot_to_real) - - .code32 - - cli - - /* just in case, set GDT */ - lgdt gdtdesc - -#; /* save the protected mode stack */ -#; movl %esp, %eax -#; movl %eax, protstack - -#; /* get the return address */ -#; movl (%esp), %eax -#; movl %eax, STACKOFF - -#; /* set up new stack */ -#; movl $STACKOFF, %eax -#; movl %eax, %esp -#; movl %eax, %ebp - - /* set up segment limits */ - movw $PSEUDO_RM_DSEG, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - movw %ax, %ss - - /* this might be an extra step */ - ljmp $PSEUDO_RM_CSEG, $tmpcseg /* jump to a 16 bit segment */ - -tmpcseg: - .code16 - - /* clear the PE bit of CR0 */ - movl %cr0, %eax - //andl $CR0_PE_OFF, %eax - andl $0x0000FFF2, %eax - movl %eax, %cr0 - - /* flush prefetch queue, reload %cs */ - ljmp $0, $realcseg - -realcseg: - /* we are in real mode now - * set up the real mode segment registers : DS, SS, ES - */ - /* zero %eax */ - xorl %eax, %eax - - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - movw %ax, %ss - - /* restore interrupts */ - /* oh, don't enable interrupt when we are controlling gateA20 */ - //sti - lidt realmode_idtdesc - - /* return on new stack! */ - DATA32 ret /* 32-bit RET!! */ - - - /*********** begin initialising page maps ***********/ - /* PML4 base, with only one entry(=512G) */ - -mem64_paging_initialized: - .byte 0 - -mem64_paging_init: - .code32 - - movl ABS(EXT_C(page_map_start)), %ebx - movl %ebx, %edi - movl %ebx, %eax - addl $0x1007, %eax - stosl # first PML4 table entry, lo - xorl %eax, %eax - stosl # first PML4 table entry, hi - - /* PDP table, with 512 entries(=512G) */ - /* entry 0x000 starts at EBX+0x002000 */ - /* entry 0x001 starts at EBX+0x003000 */ - /* .................................. */ - /* entry 0x1FF starts at EBX+0x201000 */ - - movl %ebx, %edi - addl $0x1000, %edi # PDP table starting at EBX+0x1000 - movl $512, %ecx -1: - movl $(512+2), %eax - subl %ecx, %eax # EAX=(entry number + 2) - shll $12, %eax - addl %ebx, %eax - orb $0x07, %al - stosl # PDP table entry, lo - xorl %eax, %eax - stosl # PDP table entry, hi - loop 1b - - /* PD table, identity mapping, 2M page size, 512*512entries=512G */ - movl %ebx, %edi - addl $0x2000, %edi # PD table starting at EBX+0x2000 - movl $(512*512), %ecx -1: - xorl %edx, %edx - movl $(512*512), %eax - subl %ecx, %eax - shldl $21, %eax, %edx - shll $21, %eax - orb $0x87, %al - stosl # PD table entry, lo - movl %edx, %eax - stosl # PD table entry, hi - loop 1b - orb $1, ABS(mem64_paging_initialized) - ret - /*********** end initialising page maps ***********/ - - -/* - * int mem64 (int func, __u64 dest, __u64 src, __u64 len) - * - * SRC and DEST should better align 8 for efficiency. - * - * input: - * func = 1 for memmove, 2 for memcmp, 3 for memset - * - */ - -ENTRY(mem64) - - .code32 - - pushl %ebp - movl %esp, %ebp - - #; +28 len - #; +20 src - #; +12 dest - #; +8 func - #; +4 EIP - #; ebp EBP - #; -4 ESI - #; -8 EDI - #; -12 EBX - - pushl %esi - pushl %edi - pushl %ebx - pushfl - cli - - /* backup cr3, cr4 */ - movl %cr3, %eax - movl %eax, ABS(old_cr3) # save cr3 - movl %cr4, %eax - movl %eax, ABS(old_cr4) # save cr4 - - cmpb $1, ABS(mem64_paging_initialized) - je 1f - call mem64_paging_init -1: -#if 0 - /* XXX: page maps can initialise only once for efficiency. */ - - /*********** begin initialising page maps ***********/ - /* PML4 base, with only one entry(=512G) */ - cld - movl ABS(EXT_C(page_map_start)), %ebx - movl %ebx, %edi - movl %ebx, %eax - addl $0x1007, %eax - stosl # first PML4 table entry, lo - xorl %eax, %eax - stosl # first PML4 table entry, hi - - /* PDP table, with 512 entries(=512G) */ - /* entry 0x000 starts at EBX+0x002000 */ - /* entry 0x001 starts at EBX+0x003000 */ - /* .................................. */ - /* entry 0x1FF starts at EBX+0x201000 */ - - movl %ebx, %edi - addl $0x1000, %edi # PDP table starting at EBX+0x1000 - movl $512, %ecx -1: - movl $(512+2), %eax - subl %ecx, %eax # EAX=(entry number + 2) - shll $12, %eax - addl %ebx, %eax - orb $0x07, %al - stosl # PDP table entry, lo - xorl %eax, %eax - stosl # PDP table entry, hi - loop 1b - - /* PD table, identity mapping, 2M page size, 512*512entries=512G */ - movl %ebx, %edi - addl $0x2000, %edi # PD table starting at EBX+0x2000 - movl $(512*512), %ecx -1: - xorl %edx, %edx - movl $(512*512), %eax - subl %ecx, %eax - shldl $21, %eax, %edx - shll $21, %eax - orb $0x87, %al - stosl # PD table entry, lo - movl %edx, %eax - stosl # PD table entry, hi - loop 1b - - /*********** end initialising page maps ***********/ -#endif - movl ABS(EXT_C(page_map_start)), %eax - movl %eax, %cr3 # load new PML4 base - - movl %cr4, %eax - orb $0x30, %al # 0x80=PGE, 0x20=PAE, 0x10=PSE - movl %eax, %cr4 # load new cr4 - - /* rdmsr will change EDX:EAX */ - movl $0xC0000080, %ecx # specify EFER MSR - rdmsr # enable long mode(EFER.LME=1) - orb $0x1, %ah - wrmsr - - movl %cr0, %eax - orl $0x80000000, %eax # Activate long mode by enabling paging - movl %eax, %cr0 - - ljmp $32, $ABS(1f) # ljmp to enter 64-bit mode - - .code64 -1: - - /* 28(%ebp) = len */ - /* 20(%ebp) = src */ - /* 12(%ebp) = dest */ - /* 8(%ebp) = func */ - - movl %ebp, %ebp # clear upper 32-bit of %rbp - movl 8(%rbp), %eax - testl %eax, %eax - jz 1f - cmpl $3, %eax - ja 1f - cld - movq 12(%rbp), %rdi - movq 20(%rbp), %rsi - movq 28(%rbp), %rcx - /* AL=1, 2, 3 */ - cmpb $1, %al - jne 2f - /* AL=1, memmove */ - cmpq %rdi, %rsi - jb 3f - movb %cl, %al - shrq $3, %rcx - repz movsq /* RCX=0 */ - andb $7, %al - jz 1f - movb %al, %cl - repz movsb - jmp 1f -3: - std - addq %rcx, %rsi - addq %rcx, %rdi - decq %rsi - decq %rdi - movq %rcx, %rax /* save RCX to RAX */ - xorq %rcx, %rcx - movb %al, %cl - andb $7, %cl /* if RCX=0, rep will do nothing */ - repz movsb /* RCX=0 */ - movq %rax, %rcx /* restore RCX from RAX */ - shrq $3, %rcx - subq $7, %rsi /* align 8 */ - subq $7, %rdi /* align 8 */ - repz movsq /* RCX=0 */ - cld - jmp 1f -2: - cmpb $2, %al - jne 2f - /* AL=2, memcmp */ - movb %cl, %al - shrq $3, %rcx - repz cmpsq - jnz 1f - andb $7, %al /* RCX=0 */ - jz 1f - movb %al, %cl - repz cmpsb - jmp 1f -2: - /* AL=3, memset */ - movl %esi, %eax /* get AL for the char to write */ - movzbq %al, %rax - testb %al, %al - jz 2f - movb %al, %ah - movw %ax, %si - shll $16, %eax - movw %si, %ax - movl %eax, %esi - shlq $32, %rax - movl %esi, %eax -2: - movb %cl, %dl - shrq $3, %rcx - repz stosq /* RCX=0 */ - andb $7, %dl - jz 1f - movb %dl, %cl - repz stosb -1: - setnz %al - movzbl %al, %ebx # EBX=return value - - /* back to protected mode */ - ljmp *ABS(1f) -1: - .long ABS(1f) - .word 40 # 32-bit code 4GB limit - - .code32 -1: - - /* now in 32-bit compatability mode */ - - movl %cr0, %eax - andl $0x7FFFFFFF, %eax # disable paging, leaving long mode - movl %eax, %cr0 - - movl %cs:ABS(old_cr3), %eax - movl %eax, %cr3 # restore cr3, flush the TLB - - /* now in 32-bit protected mode */ - - /* rdmsr will change EDX:EAX */ - movl $0xC0000080, %ecx # specify EFER MSR - rdmsr # disable long mode(EFER.LME=0) - andb $0xFE, %ah - wrmsr - - movl %cs:ABS(old_cr4), %eax - movl %eax, %cr4 # restore cr4 - - /* reload segment registers */ - - movw $16, %ax # 32-bit data 4GB limit - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - movw %ax, %ss - - /* ESP not touched, so it need not restore. */ - //movl %ebp, %esp - - xchgl %eax, %ebx # EAX=return value - popfl - popl %ebx - popl %edi - popl %esi - popl %ebp - - ret - -/* - * int biosdisk_int13_extensions (unsigned ax, unsigned drive, void *dap, unsigned ssize) - * - * Call IBM/MS INT13 Extensions (int 13 %ax=AX) for DRIVE. DAP - * is passed for disk address packet. If an error occurs, return - * non-zero, otherwise zero. - */ - -ENTRY(biosdisk_int13_extensions) - - .code32 - - pushl %ebp - movl %esp, %ebp - - #; +20 ssize - #; +16 dap - #; +12 drive - #; +8 ax - #; +4 EIP - #; ebp EBP - - pushl %ebx - pushl %esi - pushl %edi - - movl 0x14(%ebp), %ecx #; sector size(512 or 2048) - - /* compute the address of disk_address_packet */ - movl 0x10(%ebp), %eax #; linear address of dap - - /* if DS can be 0x40, we can avoid AWARD BIOS bug of int13/AX=4B01 */ - subl $0x400, %eax - - shll $1, %eax - movw %ax, %si - shrw $1, %si #; low 15-bit for offset - - xorw %ax, %ax - shrl $5, %eax #; segment value in AX - addw $0x40, %ax - movw %ax, %di /* save the segment to di */ - - /* drive */ - movb 0xc(%ebp), %dl - /* ax */ - movw 0x8(%ebp), %bx - /* enter real mode */ - call EXT_C(prot_to_real) - - .code16 - - sti #; cli should also work for biosdisk_int13_extensions - - movw %bx, %ax - movw %di, %ds - - /* set additional registers to serve buggy BIOSes. */ - pushw %ds - pushw %si - pushw %dx - pushw %cx - pushw %bx - //movw %cx, %es - //movw %si, %di - //movw %si, %bx - - andb $0xFE, %bh - cmpb $0x42, %bh /* is it read/write? */ - jne 2f -#if 0 - testb %cl, %cl /* single sector access? */ - jz 2f /* no */ - cmpb $0x2, %ch /* is it normal sector size? */ -#else - cmpw $0x201, %cx -#endif - stc - je 1f -2: -#if 1 - int $0x13 -#else - call safe_int13 -#endif - -1: - popw %bx - popw %cx - popw %dx - popw %si - popw %ds - - jnc 1f - movw %bx, %ax /* read(0x42) or write(0x43) */ - andb $0xFE, %ah - cmpb $0x42, %ah /* is it read/write? */ - jne 2f - cmpb $0x2, %ch /* is it normal sector size? */ - jne 2f - /* try reading sectors one by one */ - movw 2(%si), %cx /* number of sectors to read/write */ - cmpw $2, %cx - jb 2f - cmpw $0x7F, %cx - ja 2f - lesw 4(%si), %di /* get buffer address in ES:DI */ - subw $0x200, %di - movl 8(%si), %eax /* starting sector number lo */ - movl 12(%si), %ebp /* starting sector number hi */ - decl %eax - cmpl $-1, %eax - jne 3f - decl %ebp -3: - addw $0x200, %di - incl %eax - jnz 4f - incl %ebp -4: - pushw %ds - pushw %es - pushal - - pushl %ebp /* sector number hi */ - pushl %eax /* sector number lo */ - pushw %es /* buffer segment */ - pushw %di /* buffer offset */ - pushw $0x0001 /* read/write only one sector */ - pushw $0x0010 /* packet size */ - - xorw %si, %si - movw %si, %ds /* DS=SS=0 */ - movw %sp, %si /* DS:SI points to packet */ - - movw %bx, %ax /* read(0x42) or write(0x43) */ - /* set additional registers to serve buggy BIOSes. */ - movw %di, %bx -#if 1 - int $0x13 -#else - call safe_int13 -#endif - popaw /* discard packet on the stack */ - - popal - popw %es - popw %ds - - jc 1f - loop 3b - jmp 1f /* CF=0, success */ -2: - stc -1: - -#if 1 - /* some buggy USB BIOSes fail to clear AH on success */ - setc %dl -#else - movb $1, %dl /* set error */ - jc 1f - movb %ah, %dl /* save return value */ -1: -#endif - - /* clear the data segment */ - xorw %ax, %ax - movw %ax, %ds - movw %ax, %es - - /* if it is not read/write operation, we can skip the A20 code. */ - - andb $0xFE, %bh - cmpb $0x42, %bh - jne 1f - - /* ensure A20 is on when we come back to protected mode. */ - - pushal - - movw $0x00ff, %cx # try so many times on failure - movw $0x0001, %dx # DL=enable A20, DH=debug off - - cli /* yes, keep interrupt off when controlling A20 */ - call enable_disable_a20 - sti - - //sete %dl # DL=1 means success - - popal -1: - /* back to protected mode */ - call EXT_C(real_to_prot) - .code32 - - sti - - movzbl %dl, %eax /* return value in %eax */ - - popl %edi - popl %esi - popl %ebx - popl %ebp - - ret - -/* - * int biosdisk_standard (int ah, int drive, int coff, int hoff, int soff, - * int nsec, int segment) - * - * Call standard and old INT13 (int 13 %ah=AH) for DRIVE. Read/write - * NSEC sectors from COFF/HOFF/SOFF into SEGMENT. If an error occurs, - * return non-zero, otherwise zero. - */ - -ENTRY(biosdisk_standard) - - .code32 - - pushl %ebp - movl %esp, %ebp - - pushl %ebx - pushl %esi - pushl %edi - - /* set up CHS information */ - movl 0x10(%ebp), %eax /* EAX = Cylinder */ - movb %al, %ch /* low 8 bits to CH */ - movb 0x18(%ebp), %al /* AL = Sector */ - shlb $2, %al /* move low 2 bits of AH .. */ - shrw $2, %ax /* .. to high 2 bits of AL */ - movb %al, %cl /* CX is built OK */ - movb 0x14(%ebp), %dh /* DH = Head */ - /* drive */ - movb 0xc(%ebp), %dl /* DL = drive */ - /* segment */ - movw 0x20(%ebp), %bx /* BX = segment */ - /* save nsec and ah to %di */ - movb 0x8(%ebp), %ah /* AH = read/write */ - movb 0x1c(%ebp), %al /* AL = nsec */ - movw %ax, %di - /* enter real mode */ - call EXT_C(prot_to_real) - - .code16 - - //sti #; biosdisk_standard won't require sti - sti #; added 2006-11-30 - - movw %bx, %es - movw $3, %si /* attempt at least 3 times */ - -1: - pushw %si - pushw %di - pushw %cx - pushw %dx - xorw %bx, %bx - movw %di, %ax -#if 1 - int $0x13 -#else - call safe_int13 -#endif - popw %dx - popw %cx - popw %di - popw %si - -#if 1 - /* some buggy USB BIOSes fail to clear AH on success */ - setc %bl - jnc 2f -#else - movb %ah, %bl /* save return value */ - jc 3f /* check if successful */ - - testb %ah, %ah - jz 2f -3: -#endif - - movw %di, %ax /* get function number */ - cmpb $0x04, %ah /* verify sectors? */ - je 4f /* yes, do not retry */ - /* if fail, reset the disk system */ - pushw %si - pushw %di - pushw %cx - pushw %dx - xorw %ax, %ax -#if 1 - int $0x13 -#else - call safe_int13 -#endif - popw %dx - popw %cx - popw %di - popw %si - - decw %si - jnz 1b /* retry */ -4: - movb $1, %bl /* set error */ -2: - /* ensure A20 is on when we come back to protected mode. */ - - pushal - - movw $0x00ff, %cx # try so many times on failure - movw $0x0001, %dx # DL=enable A20, DH=debug off - - cli /* yes, keep interrupt off when controlling A20 */ - call enable_disable_a20 - sti - - //sete %dl # DL=1 means success - - popal - /* back to protected mode */ - call EXT_C(real_to_prot) - .code32 - - sti - - movzbl %bl, %eax /* return value in %eax */ - - popl %edi - popl %esi - popl %ebx - popl %ebp - - ret - - -/* - * int check_int13_extensions (unsigned drive, unsigned lba1sector) - * - * Check if LBA is supported for DRIVE. If it is supported, then return - * the major version and API support bits of extensions, otherwise zero. - * On return: - * EAX bit 0 = 1, LBA supported - * bit 8 = 0, with 127-sector readability - * bit 8 = 1, without 127-sector readability - * EAX bit 0 = 0, no LBA support - */ - -ENTRY(check_int13_extensions) - - .code32 - - pushl %ebp - movl %esp, %ebp - - pushl %ebx - pushl %esi - pushl %edi - - movw 0xC(%ebp), %di // lba1sector - movb 0x8(%ebp), %dl // drive - /* enter real mode */ - call EXT_C(prot_to_real) - - .code16 - - sti #; added 2006-11-30 - - pushw %dx - pushw %di - - movb $0x41, %ah - movw $0x55aa, %bx -#if 1 - int $0x13 -#else - call safe_int13 -#endif - popw %di - popw %dx - - /* check the result */ - jc 1f - cmpw $0xaa55, %bx - jne 1f - - movb %ah, %bl /* save the major version into %bl */ - - /* check if AH=0x42 is supported if FORCE_LBA is zero */ - movb ABS(EXT_C(force_lba)), %al -#if 0 - testb %al, %al -#if 0 - jnz 2f - andw $1, %cx - jnz 2f -#else - setnz %al - orb %al, %cl - jmp 2f -#endif -#else - andb $0x01, %al /* only use bit 0 for FORCE_LBA */ - orb %al, %cl - /*****************************************************************/ - /* workaround for ASRock's ConRoe865PE mainboard. See issue 153. */ - testb $0x01, %cl - jnz 3f - /* read a sector with function 42h */ - /* no need to save segment registers */ - pushw %di - pushw %bx - pushw %cx - /* first, clear the buffer */ - movw $0x2000, %cx /* GEOMTUNE_SEG */ - movw %cx, %ds - movw %cx, %es - movw $0x100, %cx /* 1 sector */ - xorw %ax, %ax /* fill the first buffer with zeroes */ - xorw %di, %di - cld - rep stosw - movw $0x100, %cx /* 1 sector */ - decw %ax /* fill the second buffer with 0xFF's */ - rep stosw - /* read the boot sector at 2000:0000 */ - /* disk address packet at 2000:8000 */ - movw $0x8000, %di - movw %di, %si - movw $0x0010, (%di) /* packet size and reserved byte */ - movw $0x0001, 2(%di) /* number of blocks to read */ - movw $0x0000, 4(%di) /* buffer offset */ - movw $0x2000, 6(%di) /* buffer segment = GEOMTUNE_SEG */ - movl $0, 8(%di) /* lo 32 bits of starting block number */ - movl $0, 12(%di) /* hi 32 bits of starting block number */ - movw $0x4200, %ax - pushw %ds - pushw %es - pushw %dx -#if 1 - int $0x13 -#else - call safe_int13 -#endif - popw %dx - popw %es - popw %ds - /* read the boot sector again at 2000:0200 */ - /* disk address packet at 2000:8000 */ - movw $0x8000, %di - movw %di, %si - movw $0x0010, (%di) /* packet size and reserved byte */ - movw $0x0001, 2(%di) /* number of blocks to read */ - movw $0x0200, 4(%di) /* buffer offset */ - movw $0x2000, 6(%di) /* buffer segment = GEOMTUNE_SEG */ - movl $0, 8(%di) /* lo 32 bits of starting block number */ - movl $0, 12(%di) /* hi 32 bits of starting block number */ - movw $0x4200, %ax - pushw %ds - pushw %es - pushw %dx -#if 1 - int $0x13 -#else - call safe_int13 -#endif - popw %dx - popw %es - popw %ds - /* compare the two buffers */ - movw $0x0000, %si - movw $0x0200, %di - movw $0x100, %cx - cld - repe cmpsw - /* if equal, account as "extended disk access functions supported" */ - sete %al - popw %cx - orb %al, %cl - popw %bx - popw %di -3: - /* end of workaround */ - /*****************************************************************/ - jmp 2f -#endif - -1: - xorw %bx, %bx - xorw %cx, %cx -2: - shll $16, %ebx #; version number in high word - movb %cl, %bl #; API subset support bitmap in low word - - testb $1, %bl // support LBA? - jz 1f // no - /* make sure if it could read 127 sectors at a time */ - /* first, check sector size */ - /* fill the 2048-byte buffer with FF's */ - movw $0x2000, %cx /* GEOMTUNE_SEG */ - movw %cx, %ds - movw %cx, %es - movw $0x400, %cx /* 4 sectors */ - xorw %ax, %ax - decw %ax /* fill the buffer with 0xFF's */ - pushw %di - xorw %di, %di - cld - rep stosw - popw %di - - pushw %ds - pushw %es - pushal - xorl %eax, %eax - pushl %eax /* sector hi */ - pushl %eax /* sector lo */ - pushw $0x2000 /* buffer segment = GEOMTUNE_SEG */ - pushw %ax /* offset=0 */ - pushw $0x0001 /* read 1 sector */ - pushw $0x0010 /* packet size */ - movw %ax, %ds /* DS=SS=0 */ - movw %sp, %si - movw $0x4200, %ax -#if 1 - int $0x13 -#else - call safe_int13 -#endif - popaw /* discard packet on the stack */ - popal - popw %es - popw %ds - jnc 2f - andb $0xFE, %bl /* no LBA */ - jmp 1f -2: - pushw %di - movw $0x600, %cx - movw $0x200, %di - cld - repz scasb - popw %di - jne 1f /* big 2048-byte sector */ - /* try again, fill the 2048-byte buffer with 00's */ - movw $0x2000, %cx /* GEOMTUNE_SEG */ - movw %cx, %ds - movw %cx, %es - movw $0x400, %cx /* 4 sectors */ - xorw %ax, %ax /* fill the buffer with 00's */ - pushw %di - movw $0x8000, %di - cld - rep stosw - popw %di - - pushw %ds - pushw %es - pushal - xorl %eax, %eax - pushl %eax /* sector hi */ - pushl %eax /* sector lo */ - pushw $0x2000 /* buffer segment = GEOMTUNE_SEG */ - pushw $0x8000 /* offset=0x8000 */ - pushw $0x0001 /* read 1 sector */ - pushw $0x0010 /* packet size */ - movw %ax, %ds /* DS=SS=0 */ - movw %sp, %si - movw $0x4200, %ax -#if 1 - int $0x13 -#else - call safe_int13 -#endif - popaw /* discard packet on the stack */ - popal - popw %es - popw %ds - jnc 2f - andb $0xFE, %bl /* no LBA */ - jmp 1f -2: - pushw %di - movw $0x600, %cx - movw $0x8200, %di - cld - repz scasb - popw %di - jne 1f /* big 2048-byte sector */ - - /* now it is 512-byte sector size */ - - testw %di, %di - jz 2f - testw $0x0080, %di /* lba127sector */ - jnz 2f - movb $1, %bh /* failure, cannot read 127 sectors */ - jmp 1f -2: -#if 0 - /* detailed check for all possibilities */ - movw $0x7F, %cx - xorw %di, %di - -lba_check_loop: - incw %di /* number of sectors to read */ - - pushal - pushw %di - pushw $ABS(LBA_read_sectors_message) - call realmode_printf - popw %ax - popw %di - popal -#else - movw $3, %cx /* try it for 3 times. */ - /* only check 127-sector accessibility */ - movw $127, %di /* number of sectors to read */ - -lba_try_again: - - pushal - xorb %dh, %dh - pushw %dx /* drive number */ - pushw $ABS(LBA_read_sectors_message) - call realmode_printf - popw %ax - popw %dx - popal -#endif - - pushw %ds - pushw %es - pushal - xorl %eax, %eax - pushl %eax /* sector hi */ - pushl %eax /* sector lo */ - pushw $0x2000 /* buffer segment = GEOMTUNE_SEG */ - pushw %ax /* offset=0 */ - pushw %di /* sectors to read */ - pushw $0x0010 /* packet size */ - movw %ax, %ds /* DS=SS=0 */ - movw %sp, %si - movw $0x4200, %ax -#if 1 - int $0x13 -#else - call safe_int13 -#endif - popaw /* discard packet on the stack */ - popal - popw %es - popw %ds -#if 0 - loop lba_check_loop - setc %bh /* failure, cannot read 127 sectors */ -#else - jnc 2f - loop lba_try_again -2: - setc %bh /* failure, cannot read 127 sectors */ - pushal - pushw $ABS(LBA_read_sectors_message_wipe) - call realmode_printf - popw %ax - popal -#endif -1: - /* back to protected mode */ - call EXT_C(real_to_prot) - .code32 - - sti - - xchgl %eax, %ebx /* return value in %eax */ - - popl %edi - popl %esi - popl %ebx - popl %ebp - - ret - -LBA_read_sectors_message: -#if 0 - .ascii "\r\nTry reading %d sectors ... \0" -#else - .ascii "\r\nIf hangup, use \'geometry --lba1sector (%d)\' at the beginning of preset menu. \0" -LBA_read_sectors_message_wipe: - .ascii "\r \r\0" -#endif - -/* - * int get_diskinfo_standard (unsigned long drive, unsigned long *cylinders, - * unsigned long *heads, unsigned long *sectors) - * - * if bit 8-15 of drive(dh) != 0 on call, then geometry_tune will be used. - * - * Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an - * error occurs, then return non-zero, otherwise zero. - */ - -ENTRY(get_diskinfo_standard) - - .code32 - - pushl %ebp - movl %esp, %ebp - - pushl %ebx - pushl %esi - pushl %edi - - /* Heads */ - movl 0x10(%ebp), %edi - movl (%edi), %edi - movl %edi, ABS(Heads_passed_in) - - /* Sectors */ - movl 0x14(%ebp), %edi - movl (%edi), %edi - movl %edi, ABS(Sectors_passed_in) - - /* drive */ - movl 0x8(%ebp), %edx - - /* enter real mode */ - call EXT_C(prot_to_real) - - .code16 - - sti - - testb %dh, %dh - jz 2f - - call geometry_tune - - movb $1, %bh /* geometry_tune indicator */ - jmp 1f -2: - xorw %cx, %cx - movb $0x8, %ah -#if 1 - int $0x13 -#else - call safe_int13 -#endif - movb $0, %bh /* geometry_tune indicator */ - jc 2f - - /* check if successful */ - testb %ah, %ah - jnz 1f /* Error number in AH */ - - /* bogus BIOSes may not return an error number */ - testb $0x3f, %cl /* 0 sectors means no disk */ - jnz 1f /* if non-zero, then succeed */ -2: - /* failure */ - /* XXX 0x60 is one of the unused error numbers */ - movb $0x60, %ah -1: - movb %ah, %bl /* save return value in %bl */ - /* back to protected mode */ - call EXT_C(real_to_prot) - - .code32 - - sti - - testb %bl, %bl /* check failure */ - jnz 1f /* failure */ - - /* restore %ebp */ - leal 12(%esp), %ebp - - /* heads */ - xorl %eax, %eax - movb %dh, %al - incl %eax /* number of heads is counted from zero */ - movl 0x10(%ebp), %edi - //movl %eax, (%edi) - stosl - - /* sectors */ - xorl %eax, %eax - movb %cl, %al - andb $0x3f, %al - movl 0x14(%ebp), %edi - //movl %eax, (%edi) - stosl - - /* cylinders */ - - testb %bh, %bh - jnz 1f /* geometry_tune won't touch cylinders */ - - xorl %eax, %eax - shrb $6, %cl - movb %cl, %ah - movb %ch, %al - incl %eax /* number of cylinders is counted from zero */ - movl 0x0C(%ebp), %edi - //movl %eax, (%edi) - stosl -1: - movzbl %bl, %eax /* return value in %eax */ - - popl %edi - popl %esi - popl %ebx - popl %ebp - - ret - -#if defined(USE_DEBUG_DUMP) - .code16 -debug_dump_regs_format: - .ascii "di%4X si%4X bp%4X sp%4X bx%4X dx%4X cx%4X ax%4X f%4X ip%4X ln%u\r\n\0" - /* debug_dump_regs_ln */ -debug_dump_regs: - pushfw - pushaw - pushw $ABS(debug_dump_regs_format) - call realmode_printf - popw %ax - popaw - popfw - ret $2 -debug_pause: - pushfw - pushw %ax - movb $0, %ah - int $0x16 - popw %ax - popfw - ret -#define DEBUG_DUMP pushw $__ ## LINE ## __ ; call debug_dump_regs -#define DEBUG_DUMP_P pushw $__ ## LINE ## __ ; call debug_dump_regs ; call debug_pause -#else -#define DEBUG_DUMP -#define DEBUG_DUMP_P -#endif - - -#define GEOMTUNE_SEG 0x2000 - /* geometry_tune uses 64KiB buffer at this segment */ -#define GEOMTUNE_BUFFERSEG BUFFERSEG - /* geometry_tune uses 31.5KiB buffer at this segment */ - - /* offset of variables in GEOM_TUNE_SEG */ -#define GEOMTUNE_Smax_tuned 0x0000 -#define GEOMTUNE_Hmax_tuned 0x0002 -#define GEOMTUNE_Smax_readable 0x0004 - /* upperbound of Smax, cannot read past this sector number */ -#define GEOMTUNE_Hmax_readable 0x0006 - /* upperbound of Hmax, cannot read past this head */ -#define GEOMTUNE_read_ax 0x0008 - /* byte0 = number of sectors to read */ - /* byte1 = 2 */ -#define GEOMTUNE_cmps_cx 0x000A - /* (tune Hmax) number of DWORD to compare */ -#define GEOMTUNE_next_read 0x000C - /* (tune Hmax) boolean : 1 = next cylinder head 0 is read successfully */ - /* (tune Smax) boolean : 1 = next track sector 1 is read successfully */ -#define GEOMTUNE_equal 0x0100 - /* (tune Hmax) - * [0] nonzero = There exist at least 1 track that have data equal to head 0. - * [1...254] - * bit0: 0=data from this head differ from data in head 0 same cylinder 1=no difference encountered - * bit1: 0=data from this head differ from data in head 0 next cylinder 1=no difference encountered - * [255] padding - * (tune Smax) - * [0] nonzero = There exist at least 1 sector that have data equal to sector 1. - * [1...62] - * bit0: 0=data from sector i+1 differ from data in sector 1 same track 1=no difference encountered - * bit1: 0=data from sector i+1 differ from data in sector 1 next track 1=no difference encountered - * [63] padding - */ -#define GEOMTUNE_H_buf_cch0 0x0200 - /* 0200 - 7FFF buffer current cylinder head0 (upto 63 sectors) */ -#define GEOMTUNE_H_buf_nch0 0x8000 - /* 8000 - FDFF buffer next cylinder head0 (upto 63 sectors) */ -#define GEOMTUNE_S_buf_ct 0x0200 - /* 0200 - 7FFF buffer current track */ -#define GEOMTUNE_S_buf_nt 0x8000 - /* 8000 - FDFF buffer next track */ - - /* offset of variables in BUFFERSEG */ -#define GEOMTUNE_H_buf_ct 0x0000 - /* 0000 - 7DFF buffer current track (upto 63 sectors) */ - - .code16 - -geometry_tune: - - /* on call: - * CS 0 - * - * on return: - * AH=0 success, otherwise failure - * CL max sector number - * DH max head number - * DS changed - * ES changed - * EAX changed - * BX changed - * CX changed - * DX changed - * SI changed - * DI changed - */ - - /* check for fb status */ - cmpb $0, %cs: ABS(EXT_C(fb_status)) - jz no_fb - cmpb %dl, %cs: ABS(EXT_C(fb_status)) + 1 - jnz no_fb - movb %cs: ABS(EXT_C(fb_status)) + 2, %cl - movb %cs: ABS(EXT_C(fb_status)) + 3, %dh - decb %dh - xorb %ah, %ah - ret -no_fb: -#ifdef USE_OLD_GEOMETRY_TUNE -////////////////////////////////////////////////////////////////////////////// - - /* find Max sector by reading each sector on the first track. */ - -#if 0 - pushal - pushw %ds - pushw %es - movw $0x0e41, %ax - xorw %bx, %bx - int $0x10 - popw %es - popw %ds - popal -#endif - - /* try the passed-in value first */ - movw %cs:ABS(Sectors_passed_in), %cx /* cylinder=0 */ - call check_sector_readable - jnc 1f - xorw %cx, %cx -1: - cmpw $63, %cx - jnb 2f /* this is the maximum value */ - - incw %cx - call check_sector_readable - jc 1f - cmpw $63, %cx - jb 1b - jmp 2f -1: - /* Max Sector = CX - 1 */ - decw %cx - cmpb $2, %cl - jnb 2f - movb $1, %ah /* failure */ - ret - -check_sector_readable: - movw $0x27E0, %ax /* Don't use SCRATCHSEG */ - movw %ax, %es - movw %ax, %ds - xorw %bx, %bx - movw $0x201, %ax /* read 1 sector */ - movb $0, %dh /* head=0 */ - pushaw - movw %bx, %si - movw %bx, %di -#if 1 - int $0x13 -#else - call safe_int13 -#endif - popaw - ret - -2: - cmpw $63, %cx - jbe 2f - movw $63, %cx -2: - /* CX=Max Sector */ - movw %cx, %cs:ABS(Smax_tuned) - -#if 0 - pushal - pushw %ds - pushw %es - movw $0x0e20, %ax - addb %cl, %al - xorw %bx, %bx - int $0x10 - popw %es - popw %ds - popal -#endif - -////////////////////////////////////////////////////////////////////////////// -#if 0 - /* check if we can read sectors across the track boundary */ - - /* first, read a track plus one sector */ - - movb $0, %cs:ABS(cross_track) - - movw $1, %cx /* sector 1, cylinder 0 */ - movb $0, %dh /* head 0 */ - movb %cs:ABS(Smax_tuned), %al /* sectors to read */ - incw %ax /* read 1 more sector */ - movb $2, %ah /* READ */ - movw $0x2000, %bx - movw %bx, %es - movw %bx, %ds - xorw %bx, %bx - pushaw - movw %bx, %si - movw %bx, %di -#if 1 - int $0x13 -#else - call safe_int13 -#endif - popaw - jc 1f /* cross-track read is not supported */ - - /* read again normally, only the track */ - - movb %cs:ABS(Smax_tuned), %al /* sectors to read */ - movb $2, %ah /* READ */ - movw $0x2800, %bx - movw %bx, %es - movw %bx, %ds - xorw %bx, %bx - pushaw - movw %bx, %si - movw %bx, %di -#if 1 - int $0x13 -#else - call safe_int13 -#endif - popaw - jc 2b /* failure */ - - /* compare the two tracks */ - - pushw %cx - pushw %si - pushw %di - movw %cs:ABS(Smax_tuned), %cx /* sectors */ - shlw $7, %cx /* dwords */ - movw $0x2000, %ax - movw %ax, %ds - movw $0x2800, %ax - movw %ax, %es - xorw %si, %si - xorw %di, %di - cld - repz cmpsl - popw %di - popw %si - popw %cx - jne 1f /* cross-track read is not supported */ - movb $1, %cs:ABS(cross_track) -1: -#endif -////////////////////////////////////////////////////////////////////////////// -#if 0 - /* find Max head by reading sector 1 on each track of cylinder 0. */ - - movb $0xFF, %dh /* head=Max possible */ -1: - movw $0x27E0, %ax /* Don't use SCRATCHSEG */ - movw %ax, %es - movw %ax, %ds - xorw %bx, %bx - movw $0x201, %ax /* read 1 sector */ - movw $1, %cx /* cylinder=0, sector=1 */ - pushaw - movw %bx, %si - movw %bx, %di -#if 1 - int $0x13 -#else - call safe_int13 -#endif - popaw - jnc 1f /* found Max head */ - decb %dh - cmpb $0xFF, %dh - jne 1b - movb $1, %ah /* failure */ - ret -1: - - /* DH=Max head */ - movb %dh, %cs:ABS(Hmax_tuned) -#endif -////////////////////////////////////////////////////////////////////////////// - - /* tune Hmax */ - - /* First, try the passed-in value */ - movb %cs:ABS(Heads_passed_in), %dh - testb %dh, %dh - jz 1f /* the passed-in heads = 0x100 */ - - call tune_heads - jb 2f /* failure */ - ja 4f /* success */ -1: - movb $1, %dh /* Hmax: 1 - 255 */ -1: - call tune_heads - jb 2f /* failure */ - ja 4f /* success */ - -#if 0 - cmpb %cs:ABS(Hmax_tuned), %dh - ja 2f /* this should not happen */ - je 5f -#endif - - incb %dh /* Next Hmax */ - jnz 1b - - /* Hmax=0xFF */ -4: - /* got Hmax=DH-1 */ - - decb %dh - movb %dh, %cs:ABS(Hmax_tuned) -5: - /* Hmax is tuned ok. */ - - cmpb $0xFF, %dh - jne 1f - /* consider Hmax=0xFF as a failure! Use the passed-in value. */ - movb %cs:ABS(Heads_passed_in), %dh - testb %dh, %dh - jnz 4f - decb %dh -4: - decb %dh - movb %dh, %cs:ABS(Hmax_tuned) -1: - -#if 0 - pushal - pushw %ds - pushw %es - movw $0x0e21, %ax - xorw %bx, %bx - int $0x10 - popw %es - popw %ds - popal -#endif - -////////////////////////////////////////////////////////////////////////////// - - /* tune Smax */ - - /* First, try the passed-in value */ - movb %cs:ABS(Sectors_passed_in), %cl -// cmpb $0, %cs:ABS(cross_track) -// jnz 4f -// cmpb %cs:ABS(Smax_tuned), %cl -// jnb 1f -// cmpb $8, %cl -// jb 1f -4: - call tune_sectors - jb 2f /* failure */ - ja 4f /* success */ -1: - movb $8, %cl /* Smax: 8 - 63 */ -1: - call tune_sectors - jb 2f /* failure */ - ja 4f /* success */ - - incw %cx /* Next Smax */ - cmpb %cs:ABS(Smax_tuned), %cl - jb 1b - cmpb $63, %cl - jbe 4f - movb $63, %cl - -4: - /* got Smax=CL */ - - movb %cl, %cs:ABS(Smax_tuned) - - /* Smax is tuned ok. */ - -#if 0 - pushal - pushw %ds - pushw %es - movw $0x0e21, %ax - xorw %bx, %bx - int $0x10 - popw %es - popw %ds - popal -#endif - -////////////////////////////////////////////////////////////////////////////// - - movw %cs:ABS(Smax_tuned), %cx - movb %cs:ABS(Hmax_tuned), %dh - movb $0, %ah /* success */ - ret -2: - movb $1, %ah /* failure */ - ret - -////////////////////////////////////////////////////////////////////////////// - -tune_heads: - - /* input: DH = MaxHead + 1 */ - - movb $0, %ch /* cylinder: 0 - 4 */ -2: - /* read ending track of this cylinder */ - -#if 0 - pushal - pushw %ds - pushw %es - movw $0x0e22, %ax - xorw %bx, %bx - int $0x10 - popw %es - popw %ds - popal -#endif - - movb $1, %cl /* sector 1=the leading sector */ - movb $2, %ah /* READ */ - movb %cs:ABS(Smax_tuned), %al /* sectors to read */ - movw $0x2000, %bx - movw %bx, %es - movw %bx, %ds - xorw %bx, %bx - pushaw - movw %bx, %si - movw %bx, %di -#if 1 - int $0x13 -#else - call safe_int13 -#endif - popaw - //jc 2f /* failure */ - incb %ch - jc 4f /* considered OK */ - decb %ch - - /* read beginning track of this cylinder */ - - movb $1, %cl /* sector 1=the leading sector */ - movb $2, %ah /* READ */ - movb %cs:ABS(Smax_tuned), %al /* sectors to read */ - movw $0x2800, %bx - movw %bx, %es - movw %bx, %ds - xorw %bx, %bx - pushaw - movw %bx, %si - movw %bx, %di - movb $0, %dh -#if 1 - int $0x13 -#else - call safe_int13 -#endif - popaw - jc 2f /* failure */ - - incb %ch /* next cylinder */ - - /* compare the two tracks */ - call cmp_track - je 4f /* ok, try next cylinder */ - - /* read beginning track of the next cylinder */ - - movb $1, %cl /* sector 1=the leading sector */ - movb $2, %ah /* READ */ - movb %cs:ABS(Smax_tuned), %al /* sectors to read */ - movw $0x2800, %bx - movw %bx, %es - movw %bx, %ds - xorw %bx, %bx - pushaw - movw %bx, %si - movw %bx, %di - movb $0, %dh -#if 1 - int $0x13 -#else - call safe_int13 -#endif - popaw - jc 2f /* failure */ - - /* compare the two tracks */ - call cmp_track - jne 3f /* Next Hmax */ -4: - cmpb $5, %ch /* cylinder: 0 - 4 */ - jb 2b /* Next cylinder */ - - /* all passed, DH-1 is the final Hmax */ - cmpb $0, %dh - je 2f /* failure */ - ret /* Flag: above */ -3: - cmpb %dh, %dh /* Flag: equal */ - ret -2: - stc /* Flag: below */ - ret - -cmp_track: - pushw %cx - pushw %si - pushw %di - movw %cs:ABS(Smax_tuned), %cx /* sectors */ - shlw $7, %cx /* dwords */ - movw $0x2000, %ax - movw %ax, %ds - movw $0x2800, %ax - movw %ax, %es - xorw %si, %si - xorw %di, %di - cld - repz cmpsl - popw %di - popw %si - popw %cx - ret - -////////////////////////////////////////////////////////////////////////////// - -tune_sectors: - - /* input: CL = MaxSector */ - - movw $16, %cs:ABS(Smax_count) - - movb $0, %ch /* cylinder: 0 - 6 */ - movb $0, %dh /* head: 0 - Hmax */ -6: - /* read beginning sector of this track. */ - - movw $0x201, %ax /* read 1 sector */ - movw $0x2800, %bx - movw %bx, %es - movw %bx, %ds - xorw %bx, %bx - pushaw - movw %bx, %si - movw %bx, %di - movb $1, %cl /* beginning sector */ -#if 1 - int $0x13 -#else - call safe_int13 -#endif - popaw - jc 2f /* failure */ - - /* read ending sector of this track. */ - - movw $0x202, %ax /* read 2 sectors */ - movw $0x2000, %bx - movw %bx, %es - movw %bx, %ds - xorw %bx, %bx - pushaw - movw %bx, %si - movw %bx, %di -#if 1 - int $0x13 -#else - call safe_int13 -#endif - popaw - //jc 2f /* failure */ - - /* locate the next track. */ - - pushfw /* save CF */ - cmpb %cs:ABS(Hmax_tuned), %dh - jb 3f /* Next track */ - movb $0xFF, %dh /* head 0 of ... */ - incb %ch /* ... the next cylinder. */ -3: - incb %dh /* next track */ - popfw /* restore CF */ - jc 4f /* considered OK */ - - /* compare the 2 sectors */ - call cmp_sector - je 4f /* ok, try next track */ - - /* read beginning sector of the next track. */ - - movw $0x201, %ax /* read 1 sector */ - movw $0x2800, %bx - movw %bx, %es - movw %bx, %ds - xorw %bx, %bx - pushaw - movw %bx, %si - movw %bx, %di - movb $1, %cl /* sector 1=the leading sector */ -#if 1 - int $0x13 -#else - call safe_int13 -#endif - popaw - jc 2f /* failure */ - - /* compare the 2 sectors */ - call cmp_sector - jne 3f /* Next Smax */ -4: - decw %cs:ABS(Smax_count) - jz 6f - - //cmpb %cs:ABS(Hmax_tuned), %dh - //jb 6b /* Next track */ - //movb $0, %dh /* head 0 of ... */ - //incb %ch /* ... the next cylinder. */ - cmpb $7, %ch /* any cylinder remains to check? */ - jb 6b /* yes, next track */ -6: - /* all passed, CL is the final Smax */ - cmpb $1, %cl - jbe 2f /* failure */ - ret /* Flag: above */ -3: - /* not Maximum sector number */ - cmpb %cl, %cl /* Flag: equal */ - ret -2: - /* I/O error, sector tune failed */ - stc /* Flag: below */ - ret - -cmp_sector: - pushw %cx - pushw %si - pushw %di - movw $0x80, %cx /* 1 sector == 0x80 dwords */ - movw $0x2020, %ax - movw %ax, %ds - movw $0x2800, %ax - movw %ax, %es - xorw %si, %si - xorw %di, %di - cld - repz cmpsl - popw %di - popw %si - popw %cx - ret - -#else /* ndef USE_OLD_GEOMETRY_TUNE */ - - ////////////////////////////////////////////////////////////////////////////// - /* find Max sector by reading each sector on the first track. */ - - movw $GEOMTUNE_SEG, %ax /* Don't use SCRATCHSEG */ - movw %ax, %es - movw %ax, %ds - - /* try the passed-in value first */ - movw %cs:ABS(Sectors_passed_in), %cx /* cylinder=0 */ - xorw %ax, %ax - cmpw $63, %cx - ja 1f - call check_sector_readable - sbbw %ax, %ax - notw %ax -1: - andw %ax, %cx /* if read failure, cx=0 */ -1: - cmpb $63, %cl - jnb 2f /* this is the maximum value */ - incw %cx - call check_sector_readable - jnc 1b - - /* Max Sector = CX - 1 */ - decw %cx - cmpb $2, %cl - jnb 2f /* CX=Max Sector */ - movb $1, %ah /* failure */ - ret - -check_sector_readable: - xorw %bx, %bx - movw $0x201, %ax /* read 1 sector */ - movb $0, %dh /* head=0 */ - pushaw - //movw %bx, %si - //movw %bx, %di - int $0x13 - jc 1f - decb %al - addb $255, %al /* set CF if returned AL != 1 */ -1: - popaw - ret -2: - /* CX=Max Sector */ - movw %cx, GEOMTUNE_Smax_readable - - ////////////////////////////////////////////////////////////////////////////// - /* tune Hmax */ - - /* invalidate disk cache */ - movl $(-1),%cs:ABS(EXT_C(buf_track)) - - movw $GEOMTUNE_SEG, %bx - movw %bx, %ds - movw %bx, %es - movw $254, GEOMTUNE_Hmax_readable - - movb $2, %ch - movw %cx, GEOMTUNE_read_ax /* number of readable sectors per track */ - shlw $7, %cx /* x128 DWORDs per sector */ - movw %cx, GEOMTUNE_cmps_cx /* number of DWORDs to compare */ - /* fill array */ - cld - movw $GEOMTUNE_equal, %di - movl $0x03030303, %eax - movw $0x40, %cx /* 0x100/4 = 0x40 */ - rep stosl - - /* cx is now 0 */ /* start with cylinder 0*/ - -10: /* cylinder loop */ - movb $1, %cl /* sector 1 */ - xorb %dh, %dh /* head 0 */ - movw GEOMTUNE_read_ax, %ax - movw %ds, %bx - movw %bx, %es /* GEOMTUNE_SEG */ - - /* read next cylinder, head 0 */ - pushaw - incb %ch /* next cylinder */ - movw $GEOMTUNE_H_buf_nch0, %bx - int $0x13 - setnc %ah - cmpb GEOMTUNE_read_ax, %al - sete %al - andb %ah, %al /* 1=no error and read all required sectors */ - movb %al, GEOMTUNE_next_read /* save boolean value for later use */ - popaw - - /* read current cylinder, head 0 */ - pushaw - movw $GEOMTUNE_H_buf_cch0, %bx - int $0x13 - setnc %ah - cmpb GEOMTUNE_read_ax, %al - sete %al - andb %ah, %al /* 1=no error and read all required sectors */ - popaw - jz 14f /* error, end cylinder loop */ - - /* read current cylinder, head 1-254 */ - movw $GEOMTUNE_BUFFERSEG, %bx - movw %bx, %es - /* DH is now 0 */ - movb %dh, GEOMTUNE_equal /* GEOMTUNE_equal[0] = 0 */ - -11: /* head loop */ - addb $1, %dh - cmp GEOMTUNE_Hmax_readable, %dh - ja 13f /* end head loop */ - - movb $(GEOMTUNE_equal >> 8), %bh - movb %dh, %bl - /* DS:BX = address of GEOMTUNE_equal[DH] */ - movb (%bx), %al - testb %al, %al /* 0=this head has already returned different data from head 0, no need to compare again */ - jz 11b /* head loop */ - - pushaw - xorw %bx, %bx /* offset GEOMTUNE_H_buf_ct is 0 */ - movw GEOMTUNE_read_ax, %ax - int $0x13 - setnc %ah - cmpb GEOMTUNE_read_ax, %al - sete %al - andb %ah, %al /* no error and read all required sectors */ - popaw - jz 12f /* read error head 1-254 */ - - pushaw - testb $1, %al - jz 1f - /* compare with same cylinder head 0 */ - movw GEOMTUNE_cmps_cx, %cx - movw $GEOMTUNE_H_buf_cch0, %si - xorw %di, %di /* offset GEOMTUNE_H_buf_ct is 0 */ /* ES is BUF_SEG */ - repe cmpsl - je 1f - /* different data */ - andb $(0xFF-1), %al -1: - testb $2, %al - jz 1f - /* compare with next cylinder head 0 */ - testb $1, GEOMTUNE_next_read /* skip if next cylinder head 0 has not been read successfully */ - jz 1f - movw GEOMTUNE_cmps_cx, %cx - movw $GEOMTUNE_H_buf_nch0, %si - xorw %di, %di /* offset GEOMTUNE_H_buf_ct is 0 */ /* ES is BUF_SEG */ - repe cmpsl - je 1f - /* different data */ - andb $(0xFF-2), %al -1: - movb %al, (%bx) - orb %al, GEOMTUNE_equal /* GEOMTUNE_equal[0] */ - popaw - - /* continue, next head */ - jmp 11b /* head loop */ - -12: /* read error head 1-254 */ - test %ch, %ch /* Is this cylinder 0 ? */ - /* If error on cylinder >0, end. */ - jnz 14f /* end cylinder loop */ - decb %dh /* Error on cylinder 0 = end of cylinder. Adjust readable head number */ - movb %dh, GEOMTUNE_Hmax_readable - -13: /* end head loop */ - movb GEOMTUNE_equal, %al - test %al, %al /* 0: all readable heads(>0) differ from head0 */ - jz 14f /* end cylinder loop */ - - /* next cylinder */ - incb %ch - cmpb $5, %ch /* max number of cylinders to read */ - jb 10b /* cylinder loop */ - -14: /* end cylinder loop */ - movw %ds, %bx - movw %bx, %es /* GEOMTUNE_SEG */ - movw %cx, %bx - movw $(GEOMTUNE_equal +1), %di - movw GEOMTUNE_Hmax_readable, %cx - incw %cx - xorw %ax, %ax - repz scasb /* skip heads that have different data from head0 */ - DEBUG_DUMP - subw $(GEOMTUNE_equal +2), %di - movw %di, GEOMTUNE_Hmax_tuned - - ////////////////////////////////////////////////////////////////////////////// - /* tune Smax */ - - /* DS = ES = GEOMTUNE_SEG */ - - movw $GEOMTUNE_equal, %di - movl $0x03030303, %eax - movw $(64/4), %cx - rep stosl - - /* read first track */ - movw $1, %cx /* cyl 0 sector 1 */ - xorb %dh, %dh /* head 0 */ - movw GEOMTUNE_read_ax, %ax - movw $GEOMTUNE_S_buf_ct, %bx - pushaw - int $0x13 - popaw - jc 2f - /* save data in disk cache */ - movw %bx, %si - xorw %di, %di - movw $GEOMTUNE_BUFFERSEG, %bx - movw %bx, %es - movw $(63*512/4), %cx - rep movsl - movw %ds, %bx - movw %bx, %es -#if 0 - /* update buf_track variable */ - movl $0, %cs:ABS(EXT_C(buf_track)) - movl $0, %cs:ABS(EXT_C(buf_track)) + 4 -#else - /* Invalidate the buffer, because the buffer is not exactly 1 track. */ - /* The buffer size is now 64K. */ - movl $-1, %cs:ABS(EXT_C(buf_track)) - /* need not set the higher 32 bits of buf_track. */ -#endif - movw $1, %cx /* cyl 0 sector 1 */ - -20: /* track loop */ - /* compare sector 1 with sectors 2-63 */ - /* AL = number of sectors read */ - - pushw %cx - pushw %dx - xorb %ah, %ah - movw $GEOMTUNE_equal, %bx - movw $GEOMTUNE_S_buf_ct, %dx -21: /* sector loop */ - incw %bx - cmpb %al, %bl - jae 22f /* end sector loop */ - addw $512, %dx - movw %dx, %di - movw $GEOMTUNE_S_buf_ct, %si - movw $(512/4), %cx - repe cmpsl - setne %cl /* eq:0 dif:1 */ - notb %cl /* eq:255 dif:255-1 */ - andb %cl, (%bx) /* clear bit0 if dif */ - setnz %cl /* dif:0 eq:1 */ - orb %cl, %ah /* AH=1 if there is some sector that has equal data to sector 1 */ - jmp 21b /* sector loop */ -22: /* end sector loop */ - popw %dx - popw %cx - - testb $0xFF, %ah /* AH=1 if there is sector that has equal data to sector 1 */ - jz 25f /* end track loop */ /* no more equal sector */ - /* next track */ - incb %dh - cmpb GEOMTUNE_Hmax_tuned, %dh - jna 1f - /* next cylinder */ - xorb %dh, %dh - incb %ch - cmpb $7, %ch /* max cylinder number to read and compare */ - ja 25f /* end track loop */ -1: /* read new track */ - movw GEOMTUNE_read_ax, %ax - movw $GEOMTUNE_S_buf_nt, %bx - pushaw - int $0x13 - popaw - jc 2f - /* compare sector 1 with sectors 2-63 from previous track */ - /* AL = number of sectors read */ - pushaw - movw $GEOMTUNE_equal, %bx - movw $GEOMTUNE_S_buf_ct, %dx -23: /* sector loop */ - incw %bx - cmpb %al, %bl - jae 24f /* end sector loop */ - addw $512, %dx - movw %dx, %di - movw $GEOMTUNE_S_buf_nt, %si - movw $(512/4), %cx - repe cmpsl - setne %cl /* eq=>0 dif=>1 */ - addb %cl, %cl /* eq=>0 dif=>2 */ - notb %cl /* eq=>255 dif=>255-2 */ - andb %cl, (%bx) /* clear bit1 if dif */ - jmp 23b /* sector loop */ -24: /* end sector loop */ - /* copy next track buffer to current track buffer */ - movw $GEOMTUNE_S_buf_nt, %si - movw $GEOMTUNE_S_buf_ct, %di - movw $(63*512/4), %cx - rep movsl - popaw - jmp 20b /* track loop */ -25: /* end track loop */ - movw $(GEOMTUNE_equal +1), %di - movw GEOMTUNE_Smax_readable, %cx - xorw %ax, %ax /* AL = 0 */ - repe scasb /* skip 0 */ - DEBUG_DUMP - subw $(GEOMTUNE_equal +1), %di - movw %di, GEOMTUNE_Smax_tuned - - movw %di, %cx - movb GEOMTUNE_Hmax_tuned, %dh - movb $0, %ah /* success */ - ret -2: - movb $1, %ah /* failure */ - ret -#endif /* ndef USE_OLD_GEOMETRY_TUNE */ - -////////////////////////////////////////////////////////////////////////////// - - .align 4 - -Sectors_passed_in: - .long 0 -Heads_passed_in: - .long 0 -#ifdef USE_OLD_GEOMETRY_TUNE -Smax_tuned: - .word 0 -Hmax_tuned: - .word 0 -Smax_count: - .word 0 -cross_track: - .byte 0 -#endif - -////////////////////////////////////////////////////////////////////////////// - - -/* - * - * get_memsize(i) : return the memory size in KB. i == 0 for conventional - * memory, i == 1 for extended memory - * BIOS call "INT 12H" to get conventional memory size - * BIOS call "INT 15H, AH=88H" to get extended memory size - * Both have the return value in AX. - * - */ - -ENTRY(get_memsize) - - .code32 - - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - - movl 0x14(%esp), %ebx - - call EXT_C(prot_to_real) /* enter real mode */ - - .code16 - - sti /* for hardware interrupt or watchdog */ - - cmpb $0x1, %bl - je 1f - - int $0x12 - jmp 2f - -1: - movb $0x88, %ah - pushfw - lcall *ABS(EXT_C(ROM_int15)) -2: - movw %ax, %bx - - call EXT_C(real_to_prot) - .code32 - - sti - - movw %bx, %ax - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - -/* - * - * get_eisamemsize() : return packed EISA memory map, lower 16 bits is - * memory between 1M and 16M in 1K parts, upper 16 bits is - * memory above 16M in 64K parts. If error, return -1. - * BIOS call "INT 15H, AH=E801H" to get EISA memory map, - * AX = memory between 1M and 16M in 1K parts. - * BX = memory above 16M in 64K parts. - * - */ - -ENTRY(get_eisamemsize) - - .code32 - - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - - call EXT_C(prot_to_real) /* enter real mode */ - - .code16 - - //sti /* it is not bad keeping interrupt off */ - sti /* for hardware interrupt or watchdog */ - - movl $0xe801, %eax - //int $0x15 -2: - pushl %eax - pushfw - lcall *ABS(EXT_C(ROM_int15)) - jc 1f - testb $0x80, %ah - jnz 1f - - shll $16, %ebx - movw %ax, %bx - testl %ebx, %ebx - jnz 3f - movw %cx, %ax - movw %dx, %bx - shll $16, %ebx - movw %ax, %bx -3: - popl %eax - jmp 2f -1: - popl %eax - cmpw $0xE881, %ax - movw $0xE881, %ax - jne 2b - //movl $0xFFFFFFFF, %ebx - /* call the old function 88h */ - movw $0x8800, %ax - pushfw - lcall *ABS(EXT_C(ROM_int15)) - movzwl %ax, %ebx -2: - xorw %ax, %ax - movw %ax, %ds - movw %ax, %es - - call EXT_C(real_to_prot) - .code32 - - sti - - movl %ebx, %eax - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - -/* - * - * get_mmap_entry(addr, cont) : address and old continuation value (zero to - * start), for the Query System Address Map BIOS call. - * - * Sets the first 4-byte int value of "addr" to the size returned by - * the call. If the call fails, sets it to zero. - * - * Returns: new (non-zero) continuation value, 0 if done. - * - * NOTE: Currently hard-coded for a maximum buffer length of 1024. - * Note: addr must be addressible by BIOS in the low memory. -Tinybit - */ - -ENTRY(get_mmap_entry) - - .code32 - - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - - /* place address (+4) in ES:DI */ - movl 0x14(%esp), %eax /* addr */ - addl $4, %eax - movl %eax, %edi - andl $0xf, %edi /* offset */ - shrl $4, %eax /* segment */ - movl %eax, %esi - - /* set continuation value */ - movl 0x18(%esp), %ebx /* cont */ - - pushl %ecx /* save ECX */ - - /* set default maximum buffer size */ - movl $0x14, %ecx - - /* set EDX to 'SMAP' */ - movl $0x534d4150, %edx - - call EXT_C(prot_to_real) /* enter real mode */ - - .code16 - - //sti /* it is not bad keeping interrupt off */ - sti /* for hardware interrupt or watchdog */ - - movw %si, %es /* ES=segment */ - - /* set additional registers to serve buggy BIOSes. */ - movw %si, %ds - movw %di, %si - - movl $0xe820, %eax - int $0x15 -// pushfw -// lcall %cs:*ABS(EXT_C(ROM_int15)) - - jnc 1f - movl $0, %ebx /* set end indicator */ -1: - cmpl $0x534d4150, %eax - jne 1f - - /* 20-byte length is currently standard. So others are considered - * invalid. - */ - - cmpl $0x14, %ecx - je 2f - -1: - movl $0, %ecx -2: - - xorw %ax, %ax - movw %ax, %ds - movw %ax, %es - - call EXT_C(real_to_prot) - .code32 - - sti - - popl %eax /* OLD ECX */ - - /* write length of buffer (zero if error) into "addr" */ - movl 0x14(%esp), %edi - xchgl %eax, %ecx - stosl - - /* set return value to continuation */ - movl %ebx, %eax - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - -/* - * get_rom_config_table() - * - * Get the linear address of a ROM configuration table. Return zero, - * if fails. - */ - -ENTRY(get_rom_config_table) - - .code32 - - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - - /* zero %ebx for simplicity */ - xorl %ebx, %ebx - - call EXT_C(prot_to_real) - - .code16 - - sti /* for hardware interrupt or watchdog */ - - movb $0xc0, %ah - int $0x15 - - jc no_rom_table - testb %ah, %ah - jnz no_rom_table - - movw %es, %dx - jmp found_rom_table - -no_rom_table: - xorw %dx, %dx - xorw %bx, %bx - -found_rom_table: - - xorw %ax, %ax - movw %ax, %ds - movw %ax, %es - - call EXT_C(real_to_prot) - .code32 - - sti - - /* compute the linear address */ - xorl %eax, %eax - movw %dx, %ax - shll $4, %eax - addl %ebx, %eax - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - -/* - * int get_vbe_controller_info (struct vbe_controller *controller_ptr) - * - * Get VBE controller information. - */ - -ENTRY(get_vbe_controller_info) - - .code32 - - pushl %ebp - movl %esp, %ebp - - pushl %ebx - pushl %esi - pushl %edi - - /* Convert the linear address to segment:offset */ - movl 8(%ebp), %eax - movl %eax, %edi - andl $0x0000000f, %edi - shrl $4, %eax - movl %eax, %ebx - - call EXT_C(prot_to_real) - - .code16 - - sti /* for hardware interrupt or watchdog */ - - movw %bx, %es - - /* set additional registers to serve buggy BIOSes. */ - movw %bx, %ds - movw %di, %si - - movw $0x4F00, %ax - int $0x10 - - movw %ax, %bx - - xorw %ax, %ax - movw %ax, %ds - movw %ax, %es - - call EXT_C(real_to_prot) - .code32 - - sti - - movzwl %bx, %eax - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - -/* - * int get_vbe_mode_info (int mode_number, struct vbe_mode *mode_ptr) - * - * Get VBE mode information. - */ - -ENTRY(get_vbe_mode_info) - - .code32 - - pushl %ebp - movl %esp, %ebp - - pushl %ebx - pushl %esi - pushl %edi - - /* Convert the linear address to segment:offset */ - movl 0xc(%ebp), %eax - movl %eax, %edi - andl $0x0000000f, %edi - shrl $4, %eax - movl %eax, %ebx - - /* Save the mode number in %cx */ - movl 0x8(%ebp), %ecx - - call EXT_C(prot_to_real) - - .code16 - - sti /* for hardware interrupt or watchdog */ - - movw %bx, %es - movw $0x4F01, %ax - int $0x10 - - movw %ax, %bx - call EXT_C(real_to_prot) - .code32 - - sti - - movzwl %bx, %eax - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - -/* - * int set_vbe_mode (int mode_number) - * - * Set VBE mode. Don't support user-specified CRTC information. - */ - -ENTRY(set_vbe_mode) - - .code32 - - pushl %ebp - movl %esp, %ebp - - pushl %ebx - pushl %esi - pushl %edi - - /* Save the mode number in %bx */ - movl 0x8(%ebp), %ebx - /* Clear bit D11 */ - andl $0xF7FF, %ebx - - call EXT_C(prot_to_real) - - .code16 - - //sti /* it is not bad keeping interrupt off */ - sti /* for hardware interrupt or watchdog */ - - movw $0x4F02, %ax - int $0x10 - - movw %ax, %bx - call EXT_C(real_to_prot) - .code32 - - sti - - movzwl %bx, %eax - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - -#ifdef SUPPORT_GFX - -/* - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * - * graphical menu functions - * - */ - -/* - * int gfx_init_v1 (gfx_data_v1_t *gfx_data) - * - * init gfx things - * - * return vales: - * 0: ok - * 1: failed - * sets gfx_data->ok - */ - -ENTRY(gfx_init_v1) - - .code32 - - pushl %ebp - movl %esp, %ebp - - pushl %ebx - pushl %esi - pushl %edi - - movl 8(%ebp),%edx - movl %edx,%edi - andl $0xf,%edi - shrl $4,%edx - - pushl %ebp - - call EXT_C(prot_to_real) - .code16 - - pushw %ds - - movw %dx,%ds - leal gfx_ofs_v1_sys_cfg(%di),%esi - movl gfx_ofs_v1_mem_file(%di),%eax - movl gfx_ofs_v1_mem_cur(%di),%ebx - movl gfx_ofs_v1_mem_max(%di),%ecx - movw %ds,%dx - - /* basically just a lcall, but we need %edi */ - pushw %cs - pushw $gfx_init_50_v1 - pushl gfx_ofs_v1_jmp_table + 4 * 0 (%di) - - movl gfx_ofs_v1_mem_align(%di),%edi - - lret - -gfx_init_50_v1: - movl $0,%ebx - adcl $0,%ebx - - popw %ds - - call EXT_C(real_to_prot) - .code32 - - sti - - popl %ebp - - movl %ebx,%eax - negl %ebx - incl %ebx - movl 8(%ebp),%edx - movl %ebx,gfx_ofs_v1_ok(%edx) - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - -/* - * int gfx_done_v1 (gfx_data_v1_t *gfx_data) - * - * shut down gfx things - * - * return vales: - * always 0 - * sets gfx_data->ok - */ - -ENTRY(gfx_done_v1) - - .code32 - - pushl %ebp - movl %esp, %ebp - - pushl %ebx - pushl %esi - pushl %edi - - movl 8(%ebp),%edx - movl %edx,%ebx - andl $0xf,%ebx - shrl $4,%edx - - pushl %ebp - - call EXT_C(prot_to_real) - .code16 - - pushw %ds - - movw %dx,%ds - - lcall *gfx_ofs_v1_jmp_table + 4 * 1 (%bx) - - popw %ds - - call EXT_C(real_to_prot) - .code32 - - sti - - popl %ebp - - xorl %eax,%eax - movl 8(%ebp),%edx - movl %eax,gfx_ofs_v1_ok(%edx) - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - -/* - * int gfx_input_v1 (gfx_data_v1_t *gfx_data, int *menu_entry) - * - * let user enter a command line - * - * uses gfx_data->cmdline as buffer - * - * return values: - * 1: abort - * 2: boot - * menu_entry: selected entry - */ - -ENTRY(gfx_input_v1) - - .code32 - - pushl %ebp - movl %esp, %ebp - - pushl %esi - pushl %ebx - pushl %edi - - movl 8(%ebp),%edx - movl %edx,%ebx - andl $0xf,%ebx - shrl $4,%edx - - pushl %ebp - - call EXT_C(prot_to_real) - .code16 - - pushw %ds - - movw %dx,%ds - shll $4,%edx - movl gfx_ofs_v1_cmdline(%bx),%edi - subl %edx,%edi - movw gfx_ofs_v1_cmdline_len(%bx),%cx - movw gfx_ofs_v1_timeout(%bx),%ax - imulw $18,%ax - - pushl %ebp - lcall *gfx_ofs_v1_jmp_table + 4 * 2 (%bx) - popl %ebp - movl %eax,%ecx - - popw %ds - - call EXT_C(real_to_prot) - .code32 - - sti - - popl %ebp - - movl 12(%ebp),%edx - movl %ebx,(%edx) - - movl %ecx,%eax - - popl %edi - popl %ebx - popl %esi - popl %ebp - ret - - -/* - * int gfx_setup_menu_v1 (gfx_data_v1_t *gfx_data) - * - * draw boot menu - * - * return values: - * always 0 - */ - -/* menu entry descriptor */ -#define menu_v1_entries 0 -#define menu_v1_default 2 /* seg:ofs */ -#define menu_v1_ent_list 6 /* seg:ofs */ -#define menu_v1_ent_size 10 -#define menu_v1_arg_list 12 /* seg:ofs */ -#define menu_v1_arg_size 16 -#define sizeof_menu_v1_desc 18 - -ENTRY(gfx_setup_menu_v1) - - .code32 - - pushl %ebp - movl %esp, %ebp - - pushl %ebx - pushl %esi - pushl %edi - - movl 8(%ebp),%edx - movl %edx,%ebx - andl $0xf,%ebx - shrl $4,%edx - - call EXT_C(prot_to_real) - .code16 - - pushw %ds - - movw %dx,%ds - shll $4,%edx - - subw $sizeof_menu_v1_desc,%sp - movw %sp,%bp - - movl gfx_ofs_v1_menu_entries(%bx),%eax - movw %ax,menu_v1_entries(%bp) - - movl gfx_ofs_v1_menu_default_entry(%bx),%eax - subl %edx,%eax - movw %ax,menu_v1_default(%bp) - movw %ds,menu_v1_default+2(%bp) - - movl gfx_ofs_v1_menu_list(%bx),%eax - subl %edx,%eax - movw %ax,menu_v1_ent_list(%bp) - movw %ds,menu_v1_ent_list+2(%bp) - - movl gfx_ofs_v1_menu_entry_len(%bx),%eax - movw %ax,menu_v1_ent_size(%bp) - - movl gfx_ofs_v1_args_list(%bx),%eax - subl %edx,%eax - movw %ax,menu_v1_arg_list(%bp) - movw %ds,menu_v1_arg_list+2(%bp) - - movl gfx_ofs_v1_args_entry_len(%bx),%eax - movw %ax,menu_v1_arg_size(%bp) - - movw %bp,%si - pushw %ss - popw %es - - lcall %ds: *gfx_ofs_v1_jmp_table + 4 * 3 (%bx) - - addw $sizeof_menu_v1_desc,%sp - - popw %ds - - call EXT_C(real_to_prot) - .code32 - - sti - - xorl %eax,%eax - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - -/* - * int gfx_init_v2 (gfx_data_v2_t *gfx_data) - * - * init gfx things - * - * return vales: - * 0: ok - * 1: failed - * sets gfx_data->ok - */ - -ENTRY(gfx_init_v2) - - .code32 - - pushl %ebp - movl %esp, %ebp - - pushl %ebx - pushl %esi - pushl %edi - - movl 8(%ebp),%edx - movl %edx,%edi - leal gfx_ofs_v2_sys_cfg(%edx),%esi - andl $0xf,%edi - shrl $4,%edx - - pushl %ebp - - call EXT_C(prot_to_real) - .code16 - - pushw %ds - movw %dx,%ds - - lcall *gfx_ofs_v2_jmp_table + 4 * 0 (%di) - - sbbl %ebx,%ebx - negl %ebx - - popw %ds - - call EXT_C(real_to_prot) - .code32 - - sti - - popl %ebp - - movl %ebx,%eax - xorl $1,%ebx - movl 8(%ebp),%edx - movl %ebx,gfx_ofs_v2_ok(%edx) - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - -/* - * int gfx_done_v2 (gfx_data_v2_t *gfx_data) - * - * shut down gfx things - * - * return vales: - * always 0 - * sets gfx_data->ok - */ - -ENTRY(gfx_done_v2) - - .code32 - - pushl %ebp - movl %esp, %ebp - - pushl %ebx - pushl %esi - pushl %edi - - movl 8(%ebp),%edx - movl %edx,%ebx - andl $0xf,%ebx - shrl $4,%edx - - pushl %ebp - - call EXT_C(prot_to_real) - .code16 - - pushw %ds - - movw %dx,%ds - - lcall *gfx_ofs_v2_jmp_table + 4 * 1 (%bx) - - popw %ds - - call EXT_C(real_to_prot) - .code32 - - sti - - popl %ebp - - xorl %eax,%eax - movl 8(%ebp),%edx - movl %eax,gfx_ofs_v2_ok(%edx) - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - -/* - * int gfx_input_v2 (gfx_data_v2_t *gfx_data, int *menu_entry) - * - * let user enter a command line - * - * uses gfx_data->cmdline as buffer - * - * return values: - * 1: abort - * 2: boot - * menu_entry: selected entry - */ - -ENTRY(gfx_input_v2) - - .code32 - - pushl %ebp - movl %esp, %ebp - - pushl %ebx - pushl %esi - pushl %edi - - movl 8(%ebp),%edx - movl %edx,%ebx - leal gfx_ofs_v2_sys_cfg(%edx),%esi - andl $0xf,%ebx - shrl $4,%edx - - pushl %ebp - - call EXT_C(prot_to_real) - .code16 - - pushw %ds - - movw %dx,%ds - - movl gfx_ofs_v2_cmdline(%bx),%edi - movl gfx_ofs_v2_cmdline_len(%bx),%ecx - movl gfx_ofs_v2_timeout(%bx),%eax - imull $18,%eax - - lcall *gfx_ofs_v2_jmp_table + 4 * 2 (%bx) - - movl %eax,%ecx - - popw %ds - - call EXT_C(real_to_prot) - .code32 - - sti - - popl %ebp - - movl 12(%ebp),%edx - movl %ebx,(%edx) - - movl %ecx,%eax - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - -/* - * int gfx_setup_menu (gfx_data_t *gfx_data) - * - * draw boot menu - * - * return values: - * always 0 - */ - -/* menu entry descriptor */ -#define menu_v2_entries 0 -#define menu_v2_default 2 /* seg:ofs */ -#define menu_v2_ent_list 6 /* seg:ofs */ -#define menu_v2_ent_size 10 -#define menu_v2_arg_list 12 /* seg:ofs */ -#define menu_v2_arg_size 16 -#define sizeof_menu_v2_desc 18 - -ENTRY(gfx_setup_menu_v2) - - .code32 - - pushl %ebp - movl %esp, %ebp - - pushl %ebx - pushl %esi - pushl %edi - - movl 8(%ebp),%edx - movl %edx,%ebx - andl $0xf,%ebx - shrl $4,%edx - - call EXT_C(prot_to_real) - .code16 - - pushw %ds - - movw %dx,%ds - shll $4,%edx - - subw $sizeof_menu_v2_desc,%sp - movw %sp,%bp - - movl gfx_ofs_v2_menu_entries(%bx),%eax - movw %ax,menu_v2_entries(%bp) - - movl gfx_ofs_v2_menu_default_entry(%bx),%eax - subl %edx,%eax - movw %ax,menu_v2_default(%bp) - movw %ds,menu_v2_default+2(%bp) - - movl gfx_ofs_v2_menu_list(%bx),%eax - subl %edx,%eax - movw %ax,menu_v2_ent_list(%bp) - movw %ds,menu_v2_ent_list+2(%bp) - - movl gfx_ofs_v2_menu_entry_len(%bx),%eax - movw %ax,menu_v2_ent_size(%bp) - - movl gfx_ofs_v2_args_list(%bx),%eax - subl %edx,%eax - movw %ax,menu_v2_arg_list(%bp) - movw %ds,menu_v2_arg_list+2(%bp) - - movl gfx_ofs_v2_args_entry_len(%bx),%eax - movw %ax,menu_v2_arg_size(%bp) - - movl %ss,%esi - shll $4,%esi - addl %ebp,%esi - - lcall %ds: *gfx_ofs_v2_jmp_table + 4 * 3 (%bx) - - addw $sizeof_menu_v2_desc,%sp - - popw %ds - - call EXT_C(real_to_prot) - .code32 - - sti - - xorl %eax,%eax - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - -/* - * - * end graphics stuff - * - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ -#endif /* SUPPORT_GFX */ - - -/* - * int gateA20(int linear) - * - * Gate address-line 20 for high memory. - * - * This routine is probably overconservative in what it does, but so what? - * - * It also eats any keystrokes in the keyboard buffer. :-( - * - * on call: linear=0 for a20 off and 1 for on - * - * return value: 0 for failure and 1 for success - * - */ - -ENTRY(gateA20) - - .code32 - - pushl %ebp - movl 8(%esp), %edx /* the value of `linear' */ - -#if 1 - /* first, check if A20 status is already what we desired. */ - - /* disable CPU cache for the test to work reliably. */ - movl %cr0, %eax - pushl %eax /* save old cr0 */ -// andl $0x00000011, %eax - orl $0x60000000, %eax /* set CD and NW */ - movl %eax, %cr0 - movl %cr0, %eax - testl $0x60000000, %eax /* check if we can use wbinvd. */ - jz 1f /* CPU has no wbinvd instruction. */ - wbinvd - andl $0xDFFFFFFF, %eax /* clear NW */ - movl %eax, %cr0 -1: - movl 0x00000000, %eax - pushl %eax /* save old int0 vector */ - - cmpl 0x00100000, %eax - jne 1f /* A20 is on */ - - notl 0x00000000 - movl 0x00000000, %eax - cmpl 0x00100000, %eax - notl 0x00000000 /* logical `NOT' won't touch flags */ -1: - /* ZF=0(means not equal) for A20 on, ZF=1(means equal) for A20 off. */ - sete %al /* save ZF to AL */ - testl %edx, %edx - sete %ah /* save ZF to AH */ - cmpb %al, %ah - - /* ZF=1(means equal) for desired and we needn't do anything. */ - - popl %eax /* restore int0 vector */ - movl %eax, 0x00000000 - popl %eax /* restore cr0 */ - movl %eax, %cr0 - movl $1, %eax /* return value 1 means success */ - - jz 1f /* success */ - -#endif - - /* failure, then call a real-mode function enable_disable_a20 */ - - call EXT_C(prot_to_real) - - .code16 - - sti /* for hardware interrupt or watchdog */ - - movw $0x00ff, %cx # try so many times on failure - movb $0x01, %dh # with a20 debug on - - cli /* yes, keep interrupt off when controlling A20 */ - call enable_disable_a20 - sti /* for hardware interrupt or watchdog */ - - sete %dl # DL=1 means success - -#if 0 /* comment out to avoid hanging ONDA C51G board. */ - pushal - -#if 0 - # qemu arrow keys will not work if we turn on NumLock in this way. - - /* Turn on Number Lock */ - orb $0x20, 0x417 -#endif - - /* reset mouse */ - movw $0xC201, %ax - int $0x15 - - /* disable mouse */ - movw $0xC200, %ax - xorw %bx, %bx /* BH=0 means disable */ - int $0x15 - - popal -#endif - - call EXT_C(real_to_prot) - - .code32 - - sti - - movzbl %dl, %eax - -1: - popl %ebp - ret -chain_stage1_esp: - .long 0 - -/****************************************************************************/ - -/* - * long realmode_run(long regs_ptr) - * - */ - -ENTRY(realmode_run) - - .code32 - - pushl %ebp - movl %esp, %ebp - - pushl %ebx - movl 8(%ebp), %ebx /* EBX=regs_ptr */ - - /* check sanity */ - - xorl %eax, %eax /* EAX=0 for failure */ - - movl 0x20(%ebx), %ecx /* GS */ - incl %ecx - jz 1f - decl %ecx - shrl $16, %ecx - jnz 2f /* failure */ -1: - - movl 0x24(%ebx), %ecx /* FS */ - incl %ecx - jz 1f - decl %ecx - shrl $16, %ecx - jnz 2f /* failure */ -1: - - movl 0x28(%ebx), %ecx /* ES */ - incl %ecx - jz 1f - decl %ecx - shrl $16, %ecx - jnz 2f /* failure */ -1: - - movl 0x2C(%ebx), %ecx /* DS */ - incl %ecx - jz 1f - decl %ecx - shrl $16, %ecx - jnz 2f /* failure */ -1: - - movl 0x30(%ebx), %ecx /* SS */ - movl 0x0C(%ebx), %edx /* ESP */ - incl %ecx - jz 1f - decl %ecx - orl %edx, %ecx - shrl $16, %ecx - jnz 2f /* failure */ - jmp 3f -1: - incl %edx - jnz 2f /* failure */ -3: - - movl 0x38(%ebx), %ecx /* CS */ - movl 0x34(%ebx), %edx /* EIP */ - incl %ecx - jz 1f - decl %ecx - orl %edx, %ecx - shrl $16, %ecx - jnz 2f /* failure */ - jmp 3f -1: - cmpb $0xCD, %dl - jnz 2f /* failure */ - shrl $16, %edx - incw %dx - jnz 2f /* failure */ -3: - /* sanity check ok, run it! */ - - pushal - pushal - pushal - pushal - movl %esp, ABS(chain_stage1_esp) - - /* mov the struct to stack */ - subl $64, %esp - movl %esp, %edi - movl %ebx, %esi - movl $16, %ecx - cld - repz movsl - - movl %esp, %ebp /* EBP point to struct on stack */ - - call EXT_C(prot_to_real) - - .code16 - - sti - - movl %ebp, %esp - - /* check CS:EIP */ - - movl 0x38(%bp), %ecx /* CS */ - movl 0x34(%bp), %edx /* EIP */ - incl %ecx /* CS = -1? */ - jz 3f /* yes, jump to INTxx code */ - - /* run user defined code */ - decl %ecx /* CS */ - /* 0xEA might have been changed to 0xCD previously, so we must restore - * it back to 0xEA. - */ - movb $0xEA, ABS(1f-1) /* opcode for "far jump" */ - movw %dx, ABS(1f) /* IP in the far jump instruction */ - movw %cx, ABS(1f + 2) /* CS in the far jump instruction */ - - /* set return address for user code to return */ - movl $ABS(4f), %ecx - movl %ecx, 0x8201 - jmp 6f -3: - /* run int xx */ - movw %dx, ABS(1f - 1) /* int XX */ - movb $0xE9, ABS(1f + 1) /* jmp */ - movw $(4f - 1f - 4), ABS(1f + 2) -6: - movw %sp, ABS(8f) /* initial SP */ - movw %ss, ABS(7f) /* initial SS */ - - /* set DS, ES, FS, GS */ - movl 0x20(%bp), %ecx /* GS */ - incl %ecx - jz 5f - decl %ecx - movw %cx, %gs -5: - - movl 0x24(%bp), %ecx /* FS */ - incl %ecx - jz 5f - decl %ecx - movw %cx, %fs -5: - - movl 0x28(%bp), %ecx /* ES */ - incl %ecx - jz 5f - decl %ecx - movw %cx, %es -5: - - movl 0x2C(%bp), %ecx /* DS */ - incl %ecx - jz 5f - decl %ecx - movw %cx, %ds -5: - - movl 0x30(%bp), %ecx /* SS */ - incl %ecx - jz 5f - decl %ecx - movw %cx, ABS(7f) - movw 0x0C(%bp), %dx /* SP */ - movw %dx, ABS(8f) -5: - movl 0x3C(%bp), %ecx /* EFLAGS */ - incl %ecx - jz 5f - decl %ecx - pushl %ecx - popfl -5: - popal /* setup general registers */ - - /* move SS and SP */ - .byte 0xBC /* MOV SP */ -7: - .word 0 /* SS */ - movw %sp, %ss - .byte 0xBC /* MOV SP */ -8: - .word 0 /* SP */ - - /* far jump to user code */ - .byte 0xEA /* ljmp */ -1: - .word 0 /* IP */ - .word 0 /* CS */ - -4: /* return from user code */ - - /* CS:IP need not care */ - - /* use the stack already built by the user */ - - pushal - pushfl - pushl %cs - pushl $0 - pushl %ss - pushl %ds - pushl %es - pushl %fs - pushl %gs - - movl %ss, %ebp - shll $4, %ebp - xorl %eax, %eax - movw %ax, %ds - movw %ax, %es - movw %sp, %ax - addl %eax, %ebp /* physical address of stack */ - - call EXT_C(real_to_prot) - - .code32 - - sti - - cld - movl %ebp, %esi - - movl ABS(chain_stage1_esp), %esp - movl 16(%esp), %ebx /* EBX=regs_ptr */ - - leal 32(%ebx), %edi - movl $8, %ecx - repz movsl - - leal 32(%ebp), %esi - movl %ebx, %edi - movl $8, %ecx - repz movsl - - /* the stack should not change! */ - - /* fix the pushed ESPs before checking */ - movl $32, %ecx - subl %ecx, (32 + 12)(%esp) - movl $64, %ecx - subl %ecx, (64 + 12)(%esp) - movl $96, %ecx - subl %ecx, (96 + 12)(%esp) - - movl %esp, %esi - leal 32(%esp), %edi - movl $8, %ecx - repz cmpsl - jnz 1f - movl %esp, %esi - leal 64(%esp), %edi - movl $16, %ecx - repz cmpsl - jnz 1f - popal - popal - popal - popal - movl $1, %eax /* success */ - popl %ebx - popl %ebp - ret -1: - popal - popal - popal - popal - xorl %eax, %eax /* failure */ -2: - popl %ebx - popl %ebp - ret - - -realmode_int: - - .code32 - - pushl %eax - - call EXT_C(prot_to_real) - - .code16 - - sti - - .byte 0xCD /* opcode for "INT xx" */ -VARIABLE(interrupt_number) - .byte 0 /* interrupt number */ - - call EXT_C(real_to_prot) - - .code32 - - sti - - popl %eax - - iret - -/* - * linux_boot() - * - * Does some funky things (including on the stack!), then jumps to the - * entry point of the Linux setup code. - */ - -VARIABLE(linux_text_len) - .long 0 - -VARIABLE(linux_data_tmp_addr) - .long 0 - -VARIABLE(linux_data_real_addr) - .long 0 - -VARIABLE(linux_bzimage_tmp_addr) -// .long SYSTEM_RESERVED_MEMORY - .long LINUX_TMP_MEMORY - -ENTRY(linux_boot) - - .code32 - - cli - - /* don't worry about saving anything, we're committed at this point */ - cld /* forward copying */ - - ///* realmode_idtdesc is at memory address below 0x10000 */ - //lidt realmode_idtdesc - - /* copy kernel */ - movl EXT_C(linux_text_len), %ecx - addl $3, %ecx - shrl $2, %ecx - movl EXT_C(linux_bzimage_tmp_addr), %esi # SYSTEM_RESERVED_MEMORY - movl $LINUX_ZIMAGE_ADDR, %edi # 0x10000 - - rep movsl - - jmp linux_real_mode_startup - -ENTRY(big_linux_boot) - - .code32 - - cli - cld - - ///* realmode_idtdesc is at memory address below 0x10000 */ - //lidt realmode_idtdesc - - /* copy kernel */ - movl EXT_C(linux_text_len), %ecx - addl $3, %ecx - shrl $2, %ecx - movl EXT_C(linux_bzimage_tmp_addr), %esi # SYSTEM_RESERVED_MEMORY - movl $LINUX_BZIMAGE_ADDR, %edi # 0x100000 - - rep movsl - -linux_real_mode_startup: - - movl EXT_C(linux_data_real_addr), %ebx - - /* copy the real mode part */ - movl EXT_C(linux_data_tmp_addr), %esi - movl %ebx, %edi - movl $LINUX_SETUP_MOVE_SIZE, %ecx # 0x9400 - cld - rep movsb - - /* change %ebx to the segment address */ - shrl $4, %ebx #; CS of LINUX SETUP, high word = 0 - movl %ebx, %eax - addl $0x20, %eax #; one sector - movw %ax, 1f // linux_setup_seg - - /* final setup for linux boot */ - - call EXT_C(prot_to_real) - - .code16 - - /* final setup for linux boot */ - cli - movw %bx, %ss - movw $LINUX_SETUP_STACK, %sp # 0x9000 - - movw %bx, %ds - movw %bx, %es - movw %bx, %fs - movw %bx, %gs - - /* jump to start */ - /* ljmp */ - .byte 0xea - .word 0 -1: //linux_setup_seg: - .word 0 - -#if 0 -/* - * void toggle_blinking (void) - * BIOS call "INT 10H Function 1003h" to toggle intensity/blinking bit - * Call with %ax = 0x1003 - * %bl = new state: - * 0x00 enable background intensity - * 0x01 enable blinking - * %bh = 0x00 to avoid problems on some adapters - * Returns nothing - */ - - -ENTRY(toggle_blinking) - - .code32 - - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - - movl EXT_C(blinking), %ebx - call EXT_C(prot_to_real) - - .code16 - - //sti /* it is not bad keeping interrupt off */ - sti /* for hardware interrupt or watchdog */ - - xorb %bh, %bh - testb %bl, %bl - setnz %bl - movw $0x1003, %ax - int $0x10 - - call EXT_C(real_to_prot) - .code32 - - sti - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret -#endif - -/* - * unsigned int console_putchar (unsigned int c, unsigned int max_width) - * - * Put the character C on the console. Because GRUB wants to write a - * character with an attribute, this implementation is a bit tricky. - * If C is a control character (CR, LF, BEL, BS), use INT 10, AH = 0Eh - * (TELETYPE OUTPUT). Otherwise, save the original position, put a space, - * save the current position, restore the original position, write the - * character and the attribute, and restore the current position. - * - * The reason why this is so complicated is that there is no easy way to - * get the height of the screen, and the TELETYPE OUPUT BIOS call doesn't - * support setting a background attribute. - */ -ENTRY(console_putchar) - - .code32 - - movl 0x4(%esp), %edx - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - movl EXT_C(current_color), %ebx - - movb EXT_C(fontx), %cl - movb EXT_C(fonty), %ch - - - call EXT_C(prot_to_real) - .code16 - - sti /* for hardware interrupt or watchdog */ - - movb %dl, %al - xorb %bh, %bh - - cmpb $80, %cl - jb 5f - movb $0, %cl - movw %cx, %dx - pushaw - movb $0x02, %ah - int $0x10 - popaw - incb %ch - - cmpb $25, %ch - jb 5f - /* scroll up */ - pushaw - movw $0x0e0d, %ax - int $0x10 - movw $0x0e0a, %ax - int $0x10 - popaw - decb %ch - jmp 3f -5: - movw %cx, %dx - pushaw - movb $0x02, %ah - int $0x10 - popaw -3: - - /* use teletype output if control character */ - cmpb $0x07, %al - je 1f - cmpb $0x08, %al - je 1f - cmpb $0x0a, %al - je 1f - cmpb $0x0d, %al - je 1f - -// /* save the character and the attribute on the stack */ -// pushw %ax -// pushw %bx -// -// /* get the current position */ -// movb $0x03, %ah -// int $0x10 -// -// /* check the column with the width */ -// cmpb $79, %dl -// jb 2f -// -// /* print CR and LF, if next write will exceed the width */ -// movw $0x0e0d, %ax -// int $0x10 -// movw $0x0e0a, %ax -// int $0x10 -// -// /* get the current position */ -// movb $0x03, %ah -// int $0x10 -// -//2: -// /* restore the character and the attribute */ -// popw %bx -// popw %ax - - pushw %cx - - /* write the character with the attribute */ - movb $0x09, %ah - movw $1, %cx - int $0x10 - - popw %dx - - /* move the cursor forward */ - incb %dl -// movb $0x02, %ah -// int $0x10 - - /* if showcursor, print CRLF on needed */ - testb $1, ABS(EXT_C(cursor_state)) - jz 3f - - cmpb $80, %dl - jb 5f - movb $0, %dl - pushaw - movb $0x02, %ah - int $0x10 - popaw - incb %dh - - cmpb $25, %dh - jb 5f - /* scroll up */ - pushaw - movw $0x0e0d, %ax - int $0x10 - movw $0x0e0a, %ax - int $0x10 - popaw - decb %dh - jmp 3f -5: - pushaw - movb $0x02, %ah - int $0x10 - popaw - jmp 3f - -1: - movb $0x0e, %ah - int $0x10 - /* update fontx, fonty */ - xorb %bh, %bh /* set page to 0 */ - movb $0x3, %ah - int $0x10 /* get cursor position */ - -3: - call EXT_C(real_to_prot) - .code32 - - sti - - /* EAX = 0 */ - - movb %dl, %al - movl %eax, EXT_C(fontx) - movb %dh, %al - movl %eax, EXT_C(fonty) - - popl %edi - popl %esi - popl %ebx - popl %ebp - movl $0x00000001, %eax /* always return 1 char printed. */ - ret - - -/* - * remap_ascii_char remaps the ascii code %dl to another if the code is - * contained in ASCII_KEY_MAP. - */ -remap_ascii_char: - - .code32 - - //pushl %esi - - movl $ABS(EXT_C(ascii_key_map)), %esi -1: - lodsl - /* check if this is the end */ - testl %eax, %eax - jz 2f - /* check if this matches the ascii code */ - cmpw %ax, %dx - jne 1b - /* if so, perform the mapping */ - shrl $16, %eax - movw %ax, %dx -2: - //popl %esi - - ret - - .align 4 -ENTRY(ascii_key_map) - .space (KEY_MAP_SIZE + 1) * 4 - - -/* - * int console_getkey (void) - * BIOS call "INT 16H Function 00H" to read character from keyboard - * Call with %ah = 0x0 - * Return: %ah = keyboard scan code - * %al = ASCII character - */ - -ENTRY(console_getkey) - - .code32 - - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - -#if 0 - /* MacBook cannot work with this pmode code. Comment out 2012-10-15 */ - - cld - xorl %eax, %eax -1: - cli - movl $0x41A, %esi - lodsw /* EAX=buf_head, ESI=0x41C, point to buf_tail */ - cmpw %ax, (%esi) /* head == tail ? */ - sti /* Enable interrupt. Wait for a key. */ - je 1b /* No key. loop and continue to check buffer. */ -1: - /* Found a key code in buffer. */ - /* EAX = buf_head */ - /* get int16 key code */ - movzwl 0x400(%eax), %edx /* DL=ASCII code, DH=scan code */ - /* clear ASCII code if needed */ - cmpb $0xE0, %dl - je 2f - cmpb $0xF0, %dl - jne 1f - cmpb $0x00, %dh - je 1f -2: - movb $0x00, %dl -1: - /* set new buf_head */ - incl %eax - incl %eax -#if 0 - movl $0x480, %esi /* point to buf_start and buf_end */ - cmpw 2(%esi), %ax /* buf_head >= buf_end ? */ -#else - cmpw $0x003E, %ax /* buf_head >= buf_end ? */ -#endif - jb 1f -#if 0 - movw (%esi), %ax /* let buf_head = buf_start */ -#else - movw $0x001E, %ax /* let buf_head = buf_start */ -#endif -1: - /* update buf_head in the BIOS Data Area. */ - movw %ax, 0x41A - - /* the int16 key code is in DX */ - call remap_ascii_char /* ESI changed */ - movzwl %dx, %eax -#else -4: - call EXT_C(prot_to_real) - - .code16 - -1: - sti /* getkey needs interrupt on */ - // hlt - call conditional_hlt - - #; work around for Apple BIOS getkey bug - #; check the keyboard buffer, until there is a keypress. - -#if 0 - /* first, use normal check key function */ - movb $0x01, %ah #; check key - int $0x16 - jz 2f #; no normal key, try enhanced key - - /* found a normal key */ - movb $0x00, %ah #; get the normal key - int $0x16 - jmp 1f -2: -#endif - -#if 1 - /* then, use enhanced check key function */ - movb $0x11, %ah #; check enhanced key - int $0x16 -// jz 1b #; no keypress, loop - movl $0xFFFFFFFF, %edx /* value for no key-press */ - jz 3f /* jump if no key-press */ - - /* found an enhanced key */ - movb $0x10, %ah #; get the enhanced key - int $0x16 - /* clear ASCII code if needed */ - cmpb $0xE0, %al - je 2f - cmpb $0xF0, %al - jne 1f - cmpb $0x00, %ah - je 1f -2: - movb $0x00, %al -#else - /* avoid calling enhanced functions */ - jmp 1b -#endif -1: - movzwl %ax, %edx - //call translate_keycode -3: - call EXT_C(real_to_prot) - .code32 - - sti - - cmpl $0xFFFFFFFF, %edx - jne 1f - pushl $1 - call defer; - popl %eax - cmpb $0, beep_enable - je 2f - call beep_func -2: - cmpb $0, DateTime_enable - je 2f - call DateTime_refresh -2: - cmpl $0, graphics_inited - je 4b - cmpb $0, animated_enable - je 4b - call animated - cmpw $0x3c00, %ax - jne 4b - movw %ax, %dx -1: - call remap_ascii_char /* ESI changed */ - movzwl %dx, %eax -#endif - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - -/* - * int console_checkkey (void) - * if there is a character pending, return it; otherwise return -1 - * BIOS call "INT 16H Function 01H" to check whether a character is pending - * Call with %ah = 0x1 - * Return: - * If key waiting to be input: - * %ah = keyboard scan code - * %al = ASCII character - * Zero flag = clear - * else - * Zero flag = set - */ -ENTRY(console_checkkey) - - .code32 - - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - xorl %edx, %edx - -#if 0 - /* MacBook cannot work with this pmode code. Comment out 2012-10-15 */ - - decl %edx /* EDX = -1 */ - - cld - xorl %eax, %eax -1: - cli - movl $0x41A, %esi - lodsw /* EAX=buf_head */ - /* ESI=0x41C, point to buf_tail */ - cmpw %ax, (%esi) /* head == tail ? */ - sti /* Enable interrupt. Wait for a key. */ - je 9f /* no key press. return -1 immediately. */ -1: - /* Found a key code in buffer. */ - /* EAX = buf_head */ - /* get int16 key code */ - movzwl 0x400(%eax), %edx /* DL=ASCII code, DH=scan code */ - /* clear ASCII code if needed */ - cmpb $0xE0, %dl - je 2f - cmpb $0xF0, %dl - jne 1f - cmpb $0x00, %dh - je 1f -2: - movb $0x00, %dl -1: - /* return the key in DX immediately */ - //jmp 9f -#else - - call EXT_C(prot_to_real) /* enter real mode */ - - .code16 - - movl $500, %ecx -1: - movl 0x46c, %eax /* get old timer counter */ - - sti /* checkkey needs interrupt on */ - // hlt - call conditional_hlt - - cmpl 0x46c, %eax /* timer counter changed by int 8? */ - loopz 1b /* no change, wait a timer interrupt */ - - /* counter changed or timed out. */ - -#if 0 - /* first, use normal check key function */ - movb $0x01, %ah #; check key - int $0x16 - jnz 2f /* there is a key-press. */ -#endif - -#if 1 - /* then, use enhanced check key function */ - movb $0x11, %ah #; check enhanced key - int $0x16 - movl $0xFFFFFFFF, %edx /* value for no key-press */ - jz 1f /* jump if no key-press */ - /* clear ASCII code if needed */ - cmpb $0xE0, %al - je 3f - cmpb $0xF0, %al - jne 4f - cmpb $0x00, %ah - je 4f -3: - movb $0x00, %al -4: -#else - /* avoid calling enhanced functions */ - movl $0xFFFFFFFF, %edx /* value for no key-press */ - jmp 1f -#endif -2: - /* Yes, there is a key. */ - movzwl %ax, %edx - //call translate_keycode - -1: - call EXT_C(real_to_prot) - .code32 - - sti -#endif - -9: - cmpl $0xFFFFFFFF, %edx - jne 3f - pushl $1 - call defer - popl %eax - cmpb $0, beep_enable - jz 2f - call beep_func -2: - cmpb $0, DateTime_enable - je 2f - call DateTime_refresh -2: - cmpl $0, graphics_inited - je 5f - cmpb $0, animated_enable - je 5f - call animated -5: - movl $0xFFFFFFFF, %edx - jmp 1f -3: - call remap_ascii_char /* ESI changed */ -1: - mov %edx, %eax - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - -/* - * int console_getxy (void) - * BIOS call "INT 10H Function 03h" to get cursor position - * Call with %ah = 0x03 - * %bh = page - * Returns %ch = starting scan line - * %cl = ending scan line - * %dh = row (0 is top) - * %dl = column (0 is left) - */ - - -ENTRY(console_getxy) - - .code32 - - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - - call EXT_C(prot_to_real) - - .code16 - - sti /* for hardware interrupt or watchdog */ - - xorb %bh, %bh /* set page to 0 */ - movb $0x3, %ah - int $0x10 /* get cursor position */ - - call EXT_C(real_to_prot) - .code32 - - sti - - //movb %dl, %ah - //movb %dh, %al - movw %dx, %ax - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - -/* - * void console_gotoxy(int x, int y) - * BIOS call "INT 10H Function 02h" to set cursor position - * Call with %ah = 0x02 - * %bh = page - * %dh = row (0 is top) - * %dl = column (0 is left) - */ - - -ENTRY(console_gotoxy) - - .code32 - - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - - movl 0x14(%esp), %eax /* x */ - movl %eax, EXT_C(fontx) - movb %al, %dl - movl 0x18(%esp), %eax /* y */ - movl %eax, EXT_C(fonty) - movb %al, %dh - - call EXT_C(prot_to_real) - - .code16 - - sti /* for hardware interrupt or watchdog */ - - xorb %bh, %bh /* set page to 0 */ - movb $0x2, %ah - int $0x10 /* set cursor position */ - - call EXT_C(real_to_prot) - .code32 - - sti - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - -/* - * void console_cls (void) - * BIOS call "INT 10H Function 09h" to write character and attribute - * Call with %ah = 0x09 - * %al = (character) - * %bh = (page number) - * %bl = (attribute) - * %cx = (number of times) - */ - - -ENTRY(console_cls) - - .code32 - - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - movb EXT_C(current_color), %bh - call EXT_C(prot_to_real) - - .code16 - - sti /* for hardware interrupt or watchdog */ -/* -* BIOS call "INT 10H Function 06h" to Scroll up window -* Call with %AH = 0x06 -* %AL = lines to scroll (0 = clear, CH, CL, DH, DL are used) -* %BH = attribute -* %CH = Upper row number -* %CL = Left column number -* %DH = Lower row number -* %DL = Right column number -*/ - movw $0x0600, %ax - xorw %cx, %cx - movb 0x44a, %dl //40:004a Screen width in text columns - movb 0x484, %dh //40:0084 maximum valid row value - int $0x10 - xorb %bh, %bh - /* move back the cursor */ - xorw %dx, %dx - movb $0x02, %ah - int $0x10 - - call EXT_C(real_to_prot) - .code32 - - sti - - /* EAX = 0 */ - movl %eax, EXT_C(fontx) - movl %eax, EXT_C(fonty) - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - -ENTRY(console_beep) - - .code32 - - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - - call EXT_C(prot_to_real) - .code16 - - sti /* for hardware interrupt or watchdog */ - cmpw $0, EXT_C(beep_frequency) - je 1f - movb $0xb6, %al - outb %al, $0x43 - movw EXT_C(beep_frequency), %ax - outb %al, $0x42 - xchgb %ah, %al - outb %al, $0x42 - inb $0x61, %al - orb $3, %al - outb %al, $0x61 - jmp 2f -1: - inb $0x61, %al - andb $0xFC, %al - outb %al, $0x61 -2: - call EXT_C(real_to_prot) - .code32 - - sti - movw %dx, %ax - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - -/* - * void console_setcursor (unsigned long on) - * BIOS call "INT 10H Function 01h" to set cursor type - * Call with %ah = 0x01 - * %ch = cursor starting scanline - * %cl = cursor ending scanline - */ - -VARIABLE(cursor_state) - .long 0 //bit 0=1 show cursor,bit 1=1 show splashimage -console_cursor_shape: - .word 0 - -ENTRY(console_setcursor) - - .code32 - - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - - /* check if the standard cursor shape has already been saved */ - movw console_cursor_shape, %ax - testw %ax, %ax - jne 1f - - call EXT_C(prot_to_real) - - .code16 - - sti /* for hardware interrupt or watchdog */ - - movb $0x03, %ah - xorb %bh, %bh - int $0x10 - - call EXT_C(real_to_prot) - .code32 - - sti - - movw %cx, console_cursor_shape -1: - /* set %cx to the designated cursor shape */ - movw $0x2000, %cx - movl 0x14(%esp), %ebx /* on */ - testl %ebx, %ebx - jz 2f - movw console_cursor_shape, %cx -2: - call EXT_C(prot_to_real) - - .code16 - - sti /* for hardware interrupt or watchdog */ - - movb $0x1, %ah - int $0x10 - - call EXT_C(real_to_prot) - .code32 - - sti - - //movb cursor_state, %al - //movb %bl, cursor_state - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - -/* graphics mode functions */ -#ifdef SUPPORT_GRAPHICS -/* - * int set_videomode(mode) - * BIOS call "INT 10H Function 0h" to set video mode - * Call with %ah = 0x0 - * %al = video mode - * //Returns old videomode. - * Return the current mode value stored at 0040:0049 in BIOS Data Area - */ -ENTRY(set_videomode) - - .code32 - - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - - movb 0x14(%esp), %cl - - call EXT_C(prot_to_real) - - .code16 - - sti /* for hardware interrupt or watchdog */ - - //xorw %bx, %bx - //movb $0xf, %ah - //int $0x10 /* Get Current Video mode */ - //movb %al, %ch - xorb %ah, %ah - movb %cl, %al - pushw %cx - pushw %ds // DS = 0 - pushw %es // ES = 0 - int $0x10 /* Set Video mode */ - popw %es // ES = 0 - popw %ds // DS = 0 - popw %cx - - cmpb 0x449, %cl // DS = 0 - jne 1f - movw $0x8000, %di // use 64-byte buffer at 0000:8000 - xorl %eax, %eax - movw $0x11, %cx // clear the buffer (64 + 4) bytes - cld - rep stosl - movw $0x8000, %di // use 64-byte buffer at 0000:8000 - movw $0x1B00, %ax // get current mode infomation - xorw %bx, %bx // BX=0 for return state infomation - int $0x10 - // the caller want to confirm AL=0x1B for a successful return. - movb %al, %cs:(0x8000+64) // it is certain CS = 0 -1: - xorb %bh, %bh - movb $0, %bl - movw $0x1003, %ax - int $0x10 - call EXT_C(real_to_prot) - .code32 - - sti - - //xorb %ah, %ah - //movb %ch, %al - movb 0x449, %al - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - -/* - * unsigned char * graphics_get_font() - * BIOS call "INT 10H Function 11h" to set font - * Call with %ah = 0x11 - */ -ENTRY(graphics_get_font) - - .code32 - - push %ebp - push %ebx - push %esi - push %edi - - call EXT_C(prot_to_real) - - .code16 - - sti /* for hardware interrupt or watchdog */ - - movw $0x1130, %ax - movb $6, %bh /* font 8x16 */ - int $0x10 - movw %bp, %dx - movw %es, %cx - - call EXT_C(real_to_prot) - .code32 - - sti - - xorl %eax, %eax - movw %cx, %ax - shll $4, %eax - movw %dx, %ax - - pop %edi - pop %esi - pop %ebx - pop %ebp - ret - - -/* - * void bios_scroll_up() - * BIOS call "INT 10H Function 6h" to scroll up window - * - * VIDEO - SCROLL UP WINDOW - * AH = 06h - * AL = number of lines by which to scroll up (00h = clear entire window) - * BH = attribute used to write blank lines at bottom of window - * CH,CL = row,column of window's upper left corner - * DH,DL = row,column of window's lower right corner - * - * Return: Nothing - * - * Note: Affects only the currently active page (see AH=05h) - * - * BUGS: Some implementations (including the original IBM PC) have a bug - * which destroys BP. The Trident TVGA8900CL (BIOS dated 1992/9/8) clears - * DS to 0000h when scrolling in an SVGA mode (800x600 or higher) - */ -ENTRY(bios_scroll_up) - - .code32 - - push %ebp - push %ebx - push %esi - push %edi - - movb EXT_C(x1), %dl /* bytes per line */ - movb EXT_C(y1), %dh /* number of lines */ - - call EXT_C(prot_to_real) - - .code16 - - sti - - decb %dl - decb %dh - movw $0x0601, %ax /* scroll up 1 line */ - movb $0, %bh /* use background color */ - xorw %cx, %cx /* upper left corner */ - int $0x10 - - call EXT_C(real_to_prot) - .code32 - - sti - - pop %edi - pop %esi - pop %ebx - pop %ebp - ret - - - -/* - * graphics_set_palette(index, color) - * BIOS call "INT 10H Function 10h" to set individual dac register - * Call with %ah = 0x10 - * %bx = register number - * %ch = new value for green (0-63) - * %cl = new value for blue (0-63) - * %dh = new value for red (0-63) - */ - -ENTRY(graphics_set_palette) - - .code32 - - push %ebp - push %ebx - push %esi - push %edi - -#if 0 - movw $0x3c8, %bx /* address write mode register */ - - /* wait vertical retrace */ - - movw $0x3da, %dx -1: inb %dx, %al /* wait vertical active display */ - test $8, %al - jnz 1b - -2: inb %dx, %al /* wait vertical retrace */ - test $8, %al - jnz 2b - - mov %bx, %dx - movb 0x14(%esp), %al /* index */ - outb %al, %dx - inc %dx - - movb 0x1A(%esp), %al /* red */ - shrb $2, %al - outb %al, %dx - - movb 0x19(%esp), %al /* green */ - shrb $2, %al - outb %al, %dx - - movb 0x18(%esp), %al /* blue */ - shrb $2, %al - outb %al, %dx -#endif - movw 0x14(%esp), %bx -#if 1 - movl 0x18(%esp), %ecx - movl %ecx, %edx - shrl $10, %edx /* DH = red */ - shrb $2, %ch /* CH = green */ - shrb $2, %cl /* CL = blue */ -#endif - - call EXT_C(prot_to_real) - - .code16 - - sti /* for hardware interrupt or watchdog */ - -#if 1 - // VIDEO - SET INDIVIDUAL DAC REGISTER (VGA/MCGA) - // - // AX = 1010h - // BX = register number - // CH = new value for green (0-63) - // CL = new value for blue (0-63) - // DH = new value for red (0-63) - // - // Return: Nothing - - pushal - movw $0x1010, %ax - int $0x10 - popal -#endif - - // VIDEO - SET SINGLE PALETTE REGISTER (PCjr,Tandy,EGA,MCGA,VGA) - // - // AX = 1000h - // BL = palette register number (00h-0Fh) - // = attribute register number (undocumented, see below) - // BH = color or attribute register value - // - // Return: Nothing - // - // Notes: On MCGA, only BX = 0712h is supported. Under UltraVision, - // the palette locking status (see AX=CD01h) determines the outcome - // - // (undocumented) values for attribute register number: - // 10h attribute mode control register (should let BIOS control this) - // 11h overscan color register - // 12h color plane enable register (bits 3-0 enable corresponding text attribute bit) - // 13h horizontal PEL panning register - // 14h color select register - - movb %bl, %bh - movw $0x1000, %ax - int $0x10 - - call EXT_C(real_to_prot) - .code32 - - sti - - pop %edi - pop %esi - pop %ebx - pop %ebp - ret - -#endif /* SUPPORT_GRAPHICS */ - -/* - * getrtsecs() - * if a seconds value can be read, read it and return it (BCD), - * otherwise return 0xFF - * BIOS call "INT 1AH Function 02H" to check whether a character is pending - * Call with %ah = 0x2 - * Return: - * If RT Clock can give correct values - * %ch = hour (BCD) - * %cl = minutes (BCD) - * %dh = seconds (BCD) - * %dl = daylight savings time (00h std, 01h daylight) - * Carry flag = clear - * else - * Carry flag = set - * (this indicates that the clock is updating, or - * that it isn't running) - */ -ENTRY(getrtsecs) - - .code32 - - push %ebp - - call EXT_C(prot_to_real) /* enter real mode */ - - .code16 - - #;sti /* getrtsecs needs interrupt on */ - sti #; added 2006-11-30 - -#if 0 - movb $0x2, %ah - - /* Ralf Brown's Interrupt List says: - * - * BUG: Some BIOSes leave CF unchanged if successful, - * so CF should be cleared before calling this function - */ - - clc - int $0x1a - - DATA32 jnc gottime - movb $0xff, %dh - -gottime: -#else - /* The call int1A/ah=02 could fail all the time. - * So we should avoid using it. Instead, we use ticks at 0040:006C. - * - Tinybit 2007-04-21 - */ - pushl %ecx - movl 0x46C, %eax -// movl $5, %ecx /* 5 seconds */ -// mull %ecx - xorl %edx, %edx -// movl $91, %ecx /* 91 ticks = 5 seconds */ - movl $18, %ecx - divl %ecx - xorl %edx, %edx - movl $60, %ecx - divl %ecx /* EDX=seconds (0 .. 59) */ - movb %dl, %dh - popl %ecx - -#endif - call EXT_C(real_to_prot) - .code32 - - sti - - movb %dh, %al - - pop %ebp - ret - - -/* - * void get_datetime(unsigned long *date, unsigned long *time); - */ -ENTRY(get_datetime) - - .code32 - - pushl %ebp - call EXT_C(prot_to_real) - - .code16 - - sti /* for hardware interrupt or watchdog */ - movb $2, %ah - clc - int $0x1a - jc 2f - - pushw %cx - pushw %dx - - movb $4, %ah - clc - int $0x1a - jc 3f - - pushw %cx - pushw %dx - popl %edx - popl %ecx - jmp 1f - -3: - popl %eax - -2: - xorl %ecx, %ecx - xorl %edx, %edx - -1: - call EXT_C(real_to_prot) - .code32 - - sti - - movl %esp, %ebp - movl 8(%ebp), %eax - movl %edx, (%eax) - movl 12(%ebp), %eax - movl %ecx, (%eax) - - popl %ebp - ret - -#if 0 - /* This BIOS call should NOT be called since it will clear the byte at 0040:0070. */ - -/* - * currticks() - * return the real time in ticks, of which there are about - * 18-20 per second - */ -ENTRY(currticks) - .code32 - pushl %ebp - - call EXT_C(prot_to_real) /* enter real mode */ - - .code16 - - #;sti /* currticks needs interrupt on */ - sti #; added 2006-11-30 - - /* %ax is already zero */ - int $0x1a - - call EXT_C(real_to_prot) - .code32 - - sti - - movl %ecx, %eax - shll $16, %eax - movw %dx, %ax - - popl %ebp - ret -#endif - -/* - * multi_boot(int start, int mb_info, int, int, int, int, int) - * - * This starts a kernel in the manner expected of the multiboot standard. - */ - -ENTRY(multi_boot) - - .code32 - - cli - - /* The protected-mode IDT at 3M will be destroyed. Although cli has - * been executed, the multiboot kernel might still need to call the - * real-mode BIOS functions(int15/E820, etc). So we need to load the - * default real-mode IDT descriptor. - */ - - lidt realmode_idtdesc - - /* Now the IDT is wrong for protected-mode code! Do not sti in - * pmode. Only do it in real-mode. - */ - - /* before moving kernel, move module list(mll) down to 0x20000. */ - - movl $ABS(EXT_C(mll)), %esi - movl $0x20000, %edi /* at physical address 128K. */ - movl $0x200, %ecx /* (0x200*4=)2K is enough for mll[99]. */ - cld - repz movsl - - /* move image down to 1M. This will destroy code at above 1M. So this - * function must be at below 1M, together with real-mode functions. - */ - -// movl $(SYSTEM_RESERVED_MEMORY + 0x0100000), %esi - movl $(LINUX_TMP_MEMORY + 0x0100000), %esi - movl $0x0100000, %edi /* 1M */ - movl ABS(EXT_C(cur_addr)), %ecx - subl %esi, %ecx - addl $3, %ecx - shrl $2, %ecx - cld - repz movsl - - ///* no need to save anything */ - //call EXT_C(stop_floppy) - - movl 0x10(%esp), %ecx - jecxz 1f - - movl $0x2BADB002, %eax - movl 0x8(%esp), %ebx - - /* boot kernel here (absolute address call) */ - call *0x4(%esp) - - /* error */ - call EXT_C(stop) - -1: - /* BSD boot */ - popl %eax /* discard return address */ - popl %eax /* EAX=entry_addr */ - call *%eax - - /* error */ - call EXT_C(stop) - - -/* - * This is the area for all of the special variables. - */ - - .align 4 - -#;protstack: -#; .long PROTSTACKINIT - - /* an address can only be long-jumped to if it is in memory, this - is used by multiple routines */ -offset: - .long 0x8000 -segment: - .word 0 - -#if 0 -VARIABLE(apm_bios_info) - .word 0 /* version */ - .word 0 /* cseg */ - .long 0 /* offset */ - .word 0 /* cseg_16 */ - .word 0 /* dseg_16 */ - .word 0 /* cseg_len */ - .word 0 /* cseg_16_len */ - .word 0 /* dseg_16_len */ -#endif - -/* - * This is the Global Descriptor Table - * - * An entry, a "Segment Descriptor", looks like this: - * - * 31 24 19 16 7 0 - * ------------------------------------------------------------ - * | | |B| |A| | | |1|0|E|W|A| | - * | BASE 31..24 |G|/|0|V| LIMIT |P|DPL| TYPE | BASE 23:16 | - * | | |D| |L| 19..16| | |1|1|C|R|A| | - * ------------------------------------------------------------ - * | | | - * | BASE 15..0 | LIMIT 15..0 | - * | | | - * ------------------------------------------------------------ - * - * Note the ordering of the data items is reversed from the above - * description. - */ - -#if 0 - .align 16 -gdt: - .word 0, 0 - .byte 0, 0, 0, 0 - - /* code segment */ - .word 0xFFFF, 0 - .byte 0, 0x9A, 0xCF, 0 - - /* data segment */ - .word 0xFFFF, 0 - .byte 0, 0x92, 0xCF, 0 - - /* 16 bit real mode CS */ - .word 0xFFFF, 0 - .byte 0, 0x9E, 0, 0 - - /* 16 bit real mode DS */ - .word 0xFFFF, 0 - .byte 0, 0x92, 0, 0 - - -/* this is the GDT descriptor */ -gdtdesc: - .word 0x27 /* limit */ - .long gdt /* addr */ -#endif - -pmode_idtdesc: - .word 0x7FF - .long 0x300000 /* at 3M */ - .word 0 // pad - - -/* this code will be moved to and get executed at HMA_ADDR=0x2B0000 */ - -/* our gdt starts at HMA_ADDR=0x2B0000 */ - -ENTRY(HMA_start) - - .code32 - - /* the first entry of GDT, i.e., the default null entry, - * can be any value. it never get used. So we use these - * 8 bytes for our jmp and GDT descriptor. - */ - - . = EXT_C(HMA_start) + 0 /* GDT entry: default null */ - - jmp 1f /* two-byte short jmp */ - - . = EXT_C(HMA_start) + 2 - - /* 6-byte GDT descriptor */ -gdtdescHMA: - .word 0x1F /* limit */ - .long HMA_ADDR /* linear base address */ - - . = EXT_C(HMA_start) + 8 /* 16-bit data 64K limit */ - - /* real mode data segment base=0x200 */ - .word 0xFFFF, 0x0200 - .byte 0x00, 0x92, 0, 0 - - . = EXT_C(HMA_start) + 0x10 /* 32-bit data 4GB limit */ - - /* data segment, although it is no use here for now */ - .word 0xFFFF, 0 - .byte 0, 0x92, 0xCF, 0 - - . = EXT_C(HMA_start) + 0x18 /* 16-bit code 64K limit */ - - /* 16-bit code segment base=0x2B0000 */ - .word 0xFFFF, 0x0000 - .byte 0x2B, 0x9E, 0, 0 - -realmode_idtdesc: - .word 0x3FF - .long 0 - .word 0 // pad - -1: - /* set up to pass boot drive */ - movb EXT_C(boot_drive), %dl - - /* check if the --ebx option is given. */ - movl (EXT_C(chain_ebx_set) - EXT_C(HMA_start) + HMA_ADDR), %eax - testl %eax, %eax - jz 1f - movl (EXT_C(chain_ebx) - EXT_C(HMA_start) + HMA_ADDR), %ebx -1: - - /* check if the --edx option is given. */ - movl (EXT_C(chain_edx_set) - EXT_C(HMA_start) + HMA_ADDR), %eax - testl %eax, %eax - jz 1f - movl (EXT_C(chain_edx) - EXT_C(HMA_start) + HMA_ADDR), %edx -1: - - /* move new loader from extended memory to conventional memory. - * this will overwrite our GRUB code, data and stack, so we should not - * use instuctions like push/pop/call/ret, and we should not use - * functions like gateA20(). - */ - - /* the new loader is currently at 0x200000 */ - movl $0x00200000, %esi - xorl %eax, %eax - xorl %edi, %edi - movw (EXT_C(chain_load_segment) - EXT_C(HMA_start) + HMA_ADDR), %di - shll $4, %edi - movw (EXT_C(chain_load_offset) - EXT_C(HMA_start) + HMA_ADDR), %ax - addl %eax, %edi - //movl $0x00007c00, %edi - movl (EXT_C(chain_load_length) - EXT_C(HMA_start) + HMA_ADDR), %ecx - cld - repz movsb - - /* switch to real mode */ - - /* check if the --cx option is given. */ - movl (EXT_C(chain_cx_set) - EXT_C(HMA_start) + HMA_ADDR), %eax - testl %eax, %eax - jz 1f - movw (EXT_C(chain_cx) - EXT_C(HMA_start) + HMA_ADDR), %cx -1: - /* check if the --bx option is given. */ - movl (EXT_C(chain_bx_set) - EXT_C(HMA_start) + HMA_ADDR), %eax - testl %eax, %eax - jz 1f - movw (EXT_C(chain_bx) - EXT_C(HMA_start) + HMA_ADDR), %bx -1: - - /* set new GDT */ - cli - lgdt (gdtdescHMA - EXT_C(HMA_start) + HMA_ADDR) - lidt (realmode_idtdesc - EXT_C(HMA_start) + HMA_ADDR) - - /* set up segment limits */ - movw $PSEUDO_RM_DSEG, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - movw %ax, %ss - - movl $0x200, %esp /* points to end of interrupt vector table */ - /* SS base=0x200, so SS:SP=physical 0x400 */ - - movl $0x7c00, %ebp - - /* jump to a 16 bit segment, this might be an extra step: - * set up CS limit, also clear high word of EIP - */ - ljmp $PSEUDO_RM_CSEG, $(1f - EXT_C(HMA_start)) -1: - .code16 - - /* clear the PE bit of CR0 */ - movl %cr0, %eax - //andl $CR0_PE_OFF, %eax - andl $0x0000FFFE, %eax - movl %eax, %cr0 - - /* setup DS, ES, SS, FS and GS before loading CS */ - xorl %eax, %eax - movw %ax, %ds - movw %ax, %es - movw %ax, %ss - movl $0x400, %esp - movw %ax, %fs - movw %ax, %gs - - /* flush prefetch queue, reload %cs */ - - .byte 0xEA /* ljmp 0000:7c00 */ -VARIABLE(chain_boot_IP) - .word 0x7c00 /* offset */ -VARIABLE(chain_boot_CS) - .word 0x0000 /* segment */ - - .align 4 - -VARIABLE(chain_load_offset) - .word 0x7c00 -VARIABLE(chain_load_segment) - .word 0x0000 -VARIABLE(chain_load_length) - .long 0x200 -VARIABLE(chain_ebx) - .long 0 -VARIABLE(chain_ebx_set) - .long 0 -VARIABLE(chain_edx) - .long 0 -VARIABLE(chain_edx_set) - .long 0 -VARIABLE(chain_enable_gateA20) - .long 0 -VARIABLE(chain_bx) - .word 0 -VARIABLE(chain_bx_set) - .long 0 -VARIABLE(chain_cx) - .word 0 -VARIABLE(chain_cx_set) - .long 0 - - /* max length of code is 1 sector */ - . = . - (. - EXT_C(HMA_start))/0x201 - - .align 4 - -VARIABLE(mbi) - .space (22 * 4) - -VARIABLE(end_of_low_16bit_code) - - /* ensure this resides in the first 64KB */ - . = . - (ABS(.) / 0x10001) - - /* Although real-mode code ends at this point, the dynamic data - * of multiboot will use a piece of memory here. - */ - - -/****************************************************************************/ -/************************* 32-bit functions follow **************************/ -/****************************************************************************/ - - - .space 0x300000 /* !!!! insert 3M !!!! */ - -#if 0 -/* - * int check_64bit (void) - * - * Checks whether 64-bit mode is supported - * - * Stolen from a patch originaly intended for syslinux - * (http://syslinux.zytor.com/archives/2007-January/007832.html) - * - * Copyright (C) 2007 Byron Stanoszek - * - * Adapted to AT&T syntax by Robert Millan - */ - -ENTRY(check_64bit) - - .code32 - - pushl %ebp - pushl %ebx - pushl %edx - - /* Check if this CPU supports the CPUID command */ - pushfl - pushfl - popl %eax - movl %eax, %ebx - xorl $(1 << 21), %eax // CPUID bit - pushl %eax - popfl - pushfl - popl %eax - popfl // Restore the original flags - xorl %ebx, %eax - jz is_32bit - - /* Now check for the 64-bit flag in the CPU features byte ($0000_0001, edx) - This is bit 30 for Intel CPUs, and bit 29 for AMD CPUs */ - movl $0x00000000, %eax // Find last Intel cpuid # - cpuid - cmpl $0x00000000, %eax - je test_amd - movl $0x00000001, %eax // Read Intel CPU flags - cpuid - btl $30, %edx // 64-bit if bit 30 is set - jc is_64bit - -test_amd: - movl $0x80000000, %eax // Find last AMD cpuid # - cpuid - cmpl $0x80000000, %eax - jbe is_32bit - movl $0x80000001, %eax // Read AMD CPU flags - cpuid - btl $29, %edx // 64-bit if bit 29 is set - jnc is_32bit - -is_64bit: - movl $1, %eax - popl %edx - popl %ebx - popl %ebp - ret -is_32bit: - xorl %eax, %eax - popl %edx - popl %ebx - popl %ebp - ret -#endif - -#if 0 -/* - * set_int15_handler(void) - * - * Set up int15_handler. - */ -ENTRY(set_int15_handler) - - .code32 - - pushl %edi - - /* save the original int15 handler */ - movl $0x54, %edi -#if 0 - movw (%edi), %ax - movw %ax, ABS(int15_offset) - movw 2(%edi), %ax - movw %ax, ABS(int15_segment) - - /* save the new int15 handler */ - movw $ABS(int15_handler), %ax - movw %ax, (%edi) - xorw %ax, %ax - movw %ax, 2(%edi) -#else - movl (%edi), %eax - movl %eax, ABS(int15_offset) - - /* set the new int15 handler */ - movl $ABS(int15_handler), %eax - stosl -#endif - - popl %edi - ret - - -/* - * unset_int15_handler(void) - * - * Restore the original int15 handler - */ -ENTRY(unset_int15_handler) - - .code32 - - pushl %edi - - /* check if int15_handler is set */ - movl $0x54, %edi -#if 0 - movw $ABS(int15_handler), %ax - cmpw %ax, (%edi) - jne 1f - xorw %ax, %ax - cmpw %ax, 2(%edi) - jne 1f - - /* restore the original */ - movw ABS(int15_offset), %ax - movw %ax, (%edi) - movw ABS(int15_segment), %ax - movw %ax, 2(%edi) -#else - movl $ABS(int15_handler), %eax - cmpl %eax, (%edi) - jne 1f - - /* restore the original */ - movl ABS(int15_offset), %eax - stosl -#endif - -1: - popl %edi - ret -#endif - - -/* - * set_int13_handler(map) - * - * Copy MAP to the drive map and set up int13_handler. - */ -ENTRY(set_int13_handler) - - .code32 - - pushl %ebp - movl %esp, %ebp - - pushl %edi - pushl %esi - -#if MAP_NUM_16 - /* copy boot_drive_map to maphooked_drive_map_1 */ - movl $(DRIVE_MAP_SIZE * DRIVE_MAP_SLOT_SIZE / 8), %ecx - pushl %ecx - movl $ABS(EXT_C(hooked_drive_map_1)), %edi - movl 8(%ebp), %esi - cld - repz movsl - /* copy boot_drive_map to maphooked_drive_map_2 */ - popl %ecx - movl $ABS(EXT_C(hooked_drive_map_2)), %edi - repz movsl -#else - /* copy boot_drive_map to maphooked_drive_map */ - movl $(DRIVE_MAP_SIZE * DRIVE_MAP_SLOT_SIZE / 4), %ecx - movl $ABS(EXT_C(hooked_drive_map)), %edi - movl 8(%ebp), %esi - cld - repz movsl -#endif - - /* other variable(s) */ - movb ABS(EXT_C(is64bit)), %dl - movb %dl, ABS(int13_is64bit) - - movl 0x4C, %eax - movl %eax, ABS(EXT_C(ROM_int13)) - movl %eax, ABS(EXT_C(ROM_int13_dup)) - -// Now initialized early at the beginning of this file -// -// /* save the original int13 handler */ -// movl $0x4c, %edi -// movl (%edi), %eax -// movl %eax, ABS(EXT_C(ROM_int13)) - - /* decrease the lower memory size and set it to the BIOS memory */ - - /* read available lower memory size */ - movzwl 0x413, %eax -#ifdef CDROM_INIT - /* KBytes that int13 handler occupies */ - movl $((int13_handler_end - int13_handler + 0x3ff) / 0x400), %edx -// cmpb $0, %cs:(EXT_C(atapi_dev_count) - int13_handler) - cmpb $0, ABS(EXT_C(atapi_dev_count)) - jne 1f -#endif - movl $((cdrom_start - int13_handler + 0x3ff) / 0x400), %edx -1: -// movzbl ABS(int13_handler), %edx # EDX=KBytes used by new int13_handler - movb %dl, ABS(int13_handler) - subl %edx, %eax # EAX=new available low memory(KBytes) - /* save remaining lower memory size in BIOS data area */ - movw %ax, 0x413 - - /* copy int13_handler to the reserved area */ - shll $10, %eax - movl %eax, %edi # EDI=EAX=destination int13_handler address - movl $ABS(int13_handler), %esi -#ifdef CDROM_INIT - movl $((int13_handler_end - int13_handler + 3) / 4), %ecx -// cmpb $0, %cs:(EXT_C(atapi_dev_count) - int13_handler) - cmpb $0, ABS(EXT_C(atapi_dev_count)) - jne 1f -#endif - movl $((cdrom_start - int13_handler + 3) / 4), %ecx -1: - // cld - repz movsl - - movl %eax, %edi # EDI=EAX=linear address of int13_handler - - ///* save size (KBytes) of int13_handler in its header */ - //movb %dl, (%edi) - -#if 0 - movl %eax, (int15_e820_range0_addr - int13_handler)(%edi) -#endif - /* linear address of int13_handler (below 0x100000). yes, use 'orl' - * because we only write the lower 24 bits of the linear addess. - * The higher byte(8 bits) is on the highest byte of the gdt entry. - */ - orl %eax, (PM_DS16 + 2 + MyGDT - int13_handler)(%edi) - orl %eax, (PM_CS16 + 2 + MyGDT - int13_handler)(%edi) - //orl %eax, (PM_CS32 + 2 + MyGDT - int13_handler)(%edi) - - /* calculate linear address of MyGDT and save in gdtdesc+2 */ - addl $(MyGDT - int13_handler), %eax # EAX=linear address of MyGDT - movl %eax, (gdtdesc - int13_handler + 2)(%edi) - - /* calculate linear address of int13_lm64move_lm64_start */ - addl $(int13_lm64move_lm64_start - MyGDT), %eax - movl %eax, (int13_lm64move_lm64_start_addr - int13_handler)(%edi) - - movl %edi, %eax # EDI=EAX=linear address of int13_handler - - /* real mode segment of int13_handler */ - shrl $4, %eax - movw %ax, (int13_pgmove_to_rm_cs - int13_handler)(%edi) - - shll $16, %eax # move segment to high word - movw $(int13_handler_entry - int13_handler), %ax # AX=0x100 - movl %eax, 0x004C # save the new int13 handler - -#if 0 /* comment out so that int15 always hooks. */ - /* set ESI to the drive map */ - movl $ABS(EXT_C(hooked_drive_map)), %esi - movl $(DRIVE_MAP_SIZE), %ecx -1: - cmpb $0xFF, 1(%esi) # It is memdrive? - jne 2f # No. Try next slot. - testb $0x40, 5(%esi) # To_DRIVE is CDROM? - jz 1f # No. Memdrive indeed. Hook int15. -2: - /* try next slot */ - addl $DRIVE_MAP_SLOT_SIZE, %esi - loop 1b - jmp 2f /* no memdrives, don't hook int15 */ -1: -#endif - movl (EXT_C(e820cycles) - int13_handler)(%edi), %ecx - jecxz 2f - - /* save the new int15 handler. segment still in high word of EAX. */ - movw $(int15_e820_handler - int13_handler), %ax # offset - movl %eax, 0x54 -2: - popl %esi - popl %edi - popl %ebp - ret - -/* int - * unset_int13_handler(check_status_only) - * - * Restore the original int13 handler - * - * Return 0 for success and non-zero for failure. - */ -ENTRY(unset_int13_handler) - - .code32 - - pushl %ebp - movl %esp, %ebp - - pushl %edi - - /* check if int13_handler is set */ - movl $0x413, %edi - movw (%edi), %ax - cmpw $640, %ax - jae 1f #; needn't unset -// cmpw $632, %ax -// jb 1f - shll $(16 + 6), %eax - - /* the offset(low word) should be 0x100 */ -// movw $0x100, %ax - movw $(int13_handler_entry - int13_handler), %ax - - cmpl %eax, 0x4c - jne 1f #; not hooked, unset failure - movl %eax, %edi - shrl $12, %edi /* segment base address */ - - /* check our int13 signature "$INT13SFGRUB4DOS" */ -// cmpl $0x544E4924, 0x103(%edi) /* $INT */ - cmpl $0x544E4924, (int13_handler_entry - int13_handler + 3)(%edi) /* $INT */ - jnz 1f -// cmpl $0x46533331, 0x107(%edi) /* 13SF */ - cmpl $0x46533331, (int13_handler_entry - int13_handler + 7)(%edi) /* 13SF */ - jnz 1f -// cmpl $0x42555247, 0x10B(%edi) /* GRUB */ - cmpl $0x42555247, (int13_handler_entry - int13_handler + 0xb)(%edi) /* GRUB */ - jnz 1f -// cmpl $0x534F4434, 0x10F(%edi) /* 4DOS */ - cmpl $0x534F4434, (int13_handler_entry - int13_handler + 0xf)(%edi) /* 4DOS */ - jnz 1f - - //cmpl $0x9A000000, 0x1C(%edi) /* old int 13 */ - cmpl $0x5A000000, 0x1C(%edi) /* old int 13 */ - jb 1f - - //cmpl $0x9A000000, 0x0C(%edi) /* old int 15 */ - cmpl $0x5A000000, 0x0C(%edi) /* old int 15 */ - jb 1f - - movl ABS(EXT_C(ROM_int13)), %eax - cmpl 0x1C(%edi), %eax - jnz 1f - - movl ABS(EXT_C(ROM_int15)), %eax - cmpl 0x0C(%edi), %eax - jnz 1f - - xorl %eax, %eax - - cmpl %eax, 8(%ebp) - jnz 1f - - /* increase the lower memory size */ - - movzbw (%edi), %ax - addw %ax, 0x413 - - /* restore the original int15 handler */ - movl ABS(EXT_C(ROM_int15)), %eax - movl %eax, 0x54 - - /* restore the original int13 handler */ - movl ABS(EXT_C(ROM_int13)), %eax - movl %eax, 0x4c - - xorl %eax, %eax /* success */ -1: - /* return non-zero for failure */ - popl %edi - popl %ebp - ret - -#if 0 -/* memmove using SSE */ -/* - * void memmove_forward_SSE (void *dst, const void *src, unsigned int len) - * - */ - -ENTRY(memmove_forward_SSE) - - .code32 - - pushl %esi - pushl %edi - -#if 1 - movl %cr0, %eax - orb $2, %al // set CR0.MP - movl %eax, %cr0 - movl %cr4, %eax - orb $0x6, %ah // set CR4.OSFXSR (bit 9) OSXMMEXCPT (bit 10) - movl %eax, %cr4 -#endif - - movl 0x0C(%esp), %edi - movl 0x10(%esp), %esi - movl 0x14(%esp), %ecx - shrl $7, %ecx -1: - movdqa (%esi), %xmm0 - addl $16, %esi - movntps %xmm0, (%edi) - addl $16, %edi - movdqa (%esi), %xmm1 - addl $16, %esi - movntps %xmm1, (%edi) - addl $16, %edi - movdqa (%esi), %xmm2 - addl $16, %esi - movntps %xmm2, (%edi) - addl $16, %edi - movdqa (%esi), %xmm3 - addl $16, %esi - movntps %xmm3, (%edi) - addl $16, %edi - movdqa (%esi), %xmm4 - addl $16, %esi - movntps %xmm4, (%edi) - addl $16, %edi - movdqa (%esi), %xmm5 - addl $16, %esi - movntps %xmm5, (%edi) - addl $16, %edi - movdqa (%esi), %xmm6 - addl $16, %esi - movntps %xmm6, (%edi) - addl $16, %edi - movdqa (%esi), %xmm7 - addl $16, %esi - movntps %xmm7, (%edi) - addl $16, %edi - loop 1b - - popl %edi - popl %esi - ret -#endif - -/* get_code_end() : return the address of the end of the code - * This is here so that it can be replaced by asmstub.c. - */ - -ENTRY(get_code_end) - - .code32 - - /* will be the end of the bss */ -# if defined(HAVE_END_SYMBOL) - movl $end, %eax -# elif defined(HAVE_USCORE_END_SYMBOL) - movl $_end, %eax -# endif - shrl $2, %eax /* Round up to the next word. */ - incl %eax - shll $2, %eax - ret - -int2_nmi: - - .code32 - - movb $0x02, EXT_C(interrupt_number) - jmp realmode_int - - -irq_8_to_15: /* from the slave interrupt controller */ - - .code32 - - pushl %eax - movb $0x20, %al // End Of Interrupt(EOI) command - outb %al, $0xA0 // sent EOI to slave controller - outb %al, $0x20 // sent EOI to master controller - popl %eax - iret - -irq_0_to_7: /* from the master interrupt controller */ - - .code32 - - pushl %eax - movb $0x20, %al // End Of Interrupt(EOI) command - outb %al, $0x20 // sent EOI to master controller - popl %eax - iret - -irq_0: /* int 0x08, timer interrupt, also the CPU double fault */ - - .code32 - - /* double fault has error code 0 on stack. - * we never have the EIP = 0. - * So check the stack and we can distinguish these two. - */ - - cmpl $0, (%esp) - jnz 1f - cmpl $40, 8(%esp) // it should be the CS if it is double fault - jnz 1f - /* CPU double fault */ - addl $4, %esp // remove the error code - /* simply return for now */ - iret -1: - /* simulate the ROM real-mode routine */ - sti - pushl %eax - movb 0x440, %al // Diskette Motor shutoff counter - testb %al, %al - jz 1f // motor already stopped - decb %al - movb %al, 0x440 // decrement the counter - jnz 1f // motor is running, continue - /* time is out, stop the motor now */ - pushl %edx - movw $0x3F2, %dx // diskette controller digit-out register - inb %dx, %al - andb $0xCF, %al // shut off drive 0 and 1 - outb %al, %dx - andb $0xFC, 0x43F // Diskette motor status - // set motor staus to be off for drive 0, 1 - popl %edx -1: - movl 0x46C, %eax // Daily timer counter, cleared at midnight - incl %eax // incremented - cmpl $0x1800B0, %eax - jb 2f - xorl %eax, %eax // cleared - incb 0x470 //Clock rollover flag, set when 40:6C exceeds 24hrs -2: - movl %eax, 0x46C // get incremented or cleared - //int 0x1C // could do it in protected mode, but no need yet - - cli - movb $0x20, %al // End Of Interrupt(EOI) command - outb %al, $0x20 // sent EOI to master controller - sti - - popl %eax - iret - -irq_1: - - .code32 - - movb $9, EXT_C(interrupt_number) - jmp realmode_int - -irq_2: - - .code32 - - movb $0x0A, EXT_C(interrupt_number) - jmp realmode_int - -irq_3: - - .code32 - - movb $0x0B, EXT_C(interrupt_number) - jmp realmode_int - -irq_4: - - .code32 - - movb $0x0C, EXT_C(interrupt_number) - jmp realmode_int - -irq_5: - - .code32 - - movb $0x0D, EXT_C(interrupt_number) - jmp realmode_int - -irq_6: - - .code32 - - movb $0x0E, EXT_C(interrupt_number) - jmp realmode_int - -irq_7: - - .code32 - - movb $0x0F, EXT_C(interrupt_number) - jmp realmode_int - -irq_8: - - .code32 - - movb $0x70, EXT_C(interrupt_number) - jmp realmode_int - -irq_9: - - .code32 - - movb $0x71, EXT_C(interrupt_number) - jmp realmode_int - -irq_10: - - .code32 - - movb $0x72, EXT_C(interrupt_number) - jmp realmode_int - -irq_11: - - .code32 - - movb $0x73, EXT_C(interrupt_number) - jmp realmode_int - -irq_12: - - .code32 - - movb $0x74, EXT_C(interrupt_number) - jmp realmode_int - -irq_13: - - .code32 - - movb $0x75, EXT_C(interrupt_number) - jmp realmode_int - -irq_14: - - .code32 - - movb $0x76, EXT_C(interrupt_number) - jmp realmode_int - -irq_15: - - .code32 - - movb $0x77, EXT_C(interrupt_number) - jmp realmode_int - -default_iret: - - .code32 - - iret - - -/* - * The C code for a grub4dos executable may have defines as follows: - * - -#define sprintf ((int (*)(char *, const char *, ...))((*(int **)0x8300)[0])) -#define printf(...) sprintf(NULL, __VA_ARGS__) -#define putstr ((void (*)(const char *))((*(int **)0x8300)[1])) -#define putchar ((void (*)(int))((*(int **)0x8300)[2])) -#define get_cmdline ((int (*)(char *))((*(int **)0x8300)[3])) -#define getxy ((int (*)(void))((*(int **)0x8300)[4])) -#define gotoxy ((void (*)(int, int))((*(int **)0x8300)[5])) -#define cls ((void (*)(void))((*(int **)0x8300)[6])) -#define setcursor ((int (*)(int))((*(int **)0x8300)[7])) -#define nul_terminate ((int (*)(char *))((*(int **)0x8300)[8])) -#define safe_parse_maxint ((int (*)(char **, unsigned long long *))((*(int **)0x8300)[9])) -#define substring ((int (*)(const char *, const char *, int))((*(int **)0x8300)[10])) -#define strstr ((char *(*)(const char *, const char *))((*(int **)0x8300)[11])) -#define strlen ((int (*)(const char *))((*(int **)0x8300)[12])) -#define strtok ((char *(*)(char *, const char *))((*(int **)0x8300)[13])) -#define strncat ((int (*)(char *, const char *, int))((*(int **)0x8300)[14])) -#define strcmp ((int (*)(const char *, const char *))((*(int **)0x8300)[15])) -#define strcpy ((char *(*)(char *, const char *))((*(int **)0x8300)[16])) -#define tolower ((int (*)(int))((*(int **)0x8300)[17])) -#define isspace ((int (*)(int))((*(int **)0x8300)[18])) -#define getkey ((int (*)(void))((*(int **)0x8300)[19])) -#define checkkey ((int (*)(void))((*(int **)0x8300)[20])) -#define sleep ((unsigned int (*)(unsigned int))((*(int **)0x8300)[21])) -#define memcmp ((int (*)(const char *, const char *, int))((*(int **)0x8300)[22])) -#define memmove ((void *(*)(void *, const void *, int))((*(int **)0x8300)[23])) -#define memset ((void *(*)(void *, int, int))((*(int **)0x8300)[24])) -#define mem64 ((int (*)(int, unsigned long long, unsigned long long, unsigned long long))((*(int **)0x8300)[74])) -#define open ((int (*)(char *))((*(int **)0x8300)[26])) -#define read ((unsigned long (*)(unsigned long long, unsigned long long, unsigned long))((*(int **)0x8300)[27])) -#define close ((void (*)(void))((*(int **)0x8300)[28])) - -http://grubutils.googlecode.com/svn/trunk/src/include/grub4dos.h - * - */ - -VARIABLE(system_functions) - .long ABS(EXT_C(grub_sprintf)) - .long ABS(EXT_C(grub_putstr)) -VARIABLE(grub_putchar) - .long ABS(EXT_C(_putchar)) - .long ABS(EXT_C(get_cmdline_obsolete)) - .long ABS(EXT_C(getxy)) - .long ABS(EXT_C(gotoxy)) - .long ABS(EXT_C(cls)) - .long ABS(EXT_C(wee_skip_to)) //was obsolete setcursor - .long ABS(EXT_C(nul_terminate)) - .long ABS(EXT_C(safe_parse_maxint_with_suffix)) - .long ABS(EXT_C(substring)) - .long ABS(EXT_C(grub_strstr)) - .long ABS(EXT_C(grub_strlen)) - .long ABS(EXT_C(grub_strtok)) - .long ABS(EXT_C(grub_strncat)) - .long ABS(EXT_C(grub_strcmp)) - .long ABS(EXT_C(grub_strcpy)) - .long 0 //reserved - .long 0 //reserved - .long ABS(EXT_C(getkey)) /* getchar */ - .long ABS(EXT_C(checkkey)) - .long ABS(EXT_C(pxe_call)) //reserved 21 - .long ABS(EXT_C(grub_memcmp)) - .long ABS(EXT_C(grub_memmove)) - .long ABS(EXT_C(grub_memset)) - .long 0 //reserved - .long ABS(EXT_C(grub_open)) - .long ABS(EXT_C(grub_read)) - .long ABS(EXT_C(grub_close)) - .long 0 //reserved - .long 0 //reserved - VARIABLE(disk_read_hook) - .long 0//reserved - .long ABS(EXT_C(devread)) - .long ABS(EXT_C(devwrite)) - .long ABS(EXT_C(next_partition)) - .long ABS(EXT_C(open_device)) - .long ABS(EXT_C(real_open_partition)) - .long ABS(EXT_C(set_device)) - .long 0 //reserved - .long 0 //reserved - .long 0 //reserved - .long ABS(EXT_C(parse_string)) - .long ABS(EXT_C(hexdump)) - .long ABS(EXT_C(skip_to)) - .long ABS(EXT_C(builtin_cmd)) - .long ABS(EXT_C(get_datetime)) - .long ABS(EXT_C(find_command)) - .long 0 //reserved - .long 0 //reserved - .long ABS(EXT_C(get_mmap_entry)) - .long ABS(EXT_C(grub_malloc)) - .long ABS(EXT_C(grub_free))//51 - .long 0 // list_partitions - .long ABS(EXT_C(realmode_run)) // realmode_run - //reserved for wee - .long 0 - .long 0 - .long 0 - .long 0 - .long 0 - .long 0 - .long 0 - ////////////////////////////////////////////61 - .long ABS(EXT_C(dir)) - .long ABS(EXT_C(print_a_completion)) - .long ABS(EXT_C(print_completions)) - .long ABS(EXT_C(lba_to_chs)) - .long ABS(EXT_C(probe_bpb)) - .long ABS(EXT_C(probe_mbr)) - .long ABS(EXT_C(unicode_to_utf8)) - .long ABS(EXT_C(rawread)) - .long ABS(EXT_C(rawwrite)) - .long ABS(EXT_C(setcursor)) - .long ABS(EXT_C(grub_tolower)) - .long ABS(EXT_C(grub_isspace)) - .long ABS(EXT_C(grub_sleep)) - .long ABS(EXT_C(mem64)) - .long ABS(EXT_C(envi_cmd)) - .long ABS(EXT_C(strncmpx)) -#ifdef SUPPORT_GRAPHICS - .long ABS(EXT_C(rectangle)) -#else - .long 0 -#endif - .long ABS(EXT_C(get_cmdline)) - -/* - * The C code for a grub4dos executable may have defines as follows: - * - -#define next_partition_drive ((*(unsigned long **)0x8304)[0]) -#define next_partition_dest ((*(unsigned long **)0x8304)[1]) -#define next_partition_partition ((*(unsigned long ***)0x8304)[2]) -#define next_partition_type ((*(unsigned long ***)0x8304)[3]) -#define next_partition_start ((*(unsigned long long ***)0x8304)[4]) -#define next_partition_len ((*(unsigned long long ***)0x8304)[5]) -#define next_partition_offset ((*(unsigned long long ***)0x8304)[6]) -#define next_partition_entry ((*(unsigned long ***)0x8304)[7]) -#define next_partition_ext_offset ((*(unsigned long ***)0x8304)[8]) -#define next_partition_buf ((*(char ***)0x8304)[9]) - - * - */ - -VARIABLE(system_variables) -VARIABLE(next_partition_drive) - .long 0 -VARIABLE(next_partition_dest) - .long 0 -VARIABLE(next_partition_partition) - .long 0 -VARIABLE(next_partition_type) - .long 0 -VARIABLE(next_partition_start) - .long 0 -VARIABLE(next_partition_len) - .long 0 -VARIABLE(next_partition_offset) - .long 0 -VARIABLE(next_partition_entry) - .long 0 -VARIABLE(next_partition_ext_offset) - .long 0 -VARIABLE(next_partition_buf) - .long 0 -VARIABLE(quit_print) - .long 0 -//VARIABLE(buf_drive) - .long -1 //reserved +#define next_partition_drive ((*(unsigned long **)0x8308)[0]) +#define next_partition_dest ((*(unsigned long **)0x8308)[1]) +#define next_partition_partition ((*(unsigned long ***)0x8308)[2]) +#define next_partition_type ((*(unsigned long ***)0x8308)[3]) +#define next_partition_start ((*(unsigned long ***)0x8308)[4]) +#define next_partition_len ((*(unsigned long ***)0x8308)[5]) +#define next_partition_offset ((*(unsigned long ***)0x8308)[6]) +#define next_partition_entry ((*(unsigned long ***)0x8308)[7]) +#define next_partition_ext_offset ((*(unsigned long ***)0x8308)[8]) +#define next_partition_buf ((*(char ***)0x8308)[9]) + + * + */ + +VARIABLE(system_variables) //IMG(0x8308) +VARIABLE(next_partition_drive) //0 int + .extent 0 +VARIABLE(next_partition_dest) //1 int + .extent 0 +VARIABLE(next_partition_partition) //2 int* + .extent 0 +VARIABLE(next_partition_type) //3 int* + .extent 0 +VARIABLE(next_partition_start) //4 long long * + .extent 0 +VARIABLE(next_partition_len) //5 long long * + .extent 0 +VARIABLE(next_partition_offset) //6 long long * + .extent 0 +VARIABLE(next_partition_entry) //7 int* + .extent 0 +VARIABLE(next_partition_ext_offset) //8 int* + .extent 0 +VARIABLE(next_partition_buf) //9 char * + .extent 0 +VARIABLE(quit_print) //10 int + .extent 0 +VARIABLE(block_io_protocol_this) //11 + .extent 0 //VARIABLE(buf_track) - .long -1 //reserved -VARIABLE(filesystem_type) - .long 0 -//VARIABLE(query_block_entries)//reserved - .long 0 //reserved -//VARIABLE(map_start_sector)//reserved - .long 0 //reserved - .long ABS(EXT_C(buf_geom)) - .long ABS(EXT_C(tmp_geom)) - .long ABS(EXT_C(term_table)) + .extent ABS(EXT_C(image)) //12 struct grub_efi_loaded_image +VARIABLE(filesystem_type) //13 int + .extent 0 +//VARIABLE(query_block_entries) + .extent ABS(EXT_C(grub_efi_image_handle)) //14 void * + .extent ABS(EXT_C(grub_efi_system_table)) //15 grub_efi_system_table * + .extent ABS(EXT_C(buf_geom)) //16 geometry + .extent ABS(EXT_C(tmp_geom)) //17 geometry +VARIABLE(CONFIG_ENTRIES) //18 char * + .extent 0 VARIABLE(current_term) - .long ABS(EXT_C(term_table)) - .long ABS(EXT_C(fsys_table)) + .extent 0 //19 term_entry +// .extent ABS(EXT_C(term_table)) //19 term_entry + .extent ABS(EXT_C(fsys_table)) //20 fsys_entry //VARIABLE(fsys_type)//reserved - .long NUM_FSYS //reserved - .long NUM_FSYS //reserved -VARIABLE(graphics_inited) - .long 0 - .long 0 //reserved -VARIABLE(font8x16) - .long 0 -VARIABLE(fontx) - .long 0 -VARIABLE(fonty) - .long 0 -VARIABLE(graphics_CURSOR) - .long 0 - .long (EXT_C(menu_border)) -VARIABLE(gzip_filemax) - .long 0 - .long 0 + .extent fsys_type //21 int + .extent NUM_FSYS //22 常数 +VARIABLE(graphics_inited) //23 int + .extent 0 + .extent ABS(EXT_C(BASE_ADDR)) //24 char * +//VARIABLE(font8x16) //25 reserved + .extent 0 +VARIABLE(fontx) //26 int + .extent 0 +VARIABLE(fonty) //27 int + .extent 0 +VARIABLE(graphics_CURSOR) //28 void * + .extent 0 + .extent (EXT_C(menu_border)) //29 border 数组 +VARIABLE(gzip_filemax) //30 long long + .extent 0 + .extent ABS(EXT_C(WENV_ENVI)) //31 char * (实际是char **)!!! //reserved for wee - .long 0 // reserved 1 - .long 0 // reserved 2 - .long 0 // reserved 3 - .long 0 // reserved 4 - .long 0 // reserved 5 - .long 0 // reserved 6 - .long 0 // reserved 7 - .long 0 // reserved 8 - .long 0 // reserved 9 - .long 0 // reserved 10 +VARIABLE(bat_md_start) //32 grub_size_t + .extent 0 +VARIABLE(bat_md_count) //33 unsigned int + .extent 0 +VARIABLE(ext_data_0) //34 unsigned long long + .extent 0 +VARIABLE(ext_data_1) //35 unsigned long long + .extent 0 +VARIABLE(map_start_sector) //36 unsigned long long* + .extent 0 +VARIABLE(map_num_sectors) //37 unsigned long long* + .extent 0 +VARIABLE(query_block_entries) //38 int + .extent 0 + .extent 0 //39 reserved + .extent 0 //40 reserved + .extent 0 //41 reserved ////////////////////////////// -VARIABLE(current_color) - .long A_NORMAL +VARIABLE(current_color) //42 int + .extent A_NORMAL +VARIABLE(current_color_64bit) //43 long long + .extent 0xAAAAAA + .extent 0 //44 i386的32位背景色,x86_64没有用。 +VARIABLE(p_get_cmdline_str) //45 未使用 + .extent ABS(EXT_C(get_cmdline_str)) +VARIABLE(splashimage_loaded) //46 int + .extent 0 +VARIABLE(putchar_hooked) //47 unsigned char * + .extent 0 +//VARIABLE(init_free_mem_start) //48 reserved + .extent 0 -VARIABLE(current_color_64bit) - .long 0xAAAAAA /* lo 32 bits for foreground */ - .long 0 /* hi 32 bits for background */ -VARIABLE(p_get_cmdline_str) - .long ABS(EXT_C(get_cmdline_str)) -VARIABLE(splashimage_loaded) - .long 0 -VARIABLE(putchar_hooked) - .long 0 -VARIABLE(init_free_mem_start) - .long 0 - - -/* - flags for vbe splashimage - splashimage_loaded & ~0xf SPLASH_BASE_ADDR - if image load success set bit 1=1; - SPLASH_BASE_ADDR+4 image Width. - SPLASH_BASE_ADDR+8 image height - SPLASH_BASE_ADDR+16 image data - the image data use 32bit colors.eg. width=4,height=2 - xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx - xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx -*/ diff --git a/stage2/badgrubstart.S b/stage2/badgrubstart.S deleted file mode 100644 index 025f75b7..00000000 --- a/stage2/badgrubstart.S +++ /dev/null @@ -1,36 +0,0 @@ -/* - * badgrubstart.S -- DOS EXE and Linux kernel startup code for GNU GRUB - * Copyright (C) 2003-2008 Tinybit(tinybit@tom.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* Note for License: Since we have copied the Linux kernel code and the - * Linux kernel follows GPL2, so only GPL2 is adoptable and it rules here. - */ - -/* - * This program is used to generate the badgrub.exe file, which can boot off - * DOS directly or, in another way, boot off Linux through KEXEC. - * - * Use the following shell command to generate the badgrub.exe file: - * - * cat badgrubstart pre_stage2 > badgrub.exe - * - */ - -#define BAD_BIOS -#include "dosstart.S" - diff --git a/stage2/bios.c b/stage2/bios.c deleted file mode 100644 index 5025907a..00000000 --- a/stage2/bios.c +++ /dev/null @@ -1,815 +0,0 @@ -/* bios.c - implement C part of low-level BIOS disk input and output */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2003,2004 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "shared.h" -#include "iso9660.h" - -/* These are defined in asm.S, and never be used elsewhere, so declare the - prototypes here. */ -extern int biosdisk_standard (unsigned ah, unsigned drive, - unsigned coff, unsigned hoff, unsigned soff, - unsigned nsec, unsigned segment); -extern int get_diskinfo_standard (unsigned long drive, - unsigned long *cylinders, - unsigned long *heads, - unsigned long *sectors); - -/* Read/write NSEC sectors starting from SECTOR in DRIVE disk with GEOMETRY - from/into SEGMENT segment. If READ is BIOSDISK_READ, then read it, - else if READ is BIOSDISK_WRITE, then write it. If an geometry error - occurs, return BIOSDISK_ERROR_GEOMETRY, and if other error occurs, then - return the error number. Otherwise, return 0. */ -int -biosdisk (unsigned long read, unsigned long drive, struct geometry *geometry, - unsigned long long sector, unsigned long nsec, unsigned long segment) -{ - int err; - unsigned long max_sec, count, seg; - unsigned long long start; - - if ((fb_status) && (drive == (unsigned char)(fb_status >> 8))) - max_sec = (unsigned char)fb_status; - else - max_sec = nsec; - - /* first, use EBIOS if possible */ - if ((geometry->flags & BIOSDISK_FLAG_LBA_EXTENSION) && (! (geometry->flags & BIOSDISK_FLAG_BIFURCATE) || (drive & 0xFFFFFF00) == 0x100)) - { - struct disk_address_packet - { - unsigned char length; - unsigned char reserved; - unsigned short blocks; - unsigned long buffer; - unsigned long long block; - - /* This structure is passed in the stack. A buggy BIOS could write - * garbage data to the tail of the struct and hang the machine. So - * we need this protection. - Tinybit - */ - unsigned char dummy[16]; - } __attribute__ ((packed)) *dap; - - /* Even the above protection is not enough to avoid stupid actions by - * buggy BIOSes. So we do it in the 0040:0000 segment. - Tinybit - */ - dap = (struct disk_address_packet *)0x580; - - if (drive == 0xffff || (drive == ram_drive && rd_base != -1ULL)) - { - unsigned long long disk_sector; - unsigned long long buf_address; - unsigned long long tmp; - - if (nsec <=0 || nsec >= 0x80) - return 1; /* failure */ - if (sector + nsec > geometry->total_sectors) - return 1; /* failure */ - //if ((unsigned long)sector + (unsigned long)nsec >= 0x800000) - // return 1; /* failure */ - - tmp = ((sector + nsec) << 9); - if (drive == ram_drive) - tmp += rd_base; - else - tmp += md_part_base; - if (tmp > 0x100000000ULL && ! is64bit) - return 1; /* failure */ - disk_sector = ((sector<<9) + ((drive==0xffff) ? md_part_base : rd_base)); - buf_address = (segment<<4); - - if (read) /* read == 1 really means write to DISK */ - grub_memmove64 (disk_sector, buf_address, nsec << 9); - else /* read == 0 really means read from DISK */ - grub_memmove64 (buf_address, disk_sector, nsec << 9); - - return 0; /* success */ - } - - start = sector; - count = nsec; - seg = segment; - do - { - unsigned long n; - - n = (count > max_sec) ? max_sec : count; - if (n > 127) - n = 127; - - dap->length = 0x10; - dap->block = start; - dap->blocks = n; - dap->reserved = 0; - dap->buffer = seg << 16; - - if ((start > 0x100000000ULL) && (! is64bit)) - { - printf_debug ("biosdisk_int13_extensions read=%d, drive=0x%x, sector=0x%lx, \n", read, drive, sector); - return 1; - } - err = biosdisk_int13_extensions ((read + 0x42) << 8, (unsigned char)drive, dap, geometry->sector_size | (!!(geometry->flags & BIOSDISK_FLAG_LBA_1_SECTOR))); - start += n; - count -= n; - seg += n << 5; - } while ((count) && (! err)); - - if (!err) - return 0; /* success */ - - /* bootable CD-ROM specification has no standard CHS-mode call */ - if (geometry->flags & BIOSDISK_FLAG_CDROM) - { - printf_debug ("biosdisk_int13_extensions read=%d, drive=0x%x, dap=%x, err=0x%x\n", read, drive, dap, err); - return err; - } - - if (geometry->flags & BIOSDISK_FLAG_BIFURCATE) - return err; - - } /* if (geometry->flags & BIOSDISK_FLAG_LBA_EXTENSION) */ - - /* try the standard CHS mode */ - - if (sector >> 32) /* sector exceeding 32 bit, too big */ - return 1; /* failure */ - { - unsigned long cylinder_offset, head_offset, sector_offset; - unsigned long head; - - /* SECTOR_OFFSET is counted from one, while HEAD_OFFSET and - CYLINDER_OFFSET are counted from zero. */ - sector_offset = ((unsigned long)sector) % geometry->sectors + 1; - head = ((unsigned long)sector) / geometry->sectors; - head_offset = head % geometry->heads; - cylinder_offset = head / geometry->heads; - - if (cylinder_offset > 1023) /* cylinder too big */ - return 1; /* failure */ - do - { - unsigned long n; - - n = (nsec > max_sec) ? max_sec : nsec; - - /* we should avoid accessing sectors across track boundary. */ - if (n > geometry->sectors - sector_offset + 1) - n = geometry->sectors - sector_offset + 1; - - err = biosdisk_standard (read + 0x02, drive, - cylinder_offset, head_offset, sector_offset, - n, segment); - sector_offset += n; - nsec -= n; - segment += n << 5; - } while ((nsec) && (! err)); - } - - return err; -} - -/* Check bootable CD-ROM emulation status. Return 0 on failure. */ -int -get_cdinfo (unsigned long drive, struct geometry *geometry) -{ - int err; - struct iso_spec_packet - { - unsigned char size; - unsigned char media_type; - unsigned char drive_no; - unsigned char controller_no; - unsigned long image_lba; - unsigned short device_spec; - unsigned short cache_seg; - unsigned short load_seg; - unsigned short length_sec512; - unsigned char cylinders; - unsigned char sectors; - unsigned char heads; - - unsigned char dummy[16]; - } __attribute__ ((packed)); - - struct iso_spec_packet *cdrp; - - cdrp = (struct iso_spec_packet *)0x580; - grub_memset (cdrp, 0, sizeof (struct iso_spec_packet)); - cdrp->size = sizeof (struct iso_spec_packet) - 16; - - printf_debug ("\rget_cdinfo int13/4B01(%X), ", drive); - err = biosdisk_int13_extensions (0x4B01, drive, cdrp, 2048); - printf_debug("err=%X, ", err); - - if (drive == 0x7F && drive < (unsigned long)(cdrp->drive_no)) - drive = cdrp->drive_no; - - if (! err && cdrp->drive_no == drive && !(cdrp->media_type & 0x0F)) - { - /* No-emulation mode bootable CD-ROM */ - geometry->flags = BIOSDISK_FLAG_LBA_EXTENSION | BIOSDISK_FLAG_CDROM; - geometry->cylinders = 65536; - geometry->heads = 255; - geometry->sectors = 15; - geometry->sector_size = 2048; - geometry->total_sectors = 65536 * 255 * 15; - printf_debug ("drive=%d\n", drive); - DEBUG_SLEEP - return drive; - } - if (debug > 1) { - if (err) - grub_printf ("drive=0\n"); - else - grub_printf ("\r%40s\r", " "); /* erase line if no err and drive are both 0 */ - } - return 0; /* failure */ -} - -static unsigned long flags; -static unsigned long cylinders; -static unsigned long heads; -static unsigned long sectors; -static unsigned long heads_ok; -static unsigned long sectors_ok; -unsigned long force_geometry_tune = 0; - -/* Return the geometry of DRIVE in GEOMETRY. If an error occurs, return - non-zero, otherwise zero. */ -int -get_diskinfo (unsigned long drive, struct geometry *geometry, unsigned long lba1sector) -{ - int err; - int version; - unsigned long long total_sectors = 0, tmp = 0; -#if MAP_NUM_16 - /* backup hooked_drive_map_1[0] onto hooked_drive_map[0] */ - grub_memmove ((char *) &hooked_drive_map[0], (char *) &hooked_drive_map_1[0], sizeof (struct drive_map_slot)*8); - /* backup hooked_drive_map_2[0] onto hooked_drive_map[8] */ - grub_memmove ((char *) &hooked_drive_map[8], (char *) &hooked_drive_map_2[0], sizeof (struct drive_map_slot)*9); -#endif - - if (drive == 0xffff) /* memory disk */ - { - unsigned long long total_mem_sectors; - total_mem_sectors = 0; - - if (mbi.flags & MB_INFO_MEM_MAP) - { - struct AddrRangeDesc *map = (struct AddrRangeDesc *) saved_mmap_addr; - unsigned long end_addr = saved_mmap_addr + saved_mmap_length; - - for (; end_addr > (unsigned long) map; map = (struct AddrRangeDesc *) (((int) map) + 4 + map->size)) - { - unsigned long long top_end; - - if (map->Type != MB_ARD_MEMORY) - continue; - top_end = map->BaseAddr + map->Length; - /* check overflow... */ - if (top_end < map->BaseAddr && top_end < map->Length) - total_mem_sectors = 0x80000000000000ULL; - else - { - if (top_end > 0x100000000ULL && ! is64bit) - top_end = 0x100000000ULL; - if (total_mem_sectors < (top_end >> SECTOR_BITS)) - total_mem_sectors = (top_end >> SECTOR_BITS); - } - - } - } - else - grub_printf ("Address Map BIOS Interface is not activated.\n"); - -// if (total_mem_sectors) -// { - geometry->flags = BIOSDISK_FLAG_LBA_EXTENSION; - geometry->sector_size = SECTOR_SIZE; - /* if for some reason(e.g., a bios bug) the memory is reported less than 1M(too few), then we suppose the memory is unlimited. */ - if (md_part_size) - geometry->total_sectors = (md_part_size >> SECTOR_BITS) + !!(md_part_size & (SECTOR_SIZE - 1)); - else - geometry->total_sectors = (total_mem_sectors < 0x800ULL ? 0x80000000000000ULL : total_mem_sectors); - geometry->heads = 255; - geometry->sectors = 63; - geometry->cylinders = (geometry->total_sectors > (0xFFFFFFFFULL - 255 * 63 + 1) ? 0xFFFFFFFFUL / (255UL * 63UL):((unsigned long)geometry->total_sectors + 255 * 63 -1) / (255 * 63)); - return 0; -// } - - } else if (drive == ram_drive) /* ram disk device */ - { - if (rd_base != -1ULL) - { - geometry->flags = BIOSDISK_FLAG_LBA_EXTENSION; - geometry->sector_size = SECTOR_SIZE; - geometry->total_sectors = (rd_size >> SECTOR_BITS) + !!(rd_size & (SECTOR_SIZE - 1)); - geometry->heads = 255; - geometry->sectors = 63; - geometry->cylinders = (geometry->total_sectors > (0xFFFFFFFFULL - 255 * 63 + 1) ? 0xFFFFFFFFUL / (255UL * 63UL):((unsigned long)geometry->total_sectors + 255 * 63 -1) / (255 * 63)); - return 0; - } - } - - if (drive == cdrom_drive || (drive >= (unsigned char)min_cdrom_id && drive < (unsigned char)(min_cdrom_id + atapi_dev_count))) - { - /* No-emulation mode bootable CD-ROM */ - geometry->flags = BIOSDISK_FLAG_LBA_EXTENSION | BIOSDISK_FLAG_CDROM; - geometry->cylinders = 65536; - geometry->heads = 255; - geometry->sectors = 15; - geometry->sector_size = 2048; - geometry->total_sectors = 65536 * 255 * 15; - return 0; - } - - /* Clear the flags. */ - flags = 0; - heads_ok = 0; - sectors_ok = 0; - -#define FIND_DRIVES (*((char *)0x475)) - if (((unsigned char)drive) >= 0x80 + FIND_DRIVES /* || (version && (drive & 0x80)) */ ) - { - /* Possible CD-ROM - check the status. */ - if (get_cdinfo ((unsigned char)drive, geometry)) - return 0; - } - - //if (! force_geometry_tune) - { - unsigned long j; - unsigned long d; - - /* check if the drive is virtual. */ - d = (unsigned char)drive; - j = DRIVE_MAP_SIZE; /* real drive */ - if (! unset_int13_handler (1)) - for (j = 0; j < DRIVE_MAP_SIZE; j++) - { - if (drive_map_slot_empty (hooked_drive_map[j])) - { - j = DRIVE_MAP_SIZE; /* real drive */ - break; - } - - if (((unsigned char)drive) != hooked_drive_map[j].from_drive) - continue; - - /* this is a mapped drive */ - /* check cdrom emulation first */ - if (hooked_drive_map[j].to_cylinder & 0x2000) /* drive is cdrom */ - { - geometry->flags = BIOSDISK_FLAG_CDROM | BIOSDISK_FLAG_LBA_EXTENSION; - geometry->heads = 255; - geometry->sectors = 15; - geometry->sector_size = 2048; - geometry->total_sectors = hooked_drive_map[j].sector_count >> 2; - geometry->cylinders = (geometry->total_sectors > (0xFFFFFFFFULL - 255 * 15 + 1) ? 0xFFFFFFFFUL / (255UL * 15UL):((unsigned long)geometry->total_sectors + 255 * 15 -1) / (255 * 15)); - if (! geometry->cylinders) - { - geometry->cylinders = 65536; - geometry->total_sectors = 65536 * 255 * 15; - } - return 0; - } - if ((hooked_drive_map[j].max_sector & 0x3E) == 0 && hooked_drive_map[j].start_sector == 0 && hooked_drive_map[j].sector_count <= 1) - { - /* this is a map for the whole drive. */ - d = hooked_drive_map[j].to_drive; - j = DRIVE_MAP_SIZE; /* real drive */ - break; - } - //break; - /* this is a drive emulation, get the geometry from the drive map table */ - geometry->flags = BIOSDISK_FLAG_LBA_EXTENSION; - geometry->heads = hooked_drive_map[j].max_head + 1; - geometry->sectors = hooked_drive_map[j].max_sector & 0x3F; - geometry->sector_size = 512; - geometry->total_sectors = hooked_drive_map[j].sector_count; - geometry->cylinders = (geometry->heads * geometry->sectors); - geometry->cylinders = (geometry->total_sectors > (0xFFFFFFFFULL - geometry->cylinders + 1) ? 0xFFFFFFFFUL / geometry->cylinders:((unsigned long)geometry->total_sectors + geometry->cylinders - 1) / geometry->cylinders); - return 0; - } - - if (j == DRIVE_MAP_SIZE) /* real drive */ - { - if (d >= 0x80 && d < 0x88) - { - d -= 0x80; - if (lba1sector & 0x80) - hd_geom[d].flags &= ~BIOSDISK_FLAG_LBA_1_SECTOR; - else if (lba1sector & 1) - hd_geom[d].flags |= BIOSDISK_FLAG_LBA_1_SECTOR; - flags = (hd_geom[d].flags & (BIOSDISK_FLAG_GEOMETRY_OK | BIOSDISK_FLAG_LBA_1_SECTOR)); - heads_ok = hd_geom[d].heads; - sectors_ok = hd_geom[d].sectors; - if (hd_geom[d].sector_size == 512 && hd_geom[d].sectors > 0 && hd_geom[d].sectors <= 63 && hd_geom[d].heads <= 256) - { - if ((! force_geometry_tune) || (flags & BIOSDISK_FLAG_GEOMETRY_OK)) - { - geometry->flags = hd_geom[d].flags; - if ((geometry->flags & BIOSDISK_FLAG_BIFURCATE) && (drive & 0xFFFFFF00) == 0x100) - { - if (geometry->flags & BIOSDISK_FLAG_CDROM) - { - geometry->cylinders = 65536; - geometry->heads = 255; - geometry->sectors = 15; - geometry->sector_size = 2048; - geometry->total_sectors = 65536 * 255 * 15; - return 0; - } - } - geometry->sector_size = hd_geom[d].sector_size; - geometry->total_sectors = hd_geom[d].total_sectors; - geometry->heads = hd_geom[d].heads; - geometry->sectors = hd_geom[d].sectors; - geometry->cylinders = hd_geom[d].cylinders; - return 0; - } - } - } else if (d < 4) { - if (lba1sector & 0x80) - fd_geom[d].flags &= ~BIOSDISK_FLAG_LBA_1_SECTOR; - else if (lba1sector & 1) - fd_geom[d].flags |= BIOSDISK_FLAG_LBA_1_SECTOR; - flags = (fd_geom[d].flags & (BIOSDISK_FLAG_GEOMETRY_OK | BIOSDISK_FLAG_LBA_1_SECTOR)); - heads_ok = fd_geom[d].heads; - sectors_ok = fd_geom[d].sectors; - if (fd_geom[d].sector_size == 512 && fd_geom[d].sectors > 0 && fd_geom[d].sectors <= 63 && fd_geom[d].heads <= 256) - { - if ((! force_geometry_tune) || (flags & BIOSDISK_FLAG_GEOMETRY_OK)) - { - geometry->flags = fd_geom[d].flags; - if ((geometry->flags & BIOSDISK_FLAG_BIFURCATE) && (drive & 0xFFFFFF00) == 0x100) - { - if (geometry->flags & BIOSDISK_FLAG_CDROM) - { - geometry->cylinders = 65536; - geometry->heads = 255; - geometry->sectors = 15; - geometry->sector_size = 2048; - geometry->total_sectors = 65536 * 255 * 15; - return 0; - } - } - geometry->sector_size = fd_geom[d].sector_size; - geometry->total_sectors = fd_geom[d].total_sectors; - geometry->heads = fd_geom[d].heads; - geometry->sectors = fd_geom[d].sectors; - geometry->cylinders = fd_geom[d].cylinders; - return 0; - } - } - } - } - } - - printf_debug ("\rget_diskinfo int13/41(%X), ", drive); - version = check_int13_extensions ((unsigned char)drive, (lba1sector | (!!(flags & BIOSDISK_FLAG_LBA_1_SECTOR)))); - printf_debug ("version=%X, ", version); - - /* Set the LBA flag. */ - if (version & 1) /* support functions 42h-44h, 47h-48h */ - { - flags |= BIOSDISK_FLAG_LBA_EXTENSION; - if (version & 0x100) /* cannot read 127 sectors at a time. */ - flags |= BIOSDISK_FLAG_LBA_1_SECTOR; - } - total_sectors = 0; - - printf_debug ("int13/08(%X), ", drive); - - version = get_diskinfo_standard ((unsigned char)drive, &cylinders, &heads, §ors); - - printf_debug ("version=%X, C/H/S=%d/%d/%d, ", version, cylinders, heads, sectors); - - printf_debug ("int13/02(%X), ", drive); - - /* read the boot sector: int 13, AX=0x201, CX=1, DH=0. Use buffer 0x20000 - 0x2FFFF */ - err = biosdisk_standard (0x02, (unsigned char)drive, 0, 0, 1, 1, 0x2F00/*SCRATCHSEG*/); - - printf_debug ("err=%X\n", err); - DEBUG_SLEEP - - //version = 0; - - /* try again using LBA */ - if (flags & BIOSDISK_FLAG_LBA_EXTENSION || ((unsigned char)drive) >= 0x80 + FIND_DRIVES) - { - struct disk_address_packet - { - unsigned char length; - unsigned char reserved; - unsigned short blocks; - unsigned long buffer; - unsigned long long block; - - unsigned char dummy[16]; - } __attribute__ ((packed)) *dap; - - dap = (struct disk_address_packet *)0x580; - - dap->length = 0x10; - dap->reserved = 0; - dap->blocks = 1; - dap->buffer = 0x2F80/*SCRATCHSEG*/ << 16; - dap->block = 0; - - /* set a known value */ - grub_memset ((char *)0x2F800, 0xEC, 0x800); - version = biosdisk_int13_extensions (0x4200, (unsigned char)drive, dap, 0); - /* see if it is a big sector */ - { - char *p; - for (p = (char *)0x2FA00; p < (char *)0x30000; p++) - { - if ((*p) != (char)0xEC) - { - flags |= BIOSDISK_FLAG_CDROM | BIOSDISK_FLAG_LBA_EXTENSION; - if (! err) - flags |= BIOSDISK_FLAG_BIFURCATE; - break; - } - } - } - if ((! version) && (! err)) - { - if (grub_memcmp ((char *)0x2F060, (char *)0x2F860, 0x150)) /* ignore BPB and partition table */ - { - flags |= BIOSDISK_FLAG_BIFURCATE; - } - } - if (err && ! (flags & BIOSDISK_FLAG_BIFURCATE) && !(flags & BIOSDISK_FLAG_CDROM)) - { - grub_memmove ((char *)0x2F000, (char *)0x2F800, 0x200); - } - - } /* if (geometry->flags & BIOSDISK_FLAG_LBA_EXTENSION) */ - - if (err && version) - return err; /* When we return with ERROR, we should not change the geometry!! */ - - geometry->flags = flags; - - if (err && (flags & BIOSDISK_FLAG_CDROM)) - { - geometry->cylinders = 65536; - geometry->heads = 255; - geometry->sectors = 15; - geometry->sector_size = 2048; - geometry->total_sectors = 65536 * 255 * 15; - return 0; - } - - geometry->cylinders = cylinders; - geometry->heads = heads; - geometry->sectors = sectors; - geometry->sector_size = SECTOR_SIZE; - if (geometry->heads > 256) - geometry->heads = 256; - if (geometry->sectors * geometry->sector_size > 63 * 512) - geometry->sectors = 63 * 512 / geometry->sector_size; - tmp = (unsigned long long)(geometry->cylinders) * - (unsigned long long)(geometry->heads) * - (unsigned long long)(geometry->sectors); -// if (total_sectors < tmp) - total_sectors = tmp; - geometry->total_sectors = total_sectors; - - /* successfully read boot sector */ - - if (force_geometry_tune != 2) /* if not force BIOS geometry */ - { - if (drive & 0x80) - { - /* hard disk */ - if ((err = probe_mbr((struct master_and_dos_boot_sector *)0x2F000/*SCRATCHADDR*/, 0, total_sectors, 0))) - { - if (probe_bpb((struct master_and_dos_boot_sector *)0x2F000/*SCRATCHADDR*/)) - { - printf_warning ("\nWarning: Unrecognized partition table for drive %X. Please rebuild it using\na Microsoft-compatible FDISK tool(err=%d). Current C/H/S=%d/%d/%d\n", drive, err, geometry->cylinders, geometry->heads, geometry->sectors); - goto failure_probe_boot_sector; - } - err = (int)"BPB"; - goto yes_fdd; - } - err = (int)"MBR"; - }else{ - /* floppy */ - if (probe_bpb((struct master_and_dos_boot_sector *)0x2F000/*SCRATCHADDR*/)) - { - goto failure_probe_boot_sector; - } - - err = (int)"BPB"; - } -yes_fdd: - if (drive & 0x80) - if (probed_cylinders != geometry->cylinders) - printf_warning ("\nWarning: %s cylinders(%d) is not equal to the BIOS one(%d).\n", err, probed_cylinders, geometry->cylinders); - - geometry->cylinders = probed_cylinders; - - if (probed_heads != geometry->heads) - printf_warning ("\nWarning: %s heads(%d) is not equal to the BIOS one(%d).\n", err, probed_heads, geometry->heads); - - geometry->heads = probed_heads; - - if (probed_sectors_per_track != geometry->sectors) - printf_warning ("\nWarning: %s sectors per track(%d) is not equal to the BIOS one(%d).\n", err, probed_sectors_per_track, geometry->sectors); - - geometry->sectors = probed_sectors_per_track; - if (probed_total_sectors) - geometry->total_sectors = probed_total_sectors; - - if (probed_total_sectors > total_sectors) - { - if (drive & 0x80) - printf_warning ("\nWarning: %s total sectors(%d) is greater than the BIOS one(%d).\nSome buggy BIOSes could hang when you access sectors exceeding the BIOS limit.\n", err, probed_total_sectors, total_sectors); -// geometry->total_sectors = probed_total_sectors; - } - - if (drive & 0x80) - if (probed_total_sectors < total_sectors) - printf_warning ("\nWarning: %s total sectors(%d) is less than the BIOS one(%d).\n", err, probed_total_sectors, total_sectors); - - } -failure_probe_boot_sector: - -#if 1 - if (flags & BIOSDISK_FLAG_GEOMETRY_OK) - { - err = geometry->heads; - version = geometry->sectors; - - geometry->heads = heads_ok; - geometry->sectors = sectors_ok; - - if (debug > 1) - { - if (err != geometry->heads) - printf_warning ("\n!! number of heads for drive %X restored from %d to %d.\n", drive, err, geometry->heads); - if (version != geometry->sectors) - printf_warning ("\n!! sectors-per-track for drive %X restored from %d to %d.\n", drive, version, geometry->sectors); - } - } - else if (force_geometry_tune==1 || (!(flags & BIOSDISK_FLAG_LBA_EXTENSION) && ! ((*(char *)0x8205) & 0x08))) - { - err = geometry->heads; - version = geometry->sectors; - - /* DH non-zero for geometry_tune */ - get_diskinfo_standard (drive | 0x0100, &geometry->cylinders, &geometry->heads, &geometry->sectors); - - if (debug > 0) - { - if (err != geometry->heads) - printf_warning ("\nNotice: number of heads for drive %X tuned from %d to %d.\n", drive, err, geometry->heads); - if (version != geometry->sectors) - printf_warning ("\nNotice: sectors-per-track for drive %X tuned from %d to %d.\n", drive, version, geometry->sectors); - } - } -#endif - - /* if C/H/S=0/0/0, use a safe default one. */ - if (geometry->sectors == 0) - { - if (drive & 0x80) - { - /* hard disk */ - geometry->sectors = 63; - }else{ - /* floppy */ - if (geometry->total_sectors > 5760) - geometry->sectors = 63; - else if (geometry->total_sectors > 2880) - geometry->sectors = 36; - else - geometry->sectors = 18; - } - } - if (geometry->heads == 0) - { - if (drive & 0x80) - { - /* hard disk */ - geometry->heads = 255; - }else{ - /* floppy */ - if (geometry->total_sectors > 5760) - geometry->heads = 255; - else - geometry->heads = 2; - } - } - if (geometry->cylinders == 0) - { - unsigned long long tmp_sectors = geometry->total_sectors; - - if (tmp_sectors > 0xFFFFFFFFULL) - tmp_sectors = 0xFFFFFFFFULL; - geometry->cylinders = (((unsigned long)tmp_sectors) / geometry->heads / geometry->sectors); - } - - if (geometry->cylinders == 0) - geometry->cylinders = 1; -// total_sectors = geometry->cylinders * geometry->heads * geometry->sectors; -// if (geometry->total_sectors < total_sectors) -// geometry->total_sectors = total_sectors; - - /* backup the geometry into array hd_geom or fd_geom. */ - - { - unsigned long j; - unsigned long d; - - /* check if the drive is virtual. */ - d = (unsigned char)drive; - j = DRIVE_MAP_SIZE; /* real drive */ - if (! unset_int13_handler (1)) - for (j = 0; j < DRIVE_MAP_SIZE; j++) - { - if (drive_map_slot_empty (hooked_drive_map[j])) - { - j = DRIVE_MAP_SIZE; /* real drive */ - break; - } - - if (((unsigned char)drive) != hooked_drive_map[j].from_drive) - continue; - if (hooked_drive_map[j].to_cylinder & 0x2000) /* drive is cdrom */ - break; - if ((hooked_drive_map[j].max_sector & 0x3E) == 0 && hooked_drive_map[j].start_sector == 0 && hooked_drive_map[j].sector_count <= 1) - { - /* this is a map for the whole drive. */ - d = hooked_drive_map[j].to_drive; - j = DRIVE_MAP_SIZE; /* real drive */ - } - break; - } - - if (j == DRIVE_MAP_SIZE) /* real drive */ - { - if (d >= 0x80 && d < 0x88) - { - d -= 0x80; - if (force_geometry_tune || hd_geom[d].sector_size != 512 || hd_geom[d].sectors <= 0 || hd_geom[d].sectors > 63 || hd_geom[d].heads > 256) - { - hd_geom[d].flags &= BIOSDISK_FLAG_GEOMETRY_OK; - hd_geom[d].flags |= geometry->flags; - hd_geom[d].sector_size = geometry->sector_size; - hd_geom[d].total_sectors = geometry->total_sectors; - hd_geom[d].heads = geometry->heads; - hd_geom[d].sectors = geometry->sectors; - hd_geom[d].cylinders = geometry->cylinders; - } - } else if (d < 4) { - if (force_geometry_tune || fd_geom[d].sector_size != 512 || fd_geom[d].sectors <= 0 || fd_geom[d].sectors > 63 || fd_geom[d].heads > 256) - { - fd_geom[d].flags &= BIOSDISK_FLAG_GEOMETRY_OK; - fd_geom[d].flags |= geometry->flags; - fd_geom[d].sector_size = geometry->sector_size; - fd_geom[d].total_sectors = geometry->total_sectors; - fd_geom[d].heads = geometry->heads; - fd_geom[d].sectors = geometry->sectors; - fd_geom[d].cylinders = geometry->cylinders; - } - } - } - } - if ((geometry->flags & BIOSDISK_FLAG_BIFURCATE) && (drive & 0xFFFFFF00) == 0x100) - { - if (geometry->flags & BIOSDISK_FLAG_CDROM) - { - geometry->cylinders = 65536; - geometry->heads = 255; - geometry->sectors = 15; - geometry->sector_size = 2048; - geometry->total_sectors = 65536 * 255 * 15; - } - } - - return 0; -} - -#undef FIND_DRIVES - diff --git a/stage2/boot.c b/stage2/boot.c index 52b2b93f..7de3ebad 100644 --- a/stage2/boot.c +++ b/stage2/boot.c @@ -20,20 +20,25 @@ #include "shared.h" -#include +#include "term.h" #include "cpio.h" #include "freebsd.h" +//void bsd_boot (kernel_t type, int bootdev, char *arg) __attribute__ ((noreturn)); +void bsd_boot (kernel_t type, int bootdev, char *arg); +int load_module (char *module, char *arg); +int load_initrd (char *initrd); + struct exec { - unsigned long a_midmag; /* htonl(flags<<26 | mid<<16 | magic) */ - unsigned long a_text; /* text segment size */ - unsigned long a_data; /* initialized data size */ - unsigned long a_bss; /* uninitialized data size */ - unsigned long a_syms; /* symbol table size */ - unsigned long a_entry; /* entry point */ - unsigned long a_trsize; /* text relocation size */ - unsigned long a_drsize; /* data relocation size */ + unsigned int a_midmag; /* htonl(flags<<26 | mid<<16 | magic) */ + unsigned int a_text; /* text segment size */ + unsigned int a_data; /* initialized data size */ + unsigned int a_bss; /* uninitialized data size */ + unsigned int a_syms; /* symbol table size */ + unsigned int a_entry; /* entry point */ + unsigned int a_trsize; /* text relocation size */ + unsigned int a_drsize; /* data relocation size */ }; #define ntohl(x) ((x << 24) | ((x & 0xFF00) << 8) | ((x >> 8) & 0xFF00) | (x >> 24)) #define htonl(x) ntohl(x) @@ -96,11 +101,11 @@ typedef struct #define EM_386 3 /* i386 -- obviously use this one */ unsigned short e_machine; /* machine types */ - unsigned long e_version; /* use same as "EI_VERSION" above */ - unsigned long e_entry; /* entry point of the program */ - unsigned long e_phoff; /* program header table file offset */ - unsigned long e_shoff; /* section header table file offset */ - unsigned long e_flags; /* flags */ + unsigned int e_version; /* use same as "EI_VERSION" above */ + unsigned int e_entry; /* entry point of the program */ + unsigned int e_phoff; /* program header table file offset */ + unsigned int e_shoff; /* section header table file offset */ + unsigned int e_flags; /* flags */ unsigned short e_ehsize; /* elf header size in bytes */ unsigned short e_phentsize; /* program header entry size */ unsigned short e_phnum; /* number of entries in program header */ @@ -128,29 +133,29 @@ Elf32_Ehdr; typedef struct { - unsigned long sh_name; /* Section name (string tbl index) */ - unsigned long sh_type; /* Section type */ - unsigned long sh_flags; /* Section flags */ - unsigned long sh_addr; /* Section virtual addr at execution */ - unsigned long sh_offset; /* Section file offset */ - unsigned long sh_size; /* Section size in bytes */ - unsigned long sh_link; /* Link to another section */ - unsigned long sh_info; /* Additional section information */ - unsigned long sh_addralign; /* Section alignment */ - unsigned long sh_entsize; /* Entry size if section holds table */ + unsigned int sh_name; /* Section name (string tbl index) */ + unsigned int sh_type; /* Section type */ + unsigned int sh_flags; /* Section flags */ + unsigned int sh_addr; /* Section virtual addr at execution */ + unsigned int sh_offset; /* Section file offset */ + unsigned int sh_size; /* Section size in bytes */ + unsigned int sh_link; /* Link to another section */ + unsigned int sh_info; /* Additional section information */ + unsigned int sh_addralign; /* Section alignment */ + unsigned int sh_entsize; /* Entry size if section holds table */ } Elf32_Shdr; typedef struct { - unsigned long p_type; - unsigned long p_offset; - unsigned long p_vaddr; - unsigned long p_paddr; - unsigned long p_filesz; - unsigned long p_memsz; - unsigned long p_flags; - unsigned long p_align; + unsigned int p_type; + unsigned int p_offset; + unsigned int p_vaddr; + unsigned int p_paddr; + unsigned int p_filesz; + unsigned int p_memsz; + unsigned int p_flags; + unsigned int p_align; } Elf32_Phdr; @@ -163,7 +168,7 @@ Elf32_Phdr; #define PT_PHDR 6 -unsigned long cur_addr; +unsigned int cur_addr; entry_func entry_addr; /* @@ -173,22 +178,22 @@ entry_func entry_addr; * sizeof(mod_list) == 16. So mll[99] occupies less than 2K. */ struct mod_list mll[99]; -static unsigned long long linux_mem_size; +//static unsigned long long linux_mem_size; /* * The next two functions, 'load_image' and 'load_module', are the building * blocks of the multiboot loader component. They handle essentially all * of the gory details of loading in a bootable image and the modules. */ - kernel_t load_image (char *kernel, char *arg, kernel_t suggested_type, - unsigned long load_flags) + unsigned int load_flags) { - unsigned long len, i, exec_type = 0, align_4k = 1; +#if 0 + unsigned int len, i, exec_type = 0, align_4k = 1; entry_func real_entry_addr = 0; kernel_t type = KERNEL_TYPE_NONE; - unsigned long flags = 0, text_len = 0, data_len = 0, bss_len = 0; + unsigned int flags = 0, text_len = 0, data_len = 0, bss_len = 0; char *str = 0, *str2 = 0; struct linux_kernel_header *lh; union @@ -200,13 +205,16 @@ load_image (char *kernel, char *arg, kernel_t suggested_type, pu; /* presuming that MULTIBOOT_SEARCH is large enough to encompass an executable header */ - unsigned char *buffer = (unsigned char *)(FSYS_BUF - MULTIBOOT_SEARCH); +// unsigned char *buffer = (unsigned char *)((char *)FSYS_BUF - MULTIBOOT_SEARCH); + unsigned char *buffer = grub_malloc (0x2000); + if (!buffer) + return 0; - if (free_mem_start > (unsigned long)linux_bzimage_tmp_addr) - { - errnum = ERR_KERNEL_WITH_PROGRAM; - goto failure; - } +// if (free_mem_start > (unsigned long)linux_bzimage_tmp_addr) +// { +// errnum = ERR_KERNEL_WITH_PROGRAM; +// goto failure; +// } errnum = ERR_NONE; /* sets the header pointer to point to the beginning of the @@ -252,11 +260,11 @@ load_image (char *kernel, char *arg, kernel_t suggested_type, else entry_addr = (entry_func) (pu.elf->e_entry & 0xFFFFFF); - if (entry_addr < (entry_func) 0x100000) - { - errnum = ERR_BELOW_1MB; - goto failure_exec_format; - } +// if (entry_addr < (entry_func) 0x100000) +// { +// errnum = ERR_BELOW_1MB; +// goto failure_exec_format; +// } /* don't want to deal with ELF program header at some random place in the file -- this generally won't happen */ @@ -309,11 +317,11 @@ load_image (char *kernel, char *arg, kernel_t suggested_type, || (pu.mb->header_addr - pu.mb->load_addr) > i) goto failure_exec_format; - if (cur_addr < 0x100000) - { - errnum = ERR_BELOW_1MB; - goto failure_exec_format; - } +// if (cur_addr < 0x100000) +// { +// errnum = ERR_BELOW_1MB; +// goto failure_exec_format; +// } pu.aout = (struct exec *) buffer; exec_type = 2; @@ -429,12 +437,12 @@ load_image (char *kernel, char *arg, kernel_t suggested_type, errnum = ERR_WONT_FIT; goto failure_exec_format; } - if (linux_data_real_addr + LINUX_SETUP_MOVE_SIZE - > RAW_ADDR ((char *) ((*(unsigned short *)0x413) << 10/*saved_mem_lower << 10*/))) - { - errnum = ERR_WONT_FIT; - goto failure_exec_format; - } +// if (linux_data_real_addr + LINUX_SETUP_MOVE_SIZE +// > RAW_ADDR ((char *) ((*(unsigned short *)0x413) << 10/*saved_mem_lower << 10*/))) +// { +// errnum = ERR_WONT_FIT; +// goto failure_exec_format; +// } if (debug > 0) grub_printf (" [Linux-%s, setup=0x%x, size=0x%x]\n", @@ -864,7 +872,7 @@ load_image (char *kernel, char *arg, kernel_t suggested_type, else symtab_err = 1; - if (mbi.syms.e.addr < (unsigned long)(RAW_ADDR(0x10000))) + if (mbi.syms.e.addr < (unsigned long long)(RAW_ADDR(0x10000))) symtab_err = 1; if (symtab_err) @@ -899,6 +907,7 @@ load_image (char *kernel, char *arg, kernel_t suggested_type, success: grub_close (); + grub_free (buffer); return type; failure_newline: @@ -914,14 +923,16 @@ load_image (char *kernel, char *arg, kernel_t suggested_type, errnum = ERR_EXEC_FORMAT; failure: - + grub_free (buffer); +#endif return KERNEL_TYPE_NONE; } int load_module (char *module, char *arg) { - unsigned long len; +#if 0 + unsigned long long len; /* if we are supposed to load on 4K boundaries */ cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000; @@ -955,23 +966,18 @@ load_module (char *module, char *arg) mbi.mods_count++; grub_close (); +#endif return 1; } +extern int disable_map_info; struct linux_kernel_header *linux_header; -unsigned long initrd_drver_block; -void cpio_set_field(char *field,unsigned long value); - -void cpio_set_field(char *field,unsigned long value) -{ - char buf[9]; - sprintf(buf,"%08x",value); - memcpy(field,buf,8); -} +unsigned int initrd_drver_block; int load_initrd (char *initrd) { +#if 0 unsigned long long len; unsigned long long moveto; unsigned long long tmp; @@ -979,21 +985,20 @@ load_initrd (char *initrd) char *arg = initrd; char *name = initrd; - //linux_header = (struct linux_kernel_header *) (cur_addr - LINUX_SETUP_MOVE_SIZE); - /* + linux_header = (struct linux_kernel_header *) (cur_addr - LINUX_SETUP_MOVE_SIZE); + tmp = ((linux_header->header == LINUX_MAGIC_SIGNATURE && linux_header->version >= 0x0203) ? linux_header->initrd_addr_max : LINUX_INITRD_MAX_ADDRESS); - */ + if (linux_mem_size) moveto = linux_mem_size; else moveto = 0x100000000ULL; - /* + moveto = (saved_mem_upper + 0x400) << 10; if (moveto > 0x100000000ULL) moveto = 0x100000000ULL; - */ top_addr = moveto; /* XXX: Linux 2.3.xx has a bug in the memory range check, so avoid @@ -1002,10 +1007,10 @@ load_initrd (char *initrd) worse than that of Linux 2.3.xx, so avoid the last 64kb. *sigh* */ moveto -= 0x10000; -/* + if (moveto > tmp) moveto = tmp; -*/ + moveto &= 0xfffff000; if (debug > 2) @@ -1062,10 +1067,10 @@ load_initrd (char *initrd) linux_header->ramdisk_size += 0xFFF; linux_header->ramdisk_size &= 0xFFFFF000; tmp += initrd_drver_block; - sprintf (map_tmp, "--mem=-%d (md)0x%x+0x%x (0x22)", (unsigned long)tmp,linux_header->ramdisk_image>>9,linux_header->ramdisk_size>>9); // INITRD_DRIVE + sprintf (map_tmp, "--mem=-%d (md)0x%x+0x%x (0x22)", (unsigned long long)tmp,linux_header->ramdisk_image>>9,linux_header->ramdisk_size>>9); // INITRD_DRIVE map_func ("(0x22) (0x22)", 0/*flags*/); } else { - sprintf (map_tmp, "--mem=-%d (md)0x800+8 (0x22)", (unsigned long)tmp); // INITRD_DRIVE + sprintf (map_tmp, "--mem=-%d (md)0x800+8 (0x22)", (unsigned long long)tmp); // INITRD_DRIVE } initrd_drver_block = tmp; @@ -1093,7 +1098,7 @@ load_initrd (char *initrd) } top_addr = moveto = initrd_start_sector << 9; moveto += linux_header->ramdisk_size; - memset ((char *)(unsigned long)moveto, 0, (tmp << 9)-linux_header->ramdisk_size); + memset ((char *)(unsigned long long)moveto, 0, (tmp << 9)-linux_header->ramdisk_size); initrd = arg; len = linux_header->ramdisk_size; @@ -1129,8 +1134,6 @@ load_initrd (char *initrd) if (tmp != filemax) { - //sprintf (map_tmp, "(0x22) (0x22)"); // INITRD_DRIVE - //map_func (map_tmp, 0/*flags*/); map_func ("(0x22) (0x22)", 0/*flags*/); if (! errnum) errnum = ERR_READ; @@ -1157,7 +1160,7 @@ load_initrd (char *initrd) buf_track = -1; } if (debug > 0) - printf (" [Linux-initrd @ 0x%x, 0x%x bytes]\n", (unsigned long)top_addr, (unsigned long)len); + printf (" [Linux-initrd @ 0x%x, 0x%x bytes]\n", (unsigned long long)top_addr, (unsigned long long)len); /* FIXME: Should check if the kernel supports INITRD. */ linux_header->ramdisk_image = RAW_ADDR (top_addr); @@ -1166,6 +1169,8 @@ load_initrd (char *initrd) fail: return ! errnum; +#endif + return 0; } @@ -1180,11 +1185,12 @@ load_initrd (char *initrd) void bsd_boot (kernel_t type, int bootdev, char *arg) { +#if 0 char *str; int clval = 0, i; struct bootinfo *bi = (struct bootinfo *)mbr; // tmp. use mbr - stop_floppy (); + // stop_floppy (); while (*(++arg) && *arg != ' '); str = arg; @@ -1250,9 +1256,9 @@ bsd_boot (kernel_t type, int bootdev, char *arg) /* FIXME: If HEADS or SECTORS is greater than 255, then this will break the geometry information. That is a drawback of BSD but not of GRUB. */ - bi->bi_bios_geom[i] = (((tmp_geom.cylinders - 1) << 16) - + (((tmp_geom.heads - 1) & 0xff) << 8) - + (tmp_geom.sectors & 0xff)); +// bi->bi_bios_geom[i] = (((tmp_geom.cylinders - 1) << 16) +// + (((tmp_geom.heads - 1) & 0xff) << 8) +// + (tmp_geom.sectors & 0xff)); } bi->bi_size = sizeof (struct bootinfo); @@ -1281,7 +1287,7 @@ bsd_boot (kernel_t type, int bootdev, char *arg) /* call entry point */ //(*entry_addr) (clval, bootdev, 0, 0, 0, ((int) bi)); - multi_boot ((int) entry_addr, clval, bootdev, 0, 0, 0, ((int) bi)); + // multi_boot ((int) entry_addr, clval, bootdev, 0, 0, 0, ((int) bi)); } else { @@ -1305,15 +1311,16 @@ bsd_boot (kernel_t type, int bootdev, char *arg) */ /* call entry point */ - unsigned long end_mark; + //unsigned long end_mark; - if (mbi.flags & MB_INFO_AOUT_SYMS) - end_mark = (mbi.syms.a.addr + 4 + mbi.syms.a.tabsize + mbi.syms.a.strsize); - else + //if (mbi.flags & MB_INFO_AOUT_SYMS) + //end_mark = (mbi.syms.a.addr + 4 + mbi.syms.a.tabsize + mbi.syms.a.strsize); + //else /* FIXME: it should be mbi.syms.e.size. */ - end_mark = 0; + //end_mark = 0; //(*entry_addr) (clval, bootdev, 0, end_mark, extended_memory, (*(unsigned short *)0x413)/*saved_mem_lower*/); - multi_boot ((int) entry_addr, clval, bootdev, 0, end_mark, extended_memory, (*(unsigned short *)0x413)/*saved_mem_lower*/); + //multi_boot ((int) entry_addr, clval, bootdev, 0, end_mark, extended_memory, (*(unsigned short *)0x413)/*saved_mem_lower*/); } +#endif } diff --git a/stage2/bootlace.inc b/stage2/bootlace.inc deleted file mode 100644 index 451f66be..00000000 --- a/stage2/bootlace.inc +++ /dev/null @@ -1,5146 +0,0 @@ -/* - * bootlace.inc -- code shared by 16-bit DOS and 32-bit Linux - * Copyright (C) 2005,2006,2007,2012 Tinybit(tinybit@tom.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - .file "bootlace.inc" - -#ifdef __DOS_16 - -#undef ABS -#define ABS(x) (x - _start + 0x100) - -#undef iBX -#define iBX %bx - -#undef iSI -#define iSI %si - -#undef iDI -#define iDI %di - -#undef iDX -#define iDX %dx - -#undef rBP -#define rBP - -#undef LEAL -#define LEAL ADDR32 leal - -#undef MOVZWL -#define MOVZWL ADDR32 movzwl - -#undef MOVL -#define MOVL ADDR32 movl - -#undef MOVW -#define MOVW ADDR32 movw - -#undef CMPL -#define CMPL ADDR32 cmpl - -#undef CMPW -#define CMPW ADDR32 cmpw - -#undef SUBL -#define SUBL ADDR32 subl - -#undef SBBL -#define SBBL ADDR32 sbbl - -#undef NEGL -#define NEGL ADDR32 negl - -#undef NOTL -#define NOTL ADDR32 notl - -#undef ADCL -#define ADCL ADDR32 adcl - -#undef ADDL -#define ADDL ADDR32 addl - -#undef DIVL -#define DIVL ADDR32 divl - - . = _start + 0x40 // dos entry point invalid_dos_exec - -#if 0 - movl $ABS(msg_invalid_dos), %ecx - call 8f - - movw $0x4c01, %ax // EXIT - TERMINATE WITH RETURN CODE 1 - int $0x21 // call DOS -#else - jmp 1f -#endif - - - ////////////////////////////////////////////////////////////////////// - - . = _start + 0x47 // dos entry point - -1: - /* dos entry point */ - - /* read stdin at _ph_offset + 1 */ - movl $(_ph_offset + 1 - _start + 0x100), %edi -2: - movw $10, %cx -1: - /* check if there is a char */ - movb $0x0B, %ah - pushw %cx - pushl %edi - int $0x21 - popl %edi - popw %cx - testb %al, %al - jnz 1f - loopz 1b - /* no chars to read */ - jmp 2f /* end of stdin */ -1: - /* read the char, direct char input without echo */ - movb $0x07, %ah - pushl %edi - int $0x21 /* AL=char read */ - popl %edi - cmpb $0x0D, %al - jne 1f - movb $0x20, %al -1: - cmpb $0x0C, %al - jne 1f - movb $0x20, %al -1: - cmpb $0x0A, %al - jne 1f - movb $0x20, %al -1: - cmpb $0x09, %al - jne 1f - movb $0x20, %al -1: - cmpb $0x20, %al - jb 2f /* end input */ - cld - stosb - cmpl $(_ph_offset + 1 - _start + 0x100 + 512), %edi - jb 2b /* read next char */ - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - movl $ABS(msg_stdin_too_long), %ecx - jmp 4f /* error */ - -2: - - cld - movb $0x20, %al - stosb /* store one more space */ - - /* move command line */ - - movl $0x81, %esi - movl $0x7f, %ecx - repz movsb - - /* the new long command line */ - - //movl $(_ph_offset + 1 - _start + 0x100), %esi - //movl $0x81, %esi - //subl %esi, %edi - subl $0x7f, %edi - movl %edi, %esi - movl $0x7f, %ecx - movb $0x0d, %al /* CR */ - - cld - repnz scasb - - decl %edi /* points to CR */ - std - movb $0, %al /* change CR to NULL */ - stosb - - movl %edi, %esi - xorl %ecx, %ecx - pushl %ecx /* 0 is the end of argv */ - xorl %edx, %edx /* find spaces */ -3: - cmpl $(_ph_offset + 1 - _start + 0x100), %esi - //cmpl $0x81, %edi - jb 3f /* args all done, exit */ - lodsb - cmpb $0x20, %al /* skip spaces */ - je 1f - cmpb $0x09, %al /* skip Tabs */ - jne 2f /* found non-space char */ -1: - /* it is a space */ - testl %edx, %edx /* we are finding spaces? */ - jz 1f /* yes, simply change to NULL */ - - notl %edx /* no, we will find spaces */ - incl %edi - pushl %edi /* argv */ - decl %edi -1: - movb $0, %al /* change spaces to NULL */ - stosb - jmp 3b /* next */ -2: - /* it is a non-space */ - testl %edx, %edx /* we are finding spaces? */ - jnz 1f /* no, simply save the char */ - incl %ecx /* yes, one more arg was found */ - notl %edx /* now we will find non-spaces */ - - cmpl $50, %ecx - jb 1f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - movl $ABS(msg_too_many_parameters), %ecx - jmp 4f /* error */ - -1: - stosb /* store the non-space char */ - jmp 3b /* next */ -3: - testl %edx, %edx - jz 1f - incl %edi - pushl %edi -1: - pushl %esi /* dummy for program name */ - incl %ecx - pushl %ecx /* argc */ - cld -#else - -#undef ABS -//#define ABS(x) (x) -#define ABS(x) (x - _start + 0x00400000) - -#undef iBX -#define iBX %ebx - -#undef iSI -#define iSI %esi - -#undef iDI -#define iDI %edi - -#undef iDX -#define iDX %edx - -#undef rBP -#define rBP (%ebp) - -#undef LEAL -#define LEAL leal - -#undef MOVZWL -#define MOVZWL movzwl - -#undef MOVL -#define MOVL movl - -#undef MOVW -#define MOVW movw - -#undef CMPL -#define CMPL cmpl - -#undef CMPW -#define CMPW cmpw - -#undef SUBL -#define SUBL subl - -#undef SBBL -#define SBBL sbbl - -#undef NEGL -#define NEGL negl - -#undef NOTL -#define NOTL notl - -#undef ADCL -#define ADCL adcl - -#undef ADDL -#define ADDL addl - -#undef DIVL -#define DIVL divl - -#endif - - popl %ecx # argc - - /* argc must be > 1 */ - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - movl %ebx, %ebp # EBP = 0 - - decl %eax // it is the rex prefix 0x48 - cmpl $1, %ecx // rcx - movl $ABS(msg_no_args), %ecx - jbe 4f /* error */ - - /* Note: ECX does not hold the argc now. */ - - xorl %eax, %eax # EAX will point to file name - //movl %ebx, ABS(filename) # save 0 to filename - popl %ecx # discard argv[0], the program name -1: - popl %ecx # argv - pushl %ecx - popl %ebx - - jecxz 3f /* end of arguments */ - jmp 2f -3: - jmp 1f -2: - - /* check if it is an option */ - cmpb $0x2D, (iBX) # "-" - jz 2f - - /* it is a filename */ - pushl %eax - popl %ecx - - jecxz 3f # filename not yet specified, continue - - /* error: only one file should be specified. */ - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - movl $ABS(msg_too_many_files), %ecx - jmp 4f /* error */ - -3: - /* encountered first filename */ - pushl %ebx # EBX = filename - popl %eax # save filename to EAX - jmp 1b # continue - -2: - - /* it is an option */ - - /* check --restore-mbr */ - - movl $14, %ecx - movl $ABS(option_restore_mbr), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - testl $0x80000000, ABS(restore_mbr) rBP - movl $ABS(msg_option_restore_mbr_with_other), %ecx - jnz 4f /* error */ - testb $1, ABS(restore_mbr) rBP - movl $ABS(msg_option_restore_mbr), %ecx - jnz 4f /* error */ - orb $1, ABS(restore_mbr) rBP - jmp 1b - -3: - - /* check --read-only */ - - movl $12, %ecx - movl $ABS(option_read_only), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $2, ABS(read_only) rBP - movl $ABS(msg_option_read_only), %ecx - jnz 4f /* error */ - - movl $0, ABS(read_only) rBP - jmp 1b - -3: - orl $0x80000000, ABS(restore_mbr) rBP # first option is not --restore-mbr/--read-only - testb $1, ABS(restore_mbr) rBP - movl $ABS(msg_option_restore_mbr_with_other), %ecx - jnz 4f /* error */ - - /* check --no-backup-mbr */ - - movl $16, %ecx - movl $ABS(option_no_backup_mbr), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $1, ABS(backup_mbr) rBP - movl $ABS(msg_option_backup_mbr), %ecx - jnz 4f /* error */ - movl $0, ABS(backup_mbr) rBP - jmp 1b - -3: - /* check --force-backup-mbr */ - - movl $19, %ecx - movl $ABS(option_force_backup_mbr), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $1, ABS(backup_mbr) rBP - movl $ABS(msg_option_backup_mbr), %ecx - jnz 4f /* error */ - movl $2, ABS(backup_mbr) rBP - jmp 1b - -3: - - /* check --mbr-enable-floppy */ - - movl $20, %ecx - movl $ABS(option_mbr_enable_floppy), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0, ABS(mbr_floppy) rBP - movl $ABS(msg_option_mbr_floppy), %ecx - jnz 4f /* error */ - movl $2, ABS(mbr_floppy) rBP - jmp 1b - -3: - - /* check --mbr-disable-floppy */ - - movl $21, %ecx - movl $ABS(option_mbr_disable_floppy), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0, ABS(mbr_floppy) rBP - movl $ABS(msg_option_mbr_floppy), %ecx - jnz 4f /* error */ - movl $1, ABS(mbr_floppy) rBP - jmp 1b - -3: - - /* check --mbr-enable-osbr */ - - movl $18, %ecx - movl $ABS(option_mbr_enable_osbr), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0, ABS(mbr_osbr) rBP - movl $ABS(msg_option_mbr_osbr), %ecx - jnz 4f /* error */ - movl $2, ABS(mbr_osbr) rBP - jmp 1b - -3: - - /* check --mbr-disable-osbr */ - - movl $19, %ecx - movl $ABS(option_mbr_disable_osbr), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0, ABS(mbr_osbr) rBP - movl $ABS(msg_option_mbr_osbr), %ecx - jnz 4f /* error */ - movl $1, ABS(mbr_osbr) rBP - jmp 1b - -3: - - /* check --mbr-no-bpb */ - - movl $13, %ecx - movl $ABS(option_mbr_no_bpb), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0, ABS(mbr_bpb) rBP - movl $ABS(msg_option_mbr_bpb), %ecx - jnz 4f /* error */ - movl $1, ABS(mbr_bpb) rBP - jmp 1b - -3: - - /* check --duce */ - - movl $7, %ecx - movl $ABS(option_duce), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0, ABS(duce) rBP - movl $ABS(msg_option_duce), %ecx - jnz 4f /* error */ - movl $1, ABS(duce) rBP - jmp 1b - -3: - - /* check --chs-no-tune */ - - movl $14, %ecx - movl $ABS(option_chs_no_tune), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0, ABS(chs_no_tune) rBP - movl $ABS(msg_option_chs_no_tune), %ecx - jnz 4f /* error */ - movl $1, ABS(chs_no_tune) rBP - jmp 1b - -3: - - /* check --boot-prevmbr-first */ - - movl $21, %ecx - movl $ABS(option_boot_prevmbr_first), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0, ABS(boot_prevmbr) rBP - movl $ABS(msg_option_boot_prevmbr), %ecx - jnz 4f /* error */ - movl $1, ABS(boot_prevmbr) rBP - jmp 1b - -3: - - /* check --boot-prevmbr-last */ - - movl $20, %ecx - movl $ABS(option_boot_prevmbr_last), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0, ABS(boot_prevmbr) rBP - movl $ABS(msg_option_boot_prevmbr), %ecx - jnz 4f /* error */ - movl $2, ABS(boot_prevmbr) rBP - jmp 1b - -3: - - /* check --preferred-drive= */ - - movl $18, %ecx - movl $ABS(option_preferred_drive), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0xff, ABS(preferred_drive) rBP - movl $ABS(msg_option_preferred_drive), %ecx - jnz 4f /* error */ - - movl $0xfe, %ebx - call 7f /* parse_number */ - movl %ebx, %edi # save EBX to EDI - movl $0, %ebx # invalid file descriptor for CLOSE below - movl $ABS(msg_invalid_number), %ecx - jc 4f /* error */ - movl %edi, ABS(preferred_drive) rBP - jmp 1b - -3: - - /* check --preferred-partition= */ - - movl $22, %ecx - movl $ABS(option_preferred_partition), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0xff, ABS(preferred_partition) rBP - movl $ABS(msg_option_preferred_partition), %ecx - jnz 4f /* error */ - - movl $0xfe, %ebx - call 7f /* parse_number */ - movl %ebx, %edi # save EBX to EDI - movl $0, %ebx # invalid file descriptor for CLOSE below - movl $ABS(msg_invalid_number), %ecx - jc 4f /* error */ - movl %edi, ABS(preferred_partition) rBP - jmp 1b - -3: - - /* check --serial-number= */ - - movl $16, %ecx - movl $ABS(option_serial_number), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0, ABS(serial_number) rBP - movl $ABS(msg_option_serial_number), %ecx - jnz 4f /* error */ - - movl $0xffffffff, %ebx - call 7f /* parse_number */ - movl %ebx, %edi # save EBX to EDI - movl $0, %ebx # invalid file descriptor for CLOSE below - movl $ABS(msg_invalid_number), %ecx - jc 4f /* error */ - cmpl $0, %edi - je 4f /* error */ - movl %edi, ABS(serial_number) rBP - jmp 1b - -3: - - /* check --time-out= */ - - movl $11, %ecx - movl $ABS(option_time_out), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - -// cmpl $0xffffff05, ABS(time_out) rBP - cmpl $0xffffff00, ABS(time_out) rBP - movl $ABS(msg_option_time_out), %ecx - jnz 4f /* error */ - - movl $0xff, %ebx - call 7f /* parse_number */ - movl %ebx, %edi # save EBX to EDI - movl $0, %ebx # invalid file descriptor for CLOSE below - movl $ABS(msg_invalid_number), %ecx - jc 4f /* error */ - movl %edi, ABS(time_out) rBP - jmp 1b - -3: - - /* check --hot-key= */ - - movl $10, %ecx - movl $ABS(option_hot_key), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0xffff3920, ABS(hot_key) rBP - movl $ABS(msg_option_hot_key), %ecx - jnz 4f /* error */ - - movl $0xffff, %ebx - call 7f /* parse_number */ - movl %ebx, %edi # save EBX to EDI - movl $0, %ebx # invalid file descriptor for CLOSE below - movl $ABS(msg_invalid_number), %ecx - jc 4f /* error */ - movl %edi, ABS(hot_key) rBP - jmp 1b - -3: - - /* check --install-partition= */ - - movl $20, %ecx - movl $ABS(option_install_partition), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0xffffffff, ABS(install_partition) rBP - movl $ABS(msg_option_install_partition), %ecx - jnz 4f /* error */ - - movl $0xffff, %ebx - call 7f /* parse_number */ - movl %ebx, %edi # save EBX to EDI - movl $0, %ebx # invalid file descriptor for CLOSE below - movl $ABS(msg_invalid_number), %ecx - jc 4f /* error */ - movl %edi, ABS(install_partition) rBP - jmp 1b - -3: - - /* check --sectors-per-track= */ - - movl $20, %ecx - movl $ABS(option_sectors_per_track), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0xffffff3f, ABS(sectors_per_track) rBP - movl $ABS(msg_option_sectors_per_track), %ecx - jnz 4f /* error */ - - movl $0x3f, %ebx # maximum is 63 - call 7f /* parse_number */ - movl %ebx, %edi # save EBX to EDI - movl $0, %ebx # invalid file descriptor for CLOSE below - movl $ABS(msg_invalid_number), %ecx - jc 4f /* error */ - cmpl $0, %edi - je 4f /* error */ - movl %edi, ABS(sectors_per_track) rBP - jmp 1b - -3: - - /* check --heads= */ - - movl $8, %ecx - movl $ABS(option_heads), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0xffff00ff, ABS(heads) rBP - movl $ABS(msg_option_heads), %ecx - jnz 4f /* error */ - - movl $0x100, %ebx # maximum is 256 - call 7f /* parse_number */ - movl %ebx, %edi # save EBX to EDI - movl $0, %ebx # invalid file descriptor for CLOSE below - movl $ABS(msg_invalid_number), %ecx - jc 4f /* error */ - cmpl $0, %edi - je 4f /* error */ - movl %edi, ABS(heads) rBP - jmp 1b - -3: - - /* check --start-sector= */ - - movl $15, %ecx - movl $ABS(option_start_sector), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0xffffffff, ABS(start_sector) rBP - movl $ABS(msg_option_start_sector), %ecx - jnz 4f /* error */ - - movl $0xfffffffe, %ebx - call 7f /* parse_number */ - movl %ebx, %edi # save EBX to EDI - movl $0, %ebx # invalid file descriptor for CLOSE below - movl $ABS(msg_invalid_number), %ecx - jc 4f /* error */ - movl %edi, ABS(start_sector) rBP - jmp 1b - -3: - - /* check --total-sectors= */ - - movl $16, %ecx - movl $ABS(option_total_sectors), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0, ABS(total_sectors) rBP - movl $ABS(msg_option_total_sectors), %ecx - jnz 4f /* error */ - - movl $0xffffffff, %ebx - call 7f /* parse_number */ - movl %ebx, %edi # save EBX to EDI - movl $0, %ebx # invalid file descriptor for CLOSE below - movl $ABS(msg_invalid_number), %ecx - jc 4f /* error */ - cmpl $0, %edi - je 4f /* error */ - movl %edi, ABS(total_sectors) rBP - jmp 1b - -3: - - /* check --floppy= */ - - movl $9, %ecx - movl $ABS(option_floppy_partition), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0xffffffff, ABS(floppy) rBP - movl $ABS(msg_option_floppy), %ecx - jnz 4f /* error */ - - movl $0xfe, %ebx - call 7f /* parse_number */ - movl %ebx, %edi # save EBX to EDI - movl $0, %ebx # invalid file descriptor for CLOSE below - movl $ABS(msg_invalid_number), %ecx - jc 4f /* error */ - movl %edi, ABS(floppy) rBP - jmp 1b - -3: - - /* check --floppy */ - - movl $8, %ecx - movl $ABS(option_floppy), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0xffffffff, ABS(floppy) rBP - movl $ABS(msg_option_floppy), %ecx - jnz 4f /* error */ - - movl $0xff, ABS(floppy) rBP - jmp 1b -3: - /* check --gpt */ - - movl $5, %ecx - movl $ABS(option_gpt), %esi - pushl %ebx - popl %edi - - cld - repz cmpsb - - jnz 3f - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0xffffffff, ABS(gpt) rBP - movl $ABS(msg_option_gpt), %ecx - jnz 4f /* error */ - - movl $0xff, ABS(gpt) rBP - jmp 1b - -3: - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - movl $ABS(msg_invalid_option), %ecx - jmp 4f /* error */ - -1: - -//---------------------------------------------------------------------------- - /* end of arguments */ - - /* ECX=EBX=0 */ - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - pushl %eax - popl %ecx - - jecxz 3f # no file name error - jmp 1f -3: - movl $ABS(msg_no_file), %ecx - jmp 4f /* error */ -1: - - pushl %eax - popl %ebx # EBX = filename - - /* check if preferred_partition matches preferred_drive */ - - movb ABS(preferred_drive) rBP, %al - movb ABS(preferred_partition) rBP, %ah - - cmpb $0xff, %al - jne 1f - - #; movl %ebx, %edi # save EBX to EDI - pushl %ebx - popl %edi - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - cmpb $0xff, %ah - movl $ABS(msg_partition_without_drive), %ecx - jne 4f /* error */ - - #; movl %edi, %ebx # restore EBX from EDI - pushl %edi - popl %ebx -1: - - /* EBX points to the pathname of the file. */ - - #; movl %ebx, %edi # save EBX to EDI - pushl %ebx - popl %edi - - xorl %ebx, %ebx # invalid file descriptor for CLOSE below - - cmpl $0xffffffff, ABS(floppy) rBP - je 1f # --floppy is not specified - - /* if --floppy is specified, should not specify the options for MBR. */ - cmpl $1, ABS(backup_mbr) rBP - movl $ABS(msg_option_backup_mbr_with_floppy), %ecx - jnz 4f /* error */ - - cmpl $0, ABS(mbr_floppy) rBP - movl $ABS(msg_option_mbr_floppy_with_floppy), %ecx - jnz 4f /* error */ - - cmpl $0, ABS(mbr_osbr) rBP - movl $ABS(msg_option_mbr_osbr_with_floppy), %ecx - jnz 4f /* error */ - - cmpl $0, ABS(mbr_bpb) rBP - movl $ABS(msg_option_mbr_bpb_with_floppy), %ecx - jnz 4f /* error */ - - cmpl $0, ABS(duce) rBP - movl $ABS(msg_option_duce_with_floppy), %ecx - jnz 4f /* error */ - - cmpl $0, ABS(chs_no_tune) rBP - movl $ABS(msg_option_chs_no_tune_with_floppy), %ecx - jnz 4f /* error */ - - cmpl $0, ABS(boot_prevmbr) rBP - movl $ABS(msg_option_boot_prevmbr_with_floppy), %ecx - jnz 4f /* error */ - - cmpl $0xff, ABS(preferred_drive) rBP - movl $ABS(msg_option_preferred_drive_with_floppy), %ecx - jnz 4f /* error */ - - cmpl $0xff, ABS(preferred_partition) rBP - movl $ABS(msg_option_preferred_partition_with_floppy), %ecx - jnz 4f /* error */ - - cmpl $0, ABS(serial_number) rBP - movl $ABS(msg_option_serial_number_with_floppy), %ecx - jnz 4f /* error */ - - cmpl $0xffffffff, ABS(install_partition) rBP - movl $ABS(msg_option_install_partition_with_floppy), %ecx - jnz 4f /* error */ - -// cmpl $0xffffff05, ABS(time_out) rBP - cmpl $0xffffff00, ABS(time_out) rBP - movl $ABS(msg_option_time_out_with_floppy), %ecx - jnz 4f /* error */ - - cmpl $0xffff3920, ABS(hot_key) rBP - movl $ABS(msg_option_hot_key_with_floppy), %ecx - jnz 4f /* error */ - - /* for a floppy, start_sector should be 0, and - * for a partition, start_sector should be non-zero - */ - cmpl $0xff, ABS(floppy) rBP - je 2f # a real floppy - - /* a single partition */ - cmpl $0, ABS(start_sector) rBP - movl $ABS(msg_partition_start), %ecx - jz 4f /* error */ - - jmp 3f -2: - /* a real floppy */ - /* */ - cmpl $0xffffffff, ABS(start_sector) rBP - je 3f - cmpl $0, ABS(start_sector) rBP - movl $ABS(msg_floppy_start), %ecx - jnz 4f /* error */ - -3: - jmp 2f - -1: - /* EBX=0 */ - - cmpl $0xffffffff, ABS(install_partition) rBP - je 2f # --install-partition is not specified - - /* should not specify --install-partition with options for MBR. */ - cmpl $1, ABS(backup_mbr) rBP - movl $ABS(msg_option_backup_mbr_with_partition), %ecx - jnz 4f /* error */ - - cmpl $0, ABS(mbr_floppy) rBP - movl $ABS(msg_option_mbr_floppy_with_partition), %ecx - jnz 4f /* error */ - - cmpl $0, ABS(mbr_osbr) rBP - movl $ABS(msg_option_mbr_osbr_with_partition), %ecx - jnz 4f /* error */ - - cmpl $0, ABS(mbr_bpb) rBP - movl $ABS(msg_option_mbr_bpb_with_partition), %ecx - jnz 4f /* error */ - - cmpl $0, ABS(duce) rBP - movl $ABS(msg_option_duce_with_partition), %ecx - jnz 4f /* error */ - - cmpl $0, ABS(chs_no_tune) rBP - movl $ABS(msg_option_chs_no_tune_with_partition), %ecx - jnz 4f /* error */ - - cmpl $0, ABS(boot_prevmbr) rBP - movl $ABS(msg_option_boot_prevmbr_with_partition), %ecx - jnz 4f /* error */ - - cmpl $0xff, ABS(preferred_drive) rBP - movl $ABS(msg_option_preferred_drive_with_partition), %ecx - jnz 4f /* error */ - - cmpl $0xff, ABS(preferred_partition) rBP - movl $ABS(msg_option_preferred_partition_with_partition), %ecx - jnz 4f /* error */ - - cmpl $0, ABS(serial_number) rBP - movl $ABS(msg_option_serial_number_with_partition), %ecx - jnz 4f /* error */ - -// cmpl $0xffffff05, ABS(time_out) rBP - cmpl $0xffffff00, ABS(time_out) rBP - movl $ABS(msg_option_time_out_with_partition), %ecx - jnz 4f /* error */ - - cmpl $0xffff3920, ABS(hot_key) rBP - movl $ABS(msg_option_hot_key_with_partition), %ecx - jnz 4f /* error */ - - cmpl $0xffffff3f, ABS(sectors_per_track) rBP - movl $ABS(msg_option_sectors_per_track_with_partition), %ecx - jnz 4f /* error */ - - cmpl $0xffff00ff, ABS(heads) rBP - movl $ABS(msg_option_heads_with_partition), %ecx - jnz 4f /* error */ - - cmpl $0xffffffff, ABS(start_sector) rBP - movl $ABS(msg_option_start_sector_with_partition), %ecx - jnz 4f /* error */ - - cmpl $0, ABS(total_sectors) rBP - movl $ABS(msg_option_total_sectors_with_partition), %ecx - jnz 4f /* error */ - -2: - - /* EBX=0, EDI points to the pathname of the file. */ - -//---------------------------------------------------------------------------- - #; movl %edi, %ebx # restore EBX from EDI - pushl %edi - popl %ebx - - /* EBX=EDI points to the pathname of the file. */ - -#ifdef __DOS_16 - - xorl %eax, %eax - movl $0xfe, %ebx - call 7f /* parse_number */ - jc 2f /* invalid number */ - /* EBX holds the bios drive number */ - movl %ebx, ABS(bios_drive_number) - jmp 1f -2: - //AH = 3Dh //OPEN EXISTING FILE - //AL = access and sharing modes (see #01402) - //DS:DX -> ASCIZ filename - //CL = attribute mask of files to look for (server call only) - - //Return: - //CF clear if successful AX = file handle - //CF set on error AX = error code (01h,02h,03h,04h,05h,0Ch,56h) - - movzbl ABS(read_only), %eax - movb $0x3d, %ah // open file for read/write - movl %edi, %edx // DS:DX points to ASCIZ filename - int $0x21 - jnc 1f - negl %eax /* EAX < 0 */ -1: -#else - - /* int open(const char *pathname, int flags, mode_t mode) */ - // mode is not used since we are not creating a new file - - /* check if in 32-bit or 64-bit mode */ - xorl %eax, %eax - decl %eax // rex prefix of 0x48 - testl %eax, %eax - /* EAX = 0 for 64-bit mode, -1 for 32-bit mode */ - jz 1f - - /* in 32-bit mode */ - movl $5, %eax // sys_open - movzbl ABS(read_only) rBP, %ecx // O_RDWR = 02 - pushl %ebx - popl %edi - pushl %ecx - popl %esi - int $0x80 - jmp 2f -1: - /* in 64-bit mode */ - movl $2, %eax // sys_open - pushl %ebx - popl %edi - movzbl ABS(read_only) rBP, %esi // O_RDWR = 02 - // mode is not used since we are not creating a new file - syscall -2: -#endif - xorl %ebx, %ebx // invalid file descriptor for CLOSE below - movl $ABS(msg_open_file_rw), %ecx - cmpl $2, ABS(read_only) rBP - je 1f - movl $ABS(msg_open_file_ro), %ecx -1: -#if 1 - testl %eax, %eax - js 4f /* error */ -#else - /* if needed, use 64-bit value for 64-bit Linux */ - pushl %eax # rax - popl %ecx # rcx - pushl %ecx - decl %eax # rex prefix of 0x48 - addl %ecx, %ecx # addq %rcx, %rcx - popl %eax - jc 4f -#endif - -//---------------------------------------------------------------------------- - /* open file succeeded */ - -#ifdef __DOS_16 - -#undef PRE -#define PRE(x) %x: -#undef ABS -#define ABS(x) (x - _start + 0x100) -#undef MBR -#define MBR(x) (x) - -#else - -#undef PRE -#define PRE(x) -#undef ABS -//#define ABS(x) (x) -#define ABS(x) (x - _start + 0x00400000) -#undef MBR -//#define MBR(x) (mbr_63_sectors + x) -#define MBR(x) (grldr_mbr_start + 0x2000 + x - _start + 0x00400000) - -#endif - pushl %eax // file descriptor, or 0 for BIOS drive - pushl %eax - popl %ebx - - /* EBX and the stack holds the file descriptor number or 0 */ - -#ifdef __DOS_16 - - /* check if there is 64K available for mbr_63_sectors and stack. */ - - xorw %ax, %ax - movw %ax, %ds - movw 0x413, %ax /* low memory in KBytes */ - shlw $6, %ax /* low memory in paragraphs */ - - movw %cs, %cx - movw %cx, %ds - addw $0x2000, %cx - cmpw %ax, %cx - movl $ABS(msg_no_enough_memory), %ecx - ja 4f - - /* move stack to next 64K to avoid memory conflict. */ - movw %cs, %ax - addw $0x1000, %ax - movw %ax, %ss - movw %ax, %ds - movw %ax, %es - popl %eax // dummy pop - pushl %ebx // file descriptor, or 0 for BIOS drive - - xorl %eax, %eax - cmpl $0xff, PRE(cs)ABS(bios_drive_number) - je 1f // not bios drive - - /* check EBIOS support */ - call 100f - movb $0x41, %ah - movw $0x55AA, %bx - movb PRE(cs)ABS(bios_drive_number), %dl - int $0x13 - movw %ss, %ax - movw %ax, %ds - movw %ax, %es - jc 3f /* No EBIOS */ - cmpw $0xAA55, %bx - jne 3f /* No EBIOS */ - testb $1, %cl - jz 3f /* No EBIOS */ - /* EBIOS supported */ - movl $1, PRE(cs)ABS(ebios_support) -// movb PRE(cs)ABS(bios_drive_number), %dl - movw $0, %si - movb $0x48, %ah - int $0x13 - jc 2f - cmpb $0x42, 0x00 - jb 2f - movw $12, %cx - movw $0x24, %si - movl $ABS(msg_Information), %edi - pushw %es - pushw %cs - popw %es - repz movsb - popw %es -2: - movw $3, %si -2: - pushw %si - /* try read using EBIOS */ - pushl $0 // hi 32bit of startLBA - pushl $0 // startLBA=0 - pushw %es // buffer segment - pushw $0 // buffer offset - pushw $0x0060 // sectors=96 - pushw $0x0010 // packet length - movw %sp, %si - movw $0x4200, %ax /* LBA read */ -// movb PRE(cs)ABS(bios_drive_number), %dl - int $0x13 - movw %ss, %ax - movw %ax, %ds - movw %ax, %es - popl %eax - popl %eax - popl %eax - popl %eax # EAX=0 - popw %si - jnc 2f // EBIOS read success - decw %si - je sb - xorw %ax, %ax -// movb PRE(cs)ABS(bios_drive_number), %dl - int $0x13 - jmp 2b -sb: - /* A read failure means actually no EBIOS support */ - movl $0, PRE(cs)ABS(ebios_support) - movl $ABS(msg_ebios_read_failure), %ecx - jmp 10f -3: - movl $ABS(msg_no_ebios_support), %ecx -10: - call 8f /* linux_print */ - - xorw %bx, %bx // BX=0 - movw $0x204, %ax // read 4 sectors of the MBR - movw $1, %cx - movb PRE(cs)ABS(bios_drive_number), %dl - movb $0, %dh - int $0x13 - movzwl %ax, %eax - movw %ss, %cx - movw %cx, %ds - movw %cx, %es - jc 2f // stop on error - movw $0x7E00, %bx - movw $1, %cx - movb PRE(cs)ABS(bios_drive_number), %dl - movb $1, %dh - movw $0x201, %ax // read 1 sector of track 1(the 2nd track) - int $0x13 - movzwl %ax, %eax - movw %ss, %cx - movw %cx, %ds - movw %cx, %es - clc // ignore error - jmp 2f -1: - //READ FROM FILE OR DEVICE - call 100f - - //AH = 3Fh - //BX = file handle - //CX = number of bytes to read - //DS:DX -> buffer for data - - //Return: - //CF clear if successful AX = number of bytes actually read (0 if at EOF before call) - //CF set on error AX = error code (05h,06h) - xchgw %ax, %dx // DX=0 - movw $0x3f00, %ax - movw $((63+32+1)*512), %cx - //movl $MBR(0), %edx - int $0x21 -2: - jnc 1f - negl %eax -1: -#else - /* ssize_t read(int fd, void *buf, size_t count) */ - //Clear buffer - call 100f - - /* check if in 32-bit or 64-bit mode */ - xorl %eax, %eax - decl %eax // rex prefix of 0x48 - testl %eax, %eax - /* EAX = 0 for 64-bit mode, -1 for 32-bit mode */ - jz 1f - - /* in 32-bit mode */ - movl $3, %eax // sys_read - movl $MBR(0), %ecx - movl $((63+32+1)*512), %edx // read 63+1 sectors - int $0x80 - jmp 2f -1: - /* in 64-bit mode */ - movl $0, %eax // sys_read - pushl %ebx - popl %edi - movl $MBR(0), %esi - movl $((63+32+1)*512), %edx // read 63+1 sectors - syscall -2: -#endif - - popl %ebx // file descriptor, or 0 for BIOS drive - testl %eax, %eax - movl $ABS(msg_read_file), %ecx - js 4f /* error */ - -//---------------------------------------------------------------------------- - - /* rewind the file for write! important! */ - - movl $0, %ecx - call 400f - - testl %eax, %eax - movl $ABS(msg_lseek_file), %ecx - js 4f /* error */ - -//---------------------------------------------------------------------------- - /* remember EBX holds file descriptor number, and don't touch it */ - - /* check if the partition table is valid. */ - -#ifdef __DOS_16 - xorl %esi, %esi - cmpw $0xAA55, 0x1fe(iSI) -#else - movl $MBR(0), %esi - pushl %eax - movl 0x1fe(iSI), %eax - andl $0xFFFF, %eax - cmpl $0xAA55, %eax - popl %eax -#endif - movl $ABS(msg_boot_signature_mbr), %ecx - //jne 4f /* error */ - clc - jne 2f - - call 9f /* probe_geometry */ - jnc 1f - -2: - - /* should be floppy since no partition table or no boot signature. */ - - /* CF=0 means no boot signature, CF=1 means no partition table. */ - - jnc 2f - - movl $ABS(msg_invalid_partition_table), %ecx -2: - cmpl $0xffffffff, PRE(cs)ABS(floppy) rBP /* Is --floppy specified? */ - je 4f /* error */ - - /* Yes, --floppy is specified */ - /* ESI points to MBR(0) */ - call 5f /* floppy routine */ - movl $0, %ecx - jc 4f /* error */ - - jmp 2f /* write file */ -1: - -//---------------------------------------------------------------------------- - /* the image type is MBR. So, should not specify --floppy */ - - /* check empty partition table */ - movl $MBR(0) + 0x1be, %edi - movb $0, %al - xorl %ecx, %ecx - movb $64, %cl - cld - repz scasb - movl $ABS(msg_invalid_partition_table), %ecx - je 2b /* empty partition table, always assume floppy. */ - - cmpl $0xffffffff, PRE(cs)ABS(floppy) rBP /* Is --floppy specified? */ - movl $ABS(msg_floppy_partition_table), %ecx - jne 4f /* error */ - - cmpl $0xffffff3f, PRE(cs)ABS(sectors_per_track) rBP - movl $ABS(msg_option_sectors_per_track_for_mbr), %ecx - jnz 4f /* error */ - - cmpl $0xffff00ff, PRE(cs)ABS(heads) rBP - movl $ABS(msg_option_heads_for_mbr), %ecx - jnz 4f /* error */ - - cmpl $0xffffffff, PRE(cs)ABS(start_sector) rBP - movl $ABS(msg_option_start_sector_for_mbr), %ecx - jnz 4f /* error */ - - cmpl $0, PRE(cs)ABS(total_sectors) rBP - movl $ABS(msg_option_total_sectors_for_mbr), %ecx - jnz 4f /* error */ - - cmpl $0xff, PRE(cs)ABS(gpt) rBP - jz 1f - -// cmpl $((pre_stage2_start - _start1) / 512), PRE(cs)ABS(mbr_free_sectors) rBP - cmpl $(0x2000 / 0x200), PRE(cs)ABS(mbr_free_sectors) rBP - movl $ABS(msg_sectors_per_track), %ecx - jb 4f /* error */ - - cmpl $0xffffffff, PRE(cs)ABS(install_partition) rBP - je 1f /* --install-partition not specified */ - -#ifdef __DOS_16 - /*****************************************/ - /* piece of code for --install-partition */ - /*****************************************/ - /* EBX holds the file descriptor number or 0 if it is BIOS drive */ - /* move partition table forward to the beginning of the 17th sector */ - cmpb $0, PRE(cs)ABS(ebios_support) //Support the expansion of reading? - movl $ABS(msg_no_ebios_support), %ecx - je 4f //no - - movl $MBR(0x01be), %esi - movl $MBR(0x2000), %edi - movl $0x10, %ecx # 0x10 dwords = 0x40 bytes - cld - repz movsl //Move the partition table - - /* load the next partition and modify the boot record */ - - /* Detection of extended partitions start logical sector */ - call 0f /* partition */ - /* Display disk information */ - movb PRE(cs)ABS(bios_drive_number), %al //bios id - subb $0x50, %al - movb %al, PRE(cs)ABS(msg_disk) - movw $0xffff, %bx - movl $MBR(0x2004), %esi - pushw %bx -33: - popw %bx - incw %bx - cmpb PRE(cs)ABS(total_partition_entries), %bl //The total number of partitions - ja 34f - pushw %bx - shlw $4, %bx - movl $MBR(0x2004), %esi - addw %bx, %si - cmpb $0, (iSI) - je 33b - movl 0x08(iSI), %eax - popw %bx -3: - pushw %bx - addb $0x30, %bl - movb %bl, PRE(cs)ABS(msg_partition) - call 66f - jmp 33b -34: - //Wait for key - movw PRE(cs)ABS(install_partition), %bx //Installation partition - cmpb PRE(cs)ABS(total_partition_entries), %bl //The total number of partitions - movl $ABS(msg_install_partition_not), %ecx - ja 4f - shlw $4, %bx - movl $MBR(0x2004), %esi - addw %bx, %si - cmpb $0, (iSI) - je 4f - movl $ABS(msg_Wait_for_key), %ecx - call 8f /* linux_print */ -3: - movb $1, %ah //Get keyboard input - int $0x16 - je 3b //not - xorl %ecx, %ecx - cmpb $0x79, %al //"y"? - jne 4f //not - //Install the boot code to disk - //24 sectors to read the specified partition es: 0000 - - movw PRE(cs)ABS(install_partition), %bx //Partition number - shlw $4, %bx - movl $MBR(0x2000), %esi - addw %bx, %si - movl 0x08(iSI), %eax - addl (iSI), %eax - pushl %eax - pushl $0 - pushl %eax - pushw %es - pushw $0 - pushw $0x04 - pushw $0x10 - movb $0x42, %ah - movw %sp, %si - movb PRE(cs)ABS(bios_drive_number), %dl //bios id - int $0x13 - popaw - popl %eax - movl $0, %ecx - jc 4f - //Determine the partition type, copy the file - xorl %esi, %esi - call 5f /* floppy routine */ - movl %ecx, %edx - movl $0, %ecx - jc 4f /* error */ - //Write from memory to the boot sector file - cmpw $2, PRE(cs)ABS(read_only) #; 0=read only, 2=read/write - jne 4f /* read only */ - //Determine whether ext2 partition usb drive installed -3: - pushl $0 - pushl %eax - pushw %es - pushw $0 - pushw PRE(cs)ABS(sectors_to_write) - pushw $0x0010 - movb $0x43, %ah - movw %sp, %si - movb PRE(cs)ABS(bios_drive_number), %dl //bios id - int $0x13 - popaw - movl $0, %ecx - jc 4f - movl $ABS(msg_success), %ecx - call 8f /* linux_print */ - - /* all partitions have been installed. */ - - xorl %eax, %eax # exit code = 0 - movb $0x4c, %ah // EXIT - TERMINATE WITH RETURN CODE in AL - int $0x21 // call DOS - -#else - jmp 4f /* error since --install-partition not implemented */ -#endif - -// ret - - /*************************************************/ - /* end the piece of code for --install-partition */ - /*************************************************/ - -1: -//---------------------------------------------------------------------------- - cmpl $0xff, PRE(cs)ABS(gpt) rBP - jnz 1f - - movl $MBR(0), %esi - movl $ABS(msg_gpt_partition_not), %ecx - cmpb $0xee, 0x1c2(iSI) - jne 4f - cmpl $0x20494645, 0x200(iSI) //"EFI PART"? - jne 4f //no - - movl 0x228(iSI), %edx - movl 0x248(iSI), %eax - shll $9, %eax - addl %eax, %esi - movl 0x20(iSI), %eax - subl $16, %eax - cmpl %edx, %eax - jae 210f - - movl $ABS(msg_cannot_install_gpt_partition), %ecx - movl $0x7f, %edi -3: - cmpl $0, 0x2c(iSI) - jne 4f - cmpl $0, 0xa4(iSI) - jne 4f - movl 0xa0(iSI), %eax - orl %eax, %eax - je 4f - movl 0x28(iSI), %edx - addl $1, %edx - subl $16, %eax - cmpl %edx, %eax - jae 210f - addl $0x80, %esi - subl $1, %edi - jne 3b - jmp 4f - -210: - movl $ABS(msg_cannot_install_gpt_partition), %ecx - cmpl $0x800000, %edx - jae 4f - movl %edx, PRE(cs)ABS(201f) rBP - movl $ABS(200f), %esi - movl $MBR(0), %edi - movl $(1f - 200f)/4, %ecx -#ifdef __DOS_16 - cs repz movsl -#else - repz movsl -#endif - movl %edx, PRE(cs)ABS(install_sectors) rBP - movl $1, PRE(cs)ABS(sectors_to_write) rBP - jmp 2f - - .code16 -200: - cli - xorl %ecx, %ecx - movw %cx, %ss - movw $0x7C00, %sp //ss:sp=0000:7c00 - pushw %cx - popw %ds //ds=0000 - sti - - cmpb $0xee, 0x7dc2 - jne 204f - - movw $3, %di -3: - pushaw - pushl %ecx - .byte 0x66,0x68 //pushl -201: - .long 0x22 - pushw $0xd00 - pushw %cx - pushw $16 - pushw $16 - movw %sp, %si - movb $0x42, %ah - int $0x13 - popaw - popaw - jnb 202f - xorw %ax, %ax - int $0x13 - decw %di - jne 3b -204: - movw $(203f - 200b + 0x7c00), %si -3: - lodsb - cmpb $0, %al - je 3f - movb $0xe, %ah - int $0x10 - jmp 3b - -3: - jmp 3b - -202: - pushw $0xd00 - pushw $0x256 - retf - -203: - .ascii "Error loading grldr.mbr" - .byte 0,0,0,0,0 - -#ifdef __DOS_16 - .code16 -#else - .code32 -#endif - -1: -//--------------------------------------------------------------------------- - - /* begin restore mbr */ - testb $1, PRE(cs)ABS(restore_mbr) rBP - jz 1f /* not --restore-mbr */ - - /* check if previous mbr is valid. */ -#ifdef __DOS_16 - xorl %esi, %esi - movw $0x200, %si - cmpw $0xAA55, 0x1fe(iSI) -#else - movl $MBR(0x200), %esi /* point to 2nd sector */ - pushl %eax - movl 0x1fe(iSI), %eax - andl $0xFFFF, %eax - cmpl $0xAA55, %eax - popl %eax -#endif - movl $ABS(msg_invalid_prev_mbr), %ecx - jnz 4f /* error */ - - call 9f /* probe_geometry */ - movl $ABS(msg_invalid_prev_mbr), %ecx - jc 4f /* error */ - - /* check if previous mbr is grldr */ - /* 2nd is not empty. if it is grldr, consider it is empty */ - movb $0xBB, %al -#ifdef __DOS_16 - xorl %edi, %edi - movw $0x260, %di -#else - movl $MBR(0x260), %edi // in 2nd sector -#endif - movl $0x150, %ecx - cld - repnz scasb - jnz 3f // 2nd is not grldr, restore it - movl $ABS(msg_invalid_prev_mbr), %ecx - cmpl $0xC38E0820, (%edi) - jz 4f /* error */ - -3: - /* copy byte 0000 to 01b7 in 2nd sector to 1st sector */ -#ifdef __DOS_16 - movl $0x200, %esi /* point to 2nd sector */ - xorl %edi, %edi -#else - movl $MBR(0x200), %esi /* point to 2nd sector */ - movl $MBR(0), %edi -#endif - movl $0x6e, %ecx // 0x6e dwords = 0x1b8 bytes - - cld - repz movsl - - movl $1, PRE(cs)ABS(sectors_to_write) rBP - /* completed. write file. */ - jmp 2f - - /* end restore mbr */ -1: -//---------------------------------------------------------------------------- - /* begin backup mbr */ - - /* auto backup */ - cmpl $1, PRE(cs)ABS(backup_mbr) rBP - jnz 1f - - /* check if the second sector begins in 106 dups of one byte */ -#ifdef __DOS_16 - movb 0x200, %al - movl $0x200, %edi -#else - movb MBR(0x200) rBP, %al - movl $MBR(0x200), %edi -#endif - movl $0x6A, %ecx // 0x6A=106 - - cld - repz scasb - - jz 10f // the second sector is empty. - /* 2nd is not empty. if it is grldr, consider it is empty */ - movb $0xBB, %al -#ifdef __DOS_16 - xorl %edi, %edi - movw $0x260, %di -#else - movl $MBR(0x260), %edi // in 2nd sector -#endif - movl $0x150, %ecx - cld - repnz scasb - jnz 3f # 2nd is not grldr, do not overwrite it - cmpl $0xC38E0820, (%edi) - jnz 3f /* error */ -10: - /* 2nd is empty. but if MBR is grldr, we still skip the backup. */ - - movb $0xBB, %al - movl $MBR(0x60), %edi // in 1st sector - movl $0x150, %ecx - cld - repnz scasb - jnz 1f # MBR is not grldr, enable backup - cmpl $0xB8661FFC, (%edi) - jz 3f # MBR is grldr, do not backup - -1: - -//---------------------------------------------------------------------------- - cmpl $0, PRE(cs)ABS(backup_mbr) rBP - jz 3f # will not backup - -#ifdef __DOS_16 - xorl %esi, %esi - movl $0x200, %edi -#else - movl $MBR(0), %esi - movl $MBR(0x200), %edi -#endif - movl $0x80, %ecx # 0x80 dwords = 0x200 bytes - - cld - repz movsl - - /* end backup mbr */ -3: - -//---------------------------------------------------------------------------- -#if 0 - /* copy byte 0000 to 01b7 of grldr.mbr to MBR(0) */ - - movl $ABS(grldr_mbr_start), %esi -#ifdef __DOS_16 - xorl %edi, %edi -#else - movl $MBR(0), %edi -#endif - movl $0x6e, %ecx # 0x6e dwords = 0x1b8 bytes - - cld -#ifdef __DOS_16 - cs repz movsl -#else - repz movsl -#endif - /* end copy boot record in sector 1 */ -#endif -//---------------------------------------------------------------------------- - ################################################# - #### copy and modify BPB ... ... #### - ################################################# - - /*************************/ - /* locate the BPB sector */ - /*************************/ - -#ifdef __DOS_16 - testb $1, PRE(cs)ABS(mbr_bpb) - jnz 1f /* mbr disable bpb */ - testl %ebx, %ebx - jnz 1f - /* BIOS drive. Need to load all 64 sectors. */ - - cmpl $0, PRE(cs)ABS(ebios_support) - jne 1f /* EBIOS succeeded previously, need not do anything more. */ - /* no EBIOS, so try BIOS with a single cross-track read. */ - movw $0x23C, %ax // read 60 sectors in the MBR track - movw $0x800, %bx // skip 4 sectors - movw $5, %cx // skip 4 sectors to load sector 5 - movb PRE(cs)ABS(bios_drive_number), %dl - movb $0, %dh - int $0x13 - movw %ss, %ax - movw %ax, %ds - movw %ax, %es - movl $0, %ebx - jnc 1f - /* cross-track read failed, so try normal BIOS read track by track */ - movl $0x3B, %ecx -3: - pushl %ecx - movb $0x02, %ah // read sectors - movb %cl, %al - movw $0x800, %bx // skip 4 sectors - movw $5, %cx // skip 4 sectors to load sector 5 - movb PRE(cs)ABS(bios_drive_number), %dl - movb $0, %dh - int $0x13 - movw %ss, %ax - movw %ax, %ds - movw %ax, %es - popl %ecx - jnc 3f - loop 3b -3: - /* CX + 4 = sectors per track */ - addw $4, %cx - cmpw $32, %cx - movl $0, %ebx - jb 1f - - movw $0x240, %ax // read sectors - subw %cx, %ax - movw %cx, %bx - shlw $9, %bx - movw $1, %cx // load sector 1 - movb PRE(cs)ABS(bios_drive_number), %dl - movb $1, %dh // head 1 - int $0x13 - movw %ss, %ax - movw %ax, %ds - movw %ax, %es - movl $0, %ebx - /* ignore error */ -1: -#endif - - movl PRE(cs)ABS(mbr_free_sectors) rBP, %eax - movl %eax, %esi - cmpl $(63+32), %eax - je 3f /* we can embed triple MBR */ - cmpl $32, %eax - jne 10f /* continue */ - - /* check if it is triple MBR previously embedded */ - movl $0xAA55, %ecx - #; cmpw %cx, MBR(0x5FE) - cmpb %cl, MBR(0x5FE) rBP - jne 10f - cmpb %ch, MBR(0x5FF) rBP - jne 10f - #; cmpw %cx, MBR(0x7FE) - cmpb %cl, MBR(0x7FE) rBP - jne 10f - cmpb %ch, MBR(0x7FF) rBP - jne 10f - #; cmpw %cx, MBR(0x9FE) - cmpb %cl, MBR(0x9FE) rBP - jne 10f - cmpb %ch, MBR(0x9FF) rBP - jne 10f - #; cmpw %cx, MBR(0xBFE) - cmpb %cl, MBR(0xBFE) rBP - jne 10f - cmpb %ch, MBR(0xBFF) rBP - jne 10f - //cmpl $0xAA555247, MBR(pre_stage2_start - _start1 - 4) - //jne 10f - xorl %ecx, %ecx - cmpl %ecx, MBR(0x0000 + 0x1C) rBP /* hidden sectors */ - jne 10f - movb $0x20, %cl - cmpl %ecx, MBR(0x4000 + 0x1C) rBP /* hidden sectors */ - jne 10f - cmpl %ecx, MBR(0xBE00 + 0x1C) rBP /* hidden sectors */ - jne 10f - subl $1, %ecx #; decl %ecx #; ECX=0x1F - cmpl %ecx, MBR(0x7E00 + 0x1C) rBP /* hidden sectors */ - jne 10f - #; movw MBR(0x1FF8), %cx /* ECX hi word=0 */ - movb MBR(0x1FF8) rBP, %cl /* ECX hi word=0 */ - movb MBR(0x1FF9) rBP, %ch /* ECX hi word=0 */ - cmpl $0x60, %ecx - jb 10f - cmpl $0x1b8, %ecx - jnb 10f - //movzwl %cx, %ecx - movl $MBR(0), %edi - addl %ecx, %edi - cmpl $0x661FFCBB, -5(iDI) - jne 10f - cmpb $0xB8, -1(iDI) - jne 10f - movl MBR(0x1FFC) rBP, %ecx - cmpl %ecx, (iDI) - jne 10f - - movl $MBR(0x4060), %esi #; 0x4000 + 0x60 - movl $MBR(0x7E60), %edi #; 0x7E00 + 0x60 - movl $((0x1b8 - 0x60) / 4), %ecx - cld - repz cmpsl - movl %eax, %esi #; 32 - jne 10f - - movl $MBR(0x4400), %esi #; 0x4000 + 0x400 - movl $MBR(0x8200), %edi #; 0x7E00 + 0x400 - movl $((0x2000 - 0x400) / 4), %ecx - cld - repz cmpsl - movl %eax, %esi #; 32 - jne 10f - - /* find partition with start_sector=0x20 */ - movl $0, PRE(cs)ABS(restore_partition_layout) rBP - movl $0x20, %eax - movl $MBR(0), %esi - movl %ebx, %edi #; save file descriptor - movl $0x1B6, %ebx -11: - incl PRE(cs)ABS(restore_partition_layout) rBP - addl $0x10, %ebx - cmpl $0x1F6, %ebx - ja 11f - cmpl $0x3F, 4(iBX, iSI) #; LBA total sectors - jna 11b - cmpl %eax, (iBX, iSI) #; 0x20 - jne 11b - #; cmpw $0x21, -6(iBX, iSI) #; CHS start sector number - cmpb $0x21, -6(iBX, iSI) #; CHS start sector number - jne 11b - cmpb $0x00, -5(iBX, iSI) #; CHS start sector number - jne 11b - - /* found partition with start_sector=0x20 */ - - /* yes, it is triple MBR */ - - movl %edi, %ebx #; restore file descriptor - - /* restore original partition layout */ - movl $(63+32), %esi - movl $32, %eax #; EAX=0x20, hidden sectors in BPB - jmp 3f #; continue to check BPB -11: - /* not found partition with start_sector=0x20 */ - movl $0, PRE(cs)ABS(restore_partition_layout) rBP - movl $32, %eax #; mbr_free_sectors - movl %eax, %esi - movl %edi, %ebx #; restore file descriptor -10: - cmpl $63, %eax - ja 1f /* too many sectors before partition */ - cmpl $(0x2000 / 0x200), %eax - jb 1f /* too few sectors before partition */ -3: - shll $9, %esi -#ifndef __DOS_16 - addl $MBR(0), %esi -#endif - - /* ESI points to BPB sector */ - - /* check if it has a valid FAT BPB */ - #; cmpw $512, 0x0B(iSI) // bytes per sector - cmpb $0x00, 0x0B(iSI) // bytes per sector, lo - jne 1f - cmpb $0x02, 0x0C(iSI) // bytes per sector, hi - jne 1f - cmpl %eax, 0x1C(iSI) // hidden_sectors = part_start? - jne 1f - movl 0x18(iSI), %eax // AX = sectors per track - movl %eax, %ecx - shrl $16, %ecx // CX = heads - andl $0xFFFF, %eax - subl $1, %eax #; decl %eax - cmpl $62, %eax - ja 1f - - subl $1, %ecx #; decl %ecx - cmpl $255, %ecx - ja 1f - movb 0x0D(iSI), %cl // sectors per cluster - testb %cl, %cl - jz 1f - movl $128, %eax - divb %cl - testb %ah, %ah - jnz 1f - movl 0x0E(iSI), %ecx // CX = reserved sectors - andl $0xFFFF, %ecx - testl %ecx, %ecx - jz 1f - movb 0x10(iSI), %al // number of FATs - decb %al - cmpb $1, %al - ja 1f - movb 0x15(iSI), %al // media descriptor - cmpb $0xF0, %al - jb 1f - - /* Yes, it has a valid FAT BPB */ - - /* it is time to restore original partition layout */ - xorl %ecx, %ecx - movl PRE(cs)ABS(restore_partition_layout) rBP, %edi - cmpl %ecx, %edi - je 3f - movb $(63+32), %cl - movl %ecx, MBR(0xBE00 + 0x1C) rBP /* hidden sectors */ - - shll $4, %edi #; EDI=EDI*16 - addl $MBR(0x1B6), %edi #; partition_start - subl $0x3F, 4(iDI) #; partition_length - addl $0x3F, (iDI) #; partition_start - movb $0x01, -7(iDI) #; CHS start head number - movl $(63+32+1), PRE(cs)ABS(sectors_to_write) rBP - jmp 2f -1: - stc -3: - pushfl - /*********************************************************/ - /* copy byte 0000 to 01b7 of grldr.mbr to MBR(0) ... ... */ - /*********************************************************/ - - pushl %esi - movl $ABS(grldr_mbr_start), %esi -#ifdef __DOS_16 - xorl %edi, %edi -#else - movl $MBR(0), %edi -#endif - movl $0x6e, %ecx # 0x6e dwords = 0x1b8 bytes - - cld -#ifdef __DOS_16 - cs repz movsl -#else - repz movsl -#endif - popl %esi - popfl - jc 1f - - /********************************************/ - /* ... ... end copy boot record in sector 1 */ - /********************************************/ - - testb $1, PRE(cs)ABS(mbr_bpb) rBP - jnz 1f /* mbr disable bpb */ - - /**********************************/ - /* copy the BPB to MBR(0) ... ... */ - /**********************************/ - - addl $0x0B, %esi -#ifdef __DOS_16 - pushw %ss - popw %es - movl $0x0B, %edi -#else - movl $MBR(0x0B), %edi -#endif - movl $(0x5A - 0x0B), %ecx - - cld - repz movsb - /**********************************/ - /* ... ... end copy BPB to MBR(0) */ - /**********************************/ - - /* modify reserved sectors ... ... */ -#ifdef __DOS_16 - xorl %esi, %esi -#else - movl $MBR(0), %esi -#endif - movl 0x1C(iSI), %eax #; EAX=hidden sectors - #; addw %ax, 0x0E(iSI) #; reserved sectors - addl 0x0E(iSI), %eax - movb %al, 0x0E(iSI) - movb %ah, 0x0F(iSI) - /* ... ... end modify reserved sectors */ - - /* modify total sectors word ... ... */ - movl 0x13(iSI), %eax - andl $0xFFFF, %eax - testl %eax, %eax - jz 3f - addl 0x1C(iSI), %eax - movb $0, 0x13(iSI) #; clear on overflow, lo - movb $0, 0x14(iSI) #; clear on overflow, hi - jc 3f - movb %al, 0x13(iSI) #; total sectors short, lo - movb %ah, 0x14(iSI) #; total sectors short, hi -3: - /* ... ... end modify total sectors word */ - - /* modify total sectors dword ... ... */ - movl 0x20(iSI), %eax - testl %eax, %eax - jz 3f - addl 0x1C(iSI), %eax - movl $0, 0x20(iSI) #; clear on overflow - jc 3f - movl %eax, 0x20(iSI) #; total sectors long -3: - /* ... ... end modify total sectors dword */ - - /* clear the hidden sectors ... ... */ - xorl %eax, %eax - movl %eax, 0x1C(iSI) - /* ... ... end clear the hidden sectors */ - -1: - ##################################################### - #### ... ... end copy and modify BPB #### - ##################################################### -//---------------------------------------------------------------------------- - /* modify PRE(cs)ABS(mbr_floppy) bit */ - - movb PRE(cs)ABS(mbr_floppy) rBP, %al - andb $0x01, %al -// movb %al, MBR(2) rBP - movb %al, MBR(0x5a) rBP - - /* modify PRE(cs)ABS(mbr_osbr) bit */ - - movb PRE(cs)ABS(mbr_osbr) rBP, %al - andb $0x01, %al - shlb $1, %al -// orb %al, MBR(2) rBP - orb %al, MBR(0x5a) rBP - - /* modify PRE(cs)ABS(duce) bit */ - - movb PRE(cs)ABS(duce) rBP, %al - andb $0x01, %al - shlb $2, %al -// orb %al, MBR(2) rBP - orb %al, MBR(0x5a) rBP - - /* modify PRE(cs)ABS(chs_no_tune) bit */ - - movb PRE(cs)ABS(chs_no_tune) rBP, %al - andb $0x01, %al - shlb $3, %al -// orb %al, MBR(2) rBP - orb %al, MBR(0x5a) rBP - - /* modify PRE(cs)ABS(boot_prevmbr) bit */ - - movb PRE(cs)ABS(boot_prevmbr) rBP, %al - notb %al - andb $0x01, %al - rorb $1, %al -// orb %al, MBR(2) rBP - orb %al, MBR(0x5a) rBP - - /* modify PRE(cs)ABS(time_out) byte */ - - movb PRE(cs)ABS(time_out) rBP, %al -// movb %al, MBR(3) rBP - movb %al, MBR(0x5b) rBP - - /* modify PRE(cs)ABS(hot_key) byte */ - - movl PRE(cs)ABS(hot_key) rBP, %eax -// movw %ax, MBR(4) rBP - movw %ax, MBR(0x5c) rBP - - /* modify PRE(cs)ABS(preferred_drive) byte */ - - movb PRE(cs)ABS(preferred_drive) rBP, %al -// movb %al, MBR(6) rBP - movb %al, MBR(0x5e) rBP - - /* modify PRE(cs)ABS(preferred_partition) byte */ - - movb PRE(cs)ABS(preferred_partition) rBP, %al -// movb %al, MBR(7) rBP - movb %al, MBR(0x5f) rBP - - /* modify disk serial number */ - - movl PRE(cs)ABS(serial_number) rBP, %eax - testl %eax, %eax - jz 1f - movl PRE(cs)ABS(grldr_mbr_start + 0x1FF8) rBP, %edi - andl $0xFFFF, %edi -#ifndef __DOS_16 - addl $MBR(0), %edi /* in the 1st sector */ -#endif - stosl - movl %eax, PRE(cs)ABS(grldr_mbr_start + 0x1FFC) rBP -1: - - /* copy byte 0400 and the rest of grldr.mbr to MBR(0) */ - - movl $ABS(grldr_mbr_start + 0x400), %esi - movl $MBR(0x400), %edi - movl $((0x2000 - 0x400) / 4), %ecx - - cld -#ifdef __DOS_16 - cs repz movsl -#else - repz movsl -#endif - - movl PRE(cs)ABS(mbr_free_sectors) rBP, %eax - /* EAX=old part_start */ - cmpl $(63+32), %eax - jne 2f - - movl $(0x2000 / 0x200), %ecx - cmpl $31, %ecx - ja 2f - - /* copy MBR to sector 32 */ - movl $MBR(0), %esi - movl $MBR(0x4000), %edi - movl $(0x2000 / 4), %ecx - cld - repz movsl - /* end copy MBR to sector 32 */ - - /* copy BPB to sector 32 */ - movl $MBR(0xBE0B), %esi - movl $MBR(0x400B), %edi - movl $(0x5A - 0x0B), %ecx - cld - repz movsb - /* end copy BPB to sector 32 */ - - /* copy MBR and BPB to sector 63 */ - movl $MBR(0x4000), %esi - movl $MBR(0x7E00), %edi - movl $(0x2000 / 4), %ecx - cld - repz movsl - /* end copy MBR and BPB to sector 63 */ - - /* modify partition entry for sector 0(MBR) */ - movl %ebx, %edi #; save file descriptor - movl $MBR(0), %esi - movl $0x1B6, %ebx -1: - movl PRE(cs)ABS(mbr_free_sectors) rBP, %eax - addl $0x10, %ebx - cmpl $0x1F6, %ebx - ja 1f - cmpl (iBX, iSI), %eax #; mbr_free_sectors - jne 3f - movb $0, -7(iBX, iSI) #; CHS start head number - movb $0x21, -6(iBX, iSI) #; CHS start sector number, lo - movb $0x00, -5(iBX, iSI) #; CHS start sector number, hi - subl $0x20, 4(iBX, iSI) #; LBA total sectors - addl %eax, 4(iBX, iSI) #; LBA total sectors - xorl %edx, %edx - movl %edx, -3(iBX, iSI) #; clear end CHS - movl $0x20, (iBX, iSI) #; LBA start sector number - - movl (iBX, iSI), %eax - addl 4(iBX, iSI), %eax - subl $1, %eax #; decl %eax #; EDX:EAX=LBA end sector number - /* translate LBA to CHS */ - movl $63, %ecx #; sectors per track=63 - divl %ecx #; EAX=track number, EDX+1=sector number - addl $1, %edx #; incl %edx - movb %dl, -2(iBX, iSI) #; CHS end sector number - xorl %edx, %edx #; EDX:EAX=track number - movl $255, %ecx #; heads=255 - divl %ecx #; EAX=cylinder number, EDX=head number - movb %dl, -3(iBX, iSI) #; CHS end head number - movb %al, -1(iBX, iSI) #; CHS end cylinder lo byte - shlb $6, %ah #; CHS end cylinder hi 2 bits - orb %ah, -2(iBX, iSI) #; put in the byte for CHS end sector number - jmp 1b -3: - /* start LBA */ - xorl %edx, %edx - movl (iBX, iSI), %eax #; EDX:EAX=LBA start sector number - cmpl $0x20, %eax - jb 1b - /* translate start LBA to CHS */ - movl $63, %ecx #; sectors per track=63 - divl %ecx #; EAX=track number, EDX+1=sector number - addl $1, %edx #; incl %edx - movb %dl, -6(iBX, iSI) #; CHS start sector number - xorl %edx, %edx #; EDX:EAX=track number - movl $255, %ecx #; heads=255 - divl %ecx #; EAX=cylinder number, EDX=head number - movb %dl, -7(iBX, iSI) #; CHS start head number - movb %al, -5(iBX, iSI) #; CHS start cylinder lo byte - shlb $6, %ah #; CHS start cylinder hi 2 bits - orb %ah, -6(iBX, iSI) #; put in the byte for CHS start sector number - /* end LBA */ - xorl %edx, %edx - movl (iBX, iSI), %eax #; EDX:EAX=LBA start sector number - addl 4(iBX, iSI), %eax - subl $1, %eax #; decl %eax #; EDX:EAX=LBA end sector number - /* translate end LBA to CHS */ - movl $63, %ecx #; sectors per track=63 - divl %ecx #; EAX=track number, EDX+1=sector number - addl $1, %edx #; incl %edx - movb %dl, -2(iBX, iSI) #; CHS end sector number - xorl %edx, %edx #; EDX:EAX=track number - movl $255, %ecx #; heads=255 - divl %ecx #; EAX=cylinder number, EDX=head number - movb %dl, -3(iBX, iSI) #; CHS end head number - movb %al, -1(iBX, iSI) #; CHS end cylinder lo byte - shlb $6, %ah #; CHS end cylinder hi 2 bits - orb %ah, -2(iBX, iSI) #; put in the byte for CHS end sector number - jmp 1b -1: - /* end modify partition entry for sector 0(MBR) */ - - /* modify BPB for sector 32 */ - movl $MBR(0x4000), %esi - movl 0x0E(iSI), %eax - addl $0x3F, %eax - movb %al, 0x0E(iSI) - movb %ah, 0x0F(iSI) - - movl $0x20, 0x1C(iSI) #; EAX=hidden sectors - - movl 0x13(iSI), %eax #; AX = total sectors short - andl $0xFFFF, %eax - jz 3f - addl $0x3F, %eax - movb %al, 0x13(iSI) - movb %ah, 0x14(iSI) - shrl $16, %eax - jz 3f - #; movw $0, 0x13(iSI) #; clear on overflow - movb %ah, 0x13(iSI) #; AH = 0 - movb %ah, 0x14(iSI) #; AH = 0 -3: - - cmpl $0, 0x20(iSI) #; total sectors long - jz 3f - addl $0x3F, 0x20(iSI) - jnc 3f - movl $0, 0x20(iSI) #; clear on overflow -3: - /* end modify BPB for sector 32 */ - - /* modify partition entry for sector 32 */ - movl $MBR(0x4000), %esi - movl $0x1B6, %ebx -1: - movl PRE(cs)ABS(mbr_free_sectors) rBP, %eax - addl $0x10, %ebx - cmpl $0x1F6, %ebx - ja 1f - cmpl (iBX, iSI), %eax #; mbr_free_sectors - jne 3f - movb $0, -7(iBX, iSI) #; CHS start head number - movb $0x20, -6(iBX, iSI) #; CHS start sector number, lo - movb $0x00, -5(iBX, iSI) #; CHS start sector number, hi - subl $0x3F, 4(iBX, iSI) #; LBA total sectors - addl %eax, 4(iBX, iSI) #; LBA total sectors - xorl %edx, %edx - movl %edx, -3(iBX, iSI) #; clear end CHS - movl $0x1F, (iBX, iSI) #; LBA start sector number - - movl (iBX, iSI), %eax - addl 4(iBX, iSI), %eax - subl $1, %eax #; decl %eax #; EDX:EAX=LBA end sector number - /* translate LBA to CHS */ - movl $63, %ecx #; sectors per track=63 - divl %ecx #; EAX=track number, EDX+1=sector number - addl $1, %edx #; incl %edx - movb %dl, -2(iBX, iSI) #; CHS end sector number - xorl %edx, %edx #; EDX:EAX=track number - movl $255, %ecx #; heads=255 - divl %ecx #; EAX=cylinder number, EDX=head number - movb %dl, -3(iBX, iSI) #; CHS end head number - movb %al, -1(iBX, iSI) #; CHS end cylinder lo byte - shlb $6, %ah #; CHS end cylinder hi 2 bits - orb %ah, -2(iBX, iSI) #; put in the byte for CHS end sector number - jmp 1b -3: - /* start LBA */ - xorl %edx, %edx - movl (iBX, iSI), %eax #; EDX:EAX=LBA start sector number - subl $0x20, %eax - jb 1b - movl %eax, (iBX, iSI) - /* translate start LBA to CHS */ - movl $63, %ecx #; sectors per track=63 - divl %ecx #; EAX=track number, EDX+1=sector number - addl $1, %edx #; incl %edx - movb %dl, -6(iBX, iSI) #; CHS start sector number - xorl %edx, %edx #; EDX:EAX=track number - movl $255, %ecx #; heads=255 - divl %ecx #; EAX=cylinder number, EDX=head number - movb %dl, -7(iBX, iSI) #; CHS start head number - movb %al, -5(iBX, iSI) #; CHS start cylinder lo byte - shlb $6, %ah #; CHS start cylinder hi 2 bits - orb %ah, -6(iBX, iSI) #; put in the byte for CHS start sector number - /* end LBA */ - xorl %edx, %edx - movl (iBX, iSI), %eax #; EDX:EAX=LBA start sector number - addl 4(iBX, iSI), %eax - subl $1, %eax #; decl %eax #; EDX:EAX=LBA end sector number - /* translate end LBA to CHS */ - movl $63, %ecx #; sectors per track=63 - divl %ecx #; EAX=track number, EDX+1=sector number - addl $1, %edx #; incl %edx - movb %dl, -2(iBX, iSI) #; CHS end sector number - xorl %edx, %edx #; EDX:EAX=track number - movl $255, %ecx #; heads=255 - divl %ecx #; EAX=cylinder number, EDX=head number - movb %dl, -3(iBX, iSI) #; CHS end head number - movb %al, -1(iBX, iSI) #; CHS end cylinder lo byte - shlb $6, %ah #; CHS end cylinder hi 2 bits - orb %ah, -2(iBX, iSI) #; put in the byte for CHS end sector number - jmp 1b -1: - /* end modify partition entry for sector 32 */ - - /* modify BPB for sector 63 */ - movl $MBR(0x7E00), %esi - - #; addw $0x20, 0x0E(iSI) #; reserved sectors - movl 0x0E(iSI), %eax - addl $0x20, %eax - movb %al, 0x0E(iSI) - movb %ah, 0x0F(iSI) - - movl $0x1F, 0x1C(iSI) #; EAX=hidden sectors - - movl 0x13(iSI), %eax #; AX = total sectors short - andl $0xFFFF, %eax - jz 3f - addl $0x20, %eax - movb %al, 0x13(iSI) - movb %ah, 0x14(iSI) - shrl $16, %eax - jz 3f - #; movw $0, 0x13(iSI) #; clear on overflow - movb %ah, 0x13(iSI) #; AH = 0 - movb %ah, 0x14(iSI) #; AH = 0 -3: - - cmpl $0, 0x20(iSI) #; total sectors long - jz 3f - addl $0x20, 0x20(iSI) - jnc 3f - movl $0, 0x20(iSI) #; clear on overflow -3: - /* end modify BPB for sector 63 */ - - /* modify partition entry for sector 63 */ - movl $MBR(0x7E00), %esi - movl $0x1B6, %ebx -1: - movl PRE(cs)ABS(mbr_free_sectors) rBP, %eax - addl $0x10, %ebx - cmpl $0x1F6, %ebx - ja 1f - cmpl (iBX, iSI), %eax #; mbr_free_sectors - jne 3f - movb $0, -7(iBX, iSI) #; CHS start head number - movb $0x21, -6(iBX, iSI) #; CHS start sector number, lo - movb $0x00, -5(iBX, iSI) #; CHS start sector number, hi - //subl $0x5F, 4(iBX, iSI) #; LBA total sectors - //addl %eax, 4(iBX, iSI) #; LBA total sectors - xorl %edx, %edx - movl %edx, -3(iBX, iSI) #; clear end CHS - movl $0x20, (iBX, iSI) #; LBA start sector number - - movl (iBX, iSI), %eax - addl 4(iBX, iSI), %eax - subl $1, %eax #; decl %eax #; EDX:EAX=LBA end sector number - /* translate LBA to CHS */ - movl $63, %ecx #; sectors per track=63 - divl %ecx #; EAX=track number, EDX+1=sector number - addl $1, %edx #; incl %edx - movb %dl, -2(iBX, iSI) #; CHS end sector number - xorl %edx, %edx #; EDX:EAX=track number - movl $255, %ecx #; heads=255 - divl %ecx #; EAX=cylinder number, EDX=head number - movb %dl, -3(iBX, iSI) #; CHS end head number - movb %al, -1(iBX, iSI) #; CHS end cylinder lo byte - shlb $6, %ah #; CHS end cylinder hi 2 bits - orb %ah, -2(iBX, iSI) #; put in the byte for CHS end sector number - jmp 1b -3: - /* start LBA */ - xorl %edx, %edx - movl (iBX, iSI), %eax #; EDX:EAX=LBA start sector number - subl $0x3f, %eax - jb 1b - movl %eax, (iBX, iSI) - /* translate start LBA to CHS */ - movl $63, %ecx #; sectors per track=63 - divl %ecx #; EAX=track number, EDX+1=sector number - addl $1, %edx #; incl %edx - movb %dl, -6(iBX, iSI) #; CHS start sector number - xorl %edx, %edx #; EDX:EAX=track number - movl $255, %ecx #; heads=255 - divl %ecx #; EAX=cylinder number, EDX=head number - movb %dl, -7(iBX, iSI) #; CHS start head number - movb %al, -5(iBX, iSI) #; CHS start cylinder lo byte - shlb $6, %ah #; CHS start cylinder hi 2 bits - orb %ah, -6(iBX, iSI) #; put in the byte for CHS start sector number - /* end LBA */ - xorl %edx, %edx - movl (iBX, iSI), %eax #; EDX:EAX=LBA start sector number - addl 4(iBX, iSI), %eax - subl $1, %eax #; decl %eax #; EDX:EAX=LBA end sector number - /* translate end LBA to CHS */ - movl $63, %ecx #; sectors per track=63 - divl %ecx #; EAX=track number, EDX+1=sector number - addl $1, %edx #; incl %edx - movb %dl, -2(iBX, iSI) #; CHS end sector number - xorl %edx, %edx #; EDX:EAX=track number - movl $255, %ecx #; heads=255 - divl %ecx #; EAX=cylinder number, EDX=head number - movb %dl, -3(iBX, iSI) #; CHS end head number - movb %al, -1(iBX, iSI) #; CHS end cylinder lo byte - shlb $6, %ah #; CHS end cylinder hi 2 bits - orb %ah, -2(iBX, iSI) #; put in the byte for CHS end sector number - jmp 1b -1: - /* end modify partition entry for sector 63 */ - - /* modify BPB for sector 95 */ - movl $MBR(0xBE00), %esi - movl $0x20, 0x1C(iSI) #; EAX=hidden sectors - /* end modify BPB for sector 95 */ - - movl %edi, %ebx #; restore file descriptor - movl $(63+32+1), PRE(cs)ABS(sectors_to_write) rBP - -//---------------------------------------------------------------------------- -2: /* label for the above floppy code to jump */ - - /* OK. Now write file! */ - - xorl %eax, %eax - - cmpl $2, PRE(cs)ABS(read_only) rBP #; 0=read only, 2=read/write - jne 3f /* read only */ - - /* read/write */ - -#ifdef __DOS_16 - - cmpl $0xff, PRE(cs)ABS(bios_drive_number) - je 1f /* not bios */ - - /* BIOS drive */ - /* Display disk information */ - movb PRE(cs)ABS(bios_drive_number), %al //bios id - subb $0x50, %al - movb %al, PRE(cs)ABS(msg_disk) - movw $0x2020, %ax - movw %ax, PRE(cs)ABS(msg_d) - movl 0x1ca, %eax - addl 0x1da, %eax - addl 0x1ea, %eax - addl 0x1fa, %eax - call 66f - //Wait for key - movl $ABS(msg_Wait_for_key), %ecx - call 8f /* linux_print */ -2: - movb $1, %ah //Get keyboard input - int $0x16 - je 2b //not - xorl %ecx, %ecx - cmpb $0x79, %al //"y" - jne 4f //not -1: -#endif - - call 300f -3: - testl %eax, %eax - movl $ABS(msg_write_file), %ecx - js 4f /* error */ - -//======================================================================================= - cmpl $0xff, PRE(cs)ABS(gpt) rBP - jnz 1f - - movl $ABS(grldr_mbr_start), %esi - movl $MBR(0), %edi - movl $0x2000/4, %ecx -#ifdef __DOS_16 - cs repz movsl -#else - repz movsl -#endif - movl PRE(cs)ABS(install_sectors) rBP, %ecx - shll $9, %ecx - call 400f - testl %eax, %eax - movl $ABS(msg_lseek_file), %ecx - js 4f /* error */ - movl $16, PRE(cs)ABS(sectors_to_write) rBP - movl PRE(cs)ABS(install_sectors) rBP, %ecx - call 300f - testl %eax, %eax - movl $ABS(msg_write_file), %ecx - js 4f /* error */ - -1: -//---------------------------------------------------------------------------- - cmpl $0xffffffff, PRE(cs)ABS(floppy) rBP - jne 3f /* floppy, skip geometry */ - - /* hard drive */ - - cmpl $0, PRE(cs)ABS(probed_sectors_per_track) rBP - je 2f - - cmpl $0, PRE(cs)ABS(probed_heads) rBP - je 2f - - movl $ABS(msg_geometry_S), %ecx - call 8f /* linux_print */ - - movl PRE(cs)ABS(probed_sectors_per_track) rBP, %eax - call 6f /* print decimal number */ - - movl $ABS(msg_geometry_H), %ecx - call 8f /* linux_print */ - - movl PRE(cs)ABS(probed_heads) rBP, %eax - call 6f /* print decimal number */ -2: - cmpl $(63+32+1), PRE(cs)ABS(sectors_to_write) rBP - jne 3f - movl $ABS(msg_success_create_triple_mbr), %ecx /* create triple MBR */ - cmpl $0, PRE(cs)ABS(restore_partition_layout) rBP - je 10f - movl $ABS(msg_success_cancel_triple_mbr), %ecx /* cancel triple MBR */ - jmp 10f -3: - movl $ABS(msg_success), %ecx -10: - call 8f /* linux_print */ -//3: -//success: - - # EBX=file descriptor, or 0 if specified BIOS drive - - xorl %eax, %eax # exit code = 0 - - jmp 1f - -//error: -4: - # EBX=file descriptor, or 0 if specified BIOS drive - - testl %ecx, %ecx - jz 2f - call 8f /* linux_print */ -2: - movl $ABS(msg_usage), %ecx - call 8f /* linux_print */ - - movl $1, %eax # exit code = 1 - -1: - testl %ebx, %ebx - jz 1f - - pushl %eax # exit code - -#ifdef __DOS_16 - - movb $0x3e, %ah // close file (BX = file handle) - int $0x21 - jnc 2f - negl %eax /* EAX < 0 */ -2: -#else - /* int close(int fd); */ - - /* check if in 32-bit or 64-bit mode */ - xorl %eax, %eax - decl %eax // rex prefix of 0x48 - testl %eax, %eax - /* EAX = 0 for 64-bit mode, -1 for 32-bit mode */ - jz 2f - - /* in 32-bit mode */ - movl $6, %eax # sys_close - int $0x80 - jmp 3f -2: - /* in 64-bit mode */ - movl $3, %eax # sys_close - pushl %ebx - popl %edi - syscall -3: -#endif - movl $ABS(msg_close_file), %ecx - testl %eax, %eax - - popl %eax # exit code - - jns 1f - - call 8f /* linux_print */ - -//exit: -1: -#ifdef __DOS_16 - - movb $0x4c, %ah // EXIT - TERMINATE WITH RETURN CODE in AL - int $0x21 // call DOS - -#else - pushl %eax // save exit code - /* check if in 32-bit or 64-bit mode */ - xorl %eax, %eax - decl %eax // rex prefix of 0x48 - testl %eax, %eax - /* EAX = 0 for 64-bit mode, -1 for 32-bit mode */ - popl %eax // restore exit code - jz 2f - - /* in 32-bit mode */ - xchgl %eax, %ebx # move exit code in EAX to EBX - movl $1, %eax # sys_exit - int $0x80 - jmp 3f -2: - /* in 64-bit mode */ - xchgl %eax, %edi # move exit code in EAX to EDI - movl $60, %eax # sys_exit - syscall -3: -#endif - - ret - -//---------------------------------------------------------------------------- -//floppy: -5: - - #; pushal - pushl %eax - pushl %ecx - pushl %edx - pushl %ebx - pushl %ebp - pushl %esi - pushl %edi - - /* Beforehand, try MBR */ - - /* ESI=$MBR(0) */ - - cld - cmpw $0xAA55, 0x1fe(iSI) - jne 1f - - pushl %esi - pushl %edi - pushl %ebx - - /* has a valid partition table ? */ - movb $0, %bl /* count valid partition entries */ - addl $0x1be, %esi -3: - cmpl $MBR(0x1fe), %esi - jnb 3f /* partition table is OK */ - movl $4, %ecx - - movl %esi, %edi -2: - lodsl - negl %eax - jc 2f - loop 2b - /* empty entry, check next */ - jmp 3b -2: - /* non-empty entry */ - movl %edi, %esi - - lodsl - shlb $1, %al /* boot indicator */ - jnz 2f - shrl $16, %eax - andb $63, %al - jz 2f - lodsl - shrl $16, %eax - andb $63, %al - jz 2f - lodsl - negl %eax - jnc 2f - lodsl - negl %eax - jnc 2f - incb %bl - jmp 3b -2: - stc /* invalid partition table */ -3: - popl %eax - popl %edi - popl %esi - - xchgl %eax, %ebx - - jc 1f - testb %al, %al - jz 1f - - /* MBR write not allowed */ - - movl $0, PRE(cs)ABS(sectors_to_write) rBP - - movl $ABS(msg_fstype_mbr_deny), %ecx - call 8f /* linux_print */ - - stc - #; popal - popl %edi - popl %esi - popl %ebp - popl %ebx - popl %edx - popl %ecx - popl %eax - ret -1: - /* First, try ext2 */ - - cmpw $0xEF53, 0x438(iSI) /* Magic signature, lo */ - jnz 1f - xorl %eax, %eax - cmpl %eax, 0x400(iSI) /* s_inodes_count */ - jz 1f - cmpl %eax, 0x404(iSI) /* s_blocks_count */ - jz 1f - cmpl %eax, 0x420(iSI) /* s_blocks_per_group */ - jz 1f - cmpl %eax, 0x428(iSI) /* s_inodes_per_group */ - jz 1f - movl 0x414(iSI), %eax /* s_first_data_block */ - movl %eax, %ebx /* BX=1 for 1K block, 0 otherwise */ - shrl $1, %eax /* must be 0 */ - jnz 1f - movl 0x418(iSI), %ecx /* s_log_block_size */ - cmpl $4, %ecx /* max size of block is 16K */ - ja 1f - negl %ecx /* CF=0 for 1K block, CF=1 otherwise */ - adcl %eax, %ebx /* EAX=0 */ - subl $1, %ebx #; decl %ebx - jnz 1f - - /* BX = 0 */ - /* write to ext2 boot area */ - - cld - //To install EXT2 PBR boot code - movl $ABS(grldr_pbr_start + 0x400), %esi - movl $MBR(0), %edi - movl $(0x400/4), %ecx - repz movsl PRE(cs)(iSI), (iDI) - movl $2, PRE(cs)ABS(sectors_to_write) rBP - movl $ABS(msg_fstype_ext2_allow), %ecx - call 8f /* linux_print */ - - clc - #; popal - popl %edi - popl %esi - popl %ebp - popl %ebx - popl %edx - popl %ecx - popl %eax - ret - -1: - /* Secondly, try FAT12/16/32/NTFS */ - - cld - cmpw $0xAA55, 0x1fe(iSI) /* boot signature */ - jne 1f /* not a normal BPB */ - cmpw $0x200, 0x0b(iSI) /* bytes per sector */ - jne 1f /* not a normal BPB */ - movb 0x0d(iSI), %al /* sectors per cluster */ - testb %al, %al - jz 1f /* invalid if = 0 */ - movb %al, %cl - movl $128, %eax - divb %cl /* quo=AL, rem=AH */ - testb %ah, %ah - jnz 1f /* invalid if not 2^n */ - movl 0x18(iSI), %eax /* AX = sectors per track */ - andl $0xFFFF, %eax - jz 1f /* invalid if = 0 */ - cmpl $63, %eax - ja 1f /* invalid if > 63 */ - movl 0x1a(iSI), %eax /* AX = number of heads */ - subl $1, %eax #; decl %eax - /* AX = Max head number, should be a byte */ - testb %ah, %ah /* should be 0 */ - jnz 1f /* invalid if number of heads > 256 */ - cmpb $0xf0, 0x15(iSI) /* media descriptor */ - jb 1f - - movb 0x10(iSI), %al /* number of FATs(NTFS:0, FAT:1,2) */ - cmpb $2, %al - ja 1f /* abnormal FAT */ - movl 0x11(iSI), %eax /* AX = max root entries */ - andl $0xFFFF, %eax - jnz 2f /* FAT12/FAT16 */ - - /* FAT32 or NTFS */ - movl 0x13(iSI), %eax /* AX = total sectors(small) */ - andl $0xFFFF, %eax - jnz 1f /* invalid FAT32 BPB */ - movl 0x16(iSI), %eax /* sectors per FAT(small) */ - andl $0xFFFF, %eax - jnz 1f /* invalid FAT32 BPB */ - movb 0x10(iSI), %al /* number of FATs(NTFS:0, FAT:1,2) */ - testb %al, %al - jz 4f /* NTFS */ - - /* FAT32 */ - movl 0x20(iSI), %eax /* FAT32 total sectors */ - testl %eax, %eax - jz 1f - movl 0x24(iSI), %eax /* FAT32 sectors per FAT */ - testl %eax, %eax - jz 1f - - /* sure it is FAT32 */ - cld - //To install FAT32 PBR boot code - movl $ABS(grldr_pbr_start), %esi - movl $MBR(0), %edi - movsw PRE(cs)(iSI), (iDI) - movb $0x90, %al - stosb - movl $ABS(grldr_pbr_start + 0x5a), %esi - movl $MBR(0x5a), %edi - movl $((0x200-0x5a)/2), %ecx - repz movsw PRE(cs)(iSI), (iDI) - movl $1, PRE(cs)ABS(sectors_to_write) rBP - movl $ABS(msg_fstype_fat32_allow), %ecx - call 8f /* linux_print */ - - clc - #; popal - popl %edi - popl %esi - popl %ebp - popl %ebx - popl %edx - popl %ecx - popl %eax - ret -4: - /* NTFS */ - movl 0x20(iSI), %eax /* FAT32 total sectors */ - testl %eax, %eax - jnz 1f - movl 0x0e(iSI), %eax /* reserved sectors */ - andl $0xFFFF, %eax - jnz 1f - /* sure it is NTFS */ - - cld -// movl $ABS(_start1 + 0xA00), %esi /* points to the 6th sector */ - movl $ABS(grldr_pbr_start + 0x0c00), %esi -#ifdef __DOS_16 - xorl %edi, %edi - cs movsw -#else - movl $MBR(0), %edi - #; lodsw PRE(cs)(iSI), %ax /* The first 2 byte: short jmp */ - movsw -#endif - - movb $0x90, %al /* yes, it is chs. */ - stosb - - movl $ABS(grldr_pbr_start + 0x0c54), %esi - movl $MBR(0x54), %edi - movl $((0x800 - 0x54)/ 4), %ecx - repz movsl PRE(cs)(iSI), (iDI) - - movl $4, PRE(cs)ABS(sectors_to_write) rBP - - movl $ABS(msg_fstype_ntfs_allow), %ecx - call 8f /* linux_print */ - - clc - #; popal - popl %edi - popl %esi - popl %ebp - popl %ebx - popl %edx - popl %ecx - popl %eax - ret - -2: - /* FAT12/FAT16 */ - movb 0x10(iSI), %al /* number of FATs(NTFS:0, FAT:1,2) */ - testb %al, %al - jz 1f - movl 0x16(iSI), %eax /* AX = sectors per FAT(small) */ - andl $0xFFFF, %eax - jz 1f - - cld - //Installation FAT12/16 PBR boot code - movl $ABS(grldr_pbr_start + 0x200), %esi - movl $MBR(0), %edi - movsw PRE(cs)(iSI), (iDI) - movb $0x90, %al - stosb - movl $ABS(grldr_pbr_start + 0x23e), %esi - movl $MBR(0x3e), %edi - movl $((0x200-0x3e)/2), %ecx - repz movsw PRE(cs)(iSI), (iDI) - movl $1, PRE(cs)ABS(sectors_to_write) rBP - movl $ABS(msg_fstype_fat16_allow), %ecx - movw MBR(0x39), %ax - cmpw $0x3631, %ax - je 2f - movl $ABS(msg_fstype_fat12_allow), %ecx -2: - call 8f /* linux_print */ - - clc - #; popal - popl %edi - popl %esi - popl %ebp - popl %ebx - popl %edx - popl %ecx - popl %eax - ret - -1: - /* Secondly, try EXFAT */ - cmpl $0x41465845, 0x03(iSI) /* EXFA */ - jnz 1f - cmpl $0x20202054, 0x07(iSI) /* T */ - jnz 1f - - /* write to EXFAT boot area */ - - cld - //Install exFAT PBR boot code - movl $ABS(grldr_pbr_start + 0x800), %esi - movl $MBR(0), %edi - movsw PRE(cs)(iSI), (iDI) - movb $0x90, %al - stosb - movl $ABS(grldr_pbr_start + 0x878), %esi - movl $MBR(0x78), %edi - movl $((0x400-0x78)/4), %ecx - repz movsl PRE(cs)(iSI), (iDI) - //Fill sector - xorl %eax, %eax - movl $MBR(0x400), %edi - movl $0x480, %ecx - repz stosl - movl $MBR(0), %esi - movw $0xAA55, %ax - movl $7, %ecx -3: - movw %ax, 0x5fe(%esi) - addl $0x200, %esi - loop 3b - -//Calculation exfat volume boot record checksum -//si=the index entry (from 0 to cx) eax=checksum cx=volume boot record check bytes (0x1600) - movl $MBR(0), %esi //Initialize the index - xorl %eax, %eax //Initialize the checksum - movl $MBR(0x1600), %ecx //Bytes volume boot record check -3: - rorl $1, %eax //"Checksum" right Cycle 1 bit - movzbl (%esi), %ebx //Check items - addl %ebx, %eax //(("Checksum" Left Cycle 31 bit) or ("Checksum" right Cycle 1 bit)) + Check items -2: - addl $1, %esi //index+1 - cmpl $MBR(0x6a), %esi //index=0x6a Exclude - je 2b - cmpl $MBR(0x6b), %esi //index=0x6b Exclude - je 2b - cmpl $MBR(0x70), %esi //index=0x70 Exclude - je 2b - cmpl %ecx, %esi //index=Maximum? - jb 3b //No, continue to -//Filling Checksum - movl $0x80, %ecx - repz stosl //0x200 byte -//Modify the backup area - movl $0x600, %ecx - movl $MBR(0), %esi - repz movsl - - movl $24, PRE(cs)ABS(sectors_to_write) rBP - movl $ABS(msg_fstype_exfat_allow), %ecx - call 8f /* linux_print */ - - clc - #; popal - popl %edi - popl %esi - popl %ebp - popl %ebx - popl %edx - popl %ecx - popl %eax - ret -1: - movl $ABS(msg_unsupported_fstype), %ecx - movl $0, PRE(cs)ABS(sectors_to_write) rBP - call 8f /* linux_print */ - - stc - #; popal - popl %edi - popl %esi - popl %ebp - popl %ebx - popl %edx - popl %ecx - popl %eax - ret - -//---------------------------------------------------------------------------- -//print decimal number in EAX -6: - /* print EAX value in decimal format */ - #; pushal - pushl %eax - pushl %ecx - pushl %edx - pushl %ebx - pushl %ebp - pushl %esi - pushl %edi - -#ifdef __DOS_16 - pushw %cs - popw %es -#endif - -#if 0 - cld - movl $ABS(number_digits), %edi - xchgl %eax, %edx // save EAX to EDX - movl $0x20202020, %eax // 4 spaces - stosl - stosl - stosb - stosb - subl $1, %edi #; decl %edi - xchgl %eax, %edx // restore EAX from EDX -#endif - std - movl $ABS(number_digits + 9), %edi - movl $10, %ebp -1: - xorl %edx, %edx - divl %ebp // quo=EAX, rem=EDX - xchgl %eax, %edx - orb $0x30, %al - stosb - xchgl %eax, %edx - testl %eax, %eax - jnz 1b - - /* all digits are stored */ - addl $1, %edi // points to the digit string - - movl %edi, %ecx - call 8f /* linux_print */ - - cld -#ifdef __DOS_16 - pushw %ss - popw %es -#endif - #; popal - popl %edi - popl %esi - popl %ebp - popl %ebx - popl %edx - popl %ecx - popl %eax - ret - -//---------------------------------------------------------------------------- -//parse_number: -7: - - /* input: EDI points to the number - * EBX upper limit of the number - * output: EBX the value of the number - * EDX changed - * ESI changed - * CF=1 failure - * CF=0 success - */ - - pushl %ebp - pushl %eax - pushl %ebx /* upper limit */ - cld - pushl %edi - popl %esi - movl $0xffffffff, %edx - xorl %ebx, %ebx - lodsw - cmpw $0x5830, %ax /* 0X */ - je 1f - cmpw $0x7830, %ax /* 0x */ - je 1f - - /* decimal */ - pushl %edi - popl %esi - movl $10, %ebp -2: - xorl %eax, %eax - lodsb - cmpb $0, %al - je 4f /* CF=0 */ - cmpb $0x30, %al - jb 3f - cmpb $0x39, %al - ja 3f - subb $0x30, %al - pushl %eax - movl %ebx, %eax - mull %ebp - movl %eax, %ebx - popl %eax - jc 3f - addl %eax, %ebx - jc 3f - popl %eax - pushl %eax /* upper limit */ - cmpl %eax, %ebx - ja 3f - jmp 2b -1: - - /* hex */ - movl $16, %ebp -2: - xorl %eax, %eax - lodsb - cmpb $0, %al - je 4f /* CF=0 */ - cmpb $0x30, %al - jb 3f - cmpb $0x39, %al - jbe 1f - orb $0x20, %al - cmpb $0x61, %al - jb 3f - cmpb $0x66, %al - ja 3f - subb $0x27, %al -1: - subb $0x30, %al - pushl %eax - movl %ebx, %eax - mull %ebp - movl %eax, %ebx - popl %eax - jc 3f - addl %eax, %ebx - jc 3f - popl %eax - pushl %eax /* upper limit */ - cmpl %eax, %ebx - ja 3f - jmp 2b - -3: - stc - popl %eax /* upper limit */ - popl %eax - popl %ebp - ret -4: - testl %edx, %edx /* CF=0 */ - jnz 3b - popl %eax /* upper limit */ - popl %eax - popl %ebp - ret - -//---------------------------------------------------------------------------- -//linux_print: -8: - - /* print a message. - * input: ECX points to message string - * output: message is displayed on the stdout device - */ - - /* ssize_t write(int fd, const void *buf, size_t count) */ - #; pushal - pushl %eax - pushl %ecx - pushl %edx - pushl %ebx - pushl %ebp - pushl %esi - pushl %edi - -#ifdef __DOS_16 - - cld - movl %ecx, %esi -1: - lodsb %cs:(%si), %al // get token - cmpb $0, %al // end of string? - je 1f -#if 0 - /* use BIOS independent of DOS */ - xorw %bx, %bx // video page 0 - movb $0x0e, %ah // print it - int $0x10 // via TTY mode -#else - /* use stdout for redirection of the output */ - movb %al, %dl // character to write - movb $0x02, %ah // WRITE CHARACTER TO STANDARD OUTPUT - int $0x21 // call DOS -#endif - jmp 1b // until done -1: - -#else - pushl %ecx - movl %ecx, %edi # scan the message string ... - movl $(msg_end - msg_start), %ecx - movb $0, %al # ... find the ending zero byte - - cld - repnz scasb - - movl %edi, %edx - popl %ecx # ECX points to the message - subl %ecx, %edx # EDX=message length - subl $1, %edx #; decl %edx - # discard the ending zero byte - - /* check if in 32-bit or 64-bit mode */ - xorl %eax, %eax - decl %eax // rex prefix of 0x48 - testl %eax, %eax - /* EAX = 0 for 64-bit mode, -1 for 32-bit mode */ - jz 1f - - /* in 32-bit mode */ - movl $4, %eax # sys_write - movl $1, %ebx # file descriptor = stdout - int $0x80 - jmp 3f -1: - /* in 64-bit mode */ - movl $1, %eax # sys_write - movl $1, %edi # file descriptor = stdout - movl %ecx, %esi - syscall -3: -#endif - - #; popal - popl %edi - popl %esi - popl %ebp - popl %ebx - popl %edx - popl %ecx - popl %eax - ret - -//---------------------------------------------------------------------------- -//probe_geometry: -9: - #; pushal - pushl %eax - pushl %ecx - pushl %edx - pushl %ebx - pushl %ebp - pushl %esi - pushl %edi - - cmpl $0xff, PRE(cs)ABS(gpt) rBP - jz 88f - - addl $0x200, %esi - - movl $0, PRE(cs)ABS(mbr_free_sectors) rBP # geometry ok - movl $0, PRE(cs)ABS(Cmax) rBP - movl $0, PRE(cs)ABS(Hmax) rBP - movl $0, PRE(cs)ABS(Smax) rBP - - movl $0, PRE(cs)ABS(i) rBP # partition number -1: - cmpl $4, PRE(cs)ABS(i) rBP - jae 1f - - /* the boot indicator must be 0x80(bootable) or 0(non-bootable) */ - - movl PRE(cs)ABS(i) rBP, %ebx - movl PRE(cs)ABS(i) rBP, %edi - shll $4, %ebx # EBX = i * 16 - movb -66(iBX, iSI), %al # boot_indicator - shlb $1, %al - jnz 6f /* geometry_probe_failed */ - - /* check if the entry is empty, i.e., all the 16 bytes are 0 */ - - movl -66(iBX, iSI), %eax - orl -62(iBX, iSI), %eax - orl -58(iBX, iSI), %eax - orl -54(iBX, iSI), %eax - jz 2f # empty partition entry - - /* valid partitions never start at 0, because this is where the MBR - * lives; and more, the number of total sectors should be non-zero. - */ - - cmpl $0, -58(iBX, iSI) # start_lba - jz 6f /* geometry_probe_failed */ - - cmpl $0, -54(iBX, iSI) # total_sectors - jz 6f /* geometry_probe_failed */ - - /* the partitions should not overlap each other */ - - movl $-1, PRE(cs)ABS(j) rBP // j = -1 -3: - // for (j = 0; j < i; j++) - incl PRE(cs)ABS(j) rBP // j++ - cmpl %edi, PRE(cs)ABS(j) rBP # i = EDI - jae 3f // j >= i, break. - - movl -58(iBX, iSI), %ecx # ECX=P[i].start_lba - - movl PRE(cs)ABS(j) rBP, %edx - shll $4, %edx # EDX = j * 16 - MOVL -58(%edx, %esi), %eax # EAX=P[j].start_lba - - // if ((P[j].start_lba <= P[i].start_lba) && (P[j].start_lba + P[j].total_sectors >= P[i].start_lba + P[i].total_sectors)) - - cmpl %ecx, %eax - ja 4f - - pushl %ecx - pushl %eax - - addl -54(iBX, iSI), %ecx // ECX = P[i].start_lba + P[i].total_sectors - ADDL -54(%edx, %esi), %eax // EAX = P[j].start_lba + P[j].total_sectors - - cmpl %ecx, %eax - - popl %eax - popl %ecx - - jb 4f - - jmp 3b //continue -4: - // if ((P[j].start_lba >= P[i].start_lba) && (P[j].start_lba + P[j].total_sectors <= P[i].start_lba + P[i].total_sectors)) - - cmpl %ecx, %eax - jb 4f - - pushl %ecx - pushl %eax - - addl -54(iBX, iSI), %ecx // ECX = P[i].start_lba + P[i].total_sectors - ADDL -54(%edx, %esi), %eax // EAX = P[j].start_lba + P[j].total_sectors - - cmpl %ecx, %eax - - popl %eax - popl %ecx - - ja 4f - - jmp 3b //continue -4: - - cmpl %ecx, %eax - jae 4f - - // P[j].start_lba < P[i].start_lba - subl %eax, %ecx // ECX = P[i].start_lba - P[j].start_lba - CMPL -54(%edx, %esi), %ecx # ECX < P[j].total_sectors - jmp 5f -4: - // P[j].start_lba >= P[i].start_lba - subl %ecx, %eax // EAX = P[j].start_lba - P[i].start_lba - cmpl -54(iBX, iSI), %eax # EAX < P[i].total_sectors -5: - jb 6f /* geometry_probe_failed */ - - jmp 3b //continue -3: - - /* the start cylinder number */ - - #; movzwl -64(iBX, iSI), %eax # start_sector_cylinder - movl -64(iBX, iSI), %eax # start_sector_cylinder - andl $0xFFFF, %eax - - - movl %eax, %edx - andl $0x003f, %edx - jz 6f /* geometry_probe_failed */ - - movl %edx, PRE(cs)ABS(X) rBP # the sector number - - cmpl %edx, PRE(cs)ABS(Smax) rBP - jae 3f - movl %edx, PRE(cs)ABS(Smax) rBP -3: - movl -58(iBX, iSI), %ecx # start_lba - addl $1, %ecx #; incl %ecx - subl %edx, %ecx - - movl $ABS(L), %edx - MOVL %ecx, PRE(cs)(%edx, %edi, 8) # L[i] - - shrb $6, %al - xchgb %al, %ah - andl $0xFFFF, %eax - - movl $ABS(C), %edx - MOVL %eax, PRE(cs)(%edx, %edi, 4) # C[i] - - cmpl %eax, PRE(cs)ABS(Cmax) rBP - jae 3f - movl %eax, PRE(cs)ABS(Cmax) rBP -3: - - movzbl -65(iBX, iSI), %eax # start_head - movl $ABS(H), %edx - MOVL %eax, PRE(cs)(%edx, %edi, 4) # H[i] - - cmpl %eax, PRE(cs)ABS(Hmax) rBP - jae 3f - movl %eax, PRE(cs)ABS(Hmax) rBP -3: - - /* the end cylinder number */ - - #; movzwl -60(iBX, iSI), %eax # end_sector_cylinder - movl -60(iBX, iSI), %eax # end_sector_cylinder - andl $0xFFFF, %eax - - movl %eax, %edx - andl $0x003f, %edx - jz 6f /* geometry_probe_failed */ - - movl %edx, PRE(cs)ABS(Y) rBP # the sector number - - cmpl %edx, PRE(cs)ABS(Smax) rBP - jae 3f - movl %edx, PRE(cs)ABS(Smax) rBP -3: - movl -58(iBX, iSI), %ecx # start_lba - addl -54(iBX, iSI), %ecx # total_sectors - # XXX: possible overflow! - - subl %edx, %ecx - jb 6f /* geometry_probe_failed */ - - addl $4, %edi # EDI=i+4 - - movl $ABS(L), %edx - MOVL %ecx, PRE(cs)(%edx, %edi, 8) # L[i+4] - - shrb $6, %al - xchgb %al, %ah - andl $0xFFFF, %eax - - movl $ABS(C), %edx - MOVL %eax, PRE(cs)(%edx, %edi, 4) # C[i+4] - - cmpl %eax, PRE(cs)ABS(Cmax) rBP - jae 3f - movl %eax, PRE(cs)ABS(Cmax) rBP -3: - xchgl %eax, %ecx # save AX to CX - # EAX = L[i+4] - - ##################################################################### - pushl %esi # save ESI before it changes - ##################################################################### - - pushl %eax # EAX = L[i+4] - movzbl -61(iBX, iSI), %eax # end_head - popl %esi # begin to use ESI(= L[i+4] initially) - - movl $ABS(H), %edx - MOVL %eax, PRE(cs)(%edx, %edi, 4) # H[i+4] - - cmpl %eax, PRE(cs)ABS(Hmax) rBP - jae 3f - movl %eax, PRE(cs)ABS(Hmax) rBP -3: - - /* Check the large disk partition -- Win98 */ - cmpl $63, PRE(cs)ABS(Y) rBP - jne 3f - cmpl %eax, PRE(cs)ABS(Hmax) rBP # EAX=H[i+4] - jne 3f - cmpl %ecx, PRE(cs)ABS(Cmax) rBP # ECX=C[i+4] - jne 3f - - cmpl $254, %eax # EAX=PRE(cs)ABS(Hmax) - jnb 4f - cmpl $1022, %ecx # CX=PRE(cs)ABS(Cmax) - jb 3f -4: - movl $63, %edx # EDX=PRE(cs)ABS(Y) - addl %edx, %esi - addl $1, %eax #; incl %eax - mull %edx # EDX:EAX=product - # EDX=0 - # EAX high word = 0 - # AX=(Hmax+1)*63 - pushl %eax # EAX=(Hmax+1)*63 - addl $1, %ecx #; incl %ecx - mull %ecx # EDX:EAX=product - # EDX=0 - cmpl %esi, %eax - popl %eax # EAX=(Hmax+1)*63 - jnb 3f - - /* EDI=i+4 at this moment */ - - pushl %eax # EAX=(Hmax+1)*63 - subl $4, %edi # EDI=i - - movl $ABS(C), %ebx - MOVL PRE(cs)(%ebx, %edi, 4), %eax # C[i] - andl $0xFFFF, %eax - - movl PRE(cs)ABS(Hmax) rBP, %esi # Hmax - addl $1, %esi #; incl %esi - - pushl %eax # EAX=C[i] - - movl $ABS(H), %ebx - MOVL PRE(cs)(%ebx, %edi, 4), %ecx # H[i] - - mull %esi # EDX=0, EAX=product - addl %ecx, %eax - movl $63, %edx - mull %edx # EDX=0, EAX=product - - movl $ABS(L), %ebx - MOVL PRE(cs)(%ebx, %edi, 8), %esi # L[i] - - cmpl %esi, %eax - popl %eax # EAX=C[i] - - jae 4f - - /* calculate CHS numbers from start LBA */ - - //pushl %eax # EAX=C[i] - - xorl %edx, %edx - xchgl %eax, %esi # ESI=C[i], EDX:EAX=L[i] - - divl PRE(cs)ABS(Y) rBP # Y=63 - # quo=EAX, rem=EDX - addl $1, %edx #; incl %edx # sector number - cmpl %edx, PRE(cs)ABS(X) rBP - je 15f - cmpl $63, PRE(cs)ABS(X) rBP - jne 4f -15: - xorl %edx, %edx - movl PRE(cs)ABS(Hmax) rBP, %ebx - addl $1, %ebx #; incl %ebx # EBX=Hmax+1 - divl %ebx # quo=EAX=cylinder number - # rem=EDX=head number - cmpl %edx, %ecx # ECX=H[i] - je 15f - subl $1, %ebx #; decl %ebx - # EBX=Hmax - cmpl %ebx, %ecx - jne 4f -15: - /* EAX=calculated cylinder number, ESI=C[i] */ - - cmpl PRE(cs)ABS(Cmax) rBP, %esi - je 4f - andl $0x3ff, %eax # low 10 bit of calculated cylinder - cmpl %eax, %esi -4: - popl %eax - //##jne 6f /* geometry_probe_failed */ - jmp 5f -3: - - /* Check the large disk partition -- Win2K */ - - /* EDI=i+4 at this moment */ - cmpl $63, PRE(cs)ABS(Y) rBP - jne 3f - movl $ABS(H), %edx - MOVL PRE(cs)(%edx, %edi, 4), %eax # H[i+4] - cmpl %eax, PRE(cs)ABS(Hmax) rBP # EAX=H[i+4] - jne 3f - - movl $ABS(L), %edx - MOVL PRE(cs)(%edx, %edi, 8), %esi # L[i+4] - - movl $ABS(C), %edx - MOVL PRE(cs)(%edx, %edi, 4), %ecx # C[i+4] - andl $0xFFFF, %ecx - - addl $1, %ecx #; incl %ecx - addl $1, %eax #; incl %eax - - mull %ecx # EDX=0, EAX=product - mull PRE(cs)ABS(Y) rBP # Y=63, EDX=0, EAX=product - addl PRE(cs)ABS(Y) rBP, %esi - cmpl %esi, %eax - jnb 3f - - movl PRE(cs)ABS(Hmax) rBP, %eax - addl $1, %eax #; incl %eax - mull PRE(cs)ABS(Y) rBP # Y=63, EDX=0, EAX=product - - xorl %edx, %edx - xchgl %eax, %esi # ESI=(Hmax+1)*63 - # EAX=L[i+4]+Y - - divl %esi # EAX=quo, EDX=rem - testl %edx, %edx - jnz 3f - subl $1, %eax #; decl %eax - andl $0x3ff, %eax - subl $1, %ecx #; decl %ecx - cmpl %eax, %ecx - jne 3f - - /* EDI=i+4 at this moment */ - - subl $4, %edi # EDI=i - - movl $ABS(C), %ebx - MOVL PRE(cs)(%ebx, %edi, 4), %eax # C[i] - - pushl %eax - mull %esi # ESI=(Hmax+1)*63 - # EDX=0, EAX=product - - pushl %esi # ESI=(Hmax+1)*63 - - xchgl %eax, %esi # ESI=product - movl $ABS(H), %ebx - MOVL PRE(cs)(%ebx, %edi, 4), %eax # H[i] - mull PRE(cs)ABS(Y) rBP # Y=63, EDX=0, EAX=H[i]*63 - - pushl %eax - - addl %eax, %esi - - movl $ABS(L), %ebx - MOVL PRE(cs)(%ebx, %edi, 8), %eax # L[i] - cmpl %eax, %esi - - popl %ebx # EBX=H[i]*63 - popl %esi # ESI=(Hmax+1)*63 - popl %ecx # ECX=C[i] - xchgl %eax, %esi - - jae 5f - xchgl %eax, %esi - subl %ebx, %eax - xorl %edx, %edx - divl %esi # EAX=quo, EDX=rem - testl %edx, %edx - //##jnz 6f /* geometry_probe_failed */ - jnz 5f /* geometry_probe_failed */ - andl $0x3ff, %eax - cmpl %eax, %ecx - //##jne 6f /* geometry_probe_failed */ - jne 5f /* geometry_probe_failed */ - - xchgl %eax, %esi - jmp 5f -3: - /* Maximum of C[n] * (H * S) + H[n] * S = 1023 * 255 * 63 + 254 * 63 = 0xFB03C1 */ - - /* EDI=i+4 at this moment */ - movl $ABS(L), %edx - MOVL PRE(cs)(%edx, %edi, 8), %esi # L[i+4] - cmpl $0xFB03C1, %esi - jbe 3f - - /* set H/S to max */ - cmpl $254, PRE(cs)ABS(Hmax) rBP - jae 4f - movl $254, PRE(cs)ABS(Hmax) rBP -4: - movl $63, PRE(cs)ABS(Smax) rBP - xorl %edx, %edx - movl %esi, %eax - divl PRE(cs)ABS(Smax) rBP - testl %edx, %edx - //##jnz 6f /* geometry_probe_failed */ - jnz 5f /* geometry_probe_failed */ - - /* EAX=L[i+4]/63, EDX=0 */ - - movl $ABS(H), %ebx - MOVL PRE(cs)(%ebx, %edi, 4), %ebx # EBX=H[i+4] - movl PRE(cs)ABS(Hmax) rBP, %ecx - addl $1, %ecx #; incl %ecx # ECX=Hmax+1 - divl %ecx - cmpl %edx, %ebx - je 15f - cmpl PRE(cs)ABS(Hmax) rBP, %ebx - //##jne 6f /* geometry_probe_failed */ - jne 5f /* geometry_probe_failed */ -15: - /* EAX=L[i+4]/63/(Hmax+1) */ - andl $0x3FF, %eax - movl $ABS(C), %edx - MOVL PRE(cs)(%edx, %edi, 4), %ebx # C[i+4] - andl $0xFFFF, %ebx - cmpl %eax, %ebx - je 15f - cmpl PRE(cs)ABS(Cmax) rBP, %ebx - //##jne 6f /* geometry_probe_failed */ - jne 5f /* geometry_probe_failed */ -15: - movl $63, %eax - mull %ecx - - /* EDI=i+4 at this moment */ - - pushl %eax # EAX=(Hmax+1)*63 - subl $4, %edi # EDI=i - - movl $ABS(C), %ebx - MOVL PRE(cs)(%ebx, %edi, 4), %eax # C[i] - andl $0xFFFF, %eax - - movl PRE(cs)ABS(Hmax) rBP, %esi # Hmax - addl $1, %esi #; incl %esi - - pushl %eax # EAX=C[i] - - movl $ABS(H), %ebx - MOVL PRE(cs)(%ebx, %edi, 4), %ecx # H[i] - - mull %esi # EDX=0, EAX=product - addl %ecx, %eax - movl $63, %edx - mull %edx # EDX=0, EAX=product - - movl $ABS(L), %ebx - MOVL PRE(cs)(%ebx, %edi, 8), %esi # L[i] - - cmpl %esi, %eax - popl %eax # EAX=C[i] - - jae 4f - - /* calculate CHS numbers from start LBA */ - - //pushl %eax # EAX=C[i] - - xorl %edx, %edx - xchgl %eax, %esi # ESI=C[i], EDX:EAX=L[i] - - divl PRE(cs)ABS(Y) rBP # Y=63 - # quo=EAX, rem=EDX - addl $1, %edx #; incl %edx # sector number - cmpl %edx, PRE(cs)ABS(X) rBP - je 15f - cmpl $63, PRE(cs)ABS(X) rBP - jne 4f -15: - xorl %edx, %edx - movl PRE(cs)ABS(Hmax) rBP, %ebx - addl $1, %ebx #; incl %ebx # EBX=Hmax+1 - divl %ebx # quo=EAX=cylinder number - # rem=EDX=head number - cmpl %edx, %ecx # ECX=H[i] - je 15f - subl $1, %ebx #; decl %ebx - # EBX=Hmax - cmpl %ebx, %ecx - jne 4f -15: - /* EAX=calculated cylinder number, EBP=C[i] */ - - cmpl PRE(cs)ABS(Cmax) rBP, %esi - je 4f - andl $0x3ff, %eax # low 10 bit of calculated cylinder - cmpl %eax, %esi -4: - popl %eax - //##jne 6f /* geometry_probe_failed */ - //jmp 5f -5: - je 5f - movl $-1, PRE(cs)ABS(mbr_free_sectors) rBP # geometry fail - jmp 3f -5: - /* EAX = (Hmax+1)*63 */ - - movl $ABS(C), %ebx - MOVL $0, PRE(cs)(%ebx, %edi, 4) # C[i]=0 - - movl $ABS(H), %ebx - MOVL $1, PRE(cs)(%ebx, %edi, 4) # H[i]=1 - - movl $ABS(L), %ebx - MOVL $63, PRE(cs)(%ebx, %edi, 8) # L[i]=63 - - addl $4, %edi # EDI=i+4 - - movl $ABS(C), %ebx - MOVL $1, PRE(cs)(%ebx, %edi, 4) # C[i+4]=1 - - movl $ABS(H), %ebx - MOVL $0, PRE(cs)(%ebx, %edi, 4) # H[i+4]=0 - - movl $ABS(L), %ebx - MOVL %eax, PRE(cs)(%ebx, %edi, 8) # L[i+4]=(Hmax+1)*63 -3: - ##################################################################### - popl %esi # restore ESI - ##################################################################### - - jmp 3f - -2: /* else */ - - /* empty entry, zero all the coefficients */ - - movl $ABS(C), %ebx - MOVL $0, PRE(cs)(%ebx, %edi, 4) # C[i]=0 - - movl $ABS(H), %ebx - MOVL $0, PRE(cs)(%ebx, %edi, 4) # H[i]=0 - - movl $ABS(L), %ebx - MOVL $0, PRE(cs)(%ebx, %edi, 8) # L[i]=0 - - addl $4, %edi - movl $ABS(C), %ebx - MOVL $0, PRE(cs)(%ebx, %edi, 4) # C[i+4]=0 - - movl $ABS(H), %ebx - MOVL $0, PRE(cs)(%ebx, %edi, 4) # H[i+4]=0 - - movl $ABS(L), %ebx - MOVL $0, PRE(cs)(%ebx, %edi, 8) # L[i+4]=0 - -3: - - incl PRE(cs)ABS(i) rBP - jmp 1b -1: - - /* all coefficients are generated ok */ - -# -------------------------------------------------------------------- - -#if 0 - - /* print the coefficients */ - - xorl %edi, %edi -1: - cmpl $4, %edi - jae 1f - - /* print C[i] */ - movl $ABS(C), %ebx - MOVL PRE(cs)(%ebx, %edi, 4), %eax # C[i] - - call 6b //print decimal number - - /* print spaces */ - movl $ABS(delimit_space), %ecx - call 8b /* linux_print */ - - /* print H[i] */ - movl $ABS(H), %ebx - MOVL PRE(cs)(%ebx, %edi, 4), %eax # H[i] - - call 6b //print decimal number - - /* print spaces */ - movl $ABS(delimit_space), %ecx - call 8b /* linux_print */ - - /* print L[i] */ - movl $ABS(L), %ebx - MOVL PRE(cs)(%ebx, %edi, 8), %eax # L[i] - - call 6b //print decimal number - - /* print spaces */ - movl $ABS(delimit_space), %ecx - call 8b /* linux_print */ - - addl $4, %edi - - /* print C[i] */ - movl $ABS(C), %ebx - MOVL PRE(cs)(%ebx, %edi, 4), %eax # C[i+4] - - call 6b //print decimal number - - /* print spaces */ - movl $ABS(delimit_space), %ecx - call 8b /* linux_print */ - - /* print H[i] */ - movl $ABS(H), %ebx - MOVL PRE(cs)(%ebx, %edi, 4), %eax # H[i+4] - - call 6b //print decimal number - - /* print spaces */ - movl $ABS(delimit_space), %ecx - call 8b /* linux_print */ - - /* print L[i] */ - movl $ABS(L), %ebx - MOVL PRE(cs)(%ebx, %edi, 8), %eax # L[i+4] - - call 6b //print decimal number - - /* print spaces */ - movl $ABS(delimit_newline), %ecx - call 8b /* linux_print */ - - subl $4, %edi - - addl $1, %edi #; incl %edi - jmp 1b -1: - -#endif - -# -------------------------------------------------------------------- - - /* mbr_free_sectors = 0 for geometry ok, -1 for failure */ - cmpl $0, PRE(cs)ABS(mbr_free_sectors) rBP - movl $1, PRE(cs)ABS(mbr_free_sectors) rBP # partition table ok - jne 6f /* -1 for failed geometry probing */ - - //movl $1, PRE(cs)ABS(mbr_free_sectors) # partition table ok - - xorl %edi, %edi # equation number PRE(cs)ABS(i) -1: - cmpl $8, %edi - jae 1f - - movl $ABS(C), %ebx - CMPL $0, PRE(cs)(%ebx, %edi, 4) # C[i] - - jne 1f - - addl $1, %edi #; incl %edi - jmp 1b -1: - - cmpl $8, %edi - jb 1f - - /* all C[i] == 0 */ - - xorl %edi, %edi # equation number PRE(cs)ABS(i) - movl $ABS(H), %ebx -2: - cmpl $8, %edi - jae 2f - - MOVL PRE(cs)(%ebx, %edi, 4), %ecx # H[i] - testl %ecx, %ecx - - jne 2f - - addl $1, %edi #; incl %edi - jmp 2b -2: - - cmpl $8, %edi - je 6f /* geometry_probe_failed */ # all H[i] == 0 - - movl $1, PRE(cs)ABS(mbr_free_sectors) rBP # partition table ok - - xorl %edx, %edx # equation number j - movl $ABS(L), %ebx -2: - cmpl %edi, %edx - jae 2f - - CMPL $0, PRE(cs)(%ebx, %edx, 8) # L[j] - - jne 6f /* geometry_probe_failed */ - - addl $1, %edx #; incl %edx - jmp 2b -2: - - /* j == i */ - - MOVL PRE(cs)(%ebx, %edi, 8), %eax # L[i] - testl %eax, %eax - - jle 6f /* geometry_probe_failed */ - # OF=0; jmp if SF=1 or ZF=1 - - cdq # EDX=0 - divl %ecx # ECX=H[i] - # EAX=quo=sectors_per_track - # EDX=rem - testl %edx, %edx - jnz 6f /* geometry_probe_failed */ - - movl %eax, PRE(cs)ABS(probed_sectors_per_track) rBP - - cmpl $63, %eax - ja 6f /* geometry_probe_failed */ - - cmpl PRE(cs)ABS(Smax) rBP, %eax - jb 6f /* geometry_probe_failed */ - - movl %eax, PRE(cs)ABS(Smax) rBP - - movl %edi, %edx - addl $1, %edx #; incl %edx - # equation number j=i+1 -2: - cmpl $8, %edx - jae 2f - - movl $ABS(H), %ebx - MOVL PRE(cs)(%ebx, %edx, 4), %ecx # H[j] - - movl $ABS(L), %ebx - MOVL PRE(cs)(%ebx, %edx, 8), %eax # L[j] - - jecxz 3f - - pushl %edx - - xchgl %eax, %ecx # EAX=H[j], ECX=L[j] - mull PRE(cs)ABS(probed_sectors_per_track) rBP # EAX=product - # EDX=0 - popl %edx - - cmpl %eax, %ecx - - jnz 6f /* geometry_probe_failed */ - - jmp 4f -3: - testl %eax, %eax - jnz 6f /* geometry_probe_failed */ -4: - - addl $1, %edx #; incl %edx - jmp 2b -2: - - movl PRE(cs)ABS(Hmax) rBP, %eax - addl $1, %eax #; incl %eax - movl %eax, PRE(cs)ABS(probed_heads) rBP - - jmp 2f -1: - movl $1, PRE(cs)ABS(mbr_free_sectors) rBP # partition table ok - - testl %edi, %edi - jz 1f - - /* xchgw C[i], C[0] */ - - movl $ABS(C), %ebx - MOVL PRE(cs)(%ebx, %edi, 4), %eax # C[i] - movl PRE(cs)(iBX), %ecx # C[0] - - movl %eax, PRE(cs)(iBX) - MOVL %ecx, PRE(cs)(%ebx, %edi, 4) - - /* xchgw H[i], H[0] */ - - movl $ABS(H), %ebx - MOVL PRE(cs)(%ebx, %edi, 4), %eax # H[i] - movl PRE(cs)(iBX), %ecx # H[0] - - movl %eax, PRE(cs)(iBX) - MOVL %ecx, PRE(cs)(%ebx, %edi, 4) - - /* xchgw L[i], L[0] */ - - movl $ABS(L), %ebx - MOVL PRE(cs)(%ebx, %edi, 8), %eax # L[i] - movl PRE(cs)(iBX), %ecx # L[0] - - movl %eax, PRE(cs)(iBX) - MOVL %ecx, PRE(cs)(%ebx, %edi, 8) - -1: - - movl $0, PRE(cs)ABS(H8) rBP # will store sectors per track - - /* for (i = 1; i < 8; i++) */ - - movl $1, %edi -1: - cmpl $8, %edi - jae 1f - - movl $ABS(L), %ebx - MOVL PRE(cs)(%ebx, %edi, 8), %eax # L[i] - - movl PRE(cs)ABS(C) rBP, %edx # C[0] - andl $0xFFFF, %edx - mull %edx # EDX:EAX=product - - MOVL %eax, PRE(cs)(%ebx, %edi, 8) # L[i] low - MOVL %edx, PRE(cs)4(%ebx, %edi, 8) # L[i] high - - movl $ABS(C), %ebx - MOVL PRE(cs)(%ebx, %edi, 4), %eax # C[i] - andl $0xFFFF, %eax - - mull PRE(cs)ABS(L) rBP # L[0] - - movl $ABS(L), %ebx - SUBL %eax, PRE(cs)(%ebx, %edi, 8) # L[i] low - SBBL %edx, PRE(cs)4(%ebx, %edi, 8) # L[i] high - - movl $ABS(H), %ebx - MOVL PRE(cs)(%ebx, %edi, 4), %eax # H[i] - - movl PRE(cs)ABS(C) rBP, %edx # C[0] - andl $0xFFFF, %edx - mull %edx # EDX:EAX=product - # EDX=0 - - MOVL %eax, PRE(cs)(%ebx, %edi, 4) # H[i] - - movl $ABS(C), %ebx - MOVL PRE(cs)(%ebx, %edi, 4), %eax # C[i] - andl $0xFFFF, %eax - - mull PRE(cs)ABS(H) rBP # H[0] - - movl $ABS(H), %ebx - SUBL %eax, PRE(cs)(%ebx, %edi, 4) # H[i] - - /* if (H[i]) */ - - jz 3f - - ja 4f - - movl $ABS(H), %ebx - NEGL PRE(cs)(%ebx, %edi, 4) # H[i] - - movl $ABS(L), %ebx - xorl %eax, %eax - NEGL PRE(cs)(%ebx, %edi, 8) # L[i] low - cmc - NOTL PRE(cs)4(%ebx, %edi, 8) # L[i] high - ADCL %eax, PRE(cs)4(%ebx, %edi, 8) - -4: - movl $ABS(L), %ebx - CMPL $0, PRE(cs)4(%ebx, %edi, 8) # L[i] high - jne 6f /* geometry_probe_failed */ - - MOVL PRE(cs)(%ebx, %edi, 8), %eax # L[i] low - testl %eax, %eax - - jle 6f /* geometry_probe_failed */ - # OF=0; jmp if SF=1 or ZF=1 - - cdq # EDX=0 - - movl $ABS(H), %ebx - DIVL PRE(cs)(%ebx, %edi, 4) # H[i] - # EAX=sectors per track - testl %edx, %edx - jnz 6f /* geometry_probe_failed */ - - movl %eax, PRE(cs)ABS(L8) rBP - - cmpl $63, %eax - ja 6f /* geometry_probe_failed */ - - cmpl PRE(cs)ABS(Smax) rBP, %eax - jb 6f /* geometry_probe_failed */ - - movl %eax, PRE(cs)ABS(Smax) rBP - - cmpl $0, PRE(cs)ABS(H8) rBP - je 4f - - cmpl %eax, PRE(cs)ABS(H8) rBP # EAX=L[8] - jne 6f /* geometry_probe_failed */ - - jmp 5f -4: - movl %eax, PRE(cs)ABS(H8) rBP # EAX=L[8] -5: - - jmp 4f -3: /* else */ - movl $ABS(L), %ebx - CMPL $0, PRE(cs)(%ebx, %edi, 8) # L[i] low - jne 6f /* geometry_probe_failed */ - - CMPL $0, PRE(cs)4(%ebx, %edi, 8) # L[i] high - jne 6f /* geometry_probe_failed */ - -4: /* end if (H[i]) */ - - addl $1, %edi #; incl %edi - jmp 1b -1: /* end for (i = 1; i < 8; i++) */ - - /* if (PRE(cs)ABS(H)[8]) */ - - cmpl $0, PRE(cs)ABS(H8) rBP - je 3f - - /* PRE(cs)ABS(H)[8] is sectors per track */ - - movl PRE(cs)ABS(H) rBP, %eax # H[0] - mull PRE(cs)ABS(H8) rBP - - //movl $ABS(L), %ebx - subl %eax, PRE(cs)ABS(L) rBP # L[0] low - sbbl %edx, PRE(cs)ABS(L) + 4 rBP # L[0] high - - jnz 6f /* geometry_probe_failed */ - - movl PRE(cs)ABS(L) rBP, %eax - testl %eax, %eax - - jle 6f /* geometry_probe_failed */ - # OF=0; jmp if SF=1 or ZF=1 - - cdq # EDX=0 - - divl PRE(cs)ABS(H8) rBP - - testl %edx, %edx - jnz 6f /* geometry_probe_failed */ - - movl PRE(cs)ABS(C) rBP, %ecx # C[0] - andl $0xFFFF, %ecx - divl %ecx - - testl %edx, %edx - jnz 6f /* geometry_probe_failed */ - - movl %eax, PRE(cs)ABS(L8) rBP # L[8] is number of heads - - cmpl $256, %eax - ja 6f /* geometry_probe_failed */ - - cmpl PRE(cs)ABS(Hmax) rBP, %eax - jbe 6f /* geometry_probe_failed */ - - movl PRE(cs)ABS(H8) rBP, %eax - movl %eax, PRE(cs)ABS(probed_sectors_per_track) rBP - - jmp 4f -3: /* else */ - - /* fail to set L[8], this means all H[i]==0, i=1,2,3,4,5,6,7 */ - - /* Now the only equation is: C[0] * H * S + H[0] * S = L[0] */ - - /* for (i = 63; i >= Smax; i--) */ - - movl PRE(cs)ABS(L) rBP, %ebx # EBX=L[0] - movl $63, %edi -3: - cmpl PRE(cs)ABS(Smax) rBP, %edi - jb 3f - - movl PRE(cs)ABS(H) rBP, %eax # H[0] - mull %edi # EDX=0 - # EAX=product - //movl %ebx, PRE(cs)ABS(L8) - //subl %eax, PRE(cs)ABS(L8) - - subl %ebx, %eax - negl %eax - - jz 5f # continue - js 5f # continue - - cdq # EDX=0 - divl %edi - - testl %edx, %edx - jnz 5f - - movl PRE(cs)ABS(C) rBP, %ecx # C[0] - andl $0xFFFF, %ecx - divl %ecx - - testl %edx, %edx - jnz 5f - - movl %eax, PRE(cs)ABS(L8) rBP # L[8] is number of heads - - cmpl $256, %eax - ja 5f - - cmpl PRE(cs)ABS(Hmax) rBP, %eax - ja 3f -5: - subl $1, %edi #; decl %edi - jmp 3b -3: /* end for (i = 63; i >= Smax; i--) */ - - cmpl PRE(cs)ABS(Smax) rBP, %edi - jb 6f /* geometry_probe_failed */ - - movl %edi, PRE(cs)ABS(probed_sectors_per_track) rBP - -4: /* end if (PRE(cs)ABS(H)[8]) */ - - movl PRE(cs)ABS(L8) rBP, %eax - movl %eax, PRE(cs)ABS(probed_heads) rBP - -2: /* end if (PRE(cs)ABS(i) == 8) */ - - /* geometry_probe_ok */ - - clc - jmp 2f - -//geometry_probe_failed: -6: - stc - movl $0, PRE(cs)ABS(probed_sectors_per_track) rBP - movl $0, PRE(cs)ABS(probed_heads) rBP -2: - /* try to get mbr_free_sectors */ - cmpl $1, PRE(cs)ABS(mbr_free_sectors) rBP # partition table ok - jl 2f # failure - - /* find a minimum StartLBA in the partition table. */ - - movl $100, %eax # greater than 63+32 - movl -58(iSI), %ecx # start_lba - jecxz 1f - cmpl %ecx, %eax - jbe 1f - movl %ecx, %eax -1: - movl -42(iSI), %ecx # start_lba - jecxz 1f - cmpl %ecx, %eax - jbe 1f - movl %ecx, %eax -1: - movl -26(iSI), %ecx # start_lba - jecxz 1f - cmpl %ecx, %eax - jbe 1f - movl %ecx, %eax -1: - movl -10(iSI), %ecx # start_lba - jecxz 1f - cmpl %ecx, %eax - jbe 1f - movl %ecx, %eax -1: - movl %eax, PRE(cs)ABS(mbr_free_sectors) rBP -88: - clc /* success */ - #; popal - popl %edi - popl %esi - popl %ebp - popl %ebx - popl %edx - popl %ecx - popl %eax - ret -2: - movl $0, PRE(cs)ABS(mbr_free_sectors) rBP # partition table fail - stc - #; popal - popl %edi - popl %esi - popl %ebp - popl %ebx - popl %edx - popl %ecx - popl %eax - ret - - -#ifdef __DOS_16 -//partition: -0: - /* load the next partition and modify the boot record */ - - /* EBX holds the file descriptor number or 0 if it is BIOS drive */ - /* partition table is at MBR(0x2000) */ - /* current partition number is PRE(cs)ABS(current_partition) */ - - pushal - - /* enumerate all partitions */ - - /* initialize the partition table, move start_LBA(the 3rd dword) - * to the total_sectors field(the 4th dword) and clear the 3rd dword. - * The sum of the 3rd and 4th dwords gives the absolute start_LBA. - */ - movl $MBR(0x2000), %ebp - xorl %eax, %eax - movl %eax, 0x00(%ebp) //Clear the parent partition - movl %eax, 0x10(%ebp) - movl %eax, 0x20(%ebp) - movl %eax, 0x30(%ebp) - - movl $0x04, PRE(cs)ABS(total_partition_entries) - /* copy extended partition entries to the end of the partition table */ - xorl %esi, %esi -1: - movb 4(%ebp, %esi), %al # partition id - cmpb $0x05, %al - je 2f - cmpb $0x0f, %al - je 2f - cmpb $0x15, %al - je 2f - cmpb $0x1f, %al - je 2f - cmpb $0x85, %al - jne 4f -2: - /* extended partition */ - movb $0, 0x04(%ebp, %esi) //Basic extended partition - movl 0x08(%ebp, %esi), %eax -2: - /* read one sector of the partition to MBR(0) */ - pushal - pushl $0 - pushl %eax - pushw %es - pushw $0 - pushw $0001 - pushw $0x0010 - movb $0x42, %ah - movw %sp, %si - movb PRE(cs)ABS(bios_drive_number), %dl //bios id - int $0x13 - popaw - popal - /* check if the partition table is valid */ - movb 0x1c2, %bl //Partition is marked? - cmpb $0x05, %bl //Extended partition? - je 3f //yes - cmpb $0x0f, %bl //Extended partition? - je 3f //yes - cmpb $0x15, %bl //Extended partition? - je 3f //yes - cmpb $0x1f, %bl //Extended partition? - je 3f //yes - cmpb $0x85, %bl //Extended partition? - jne 5f //not -3: - addl 0x1c6, %eax //Partition start LBA address - jmp 2b -5: - /* approve the partition entries and move onto the free entries */ - movl PRE(cs)ABS(total_partition_entries), %edi - shll $4, %edi - addl %ebp, %edi # EDI points to the first free entry - /* move the extended partition entry onto the first free entry */ - movl %eax, 0x00(%edi) //parent partition - movl 0x1c2, %eax - movl %eax, 0x04(%edi) - movl 0x1c6, %eax - movl %eax, 0x08(%edi) //The partition - movl 0x1ca, %eax - movl %eax, 0x0c(%edi) //The total number of sectors - //Determine whether there is an extended partition - cmpl $0, 0x1d6 - je 2f //no - incl PRE(cs)ABS(total_partition_entries) - movl 0x08(%ebp, %esi), %eax //parent partition - addl 0x1d6, %eax //LBA partition start address - jmp 2b - -4: - addl $0x10, %esi - movl PRE(cs)ABS(total_partition_entries), %edi - shll $4, %edi - cmpl %edi, %esi - jb 1b -2: - /* end of partition enumeration */ - popal - ret - - -66: - pushal - movl $ABS(msg_disk_Information), %ecx - call 8b /* linux_print */ - //Integer calculation - xorl %edx, %edx - movl $2, %ebx - divl %ebx //Disk Bytes Kb - movl $1000, %ebx //0x3e8 - xorl %edx, %edx - divl %ebx //Disk Bytes Mb - cmpl %ebx, %eax //< 1Gb? - jb 22f //yes - xorl %edx, %edx - divl %ebx //Disk Bytes Gb - cmpl %ebx, %eax //< 1Tb? - jb 3f //yes - xorl %edx, %edx - divl %ebx //Disk Bytes Tb - //Setting unit'Tb' - movb $0x54, %cl //'T' - movb %cl, PRE(cs)ABS(scM) - jmp 22f - //Setting unit'Gb' -3: - movb $0x47, %cl //'G' - movb %cl, PRE(cs)ABS(scM) - //Handle decimal -22: - movl $ABS(scS_c), %esi //Store the last bit of pre-decimal address - movw $10, %bx //0xa - pushw %ax //Save integer - movw %dx, %ax //Decimal - movw $2, %cx -23: - xorw %dx, %dx - divw %bx - orb $0x30, %dl - movb %dl, PRE(cs)(iSI) - decw %si - cmpw $0, %ax - jne 23b - //Moving two decimal - cmpb $1, %cl - jbe 3f - movl $ABS(scS_x), %edi - movl $ABS(scS_c_s), %esi - movw PRE(cs)(iSI), %ax - movw %ax, PRE(cs)(iDI) - //Handle integer -3: - decb %cl - je 3f - popw %ax //Integer - movl $ABS(scS_z_w), %esi - jmp 23b -3: - movl $ABS(scS_z_s), %ecx - call 8b /* linux_print */ - //Default units 'Mb' - movb $0x4d, %cl //'M' - movb %cl, PRE(cs)ABS(scM) - //The first 8 bytes from the integer filling spaces - movl $ABS(scS_z_s), %edi - movl $0x20202020, %eax - movl %eax, PRE(cs)(iDI) - movb $0x30, PRE(cs)ABS(scS_c) - movw $0x3030, PRE(cs)ABS(scS_c_s) - popal - ret - -#endif - - -//Clear_buffer -100: - xorl %eax, %eax - movl $MBR(0), %edi - movl $(0x60*0x200/4), %ecx - repz stosl - ret - -//---------------------------------------------------------------------------------------- -//input: ecx - -400: - pushl %ebx // file descriptor, or 0 for BIOS drive - -#ifdef __DOS_16 - - xorl %eax, %eax - cmpl $0xff, PRE(cs)ABS(bios_drive_number) - jne 1f - - movl $0x4200, %eax - movw %cx, %dx //dx=Æ«ÒÆÁ¿µÄµÍλ - shrl $16, %ecx - int $0x21 - jnc 1f - negl %eax -1: -#else - /* off_t lseek(int fildes, off_t offset, int whence) */ - - /* check if in 32-bit or 64-bit mode */ - xorl %eax, %eax - decl %eax // rex prefix of 0x48 - testl %eax, %eax - /* EAX = 0 for 64-bit mode, -1 for 32-bit mode */ - jz 1f - - /* in 32-bit mode */ - movl $19, %eax // sys_lseek - movl $0, %edx // SEEK_SET = 0 - int $0x80 - jmp 2f -1: - /* in 64-bit mode */ - movl $8, %eax // sys_lseek - pushl %ebx - popl %edi - movl %ecx, %esi - movl $0, %edx // SEEK_SET = 0 - syscall -2: -#endif - - popl %ebx // file descriptor, or 0 for BIOS drive - ret - -//---------------------------------------------------------------------------------------- -//input: ecx, es:0000, sectors_to_write - -300: - pushl %ebx # file descriptor, or 0 if specified BIOS drive - -#ifdef __DOS_16 - - xorl %eax, %eax - cmpl $0xff, PRE(cs)ABS(bios_drive_number) - je 1f /* not bios */ - - /* BIOS drive */ - cmpl $0, PRE(cs)ABS(ebios_support) - je 10f /* EBIOS not present */ - movb PRE(cs)ABS(bios_drive_number), %dl - /* EBIOS supported */ - pushl $0 // hi 32bit of startLBA - pushl %ecx - pushw %es // buffer segment - pushw $0 // buffer offset - pushw PRE(cs)ABS(sectors_to_write) - pushw $0x0010 // packet length - movw %sp, %si - movw $0x4300, %ax /* LBA write */ - int $0x13 - movw %ss, %ax - movw %ax, %ds - movw %ax, %es - popaw - jc 77f - xorl %eax, %eax - clc - jmp 2f -77: - movl $ABS(msg_ebios_write_failure), %ecx - call 8f /* linux_print */ - -10: - cmpb $0xff, PRE(cs)ABS(gpt) - jnz 10f - stc - jmp 2f -10: - /* try CHS */ - - movb $0x03, %ah // CHS write to disk - movb PRE(cs)ABS(sectors_to_write), %al - - cmpb $32, %al - stc - ja 2f /* should not write two many sectors with CHS */ - - movw $0, %bx - movw $1, %cx - movw PRE(cs)ABS(bios_drive_number), %dx - int $0x13 - movzwl %ax, %eax - movw %ss, %cx //0000 - movw %cx, %ds - movw %cx, %es - jmp 2f - -1: - //WRITE TO FILE OR DEVICE - - //AH = 40h - //BX = file handle - //CX = number of bytes to write - //DS:DX -> data to write - - //Return: - //CF clear if successful AX = number of bytes actually written - //CF set on error AX = error code (05h,06h) - movl $0x4000, %eax - movl PRE(cs)ABS(sectors_to_write), %ecx - shll $9, %ecx - movl $0, %edx - int $0x21 -2: - jnc 1f - negl %eax -1: -#else - /* ssize_t write(int fd, const void *buf, size_t count) */ - - /* check if in 32-bit or 64-bit mode */ - xorl %eax, %eax - decl %eax // rex prefix of 0x48 - testl %eax, %eax - /* EAX = 0 for 64-bit mode, -1 for 32-bit mode */ - jz 2f - - /* in 32-bit mode */ - movl $4, %eax # sys_write - movl $MBR(0), %ecx - movl PRE(cs)ABS(sectors_to_write) rBP, %edx - shll $9, %edx - int $0x80 //bx=ÎļþÃèÊö·û - jmp 1f -2: - /* in 64-bit mode */ - movl $1, %eax # sys_write - pushl %ebx - popl %edi - movl $MBR(0), %esi - movl PRE(cs)ABS(sectors_to_write) rBP, %edx - shll $9, %edx - syscall -1: -#endif - - popl %ebx # file descriptor, or 0 if specified BIOS drive - ret - -//---------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/stage2/bootlacestart.S b/stage2/bootlacestart.S deleted file mode 100644 index ff1093f8..00000000 --- a/stage2/bootlacestart.S +++ /dev/null @@ -1,1327 +0,0 @@ -/* - * bootlacestart.S -- A utility for installing GRLDR boot sectors to MBR/OSBR - * Copyright (C) 2005, 2012 Tinybit(tinybit@tom.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * This program is used to generate the GRLDR-INSTALL file. - * - * Use the following shell command to generate the GRLDR-INSTALL file: - * - * cp bootlacestart bootlace.com - * - */ - -/* Use the following command to compile and build: - * - * gcc -o bootlacestart.exec -nostdlib -I. -I.. -I../stage1 -Wl,-N -Wl,-s bootlacestart.S - * - */ - -//#define ABS(x) (x-_start+0x08048000) -//#define ABS(x) (x) - -#define __DOT_COM - - .text - .globl _start - -_start: - - /* command-line arguments: - * bootlace.com [OPTIONS] DEVICE_OR_FILE - */ - - # ELF header begin here. Its length is 0x40. - # The ELF64 header is backed up at the end of file, which can be - # used to replace the ELF header for running on 64-bit Linux. - - .byte 0x7F, 0x45, 0x4C, 0x46 # ELF magic number - // 7F 45 = jg dos_entry_point - // 4C = decw %sp - // 46 = incw %si - -#if 1 - .byte 0x01 # 32-bit - .byte 0x01 # little-endian - # not safe for 16-bit DOS code - // it changes word at [BX+DI] - // 01 01 = addw %ax, (%bx, %di) -#else - .byte 0x01 # 32-bit - .byte 0xC1 # corrupt-endian! - # Sorry! - # but safe for 16-bit DOS code - // 01 C1 = addw %ax, %cx -#endif - - .byte 0x01 # ELF version - // opcode for ADD - -#ifdef __DOT_COM - - .byte 0xC0 # pad char - // 01 C0 = addw %ax, %ax - - - .byte 0x44 # pad char - // incw %sp - - - .byte 0x4E # pad char - // decw %si - - - .byte 0xd1,0xe8 // shr ax, 1 - .byte 0x29,0x01 // subw %ax, (%bx, %di) - - .byte 0xEB, 0x24 # pad char - // jmp invalid_dos_exec - -#endif - - . = _start + 0x10 - - .word 2 # e_type = Executable - .word 3 # e_machine = i386 - .long 1 # e_version - .long (_start_linux - _start + 0x00400000) - # e_entry - .long (_ph_offset - _start) # e_phoff - .long (_sh_offset - _start) # e_shoff(section header table) - .long 0 # e_flags - .word 0x34 # e_ehsize (ELF header size) - .word 0x20 # e_phentsize(prog header entry size) - .word 1 # e_phnum(prog header entry count) - .word 0x28 # e_shentsize - .word 5 # e_shnum - .word 1 # e_shstrndx - - # ELF header end - - . = _start + 0x40 // aux dos entry point - -#ifdef __DOT_COM - -//invalid_dos_exec: - - /* this is real mode dos code */ - - .code16 - -#define __DOS_16 -#include "bootlace.inc" - - -bios_drive_number: - .long 0xff - -#endif - -_string_table: - - .ascii "\0" - - .ascii ".shstrtab\0" - - .ascii ".text\0" - - .ascii ".data\0" - - .ascii ".bss\0" - -_string_table_end: - - .align 4 - -_ph_offset: - - .long 1 # p_type - .long (_start_linux - _start) # p_offset - .long (_start_linux - _start + 0x00400000) - # p_vaddr - .long (_start_linux - _start + 0x00400000) - # p_paddr - .long (grldr_mbr_start + 0x2000 - _start_linux) # p_filesz - .long (grldr_mbr_start + 0x2000 - _start_linux + (0xBE00 + 0x200)) # p_memszz - .long 7 # p_flags - .long 0x200 # p_align - -_ph_offset_end: - -_sh_offset: - - # SHT_UNDEF section - - .long 0 # sh_name = No name - .long 0 # sh_type = Inactive - .long 0 # sh_flags = No flags - .long 0 # sh_addr = No address - .long 0 # sh_offset = No file offset - .long 0 # sh_size = No size - .long 0 # sh_link = No link information - .long 0 # sh_info = No auxiliary information - .long 0 # sh_addralign = No alignment - .long 0 # sh_entsize = No entries - - # .shstrtab - - .long 1 # sh_name - .long 3 # sh_type = SHT_STRTAB - .long 0 # sh_flags = no write,no alloc,no exec - .long 0 # sh_addr = not present in memory - - .long (_string_table - _start) - # sh_offset (where strtab begins at) - - .long (_string_table_end - _string_table) - # sh_size (size of the string table) - - .long 0 # sh_link - .long 0 # sh_info - .long 1 # sh_addralign - .long 0 # sh_entsize - - # .text - - .long 0x0b # sh_name - .long 1 # sh_type = SHT_PROGBITS - .long 7 # sh_flags = WRITE,ALLOC, EXEC - - .long (_start_linux - _start + 0x00400000) - # sh_addr(in process space) - - .long (_start_linux - _start) - # sh_offset(from beginning of file) - - .long (grldr_mbr_start + 0x2000 - _start_linux) - # sh_size - - .long 0 # sh_link - .long 0 # sh_info - .long 0x200 # sh_addralign - .long 0 # sh_entsize - - # .data - - .long 0x11 # sh_name - .long 1 # sh_type = SHT_PROGBITS - .long 3 # sh_flags = WRITE, ALLOC - - .long (grldr_mbr_start + 0x2000 - _start + 0x00400000) - # sh_addr(in process space) - - .long (grldr_mbr_start + 0x2000 - _start) - # sh_offset(from beginning of file) - - .long 0 # sh_size (no data present) - .long 0 # sh_link - .long 0 # sh_info - .long 4 # sh_addralign - .long 0 # sh_entsize - - # .bss - - .long 0x17 # sh_name - .long 8 # sh_type = SHT_NOBITS - .long 3 # sh_flags = WRITE, ALLOC - - .long (grldr_mbr_start + 0x2000 - _start + 0x00400000) - # sh_addr(in process space) - - .long (grldr_mbr_start + 0x2000 - _start) - # sh_offset(from beginning of file) - - .long (0xbe00 + 0x200) # sh_size //mbr_63_sectors - .long 0 # sh_link - .long 0 # sh_info - .long 0x200 # sh_addralign - .long 0 # sh_entsize - -_sh_offset_end: - - .align 8 - -_ph_offset_64: - - .long 1 # p_type - .long 7 # p_flags - .long (_start_linux - _start) # p_offset - .long 0 # ... hi - .long (_start_linux - _start + 0x00400000) - # p_vaddr - .long 0 # ... hi - .long (_start_linux - _start + 0x00400000) - # p_paddr - .long 0 # ... hi - .long (grldr_mbr_start + 0x2000 - _start_linux) # p_filesz - .long 0 # ... hi - .long (grldr_mbr_start + 0x2000 - _start_linux + (0xBE00 + 0x200)) - # p_memszz //mbr_63_sectors - .long 0 # ... hi - .long 0x200 # p_align - .long 0 # ... hi - -_ph_offset_64_end: - -_sh_offset_64: - - # SHT_UNDEF section - - .long 0 # sh_name = No name - .long 0 # sh_type = Inactive - .long 0 # sh_flags = No flags - .long 0 # ... hi - .long 0 # sh_addr = No address - .long 0 # ... hi - .long 0 # sh_offset = No file offset - .long 0 # ... hi - .long 0 # sh_size = No size - .long 0 # ... hi - .long 0 # sh_link = No link information - .long 0 # sh_info = No auxiliary information - .long 0 # sh_addralign = No alignment - .long 0 # ... hi - .long 0 # sh_entsize = No entries - .long 0 # ... hi - - # .shstrtab - - .long 1 # sh_name - .long 3 # sh_type = SHT_STRTAB - .long 0 # sh_flags = no write,no alloc,no exec - .long 0 # ... hi - .long 0 # sh_addr = not present in memory - .long 0 # ... hi - - .long (_string_table - _start) - # sh_offset (where strtab begins at) - .long 0 # ... hi - - .long (_string_table_end - _string_table) - # sh_size (size of the string table) - .long 0 # ... hi - - .long 0 # sh_link - .long 0 # sh_info - .long 1 # sh_addralign - .long 0 # ... hi - .long 0 # sh_entsize - .long 0 # ... hi - - # .text - - .long 0x0b # sh_name - .long 1 # sh_type = SHT_PROGBITS - .long 7 # sh_flags = WRITE,ALLOC, EXEC - .long 0 # ... hi - - .long (_start_linux - _start + 0x00400000) - # sh_addr(in process space) - .long 0 # ... hi - - .long (_start_linux - _start) - # sh_offset(from beginning of file) - .long 0 # ... hi - - .long (grldr_mbr_start + 0x2000 - _start_linux) - # sh_size - .long 0 # ... hi - - .long 0 # sh_link - .long 0 # sh_info - .long 0x200 # sh_addralign - .long 0 # ... hi - .long 0 # sh_entsize - .long 0 # ... hi - - # .data - - .long 0x11 # sh_name - .long 1 # sh_type = SHT_PROGBITS - .long 3 # sh_flags = WRITE, ALLOC - .long 0 # ... hi - - .long (grldr_mbr_start + 0x2000 - _start + 0x00400000) - # sh_addr(in process space) - .long 0 # ... hi - - .long (grldr_mbr_start + 0x2000 - _start) - # sh_offset(from beginning of file) - .long 0 # ... hi - - .long 0 # sh_size (no data present) - .long 0 # ... hi - .long 0 # sh_link - .long 0 # sh_info - .long 4 # sh_addralign - .long 0 # ... hi - .long 0 # sh_entsize - .long 0 # ... hi - - # .bss - - .long 0x17 # sh_name - .long 8 # sh_type = SHT_NOBITS - .long 3 # sh_flags = WRITE, ALLOC - .long 0 # ... hi - - .long (grldr_mbr_start + 0x2000 - _start + 0x00400000) - # sh_addr(in process space) - .long 0 # ... hi - - .long (grldr_mbr_start + 0x2000 - _start) - # sh_offset(from beginning of file) - .long 0 # ... hi - - .long (0xbe00 + 0x200) # sh_size //mbr_63_sectors - .long 0 # ... hi - .long 0 # sh_link - .long 0 # sh_info - .long 0x200 # sh_addralign - .long 0 # ... hi - .long 0 # sh_entsize - .long 0 # ... hi - -_sh_offset_64_end: - - .align 0x200 - -_start_linux: - - /* this is protected mode linux code */ - - .code32 - -#undef __DOS_16 -#include "bootlace.inc" - -option_restore_mbr: - .ascii "--restore-mbr\0" - -option_no_backup_mbr: - .ascii "--no-backup-mbr\0" - -option_force_backup_mbr: - .ascii "--force-backup-mbr\0" - -option_mbr_enable_floppy: - .ascii "--mbr-enable-floppy\0" - -option_mbr_disable_floppy: - .ascii "--mbr-disable-floppy\0" - -option_mbr_enable_osbr: - .ascii "--mbr-enable-osbr\0" - -option_mbr_disable_osbr: - .ascii "--mbr-disable-osbr\0" - -option_mbr_no_bpb: - .ascii "--mbr-no-bpb\0" - -option_duce: - .ascii "--duce\0" - -option_chs_no_tune: - .ascii "--chs-no-tune\0" - -option_boot_prevmbr_first: - .ascii "--boot-prevmbr-first\0" - -option_boot_prevmbr_last: - .ascii "--boot-prevmbr-last\0" - -option_preferred_drive: - .ascii "--preferred-drive=\0" - -option_preferred_partition: - .ascii "--preferred-partition=\0" - -option_serial_number: - .ascii "--serial-number=\0" - -option_install_partition: - .ascii "--install-partition=\0" - -option_sectors_per_track: - .ascii "--sectors-per-track=\0" - -option_heads: - .ascii "--heads=\0" - -option_start_sector: - .ascii "--start-sector=\0" - -option_total_sectors: - .ascii "--total-sectors=\0" - -option_floppy_partition: - .ascii "--floppy=\0" - -option_time_out: - .ascii "--time-out=\0" - -option_hot_key: - .ascii "--hot-key=\0" - -option_read_only: - .ascii "--read-only\0" - -option_floppy: - .ascii "--floppy\0" - -option_gpt: - .ascii "--gpt\0" - -//option_lba: -// .ascii "--lba\0" - -//option_chs: -// .ascii "--chs\0" - -//option_fat12: -// .ascii "--fat12\0" - -//option_fat16: -// .ascii "--fat16\0" - -//option_fat32: -// .ascii "--fat32\0" - -//option_ntfs: -// .ascii "--ntfs\0" - -//option_ext2: -// .ascii "--ext2\0" - -//option_vfat: -// .ascii "--vfat\0" - -msg_start: - - /* messages begins at here */ - -msg_ebios_read_failure: - - .ascii "\r\nWarning: EBIOS read failure!\r\n\0" - -msg_ebios_write_failure: - - .ascii "\r\nWarning: EBIOS write failure! Now try standard CHS write, but not reliable.\r\n\0" - -msg_no_ebios_support: - - .ascii "\r\nWarning: EBIOS not present! It is not reliable running under DOS without EBIOS.\r\n\0" - -msg_stdin_too_long: - - .ascii "\r\nError: The standard input is too long.\r\n\0" - -msg_too_many_parameters: - - .ascii "\r\nError: Too many parameters in command line.\r\n\0" - -msg_no_args: - - .ascii "\r\nError: No command-line arguments specified.\r\n\0" - -msg_too_many_files: - - .ascii "\r\nError: More than one files specified.\r\n\0" - -msg_no_file: - - .ascii "\r\nError: No device or file specified.\r\n\0" - -msg_option_restore_mbr: - .ascii "\r\nError: Specified --restore-mbr twice.\r\n\0" - -msg_option_restore_mbr_with_other: - .ascii "\r\nError: Specified --restore-mbr with other options than --read-only.\r\n\0" - -msg_invalid_prev_mbr: - .ascii "\r\nError: previous MBR is invalid, or it is the GRLDR MBR.\r\n\0" - -msg_option_backup_mbr: - .ascii "\r\nError: Specified an option twice for backing up MBR.\r\n\0" - -msg_option_backup_mbr_with_floppy: - .ascii "\r\nError: Specified --floppy with backing up MBR.\r\n\0" - -msg_option_backup_mbr_with_partition: - .ascii "\r\nError: Specified --install-partition with backing up MBR.\r\n\0" - -msg_option_mbr_floppy: - .ascii "\r\nError: Specified an option twice for searching floppy.\r\n\0" - -msg_option_mbr_floppy_with_floppy: - .ascii "\r\nError: Specified --floppy with MBR searching floppy.\r\n\0" - -msg_option_mbr_floppy_with_partition: - .ascii "\r\nError: Specified --install-partition with MBR searching floppy.\r\n\0" - -msg_option_mbr_osbr: - .ascii "\r\nError: Specified an option twice for booting osbr.\r\n\0" - -msg_option_mbr_osbr_with_floppy: - .ascii "\r\nError: Specified --floppy with booting osbr.\r\n\0" - -msg_option_mbr_osbr_with_partition: - .ascii "\r\nError: Specified --install-partition with booting osbr.\r\n\0" - -msg_option_mbr_bpb: - .ascii "\r\nError: Specified an option twice for mbr-bpb.\r\n\0" - -msg_option_mbr_bpb_with_floppy: - .ascii "\r\nError: Specified --floppy with mbr-bpb.\r\n\0" - -msg_option_mbr_bpb_with_partition: - .ascii "\r\nError: Specified --install-partition with mbr-bpb.\r\n\0" - -msg_option_duce: - .ascii "\r\nError: Specified --duce twice.\r\n\0" - -msg_option_duce_with_floppy: - .ascii "\r\nError: Specified --floppy with --duce.\r\n\0" - -msg_option_duce_with_partition: - .ascii "\r\nError: Specified --install-partition with --duce.\r\n\0" - -msg_option_chs_no_tune: - .ascii "\r\nError: Specified --chs-no-tune twice.\r\n\0" - -msg_option_chs_no_tune_with_floppy: - .ascii "\r\nError: Specified --floppy with --chs-no-tune.\r\n\0" - -msg_option_chs_no_tune_with_partition: - .ascii "\r\nError: Specified --install-partition with --chs-no-tune.\r\n\0" - -msg_option_boot_prevmbr: - .ascii "\r\nError: Specified an option twice for booting prevmbr.\r\n\0" - -msg_option_boot_prevmbr_with_floppy: - .ascii "\r\nError: Specified --floppy with booting prevmbr.\r\n\0" - -msg_option_boot_prevmbr_with_partition: - .ascii "\r\nError: Specified --install-partition with booting prevmbr.\r\n\0" - -msg_option_preferred_drive: - .ascii "\r\nError: Specified an option twice for preferred drive.\r\n\0" - -msg_option_preferred_drive_with_floppy: - .ascii "\r\nError: Specified --floppy with preferred drive.\r\n\0" - -msg_option_preferred_drive_with_partition: - .ascii "\r\nError: Specified --install-partition with preferred drive.\r\n\0" - -msg_option_preferred_partition: - .ascii "\r\nError: Specified an option twice for preferred partition.\r\n\0" - -msg_option_preferred_partition_with_floppy: - .ascii "\r\nError: Specified --floppy with preferred partition.\r\n\0" - -msg_option_preferred_partition_with_partition: - .ascii "\r\nError: Specified --install-partition with preferred partition.\r\n\0" - -msg_option_serial_number: - .ascii "\r\nError: Specified an option twice for disk serial number.\r\n\0" - -msg_option_serial_number_with_floppy: - .ascii "\r\nError: Specified --floppy with disk serial number.\r\n\0" - -msg_option_serial_number_with_partition: - .ascii "\r\nError: Specified --install-partition with disk serial number.\r\n\0" - -msg_option_install_partition: - .ascii "\r\nError: Specified an option twice for install partition.\r\n\0" - -msg_option_install_partition_with_floppy: - .ascii "\r\nError: Specified --floppy with install partition.\r\n\0" - -//msg_option_install_partition_not_implemented: -// .ascii "\r\nSorry! --install-partition not yet implemented with this release.\r\n\0" - -msg_option_time_out: - .ascii "\r\nError: Specified an option twice for time out.\r\n\0" - -msg_option_time_out_with_floppy: - .ascii "\r\nError: Specified --floppy with time out.\r\n\0" - -msg_option_time_out_with_partition: - .ascii "\r\nError: Specified --install-partition with time out.\r\n\0" - -//msg_option_time_out_without_prevmbr: -// .ascii "\r\nError: Specified --time-out without specifying --boot-prevmbr-first.\r\n\0" - -msg_option_hot_key: - .ascii "\r\nError: Specified an option twice for hot key.\r\n\0" - -msg_option_hot_key_with_floppy: - .ascii "\r\nError: Specified --floppy with hot key.\r\n\0" - -msg_option_hot_key_with_partition: - .ascii "\r\nError: Specified --install-partition with hot key.\r\n\0" - -//msg_option_hot_key_without_prevmbr: -// .ascii "\r\nError: Specified --hot-key without specifying --boot-prevmbr-first.\r\n\0" - -msg_option_sectors_per_track: - .ascii "\r\nError: Specified an option twice for sectors per track.\r\n\0" - -msg_option_sectors_per_track_with_partition: - .ascii "\r\nError: Specified --install-partition with sectors per track.\r\n\0" - -msg_option_sectors_per_track_for_mbr: - .ascii "\r\nError: Specified --sectors-per-track for a hard drive.\r\n\0" - -msg_option_heads: - .ascii "\r\nError: Specified an option twice for heads.\r\n\0" - -msg_option_heads_with_partition: - .ascii "\r\nError: Specified --install-partition with --heads.\r\n\0" - -msg_option_heads_for_mbr: - .ascii "\r\nError: Specified --heads for a hard drive.\r\n\0" - -msg_option_start_sector: - .ascii "\r\nError: Specified an option twice for start sector.\r\n\0" - -msg_option_start_sector_with_partition: - .ascii "\r\nError: Specified --install-partition with --start-sector.\r\n\0" - -msg_option_start_sector_for_mbr: - .ascii "\r\nError: Specified --start-sector for a hard drive.\r\n\0" - -msg_option_total_sectors: - .ascii "\r\nError: Specified an option twice for total sectors.\r\n\0" - -msg_option_total_sectors_with_partition: - .ascii "\r\nError: Specified --install-partition with --total-sectors.\r\n\0" - -msg_option_total_sectors_for_mbr: - .ascii "\r\nError: Specified --total-sectors for a hard drive.\r\n\0" - -msg_option_read_only: - .ascii "\r\nError: Specified an option twice for read only.\r\n\0" - -msg_option_floppy: - .ascii "\r\nError: Specified an option twice for --floppy.\r\n\0" - -msg_option_gpt: - .ascii "\r\nError: Specified an option twice for --gpt.\r\n\0" - -//msg_option_lba: -// .ascii "\r\nError: Specified an option twice for lba-chs mode.\r\n\0" - -//msg_option_lba_for_mbr: -// .ascii "\r\nError: Specified --lba for a hard drive.\r\n\0" - -//msg_option_fstypes_for_mbr: -// .ascii "\r\nError: Specified file system types for a hard-drive mbr device.\r\n\0" - -msg_partition_without_drive: - .ascii "\r\nError: Preferred partition without preferred drive.\r\n\0" - -msg_partition_start: - .ascii "\r\nError: For a single partition you must specify --start-sector to non-zero.\r\n\0" - -msg_floppy_start: - .ascii "\r\nError: For a real floppy you must specify --start-sector to 0.\r\n\0" - -msg_invalid_number: - .ascii "\r\nError: Invalid number format or invalid value for the specified option.\r\n\0" - -msg_invalid_option: - .ascii "\r\nError: Invalid option.\r\n\0" - -msg_open_file_rw: - .ascii "\r\nError: Cannot open file for read/write access.\r\n\0" - -msg_open_file_ro: - .ascii "\r\nError: Cannot open file for read-only access.\r\n\0" - -msg_read_file: - .ascii "\r\nError: Read file failed.\r\n\0" - -msg_lseek_file: - .ascii "\r\nError: Rewind file(lseek) failed.\r\n\0" - -msg_write_file: - .ascii "\r\nError: Write file failed.\r\n\0" - -msg_close_file: - .ascii "\r\nFatal! Close file failed. Please backup your disk in case it becomes unusable.\r\n\0" - -msg_boot_signature_mbr: - .ascii "\r\nError: No boot signature(55 AA). Must specify --floppy explicitly for floppy.\r\n\0" - -msg_invalid_partition_table: - .ascii "\r\nError: Invalid partition table. Must specify --floppy explicitly for floppy.\r\n\0" - -msg_floppy_partition_table: - .ascii "\r\nError: Specified --floppy for DEVICE_OR_FILE that has a valid partition table.\r\n\0" - -msg_sectors_per_track: - .ascii "\r\nError: Too few sectors to hold GRLDR.MBR.\r\n\0" - -msg_geometry_S: - .ascii "\r\nDisk geometry calculated according to the partition table:\r\n\r\n" - .ascii " Sectors per track = \0" -msg_geometry_H: - .ascii ", Number of heads = \0" -msg_success: - .ascii "\r\nSuccess.\r\n\0" -msg_success_create_triple_mbr: - .ascii "\r\nSuccess. Triple MBR installed.\r\n\0" -msg_success_cancel_triple_mbr: - .ascii "\r\nTriple MBR cancelled. Original partition layout restored.\r\n\0" - -//msg_fstype_fat32_deny: -// .ascii "\r\nError: Filesystem type is FAT32 but --fat32 was not specified.\r\n\0" - -msg_fstype_fat32_allow: - .ascii "\r\nFilesystem type is FAT32.\r\n\0" - -//msg_fstype_ntfs_deny: -// .ascii "\r\nError: Filesystem type is NTFS but --ntfs was not specified.\r\n\0" - -msg_fstype_ntfs_allow: - .ascii "\r\nFilesystem type is NTFS.\r\n\0" - -//msg_fstype_fat12_deny: -// .ascii "\r\nError: Filesystem type is FAT12 but --fat12 was not specified.\r\n\0" - -msg_fstype_fat12_allow: - .ascii "\r\nFilesystem type is FAT12.\r\n\0" - -//msg_fstype_fat16_deny: -// .ascii "\r\nError: Filesystem type is FAT16 but --fat16 was not specified.\r\n\0" - -msg_fstype_fat16_allow: - .ascii "\r\nFilesystem type is FAT16.\r\n\0" - -//msg_fstype_ext2_deny: -// .ascii "\r\nError: Filesystem type is EXT2 but --ext2 was not specified.\r\n\0" - -msg_fstype_ext2_allow: - .ascii "\r\nFilesystem type is EXT2.\r\n\0" - -//msg_fstype_exfat_deny: -// .ascii "\r\nError: Filesystem type is EXFAT but --exfat was not specified.\r\n\0" - -msg_fstype_exfat_allow: - .ascii "\r\nFilesystem type is EXFAT.\r\n\0" - -msg_unsupported_fstype: - .ascii "\r\nError: Unsupported filesystem type.\r\n\0" - -msg_fstype_mbr_deny: - .ascii "\r\nError: Cannot overwrite the MBR of a harddrive(or HD image) with --floppy.\r\n\0" - -//msg_no_ntfs_boot_record: -// .ascii "\r\nError: Filesystem type is NTFS, but no ntfs boot record was found.\r\n\0" - -msg_no_enough_memory: - .ascii "\r\nError: No enough memory.\r\n\0" - -msg_install_partition_not: - .ascii "\r\n\r\nError: Specified install partition not exist.\r\n\0" - -msg_gpt_partition_not: - .ascii "\r\n\r\nError: Specified gpt partition not exist.\r\n\0" - -msg_cannot_install_gpt_partition: - .ascii "\r\n\r\nError: Cannot install grldr.mbr to a GPT partition.\r\n\0" - -msg_disk_Information: - .ascii "\r\nHD" - -msg_disk: - .byte 0x30 - -msg_d: - .ascii "," - -msg_partition: - .byte 0x30,0x20,0x20 - -msg_Information: - .ascii " \0" - -scS_c_s: - .byte 0x30,0x30 - -scS_c: - .byte 0x30 - -scS_z_s: - .byte 0x20,0x20,0x20,0x20 - -scS_z_w: - .byte 0x20 - -scS_d: - .ascii "." - -scS_x: - .byte 0x20,0x20 - -scM: - .ascii "Mb\0" - -msg_Wait_for_key: - .ascii "\r\n\r\nPress 'y' to continue, other exit.\r\n\0" - -msg_usage: - - .ascii "\r\nBOOTLACE writes GRLDR BOOT RECORD to MBR or to the boot area of a file system.\r\n" - .ascii "Usage: bootlace.com [OPTIONS] DEVICE_OR_FILE\r\n" - .ascii "Options: --read-only, --floppy[=N], --boot-prevmbr-first, --boot-prevmbr-last,\r\n" - .ascii "--no-backup-mbr, --force-backup-mbr, --mbr-enable-floppy, --mbr-disable-floppy,\r\n" - .ascii "--mbr-enable-osbr, --mbr-disable-osbr, --duce, --time-out=T, --hot-key=K, \r\n" - .ascii "--preferred-drive=D, --preferred-partition=P, --sectors-per-track=S, --heads=H,\r\n" -// .ascii "--start-sector=B, --total-sectors=C, --install-partition=I, --lba, --chs,\r\n" -// .ascii "--fat12, --fat16, --fat32, --vfat, --ntfs, --ext2, --exfat, --serial-number=SN,\r\n" - .ascii "--start-sector=B, --total-sectors=C, --install-partition=I, --serial-number=SN,\r\n" - .ascii "--restore-mbr, --mbr-no-bpb, --chs-no-tune, --gpt\r\n" - .ascii "DEVICE_OR_FILE: Filename of the device or image. For DOS, a BIOS drive number\r\n" - .ascii "(in hex 0xHH or decimal DDD format)can be used to access the drive.\r\n\0" - -msg_end: - - .align 4 - -Cmax: .long 0 -Hmax: .long 0 -Smax: .long 0 -i: .long 0 -j: .long 0 -X: .long 0 -Y: .long 0 -C: # long, but high word is always 0 - .word 0, 0 - .word 0, 0 - .word 0, 0 - .word 0, 0 - .word 0, 0 - .word 0, 0 - .word 0, 0 - .word 0, 0 - .word 0, 0 -H: - .long 0 - .long 0 - .long 0 - .long 0 - .long 0 - .long 0 - .long 0 - .long 0 -H8: .long 0 -L: - .long 0, 0 - .long 0, 0 - .long 0, 0 - .long 0, 0 - .long 0, 0 - .long 0, 0 - .long 0, 0 - .long 0, 0 -L8: .long 0, 0 -probed_sectors_per_track: - .long 0 -probed_heads: - .long 0 -mbr_free_sectors: - .long 0 - -number_digits: - .ascii " \0" /* 10 spaces */ -delimit_space: - .ascii " \0" /* 4 spaces */ -delimit_newline: - .ascii "\n\0" - - .align 4 - -restore_mbr: - .long 0 -backup_mbr: - - /* 0 no backup, Will not touch PREV_MBR - * 1 autobackup - * 2 forcebackup. Will overwrite the old PREV_MBR - */ - - .long 1 /* default is autobackup */ - -mbr_floppy: - - /* 0 enable floppy - * 1 disable floppy - * 2 enable floppy - */ - - .long 0 /* default is enable floppy */ - -mbr_osbr: - - /* 0 enable osbr - * 1 disable osbr - * 2 enable osbr - */ - - .long 0 /* default is enable osbr */ - -mbr_bpb: - - /* 0 enable bpb - * 1 disable bpb - * 2 enable bpb - */ - - .long 0 /* default is enable bpb */ - -duce: - /* 0 enable unconditional command-line entrance - * 1 disable unconditional command-line entrance - * 2 enable unconditional command-line entrance - */ - - .long 0 /* default is enable unconditional command-line entrance */ - -chs_no_tune: - /* 0 enable geometry tune - * 1 disable geometry tune - * 2 enable geometry tune - */ - - .long 0 /* default is enable geometry tune */ - -boot_prevmbr: - - /* 0 boot prevmbr last - * 1 boot prevmbr first - * 2 boot prevmbr last - */ - - .long 0 /* default is boot prevmbr last */ - -preferred_drive: - - .long 0xff /* default is No Drive */ - -preferred_partition: - - .long 0xff /* default is Whole drive */ - -serial_number: - - .long 0 - -install_partition: - - .long 0xffffffff /* default is partition 0xff */ - -sectors_per_track: - - .long 0xffffff3f /* default is 63 */ - -heads: - - .long 0xffff00ff /* default is 255 */ - -start_sector: - - .long 0xffffffff /* default is invalid */ - -total_sectors: - - .long 0 /* default is invalid */ - -time_out: - -// .long 0xffffff05 /* low byte default is 5 seconds */ - .long 0xffffff00 /* low byte default is 0 seconds */ - -hot_key: - - .long 0xffff3920 /* low word default is space bar */ - -read_only: - - /* 0 read only - * 2 read/write - */ - - .long 2 /* default is read/write */ - -floppy: - - /* 0xffffffff for hard drive image(with leading MBR) - * 0x000000ff for floppy image - * value < 0xff for partition image - */ - - .long 0xffffffff /* default is for hard drive MBR */ - -gpt: - .long 0xffffffff - -install_sectors: - .long 0xffffffff - -//lba: - - /* 1 for lba, 0 for chs, -1 for `not specified'. */ - -// .long 0xffffffff /* default is `not specified' */ - -//fstypes: - -// /* bit 0: fat12 */ -// /* bit 1: fat16 */ -// /* bit 2: fat32 */ -// /* bit 3: ntfs */ -// /* bit 4: ext2 */ -// /* bit 5: exfat */ - -// .long 0xfffffff7 /* default is all types except ntfs */ - -sectors_to_write: - - /* default is number of sectors in GRLDR.MBR */ - -// .long ((pre_stage2_start - _start1) / 512) - .long (8192 / 512) - -restore_partition_layout: - .long 0 - -ebios_support: - .long 0 - -current_partition: - .long 0 - -total_partition_entries: - .long 0 - - - - - .align 16 - -//------------------------------------------------------------------- - -#if 0 /* begin backup sh.S for MandrakeISOinstall-10.0 */ - -/* Use the following command to compile and build: - * - * gcc -s -nostdlib -o sh sh.S - * - */ - - .globl _start - .text - -_start: - - /* fork() */ - xorl %eax, %eax - incl %eax - incl %eax - int $0x80 - testl %eax, %eax - jz 1f - /* exit(0) */ - xorl %ebx, %ebx - xorl %eax, %eax - incl %eax - int $0x80 - -1: -#if 0 - /* setpgid(0,0) */ - xorl %ebx, %ebx - xorl %ecx, %ecx - xorl %eax, %eax - movb $57, %al - int $0x80 -#else - /* setsid() */ - xorl %eax, %eax - movb $66, %al - int $0x80 -#endif -1: - /* sleep(1) */ - xorl %eax, %eax - movb $162, %al - movl $(time_sleep), %ebx - xorl %ecx, %ecx - int $0x80 - - /* access("/bin/sh", F_OK) */ - xorl %eax, %eax - movb $33, %al - movl $(shell_path), %ebx - xorl %ecx, %ecx - int $0x80 - orl %eax, %eax - jnz 1b /* loop when not exist */ - - /* execve("/bin/sh", argv, NULL) */ - xorl %eax, %eax - movb $11, %al - movl $(shell_path), %ebx - movl $(argv), %ecx - movl $(envp), %edx - int $0x80 - - /* exit(1) */ - xorl %ebx, %ebx - incl %ebx - xorl %eax, %eax - incl %eax - int $0x80 - -time_sleep: - .long 1 - .long 0 - -shell_path: - .string "/bin/sh" -arg0: - .string "mix_ISOs" -arg1: - .string "/tmp/mix_ISOs" -argv: - .long arg0 - .long arg1 -envp: - .long 0 - -#endif /* end backup sh.S for MandrakeISOinstall-10.0 */ - - .align 0x200 - -//------------------------------------------------------------------- - - ############################################################################# - - /* This backup header must be at the end of bootlace.com. It never. - * get used by the code in bootlace.com. But it is used by external - * programs to generate bootlace64.com. - */ - -_start_ELF_64: - - # ELF64 header backup here upto the end of file. Its length is 0x40. - - .byte 0x7F, 0x45, 0x4C, 0x46 # ELF magic number - // 7F 45 = jg dos_entry_point - // 4C = decw %sp - // 46 = incw %si - - .byte 0x02 # 64-bit - .byte 0x01 # little-endian - // 02 01 = addb (%bx, %di), %al - // no problem - - .byte 0x01 # ELF version - -#ifdef __DOT_COM - - .byte 0xC1 # pad char - // 01 C1 = addw %ax, %cx - - .byte 0x90 # pad char - // nop - - .byte 0x90 # pad char - // nop - - .byte 0x90 # pad char - // nop - - .byte 0x44 # pad char - // incw %sp - - .byte 0x90 # pad char - // nop - - .byte 0x90 # pad char - // nop - - .byte 0xEB, 0x30 # pad char - // jmp invalid_dos_exec - -#endif - - . = _start_ELF_64 + 0x10 - - .word 2 # e_type = Executable - .word 0x3E # e_machine = x86_64 - .long 1 # e_version - .long (_start_linux - _start + 0x00400000) - # e_entry - .long 0 # ... hi - .long (_ph_offset_64 - _start) - # e_phoff - .long 0 # ... hi - .long (_sh_offset_64 - _start) - # e_shoff(section header table) - .long 0 # ... hi - .long 0 # e_flags - .word 0x40 # e_ehsize (ELF header size) - .word 0x38 # e_phentsize(prog header entry size) - .word 1 # e_phnum(prog header entry count) - .word 0x40 # e_shentsize - .word 5 # e_shnum - .word 1 # e_shstrndx - - # ELF64 header end - - . = _start_ELF_64 + 0x40 # code ends here - -############################################################################# - - /* !!!! Do NOT append code here !!!! See comment above. */ - - .align 0x200 - -grldr_pbr_start: - -//******************************************************* -// Offset Sector Partition type -// ------------------------------------- -// 0 1 FAT32 -// 0x200 1 FAT12/16 -// 0x400 2 EXT2/3/4 -// 0x800 2 EXFAT -// 0xC00 4 NTFS -//******************************************************* - -grldr_cd_start: - -#define GRLDR_INSTALL -#include "grldrstart.S" - -grldr_mbr_start: - diff --git a/stage2/builtins.c b/stage2/builtins.c index 51f7027f..b00e073c 100644 --- a/stage2/builtins.c +++ b/stage2/builtins.c @@ -22,21 +22,23 @@ #include #include #include "iamath.h" +#include -#ifdef SUPPORT_SERIAL -# include -# include -#endif +//#ifdef SUPPORT_SERIAL +//# include +//# include +//#endif #ifdef USE_MD5_PASSWORDS # include #endif #include "freebsd.h" +#include "cpio.h" /* The type of kernel loaded. */ kernel_t kernel_type; -static kernel_t kernel_type_orig; +//static kernel_t kernel_type_orig; /* The boot device. */ static int bootdev = 0; @@ -50,11 +52,11 @@ int fallback_entries[MAX_FALLBACK_ENTRIES]; int current_entryno; #ifdef SUPPORT_GFX /* graphics file */ -char graphics_file[64]; +//char graphics_file[64]; #endif /* The address for Multiboot command-line buffer. */ static char *mb_cmdline;// = (char *) MB_CMDLINE_BUF; -static char kernel_option_video[64] = {0};/* initialize the first byte to 0 */ +//static char kernel_option_video[64] = {0};/* initialize the first byte to 0 */ /* The password. */ char *password_buf; static char password_str[128]; @@ -63,132 +65,111 @@ password_t password_type; /* The flag for indicating that the user is authoritative. */ int auth = 0; /* The timeout. */ -int grub_timeout = -1; +//int grub_timeout = -1; /* Whether to show the menu or not. */ int show_menu = 1; /* Don't display a countdown message for the hidden menu */ int silent_hiddenmenu = 0; -static int debug_prog; -static int debug_break = 0; -static int debug_check_memory = 0; +int debug_prog; +int debug_bat = 0; +int debug_ptrace = 0; +//static int debug_break = 0; +//static int debug_pid = 0; +//static int debug_check_memory = 0; static grub_u8_t msg_password[]="Password: "; -unsigned long pxe_restart_config = 0; -unsigned long configfile_in_menu_init = 0; +//unsigned int pxe_restart_config = 0; +unsigned int configfile_in_menu_init = 0; /* The first sector of stage2 can be reused as a tmp buffer. * Do NOT write more than 512 bytes to this buffer! * The stage2-body, i.e., the pre_stage2, starts at 0x8200! * Do NOT overwrite the pre_stage2 code at 0x8200! */ -extern char *mbr /* = (char *)0x8000 */; /* 512-byte buffer for any use. */ +//extern char *mbr /* = (char *)0x8000 */; /* 512-byte buffer for any use. */ extern int dir (char *dirname); #ifdef SUPPORT_GRAPHICS -extern int outline; +//extern int outline; #endif /* SUPPORT_GRAPHICS */ -/* Whether the drive map hook is on. */ -//static int int13_on_hook = 0; - -//static int floppy_not_inserted[4] = {0, 0, 0, 0}; - /* The BIOS drive map. */ -int drive_map_slot_empty (struct drive_map_slot item); - -/* backup of original BIOS floppy-count byte in 0x410 */ -extern char floppies_orig; - -/* backup of original BIOS harddrive-count byte in 0x475 */ -extern char harddrives_orig; - -extern unsigned short chain_load_segment;//0x0000; -extern unsigned short chain_load_offset;//0x7c00; -extern unsigned int chain_load_length;//0x200; -extern unsigned short chain_boot_CS;//0x0000; -extern unsigned short chain_boot_IP;//0x7c00; -extern unsigned long chain_ebx; -extern unsigned long chain_ebx_set; -extern unsigned long chain_edx; -extern unsigned long chain_edx_set; -extern unsigned long chain_enable_gateA20; -extern unsigned long chain_bx; -extern unsigned long chain_bx_set; -extern unsigned long chain_cx; -extern unsigned long chain_cx_set; -extern char HMA_start[]; - -static int chainloader_load_segment = 0; -static int chainloader_load_segment_orig = 0; -static int chainloader_load_offset = 0; -static int chainloader_load_offset_orig = 0; -static int chainloader_load_length = 0; -static int chainloader_load_length_orig = 0; -static int chainloader_skip_length = 0; -static int chainloader_skip_length_orig = 0; -static int chainloader_boot_CS = 0; -static int chainloader_boot_CS_orig = 0; -static int chainloader_boot_IP = 0; -static int chainloader_boot_IP_orig = 0; -static long chainloader_ebx = 0; -static long chainloader_ebx_orig = 0; -static int chainloader_ebx_set = 0; -static int chainloader_ebx_set_orig = 0; -static long chainloader_edx = 0; -static long chainloader_edx_orig = 0; -static int chainloader_edx_set = 0; -static int chainloader_edx_set_orig = 0; -static long chainloader_bx = 0; -static long chainloader_bx_orig = 0; -static int chainloader_bx_set = 0; -static int chainloader_bx_set_orig = 0; -static long chainloader_cx = 0; -static long chainloader_cx_orig = 0; -static int chainloader_cx_set = 0; -static int chainloader_cx_set_orig = 0; -static int chainloader_disable_A20 = 0; -static int chainloader_disable_A20_orig = 0; -static int is_sdi = 0; -static int is_sdi_orig = 0; -static int is_raw = 0; -static int is_raw_orig = 0; -static int is_isolinux = 0; -static int is_isolinux_orig = 0; -static int is_grldr = 0; -static int is_grldr_orig = 0; -static int is_io = 0; -static int is_io_orig = 0; -static char chainloader_file[256]; +//int drive_map_slot_empty (struct drive_map_slot item); +//使用于configfile_func, command_open, GetParentUtf8Name static char chainloader_file_orig[256]; static const char *warning_defaultfile = "# WARNING: If you want to edit this file directly, do not remove any line"; -static struct vbe_controller *controller = (struct vbe_controller *)0x8000;//use 512 bytes -static struct vbe_mode *mode = (struct vbe_mode *)0x700;//use 255 bytes +int probe_bpb (struct master_and_dos_boot_sector *BS); +int probe_mbr (struct master_and_dos_boot_sector *BS, unsigned int start_sector1, unsigned int sector_count1, unsigned int part_start1); +int parse_string (char *arg); +int envi_cmd(const char *var,char * const env,int flags); +//extern int count_lines; +//extern int use_pager; +#if defined(__i386__) +char * convert_to_ascii (char *buf, int c, int lo, int hi); +#else +char *convert_to_ascii (char *buf, int c, unsigned long long lo); +#endif +unsigned int prog_pid; +extern int errorcheck; +unsigned int next_partition_drive; +unsigned int next_partition_dest; +unsigned int *next_partition_partition; +unsigned int *next_partition_type; +unsigned long long *next_partition_start; +unsigned long long *next_partition_len; +unsigned long long *next_partition_offset; +unsigned int *next_partition_entry; +unsigned int *next_partition_ext_offset; +char *next_partition_buf; +unsigned char partition_signature[16]; //分区签名 +unsigned char partition_activity_flag; //分区活动标志 +int fsys_type; +extern unsigned int fats_type; +extern unsigned int iso_type; +int get_mmap_entry (struct mmar_desc *desc, int cont); +int no_install_vdisk = 0; //0/1=安装虚拟磁盘/不安装虚拟磁盘 +static int ls_func (char *arg, int flags); +static char *GRUB_MOD_ADDR=0; +static char* mod_end; +static int find_func (char *arg, int flags); +static int insmod_func(char *arg,int flags); +static unsigned long long start_sector, sector_count; +unsigned long long initrd_start_sector; +grub_efi_uint64_t part_addr; +grub_efi_uint64_t part_size; +grub_efi_uint32_t cd_boot_entry; +grub_efi_uint32_t cd_boot_start; +grub_efi_uint32_t cd_boot_size; +grub_efi_uint32_t cd_Image_part_start; +grub_efi_uint32_t cd_Image_disk_size; +grub_efi_uint32_t cd_map_count = 0; +struct grub_part_data *part_data; void set_full_path(char *dest, char *arg, grub_u32_t max_len); void set_full_path(char *dest, char *arg, grub_u32_t max_len) { int len; + if (*arg != '/' && !(*arg == '(' && arg[1] == ')')) { grub_memmove (dest, arg, max_len); return; } - print_root_device(dest,0); len = strlen(dest); - if (*arg == '/') grub_sprintf(dest + len,"%s%s",saved_dir,arg); else grub_sprintf(dest + len,"%s",arg + 2); } - +#if 0 +int drive_map_slot_empty (struct drive_map_slot item); int -drive_map_slot_empty (struct drive_map_slot item) +drive_map_slot_empty (struct drive_map_slot item)//判断驱动器映像插槽是否为空 为空,返回1 { - unsigned long *array = (unsigned long *)&item; + grub_size_t *array = (grub_size_t *)&item; - unsigned long n = sizeof (struct drive_map_slot) / sizeof (unsigned long); + grub_size_t n = sizeof (struct drive_map_slot) / sizeof (grub_size_t); while (n) { @@ -199,32 +180,13 @@ drive_map_slot_empty (struct drive_map_slot item) } return 1; - //if (*(unsigned long *)(&(item.from_drive))) return 0; - //if (item.start_sector) return 0; - //if (item.sector_count) return 0; - //return 1; } -static int -drive_map_slot_equal (struct drive_map_slot a, struct drive_map_slot b) -{ - //return ! grub_memcmp ((void *)&(a.from_drive), (void *)&(b.from_drive), sizeof(struct drive_map_slot)); - return ! grub_memcmp ((void *)&a, (void *)&b, sizeof(struct drive_map_slot)); - //if (*(unsigned long *)(&(a.from_drive)) != *(unsigned long *)(&(b.from_drive))) return 0; - //if (a.start_sector != b.start_sector) return 0; - //if (a.sector_count != b.sector_count) return 0; - //return 1; -} -int map_func (char *arg, int flags); int disable_map_info = 0; - +#endif /* Prototypes for allowing straightfoward calling of builtins functions inside other functions. */ static int configfile_func (char *arg, int flags); -void lba_to_chs (unsigned long lba, unsigned long *cl, unsigned long *ch, unsigned long *dh); -//static char *set_device (char *device); -//static int real_open_partition (int flags); -//static int open_partition (void); int command_func (char *arg, int flags); int commandline_func (char *arg, int flags); int errnum_func (char *arg, int flags); @@ -232,6 +194,7 @@ int checkrange_func (char *arg, int flags); /* Check a password for correctness. Returns 0 if password was correct, and a value != 0 for error, similarly to strcmp. */ +int check_password (char* expected, password_t type); int check_password (char* expected, password_t type) { @@ -239,7 +202,6 @@ check_password (char* expected, password_t type) char entered[32]; /* Wipe out any previously entered password */ - // entered[0] = 0; memset(entered,0,sizeof(entered)); get_cmdline_str.prompt = msg_password; get_cmdline_str.maxlen = sizeof (entered) - 1; @@ -264,33 +226,34 @@ check_password (char* expected, password_t type) } /* Print which sector is read when loading a file. */ +static void disk_read_print_func (unsigned long long sector, unsigned int offset, unsigned long long length); static void -disk_read_print_func (unsigned long long sector, unsigned long offset, unsigned long long length) +disk_read_print_func (unsigned long long sector, unsigned int offset, unsigned long long length) { - grub_printf ("[%ld,%d,%ld]", sector, offset, length); + grub_printf ("[0x%lx,0x%x,0x%lx]", sector, offset, length); } extern int rawread_ignore_memmove_overflow; /* defined in disk_io.c */ -long query_block_entries; -//unsigned long map_start_sector; -//static unsigned long map_num_sectors = 0; -static unsigned long long map_start_sector[DRIVE_MAP_FRAGMENT]; -static unsigned long long map_num_sectors[DRIVE_MAP_FRAGMENT]; +//int query_block_entries; //小于0,填充map_start_sector/map_num_sectors,不打印信息。大于等于0,只打印信息。 +//static unsigned long long map_start_sector[DRIVE_MAP_FRAGMENT]; +//static unsigned long long map_num_sectors[DRIVE_MAP_FRAGMENT]; +//unsigned long long* map_start_sector; +//unsigned long long* map_num_sectors; static unsigned long long blklst_start_sector; static unsigned long long blklst_num_sectors; -static unsigned long blklst_num_entries; -static unsigned long blklst_last_length; - -static void disk_read_blocklist_func (unsigned long long sector, unsigned long offset, unsigned long long length); +static unsigned int blklst_num_entries; +static unsigned int blklst_last_length; /* Collect contiguous blocks into one entry as many as possible, and print the blocklist notation on the screen. */ +static void disk_read_blocklist_func (unsigned long long sector, unsigned int offset, unsigned long long length); static void -disk_read_blocklist_func (unsigned long long sector, unsigned long offset, unsigned long long length) +disk_read_blocklist_func (unsigned long long sector, unsigned int offset, unsigned long long length) { - unsigned long sectorsize = buf_geom.sector_size; - unsigned char sector_bit = (sectorsize == 2048 ? 11:9); + unsigned int sectorsize = buf_geom.sector_size; +// unsigned char sector_bit = (sectorsize == 2048 ? 11 : sectorsize == 4096 ? 12 : 9); + unsigned char sector_bit = buf_geom.log2_sector_size; #ifdef FSYS_INITRD if (fsys_table[fsys_type].mount_func == initrdfs_mount) { @@ -299,7 +262,6 @@ disk_read_blocklist_func (unsigned long long sector, unsigned long offset, unsig return; } #endif - if (blklst_num_sectors > 0) { if (blklst_start_sector + blklst_num_sectors == sector @@ -314,16 +276,16 @@ disk_read_blocklist_func (unsigned long long sector, unsigned long offset, unsig if (query_block_entries >= 0) { if (blklst_last_length == 0) - grub_printf ("%s%ld+%ld", (blklst_num_entries ? "," : ""), - (unsigned long long)(blklst_start_sector - part_start), blklst_num_sectors); + grub_printf ("%s0x%lx+0x%lx", (blklst_num_entries ? "," : ""), + (unsigned long long)(blklst_start_sector/* - part_start*/), blklst_num_sectors); else if (blklst_num_sectors > 1) - grub_printf ("%s%ld+%ld,%ld[0-%d]", (blklst_num_entries ? "," : ""), - (unsigned long long)(blklst_start_sector - part_start), (blklst_num_sectors-1), - (unsigned long long)(blklst_start_sector + blklst_num_sectors-1 - part_start), + grub_printf ("%s0x%lx+0x%lx,0x%lx[0-0x%x]", (blklst_num_entries ? "," : ""), + (unsigned long long)(blklst_start_sector/* - part_start*/), (blklst_num_sectors-1), + (unsigned long long)(blklst_start_sector + blklst_num_sectors-1/* - part_start*/), blklst_last_length); else - grub_printf ("%s%ld[0-%d]", (blklst_num_entries ? "," : ""), - (unsigned long long)(blklst_start_sector - part_start), blklst_last_length); + grub_printf ("%s0x%lx[0-0x%x]", (blklst_num_entries ? "," : ""), + (unsigned long long)(blklst_start_sector/* - part_start*/), blklst_last_length); } else if (blklst_last_length == 0 && blklst_num_entries < DRIVE_MAP_FRAGMENT) { @@ -338,8 +300,8 @@ disk_read_blocklist_func (unsigned long long sector, unsigned long offset, unsig if (offset > 0) { if (query_block_entries >= 0) - grub_printf("%s%ld[%d-%d]", (blklst_num_entries ? "," : ""), - (unsigned long long)(sector - part_start), offset, (offset + length)); + grub_printf("%s0x%lx[0x%x-0x%x]", (blklst_num_entries ? "," : ""), + (unsigned long long)(sector/* - part_start*/), offset, (offset + length)); blklst_num_entries++; } else @@ -351,29 +313,25 @@ disk_read_blocklist_func (unsigned long long sector, unsigned long offset, unsig } /* blocklist */ +static int blocklist_func (char *arg, int flags); static int blocklist_func (char *arg, int flags) { char *dummy = NULL; - int i; unsigned long long err; #ifndef NO_DECOMPRESSION int no_decompression_bak = no_decompression; #endif - errnum = 0; blklst_start_sector = 0; blklst_num_sectors = 0; blklst_num_entries = 0; blklst_last_length = 0; + grub_memset (map_start_sector, 0, DRIVE_MAP_FRAGMENT * 8); + grub_memset (map_num_sectors, 0, DRIVE_MAP_FRAGMENT * 8); -// map_start_sector = 0; -// map_num_sectors = 0; - for (i = 0; i < DRIVE_MAP_FRAGMENT; i++) - { - map_start_sector[i] =0; - map_num_sectors[i] =0; - } + if (flags==255) + query_block_entries = -1; /* Open the file. */ if (! grub_open (arg)) @@ -382,7 +340,7 @@ blocklist_func (char *arg, int flags) if (fsys_table[fsys_type].mount_func == initrdfs_mount) { disk_read_hook = disk_read_blocklist_func; - err = grub_read ((unsigned long long)(unsigned int)dummy,-1ULL, GRUB_LISTBLK); + err = grub_read ((unsigned long long)(grub_size_t)dummy,-1ULL, GRUB_LISTBLK); disk_read_hook = 0; goto fail_read; } @@ -390,96 +348,65 @@ blocklist_func (char *arg, int flags) #ifndef NO_DECOMPRESSION if (compressed_file) { - if (query_block_entries < 0) + if (query_block_entries < 0 && decomp_type != DECOMP_TYPE_VHD) //为了给vhd_start_sector赋值 { /* compressed files are not considered contiguous. */ -// query_block_entries = 3; goto fail_read; } - grub_close (); no_decompression = 1; if (! grub_open (arg)) goto fail_open; } #endif /* NO_DECOMPRESSION */ - /* Print the device name. */ - if (query_block_entries >= 0) print_root_device (NULL,1); - + if (query_block_entries >= 0) print_root_device (NULL,1 | 0x100); rawread_ignore_memmove_overflow = 1; /* Read in the whole file to DUMMY. */ disk_read_hook = disk_read_blocklist_func; -// err = grub_read ((unsigned long long)(unsigned int)dummy, (query_block_entries < 0 ? buf_geom.sector_size : -1ULL), 0xedde0d90); - err = grub_read ((unsigned long long)(unsigned int)dummy, -1ULL, GRUB_LISTBLK); + err = grub_read ((unsigned long long)(grub_size_t)dummy, -1ULL, GRUB_LISTBLK); disk_read_hook = 0; rawread_ignore_memmove_overflow = 0; - if (! err) + + if (fsys_table[fsys_type].mount_func == pxe_mount) + { + map_start_sector[0] = (unsigned long long)(grub_size_t)(char*)efi_pxe_buf; + printf("0x%lx+0x%lx", (unsigned long long)(grub_size_t)(char*)efi_pxe_buf >> 9, (filemax + 0x1ff) >> 9); + query_block_entries = blklst_num_entries = 1; goto fail_read; + } + if (! err) + goto fail_read; /* The last entry may not be printed yet. Don't check if it is a * full sector, since it doesn't matter if we read too much. */ if (blklst_num_sectors > 0) + { + if (query_block_entries >= 0) + grub_printf ("%s0x%lx+0x%lx", (blklst_num_entries ? "," : ""), + (unsigned long long)(blklst_start_sector/* - part_start*/), blklst_num_sectors); + else if (blklst_num_entries < DRIVE_MAP_FRAGMENT) { - if (query_block_entries >= 0) - grub_printf ("%s%ld+%ld", (blklst_num_entries ? "," : ""), - (unsigned long long)(blklst_start_sector - part_start), blklst_num_sectors); - else if (blklst_num_entries < DRIVE_MAP_FRAGMENT) - { - map_start_sector[blklst_num_entries] = blklst_start_sector; - map_num_sectors[blklst_num_entries] = blklst_num_sectors; - } - blklst_num_entries++; + map_start_sector[blklst_num_entries] = blklst_start_sector; + map_num_sectors[blklst_num_entries] = blklst_num_sectors; } - + blklst_num_entries++; + } if (query_block_entries >= 0) grub_putchar ('\n', 255); else query_block_entries = blklst_num_entries; -#if 0 - else - { - query_block_entries = 1; - map_start_sector = start_sector; - map_num_sectors = num_sectors; - } - - if (query_block_entries < 0) - { - map_start_sector = blklst_start_sector; - blklst_start_sector = 0; - blklst_num_sectors = 0; - blklst_num_entries = 0; - blklst_last_length = 0; - rawread_ignore_memmove_overflow = 1; - /* read in the last sector to DUMMY */ - filepos = filemax ? (filemax - 1) & (-(unsigned long long)buf_geom.sector_size) : filemax; - disk_read_hook = disk_read_blocklist_func; - err = grub_read ((unsigned long long)(unsigned int)dummy, -1ULL, 0xedde0d90); - disk_read_hook = 0; - rawread_ignore_memmove_overflow = 0; - if (! err) - goto fail_read; - map_num_sectors = blklst_start_sector - map_start_sector + 1; - query_block_entries = filemax ? - map_num_sectors - ((filemax - 1) >> log2_tmp (buf_geom.sector_size)/*>> SECTOR_BITS*/) : 2; - } -#endif - fail_read: - grub_close (); fail_open: - #ifndef NO_DECOMPRESSION no_decompression = no_decompression_bak; #endif if (query_block_entries < 0) query_block_entries = 0; - return ! errnum; } @@ -494,810 +421,115 @@ static struct builtin builtin_blocklist = /* WinME support by bean. Thanks! */ -// The following routines are used to decompress IO.SYS from WinME - -static int ibuf_pos; -static char *ibuf_ptr,*obuf_ptr; -static unsigned short ibuf_tab[16]; - -static void ibuf_init(char* buf); -static unsigned short ibuf_read(int nbits); -static int expand_block(int nsec); -static long expand_file(char* src,char* dst); - -static void ibuf_init(char* buf) -{ - int i; +#define obuf_init(buf) obuf_ptr=buf +#define obuf_putc(ch) *(obuf_ptr++)=ch +#define obuf_copy(ofs,len) do { for (;len>0;obuf_ptr++,len--) *(obuf_ptr)=*(obuf_ptr-ofs); } while (0) - ibuf_ptr=buf; - ibuf_pos=0; - // ibuf_tab[i]=(1<<(i+1))-1 - ibuf_tab[0]=1; - for (i=1;i<16;i++) - ibuf_tab[i]=ibuf_tab[i-1]*2+1; -} +//static grub_efi_char16_t chainloader_type = 0; +static grub_efi_handle_t image_handle; -static unsigned short ibuf_read(int nbits) +void hexdump(grub_u64_t ofs,char* buf,int len); +void hexdump(grub_u64_t ofs,char* buf,int len) { - unsigned short res; - - res=(unsigned short)((*((unsigned long*)ibuf_ptr)>>ibuf_pos) & ibuf_tab[nbits-1]); - ibuf_pos+=nbits; - if (ibuf_pos>=8) + quit_print=0; + int align = len > 16; + while (len>0) { - ibuf_ptr+=(ibuf_pos>>3); - ibuf_pos&=7; - } - return res; -} + int cnt,k,i,j = 3; -#define obuf_init(buf) obuf_ptr=buf -#define obuf_putc(ch) *(obuf_ptr++)=ch -#define obuf_copy(ofs,len) do { for (;len>0;obuf_ptr++,len--) *(obuf_ptr)=*(obuf_ptr-ofs); } while (0) -// Don't use memcpy, otherwise we could be screwed ! + if (align) + { + i = ofs & 0xFLL; + if (i) + ofs &= ~0xFLL; + } + else + { + i = 0; + } -static int expand_block(int nsec) -{ - while (nsec>0) - { - int cnt; + if ((ofs >> 32)) + j = 7; - cnt=0x200; - while (1) - { - int flg,ofs,bts,bse,del,len; + grub_printf ("%0*lX: ", j == 3?8:10,ofs); - flg=ibuf_read(2); + cnt = 16; + if (cnt > len) + cnt = len + i; - if (flg==0) ofs=ibuf_read(6); else - if (flg==3) - { - if (ibuf_read(1)) - { - ofs=ibuf_read(12)+0x140; - if (ofs==0x113F) - break; - } - else - ofs=ibuf_read(8)+0x40; - } else - { - char ch; - - cnt--; - if (cnt<0) - { - grub_putstr("Data corrupted"); - return 1; - } - ch=ibuf_read(7); - if (flg & 1) - ch|=0x80; - obuf_putc(ch); - continue; - } - if (ofs==0) - { - grub_putstr("Data corrupted"); - return 1; - } - bse=2; - del=0; - for (bts=0;bts<9;bts++) - { - if (ibuf_read(1)) - break; - bse+=del+1; - del=del*2+1; - } - if (bts==9) - { - grub_putstr("Data corrupted"); - return 1; - } - len=(bts)?bse+ibuf_read(bts):bse; - if ((cnt=cnt-len)<0) - { - grub_putstr("Data corrupted"); - return 1; - } - obuf_copy(ofs,len); - } - nsec--; - if ((cnt) && (nsec)) + for (k=0;k<16;k++) { - grub_putstr("Data corrupted"); - return 1; + if (i>k || k >=cnt) + printf(" "); + else + printf("%02X ", (unsigned long)(unsigned char)(buf[k - i])); + if ((k!=15) && ((k & j)==j)) + printf(" "); } - } - return 0; -} - -static long expand_file(char* src,char* dst) -{ - ibuf_init(src); - obuf_init(dst); - - if (ibuf_read(16)!=0x4D43) - { - grub_putstr("First CM signature not found"); - return -1; - } - while (1) - { - unsigned short flg,len; - flg=ibuf_read(8); - len=ibuf_read(16); - if (len==0) - { - int n; + printf("; "); - n=(ibuf_ptr-src) & 0xF; - if ((n) || (ibuf_pos)) - { - ibuf_ptr+=16-n; - ibuf_pos=0; - } - if (ibuf_read(16)!=0x4D43) - { - grub_putstr("Second CM signature not found"); - return -1; - } - return obuf_ptr-dst; - } - if (flg==0) + for (k=0;kk) + putchar(' ',255); + else { - memcpy(obuf_ptr,ibuf_ptr,len); - ibuf_ptr+=len; - obuf_ptr+=len; + j = k - i; + putchar((((unsigned char)buf[j]>=32) && ((unsigned char)buf[j]<0x7f))?buf[j]:'.', 255); } - else - { - char* save_ptr; - unsigned short sec; + } - sec=(ibuf_read(16)+511)>>9; - save_ptr=ibuf_ptr; - if (ibuf_read(16)!=0x5344) - { - grub_putstr("0x5344 signature not found"); - return -1; - } - ibuf_read(16); - if (expand_block(sec)) - return -1; - ibuf_ptr=save_ptr+len; - ibuf_pos=0; - } + printf("\n"); + + if (quit_print) + break; + + ofs+=16; + cnt -= i; + len -= cnt; + buf += cnt; } } -/* boot */ + +/* cat */ +static int cat_func (char *arg, int flags); static int -boot_func (char *arg, int flags) +cat_func (char *arg, int flags) { - int old_cursor, old_errnum; - struct term_entry *prev_term = current_term; - - /* if our terminal needed initialization, we should shut it down - * before booting the kernel, but we want to save what it was so - * we can come back if needed */ - if (current_term->shutdown) - { - (*current_term->shutdown)(); - current_term = term_table; /* assumption: console is first */ - } - -#ifdef FSYS_PXE - if (kernel_type!=KERNEL_TYPE_CHAINLOADER) - pxe_unload(); -#endif + unsigned char c; +// unsigned char s[128]; + char *s; + unsigned long long Hex = 0; + unsigned int len, i, j; + char *p; + unsigned long long skip = 0; + unsigned long long length = 0xffffffffffffffffULL; + char *locate = 0; + char *replace = 0; + unsigned long long locate_align = 1; + unsigned long long len_s; + unsigned long long len_r = 0; + unsigned long long ret = 0; + unsigned long long number = -1ULL; + int locate_ignore_case = 0; - old_cursor = setcursor (1); + quit_print = 0; errnum = 0; - - //errorcheck = 1; - /* clear keyboard buffer before boot */ - while (console_checkkey () != -1) console_getkey (); - /* if arg == -1 or --int18 boot via INT 18*/ - if (*(unsigned short*)arg == 0x312d || memcmp(arg,"--int18",7) == 0) + for (;;) + { + if (grub_memcmp (arg, "--hex=", 6) == 0) { - grub_printf("Local boot via INT 18...\n"); - boot_int18(); - return 0; - }; - - switch (kernel_type) - { - case KERNEL_TYPE_FREEBSD: - case KERNEL_TYPE_NETBSD: - /* *BSD */ - bsd_boot (kernel_type, /*0*/bootdev, (char *) mbi.cmdline); - break; - - case KERNEL_TYPE_LINUX: - /* Linux */ - map_func ("(0x22) (0x22)", flags); /* delete mapping for INITRD_DRIVE */ - map_func ("--rehook", flags); - linux_boot (); - break; - - case KERNEL_TYPE_BIG_LINUX: - /* Big Linux */ - - { - unsigned int p; - /* check grub.exe */ - for (p = (unsigned int)linux_bzimage_tmp_addr; p < (unsigned int)linux_bzimage_tmp_addr + 0x8000; p += 0x200) + arg += 6; + safe_parse_maxint (&arg, &Hex); + } + else if (grub_memcmp (arg, "--hex", 5) == 0) { - if (((*(long long *)(void *)p & 0xFFFF00FFFFFFFFFFLL) == 0x02030000008270EALL) && - ((*(long long *)(void *)(p + 0x12) & 0xFFFFFFFFFFLL) == 0x0037392E30LL)) - { -#ifdef FSYS_PXE - if (pxe_entry == 0) - *(char *)(void *)(p + 5) |= 0x01; // disable pxe -#endif - if (*(long *)(void *)(p + 0x80) == 0xFFFFFFFF)//boot_drive - { - *(long *)(void *)(p + 0x80) = saved_drive; - *(long *)(void *)(p + 0x08) = saved_partition; - } - break; - } + Hex = 1; } - } - - map_func ("(0x22) (0x22)", flags); /* delete mapping for INITRD_DRIVE */ - map_func ("--rehook", flags); - big_linux_boot (); - break; - - case KERNEL_TYPE_CHAINLOADER: - /* Chainloader */ - - /* set boot drive to the root device. - * the boot drive should be either (fd0) or (hd0) for normal - * MS-style boot sectors. the BIOS only passes (fd0) or (hd0) - * to DL, because these two are the only devices that can be - * booted by BIOS. - * - * You should set boot drive using the rootnoverify command just - * before the boot command. - */ - boot_drive = saved_drive; - - /* extended chainloader */ - if (chainloader_load_length > 512 || chainloader_boot_CS > 0 || - chainloader_skip_length || - chainloader_ebx_set || - chainloader_edx_set || - chainloader_bx_set || - chainloader_cx_set || - is_sdi || is_raw || //chainloader_disable_A20 || - (chainloader_boot_IP >= 0 && chainloader_boot_IP != 0x7c00) || - (((chainloader_load_segment >= 0)? chainloader_load_segment : 0) << 4) + - ((chainloader_load_offset >= 0)? chainloader_load_offset : 0x7c00) != 0x7c00 - ) - { - unsigned long read_length; - - /* load high */ - if (chainloader_load_segment == -1) - chainloader_load_segment = 0; - if (chainloader_load_offset == -1) - { - if (chainloader_load_segment) - chainloader_load_offset = 0; - else - chainloader_load_offset = 0x7c00; - } - if (chainloader_boot_CS == -1) - chainloader_boot_CS = chainloader_load_segment; - if (chainloader_boot_IP == -1) - chainloader_boot_IP = chainloader_load_offset; - - /* Open the file. */ - if (! grub_open (chainloader_file)) - { - kernel_type = KERNEL_TYPE_NONE; - return 0; - } - if (is_sdi) - { - unsigned long long bytes_needed = filemax; - unsigned long long base = 0; - - if (mbi.flags & MB_INFO_MEM_MAP) - { - struct AddrRangeDesc *map = (struct AddrRangeDesc *) saved_mmap_addr; - unsigned long end_addr = saved_mmap_addr + saved_mmap_length; - - for (; end_addr > (unsigned long) map; map = (struct AddrRangeDesc *) (((int) map) + 4 + map->size)) - { - unsigned long long top_end; - - if (map->Type != MB_ARD_MEMORY) - continue; - top_end = map->BaseAddr + map->Length; - if (top_end > 0x100000000ULL) - top_end = 0x100000000ULL; - -#define MIN_EMU_BASE 0x200000ULL - if (map->Length >= bytes_needed - && (base = (top_end - bytes_needed) & 0xfffff000) >= MIN_EMU_BASE /* page align */ - && map->Length >= top_end - base) - break; /* success */ - base = 0; - } - } - else - grub_printf ("Address Map BIOS Interface is not activated.\n"); - - if (base < MIN_EMU_BASE) - { - grub_close (); - return ! (errnum = ERR_WONT_FIT); - } - -#undef MIN_EMU_BASE - //filepos = 0; - if (grub_read (base, -1ULL, 0xedde0d90) != filemax) - { - grub_close (); - if (errnum == ERR_NONE) - errnum = ERR_READ; - return 0; - } - grub_close (); - - unset_int13_handler (0); - -#define BootCodeOffsetLow (*(unsigned long *)((int)base + 0x10)) -#define BootCodeSizeLow (*(unsigned long *)((int)base + 0x18)) - read_length = BootCodeSizeLow; - if (read_length > 0x90000) - read_length = 0x90000; - grub_memmove((char *)0x200000, (char *)((unsigned int)base + BootCodeOffsetLow), read_length); -#undef BootCodeOffsetLow -#undef BootCodeSizeLow - if (! chainloader_edx_set) - { - chainloader_edx = (unsigned int)base | 0x41; - chainloader_edx_set = 1; - } - }else{ - /* Read the first 640K */ - read_length = filemax - chainloader_skip_length; - filepos = ((*(unsigned short *)0x413)<<10) - (chainloader_load_segment<<4) - chainloader_load_offset; - if (read_length > filepos) - read_length = filepos; - filepos = chainloader_skip_length; - - /* read the new loader to physical address 2MB, overwriting - * the backup area of DOS memory. - */ - - if (grub_read ((unsigned long long) 0x200000, read_length, 0xedde0d90) != read_length) - { - grub_close (); - kernel_type = KERNEL_TYPE_NONE; - - if (errnum == ERR_NONE) - errnum = ERR_EXEC_FORMAT; - - break; - } - grub_close (); - -#ifdef FSYS_PXE - pxe_unload(); -#endif - if (is_io) - { - /* WinMe support by bean. Thanks! */ - - // Not a very neat way to test WinME, works anyway - if ((*(unsigned short*)0x200000==0x4D43) && - // ((*(char*)0x110002==0) || (*(unsigned short*)0x110000==0x4D43)) && - (chainloader_skip_length==0x800)) - { - unsigned long len; - len=(unsigned long)expand_file((char*)0x200000,(char*)0x2A0000); - if (len==0xffffffff || len==0) - { - kernel_type = KERNEL_TYPE_NONE; - errnum = ERR_EXEC_FORMAT; - break; - } - grub_memmove((char*)0x200000,(char*)0x2A0000,len); - chainloader_load_length=read_length=len; - } - - /* import from WEE, to prevent MS from wiping int32-3F. */ - /* search these 12 bytes ... */ - /* 83 C7 08 add di,08 */ - /* B9 0E 00 mov cx,0E */ - /* AB stosw */ - /* 83 C7 02 add di,02 */ - /* E2 FA loop (-6) */ - /* ... replace with NOPs */ - { - unsigned long p = 0x200000; - unsigned long q = 0x200000 - 16 + read_length; - while (p < q) - { - if ((*(long *)p == 0xB908C783) && - (*(long long*)(p+4)==0xFAE202C783AB000ELL)) - { - ((long *)p)[2]=((long *)p)[1]= - *(long *)p = 0x90909090; - p += 12; - continue; /* would occur 3 times */ - } - p++; - } - } - } - - /* create boot info table for isolinux */ - if (is_isolinux) - { - int p; - query_block_entries = -1; /* query block list only */ -// query_block_entries = 4; - blocklist_func (chainloader_file, flags); - if (errnum) - break; -// if (query_block_entries != 1) - if (query_block_entries <= 0 || query_block_entries > DRIVE_MAP_FRAGMENT) - { - errnum = ERR_MANY_FRAGMENTS; - break; - } - *(unsigned long*)0x20000C = map_start_sector[0]; - *(unsigned long*)0x200010 = chainloader_load_length; - - old_errnum = 0; /* init to calculate the checksum */ - *(unsigned long*)(0x200000 + chainloader_load_length) = 0; - - for (p = 0; p < (chainloader_load_length - 0x40 + 3) / 4; p++) - { - old_errnum += *(long *)(0x200040 + (p << 2)); - } - - *(unsigned long*)0x200014 = old_errnum; /* checksum */ - } -#ifdef FSYS_PXE - if (is_grldr && pxe_entry == 0) - { - *(unsigned char*)0x202005 |= 0x01; /* disable pxe */ - } -#endif - - /* Turn off A20 here if --disable-a20 was specified. - * Note: we won't have access to the odd megas of the memory - * when A20 is off. - */ - if (chainloader_disable_A20) - { - if (! gateA20 (0)) - { - /* to asure A20 is on when we return to grub. */ - gateA20 (1); /* turn on A20 in case it is off */ - errnum = ERR_DISABLE_A20; - break; - } - printf_debug0 ("\nGate A20 is turned off successfully.\n"); - } - - if (! chainloader_edx_set) - { - chainloader_edx_set = 1; - chainloader_edx = boot_drive; - } - if (! is_raw) //do not check/modify HIDDEN_SECTORS for "--raw" - { - if (chainloader_edx & 0x80) - { - /* if hard-drive BPB shows HIDDEN_SECTORS=0, we assume the - * sector is MBR and it has a partition table. */ - if (! probe_bpb((struct master_and_dos_boot_sector *)0x200000)) - if (*((unsigned long *) (0x20001C)) == 0) - { - int err; - if ((err = probe_mbr ((struct master_and_dos_boot_sector *)0x200000, 0, ((chainloader_load_length + 511) >> 9), 0))) - { - printf_debug0 ("Partition table not recognized(chainloader_edx=0x%X, err=%d). ", chainloader_edx, err); - errnum = ERR_HD_VOL_START_0; - break; - } - } - } else { - /* clear number of hidden sectors for floppy */ - if (! probe_bpb((struct master_and_dos_boot_sector *)0x200000)) - if (*((unsigned long *) (0x20001C))) - *((unsigned long *) (0x20001C)) = 0; - } - } - } - - if (chainloader_load_length == -1 || chainloader_load_length > read_length) - chainloader_load_length = read_length; - - chain_load_segment = (unsigned short)chainloader_load_segment; - chain_load_offset = (unsigned short)chainloader_load_offset; - chain_boot_CS = (unsigned short)chainloader_boot_CS; - chain_boot_IP = (unsigned short)chainloader_boot_IP; - chain_load_length = chainloader_load_length; - if (! chainloader_ebx_set) - { - chainloader_ebx_set = 1; - chainloader_ebx = boot_drive; - } - chain_ebx = chainloader_ebx; - chain_ebx_set = chainloader_ebx_set; - chain_edx = chainloader_edx; - chain_edx_set = chainloader_edx_set; - chain_bx = chainloader_bx; - chain_bx_set = chainloader_bx_set; - chain_cx = chainloader_cx; - chain_cx_set = chainloader_cx_set; - chain_enable_gateA20 = ! chainloader_disable_A20; - - /* Check if we should set the int13 handler. */ - if (unset_int13_handler (1) && ! drive_map_slot_empty (bios_drive_map[0])) - { - /* Set the handler. This is somewhat dangerous. */ - set_int13_handler (bios_drive_map); - buf_drive = -1; - buf_track = -1; - } - - /* move the code to a safe place at 0x2B0000 */ - grub_memmove((char *)HMA_ADDR, HMA_start, 0x200/*0xfff0*/); - - //typedef void (*HMA_FUNC)(void); - //((HMA_FUNC)0x100000)(); /* no return */ - - /* Jump to high memory area. This will move boot code at - * 0x200000 to the destination load-segment:load-offset; - * setup edx and ebx registers; switch to real mode; - * and jump to boot-cs:boot-ip. - */ - ((void (*)(void))HMA_ADDR)(); /* no return */ - break; - } - if (chainloader_disable_A20) - { - if (gateA20 (0)) - grub_printf("\nGate A20 is turned off successfully.\n"); - else { - /* to asure A20 is on when we return to grub. */ - gateA20 (1); /* turn on A20 in case it is off */ - errnum = ERR_DISABLE_A20; - break; - } - } - /* Check if we should set the int13 handler. */ - if (unset_int13_handler (1) && ! drive_map_slot_empty (bios_drive_map[0])) - { - /* Set the handler. This is somewhat dangerous. */ - set_int13_handler (bios_drive_map); - buf_drive = -1; - buf_track = -1; - } - - if ((boot_drive & 0x80) == 0) - { - /* clear number of hidden sectors for floppy */ - if (! probe_bpb((struct master_and_dos_boot_sector *)0x7C00)) - if (*((unsigned long *) (0x7C00 + 0x1C))) - *((unsigned long *) (0x7C00 + 0x1C)) = 0; - } else { - /* if hard-drive BPB shows HIDDEN_SECTORS=0, we assume the - * sector is MBR and it has a partition table. */ - if (! probe_bpb((struct master_and_dos_boot_sector *)0x7C00)) - if (*((unsigned long *) (0x7C00 + 0x1C)) == 0) - { - int err; - if ((err = probe_mbr ((struct master_and_dos_boot_sector *)0x7C00, 0, 1, 0))) - { - printf_debug0 ("Partition table not recognized(boot_drive=0x%X, err=%d). ", boot_drive, err); - errnum = ERR_HD_VOL_START_0; - break; - } - } - } -#ifdef FSYS_PXE - pxe_unload(); -#endif - chain_stage1 (0, 0x7C00, boot_part_addr); /* no return */ - break; - - case KERNEL_TYPE_MULTIBOOT: - /* Multiboot */ - - /* Set the boot loader name. */ - mbi.boot_loader_name = (unsigned long) "GNU GRUB " VERSION; - - /* Get the ROM configuration table by INT 15, AH=C0h. */ - mbi.config_table = get_rom_config_table (); - - /* Get the drive info. */ - mbi.drives_length = 0; - mbi.drives_addr = (unsigned long)(saved_mmap_addr + saved_mmap_length); - - /* XXX: Too many drives will possibly use a piece of memory starting at 0x10000(64K). */ - -#define FIND_DRIVES (*((char *)0x475)) - { - unsigned int drive; - unsigned long addr = mbi.drives_addr; - - for (drive = 0x80; drive < 0x80 + FIND_DRIVES; drive++) - { - struct drive_info *info = (struct drive_info *) addr; - - /* Get the geometry. This ensures that the drive is present. */ - - printf_debug ("get_diskinfo(%X), ", drive); - - if (get_diskinfo (drive, &tmp_geom, 0)) - continue;//break; - - printf_debug (" %sC/H/S=%d/%d/%d, Sector Count/Size=%ld/%d\n", - ((tmp_geom.flags & BIOSDISK_FLAG_LBA_EXTENSION) ? "LBA, " : ""), - tmp_geom.cylinders, tmp_geom.heads, tmp_geom.sectors, - (unsigned long long)tmp_geom.total_sectors, tmp_geom.sector_size); - - /* Set the information. */ - info->drive_number = drive; - info->drive_mode = ((tmp_geom.flags & BIOSDISK_FLAG_LBA_EXTENSION) - ? MB_DI_LBA_MODE : MB_DI_CHS_MODE); - info->drive_cylinders = tmp_geom.cylinders; - info->drive_heads = tmp_geom.heads; - info->drive_sectors = tmp_geom.sectors; - - addr += sizeof (struct drive_info); - - info->size = addr - (unsigned long) info; - mbi.drives_length += info->size; - } - } -#undef FIND_DRIVES - - multi_boot ((int) entry_addr, (int) &mbi, 0, -1, 0, 0, 0); - break; - - default: - errnum = ERR_BOOT_COMMAND; - //return 0; - } - - old_errnum = errnum; - /* if we get back here, we should go back to what our term was before */ - setcursor (old_cursor); - current_term = prev_term; - if (current_term->startup) - /* if our terminal fails to initialize, fall back to console since - * it should always work */ - if ((*current_term->startup)() == 0) - current_term = term_table; /* we know that console is first */ - errnum = old_errnum; - return ! errnum; -} - -static struct builtin builtin_boot = -{ - "boot", - boot_func, - BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST | BUILTIN_BOOTING, - "boot [-1]", - "Boot the OS/chain-loader which has been loaded." - "with option \"-1\" will boot to local via INT 18.", -}; - -void hexdump(grub_u64_t ofs,char* buf,int len) -{ - quit_print=0; - int align = len > 16; - while (len>0) - { - int cnt,k,i,j = 3; - - if (align) - { - i = ofs & 0xFLL; - if (i) - ofs &= ~0xFLL; - } - else - { - i = 0; - } - - if ((ofs >> 32)) - j = 7; - - grub_printf ("%0*lX: ", j == 3?8:10,ofs); - - cnt = 16; - if (cnt > len) - cnt = len + i; - - for (k=0;k<16;k++) - { - if (i>k || k >=cnt) - printf(" "); - else - printf("%02X ", (unsigned long)(unsigned char)(buf[k - i])); - if ((k!=15) && ((k & j)==j)) - printf(" "); - } - - printf("; "); - - for (k=0;kk) - putchar(' ',255); - else - { - j = k - i; - putchar((((unsigned char)buf[j]>=32) && ((unsigned char)buf[j]<0x7f))?buf[j]:'.', 255); - } - } - - printf("\n"); - - if (quit_print) - break; - - ofs+=16; - cnt -= i; - len -= cnt; - buf += cnt; - } -} - - -/* cat */ -static int -cat_func (char *arg, int flags) -{ - unsigned char c; - unsigned char s[128]; - //unsigned char r[128]; - unsigned long long Hex = 0; - unsigned long long len, i, j; - char *p; - unsigned long long skip = 0; - unsigned long long length = 0xffffffffffffffffULL; - char *locate = 0; - char *replace = 0; - unsigned long long locate_align = 1; - unsigned long long len_s; - unsigned long long len_r = 0; - unsigned long long ret = 0; - unsigned long long number = -1ULL; - int locate_ignore_case = 0; - - quit_print = 0; - errnum = 0; - for (;;) - { - if (grub_memcmp (arg, "--hex=", 6) == 0) - { - arg += 6; - safe_parse_maxint (&arg, &Hex); - } - else if (grub_memcmp (arg, "--hex", 5) == 0) - { - Hex = 1; - } - else if (grub_memcmp (arg, "--skip=", 7) == 0) + else if (grub_memcmp (arg, "--skip=", 7) == 0) { arg += 7; safe_parse_maxint(&arg,&skip); @@ -1325,7 +557,7 @@ cat_func (char *arg, int flags) arg += 15; if (! safe_parse_maxint (&arg, &locate_align)) return 0; - if ((unsigned long)locate_align == 0) + if ((unsigned int)locate_align == 0) return ! (errnum = ERR_BAD_ARGUMENT); } else if (grub_memcmp (arg, "--number=",9) == 0) @@ -1366,11 +598,8 @@ cat_func (char *arg, int flags) no_decompression = no_decompression_bak; } grub_close(); - printf_debug0 ("Filesize is 0x%lX\n", (unsigned long long)filesize); - //ret = filemax; - //return ret; - //if filesize over 4GB return 0xFFFFFFFF; - return (filesize>>32)?-1:filesize; + printf_debug ("Filesize is 0x%lX\n", (unsigned long long)filesize); + return (filesize>>32)?(unsigned long long)-1:filesize; } if (replace) @@ -1403,7 +632,7 @@ cat_func (char *arg, int flags) } else { - replace = (char*)(unsigned int)len_r; + replace = (char*)(grub_size_t)(unsigned long long)len_r; len_r = Hex?Hex:8; } if ((int)len_r <= 0) @@ -1451,7 +680,7 @@ cat_func (char *arg, int flags) len = 0; if (j < length) { - len = grub_read ((unsigned long long)(SCRATCHADDR + 16), 16, 0xedde0d90); + len = grub_read ((unsigned long long)(grub_size_t)(char *)(SCRATCHADDR + 16), 16, 0xedde0d90); } if (len < 16) { @@ -1468,8 +697,8 @@ cat_func (char *arg, int flags) while (i < l) { k = j - 16 + i; - if ((locate_align == 1 || ! ((unsigned long)k % (unsigned long)locate_align)) - && strncmpx (locate, (char *)(SCRATCHADDR + (unsigned long)i), len_s,locate_ignore_case) == 0) + if ((locate_align == 1 || ! ((grub_size_t)k % (grub_size_t)locate_align)) + && strncmpx (locate, (char *)(SCRATCHADDR + (grub_size_t)i), len_s,locate_ignore_case) == 0) { /* print the address */ if (!replace || debug > 1) @@ -1480,7 +709,7 @@ cat_func (char *arg, int flags) unsigned long long filepos_bak = filepos; filepos = k; /* write len_r bytes at string replace to file!! */ - grub_read ((unsigned long long)(unsigned int)replace,len_r, 0x900ddeed); + grub_read ((unsigned long long)(grub_size_t)replace,len_r, 0x900ddeed); i += len_r; // if (filepos < filepos_bak) filepos = filepos_bak; @@ -1512,32 +741,26 @@ cat_func (char *arg, int flags) }else if (Hex == (++ret)) /* a trick for (ret = 1, Hex == 1) */ { j = 16/* - (skip & 0xF)*/; + s = grub_malloc (128); if (j > length) j = length; - while ((len = grub_read ((unsigned long long)(unsigned long)&s, j, 0xedde0d90))) +// while ((len = grub_read ((unsigned long long)(grub_size_t)&s, j, 0xedde0d90))) + while ((len = grub_read ((unsigned long long)(grub_size_t)s, j, 0xedde0d90))) { - hexdump(skip,(char*)&s,len); +// hexdump(skip,(char*)&s,len); + hexdump(skip,s,len); if (quit_print) break; skip += len; length -= len; j = (length >= 16)?16:length; } + grub_free (s); }else - for (j = 0; j < length && grub_read ((unsigned long long)(unsigned long)&c, 1, 0xedde0d90) && c; j++) + for (j = 0; j < length && grub_read ((unsigned long long)(grub_size_t)&c, 1, 0xedde0d90) && c; j++) { -#if 1 -// if (debug > 0)//chenall 2010-11-12 changed.always show. grub_putchar (c, 255); -#else - /* Because running "cat" with a binary file can confuse the terminal, - print only some characters as they are. */ - if (grub_isspace (c) || (c >= ' ' && c <= '~')) - grub_putchar (c, 255); - else - grub_putchar ('?', 255); -#endif if (quit_print) break; } @@ -1558,1309 +781,783 @@ static struct builtin builtin_cat = "--replace replaces STRING with REPLACE in FILE." "--number use with --locate,the max number for locate", }; -#ifdef CDROM_INIT -/* cdrom */ -static int -cdrom_func (char *arg, int flags) + +void map_to_svbus (grub_efi_physical_address_t address); +void +map_to_svbus (grub_efi_physical_address_t address) { - errnum = 0; - for (;;) +#if 0 + int i, j; + + //复制映射插槽 + for (i = 0, j = 0; i < DRIVE_MAP_SIZE; i++) { - if (grub_memcmp (arg, "--add-io-ports=", 15) == 0) - { - char *p; - unsigned long long tmp; + if (drive_map_slot_empty (disk_drive_map[i])) //判断驱动器映像插槽是否为空 为空,返回1 + break; - p = arg + 15; - if (! safe_parse_maxint (&p, &tmp)) - return 0; - reg_base_addr_append = tmp; - return 1; - } - else if (grub_memcmp (arg, "--init", 6) == 0) - { - init_atapi(); + //滤除软盘 + if (disk_drive_map[i].from_drive < 0x80) + continue; + //复制映射插槽 + grub_memmove ((char *)((char *)(grub_size_t)address + j*24), (char *)&disk_drive_map[i], 24); + j++; + } +#else + struct grub_disk_data *d; //磁盘数据 + struct drive_map_slot *s = (struct drive_map_slot *)(grub_size_t)address; - if (atapi_dev_count) + for (d = disk_data; d; d = d->next) //从设备结构起始查; 只要设备存在,并且驱动器号不为零; { - printf_debug0("\nFound %d CD-ROM%s. (Note: Further read could fail if the hardware does not\nfully support ATAPI).\n", atapi_dev_count, (atapi_dev_count > 1 ? "s" : "")); - } else { - printf_debug0("\nNo CD-ROMs found. Perhaps the hardware does not fully support ATAPI. If your\nCD-ROM uses unusual I/O ports, please specify them with \"--add-io-ports=P\".\n"); - } - return atapi_dev_count; - } - else if (grub_memcmp (arg, "--stop", 6) == 0) - { - atapi_dev_count = 0; - return 1; - } - else - return ! (errnum = ERR_BAD_ARGUMENT); - arg = skip_to (0, arg); + if (d->sector_count && d->drive >= 0x80) //如果是映射驱动器, 不是软盘 + { + s->from_drive = d->drive; + s->to_drive = d->to_drive; + s->max_head = 0xfe; //避免旧svbus蓝屏。支持碎片的新版本不需要 + s->fragment = d->fragment; + if (d->from_log2_sector == 0xb) + s->from_cdrom = 1; + s->to_sector = 0x3f; //避免旧svbus蓝屏。支持碎片的新版本不需要。 + s->start_sector = d->start_sector; + s->sector_count = d->sector_count; + s++; + } } - - return 1; -} - -static struct builtin builtin_cdrom = -{ - "cdrom", - cdrom_func, - BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, - "cdrom --add-io-ports=P | --init | --stop", - "Initialise/stop atapi cdroms or set additional I/O ports for a possible atapi cdrom device." - " The high word of P specifies the base register of the control block registers, and" - " the low word of P specifies the base register of the command block registers." -}; #endif - -/* chainloader */ -static int -chainloader_func (char *arg, int flags) -{ - char *p; - int force = 0; - char *filename; + //复制碎片插槽 +// grub_memmove ((char *)((char *)(grub_size_t)address + 0x148), (char *)&disk_fragment_map, FRAGMENT_MAP_SLOT_SIZE); + grub_memmove ((char *)((char *)(grub_size_t)address + 0x148), (char *)disk_fragment_map, FRAGMENT_MAP_SLOT_SIZE); +} - int is_pcdos = 0; - int is_msdos = 0; - int is_drmk = 0; - int is_romdos = 0; - int is_drdos = 0; - - chainloader_load_segment_orig = chainloader_load_segment; - chainloader_load_offset_orig = chainloader_load_offset; - chainloader_load_length_orig = chainloader_load_length; - chainloader_skip_length_orig = chainloader_skip_length; - chainloader_boot_CS_orig = chainloader_boot_CS; - chainloader_boot_IP_orig = chainloader_boot_IP; - chainloader_ebx_orig = chainloader_ebx; - chainloader_ebx_set_orig = chainloader_ebx_set; - chainloader_edx_orig = chainloader_edx; - chainloader_edx_set_orig = chainloader_edx_set; - chainloader_bx_orig = chainloader_bx; - chainloader_bx_set_orig = chainloader_bx_set; - chainloader_cx_orig = chainloader_cx; - chainloader_cx_set_orig = chainloader_cx_set; - chainloader_disable_A20_orig = chainloader_disable_A20; - is_sdi_orig = is_sdi; - is_raw_orig = is_raw; - is_isolinux_orig = is_isolinux; - is_grldr_orig = is_grldr; - is_io_orig = is_io; - kernel_type_orig = kernel_type; - grub_memmove ((char *)chainloader_file_orig, (char *)chainloader_file, sizeof(chainloader_file)); - - chainloader_load_segment = -1;//0x0000; - chainloader_load_offset = -1;//0x7c00; - chainloader_load_length = -1;//0x200; - chainloader_skip_length = 0; - chainloader_boot_CS = -1;//0x0000; - chainloader_boot_IP = -1;//0x7c00; - chainloader_ebx = 0; - chainloader_ebx_set = 0; - chainloader_edx = 0; - chainloader_edx_set = 0; - chainloader_bx = 0; - chainloader_bx_set = 0; - chainloader_cx = 0; - chainloader_cx_set = 0; - chainloader_disable_A20 = 0; - is_sdi = is_raw = 0; - is_isolinux = 0; - is_grldr = 0; - is_io = 0; - kernel_type = KERNEL_TYPE_CHAINLOADER; +//使用于get_efi_device_boot_path,find_specified_file,chainloader_func,command_func,uuid_func +static char chainloader_file[256]; - errnum = 0; - for (;;) +int find_specified_file (int drive, int partition, char* file); +int +find_specified_file (int drive, int partition, char* file) +{ + int val; + int tem_drive = current_drive; + int tem_partition = current_partition; + + if (drive >= 0xa0) //光盘 + sprintf (chainloader_file, "(%d)%s\0", drive, file); + else if (drive >= 0x80) //硬盘 + sprintf (chainloader_file, "(hd%d,%d)%s\0", drive & 0x7f, partition >> 16, file); + else //软盘 + sprintf (chainloader_file, "(%d)%s\0", drive, file); + putchar_hooked = (unsigned char*)1; //不打印ls_func信息 + val = ls_func (chainloader_file, 1); + putchar_hooked = 0; + current_partition = tem_partition; + current_drive = tem_drive; + + return val; +} + +int get_efi_device_boot_path (int drive, int flags); +int +get_efi_device_boot_path (int drive, int flags) //获得硬盘/光盘启动分区(入口) +{ + struct grub_part_data *p; +// char tmp[512]; + char *tmp; + char *cache = 0; + int self_locking = 0; + int k = 0; + part_size = 0; + int v_mbr, v_bpb, i; + static grub_efi_physical_address_t address; + grub_efi_status_t status; + grub_efi_boot_services_t *b = grub_efi_system_table->boot_services; + + cache = grub_zalloc (0x800); //分配缓存 + if (!cache) + return 0; + + if (drive >= 0x80 && drive <= 0x8f) //硬盘 { - if (grub_memcmp (arg, "--force", 7) == 0) - { - force = 1; - } - else if (grub_memcmp (arg, "--pcdos", 7) == 0) - { - is_pcdos = 1; - } - else if (grub_memcmp (arg, "--msdos", 7) == 0) - { - is_msdos = 1; - } - else if (grub_memcmp (arg, "--load-segment=", 15) == 0) - { - unsigned long long ull; - p = arg + 15; - if (! safe_parse_maxint (&p, &ull)) - goto failure; - if (ull >= 0xA000) - { - errnum = ERR_INVALID_LOAD_SEGMENT; - goto failure; - } - chainloader_load_segment = ull; - } - else if (grub_memcmp (arg, "--load-offset=", 14) == 0) - { - unsigned long long ull; - p = arg + 14; - if (! safe_parse_maxint (&p, &ull)) - goto failure; - if (ull > 0xF800) - { - errnum = ERR_INVALID_LOAD_OFFSET; - goto failure; - } - chainloader_load_offset = ull; - } - else if (grub_memcmp (arg, "--load-length=", 14) == 0) - { - unsigned long long ull; - p = arg + 14; - if (! safe_parse_maxint (&p, &ull)) - goto failure; - if (ull < 512 || ull > 0xA0000) - { - errnum = ERR_INVALID_LOAD_LENGTH; - goto failure; - } - chainloader_load_length = ull; - } - else if (grub_memcmp (arg, "--skip-length=", 14) == 0) - { - unsigned long long ull; - p = arg + 14; - if (! safe_parse_maxint (&p, &ull)) - goto failure; - //if (chainloader_skip_length < 0) - //{ - // errnum = ERR_INVALID_SKIP_LENGTH; - // goto failure; - //} - chainloader_skip_length = ull; - } - else if (grub_memcmp (arg, "--boot-cs=", 10) == 0) - { - unsigned long long ull; - p = arg + 10; - if (! safe_parse_maxint (&p, &ull)) - goto failure; - if (ull > 0xffff) - { - errnum = ERR_INVALID_BOOT_CS; - goto failure; - } - chainloader_boot_CS = ull; - } - else if (grub_memcmp (arg, "--boot-ip=", 10) == 0) - { - unsigned long long ull; - p = arg + 10; - if (! safe_parse_maxint (&p, &ull)) - goto failure; - if (ull > 0xffff) - { - errnum = ERR_INVALID_BOOT_IP; - goto failure; - } - chainloader_boot_IP = ull; - } - else if (grub_memcmp (arg, "--ebx=", 6) == 0) - { - unsigned long long ull; - p = arg + 6; - if (! safe_parse_maxint (&p, &ull)) - goto failure; - chainloader_ebx = ull; - chainloader_ebx_set = 1; - } - else if (grub_memcmp (arg, "--edx=", 6) == 0) - { - unsigned long long ull; - p = arg + 6; - if (! safe_parse_maxint (&p, &ull)) - goto failure; - chainloader_edx = ull; - chainloader_edx_set = 1; - } - else if (grub_memcmp (arg, "--sdi", 5) == 0) - { - is_sdi = 1; - } - else if (grub_memcmp (arg, "--raw", 5) == 0) - { - is_raw = 1; - } - else if (grub_memcmp (arg, "--disable-a20", 13) == 0) + for (p = partition_info; p; p = p->next) + { + if (p->drive != drive) + continue; + + if (p->partition_type != 0xee && !self_locking) //如果是MBR分区类型, 首先启动活动分区 + { + struct grub_part_data *p_back = p; + self_locking = 1; + + for (; p && p->drive == drive; p = p->next) //查找活动分区 { - chainloader_disable_A20 = 1; + if (p->partition_activity_flag == 0x80) + if (find_specified_file(drive, p->partition, EFI_REMOVABLE_MEDIA_FILE_NAME) == 1) + goto complete; } - else - break; - arg = skip_to (0, arg); + p = p_back; + } + + if (find_specified_file(drive, p->partition, EFI_REMOVABLE_MEDIA_FILE_NAME) == 1) //搜索文件 bootx64.efi + goto complete; } - if (grub_strlen(saved_dir) + grub_strlen(arg) + 20 >= sizeof(chainloader_file)) + grub_free (cache); + printf_warning("bootx64.efi not found\n"); + return 0; + +complete: + part_data = p; + part_addr = p->partition_start; + part_size = p->partition_size; + grub_free (cache); + return 1; + } + else //光盘 + { + cdrom_volume_descriptor_t *vol = (cdrom_volume_descriptor_t *)cache; + eltorito_catalog0_t *catalog = NULL; + tmp = grub_malloc (512); + + if (get_diskinfo (drive, &tmp_geom, 0)) //获得当前驱动器的磁盘信息 { - errnum = ERR_WONT_FIT; - goto failure; + errnum = ERR_NO_DISK; + goto fail_free_cache; + } + if (flags) + { + if (!map_pd) + if (!grub_open (chainloader_file_orig)) + goto fail_free_cache; + } + else + { + grub_sprintf (chainloader_file, "(0x%X)+0x%lX\0", drive, (unsigned long long)tmp_geom.total_sectors); + if (! grub_open (chainloader_file)) + goto fail_free_cache; } - set_full_path(chainloader_file,arg,sizeof(chainloader_file)); - chainloader_file[255]=0; + filepos = 17 * 0x800; + grub_read ((unsigned long long)(grub_size_t) vol, 0x800, 0xedde0d90); //读引导描述符扇区(17,规定值,不变),0x800字节 + if (vol->unknown.type != CDVOL_TYPE_STANDARD || //启动记录卷,类型 CDVOL_TYPE_STANDARD=0 + grub_memcmp ((const char *)vol->boot_record_volume.system_id, (const char *)CDVOL_ELTORITO_ID, //启动记录卷,系统id CDVOL_ELTORITO_ID="EL TORITO SPECIFICATION" + sizeof (CDVOL_ELTORITO_ID) - 1) != 0) + goto fail_close_free_cache; - errnum = ERR_NONE; - - if ((is_sdi) || (is_raw)) - return 1; + catalog = (eltorito_catalog0_t *) cache; + filepos = (grub_size_t)(*((grub_efi_uint32_t*) vol->boot_record_volume.elt_catalog)) * 0x800; //启动目录文件所在扇区*0x800 + grub_read ((unsigned long long)(grub_size_t) catalog, 0x800, 0xedde0d90); //读启动目录文件扇区 + if (catalog[0].indicator1 != ELTORITO_ID_CATALOG) //0x01 + goto fail_close_free_cache; + //查找UEFI启动入口 + for (k = 0; k < 8; k++) + { + if (catalog[k].indicator1 == 0x91 || catalog[k].platform_id == 0xEF || catalog[k].section_entries == 1) + break; + } + if (k >= 8) + k = 0; + if (catalog[k].indicator88 != ELTORITO_ID_SECTION_BOOTABLE) + goto fail_close_free_cache; +#define BS ((struct master_and_dos_boot_sector *)tmp) + filepos = (grub_size_t)catalog[k].lba * 0x800; //避免64位被截断 2023-04-24 + grub_read ((unsigned long long)(grub_size_t) tmp, 0x200, 0xedde0d90); //读启动映像mbr + v_mbr = 1; + v_bpb = 1; + putchar_hooked = (unsigned char*)1; //不在屏幕显示信息 + v_mbr = probe_mbr (BS, 0, 1, 0); + v_bpb = probe_bpb(BS); + putchar_hooked = 0; + + if (BS->boot_signature != 0xAA55 //没有磁盘签名 + || (v_mbr && v_bpb)) //即无分区表,又无BPB表 + goto fail_close_free_cache; + if (!v_mbr || v_mbr == 4) //如果有分区表(排除起始扇区为零) + { + for (i = 0; i < 4; i++) // + { + if (BS->P[i].total_sectors) + { + cd_Image_part_start = BS->P[i].start_lba; + cd_Image_disk_size = BS->P[i].start_lba + BS->P[i].total_sectors; + break; + } + } + } + else if (!v_bpb) //如果有BPB表 + { + if (BS->total_sectors_short) + cd_Image_disk_size = BS->total_sectors_short; //FAT12/16 总扇区数 + else + cd_Image_disk_size = BS->total_sectors_long; //FAT32 总扇区数 + cd_Image_part_start = 0; + } -// if (debug > 0) -// printf ("Debug: chainloader_func: set_device(%s) ...", arg); + if (flags) + { + grub_efi_uintn_t pages; + pages = (cd_Image_disk_size + 7) >> 3; + status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES, + GRUB_EFI_BOOT_SERVICES_DATA, //启动服务数据 4 + pages, &address); //调用(分配页面,分配类型->任意页面,存储类型->运行时服务数据(6),分配页,地址) + if (status != GRUB_EFI_SUCCESS) //如果失败 + { + printf_errinfo ("out of map memory: %d\n",(int)status); + goto fail_close_free_cache; + } - /* Get the drive number. */ - filename = set_device (arg); + filepos = (grub_size_t)catalog[k].lba * 0x800; //避免64位被截断 2023-04-24 + grub_read (address, (unsigned long long)cd_Image_disk_size << 9 , 0xedde0d90); + grub_close (); +// grub_sprintf (chainloader_file, "(md)0x%X+0x%X (0x%x)\0", (grub_size_t)((address >> 9) + cd_Image_part_start), cd_Image_disk_size - cd_Image_part_start, 0x60 + cd_map_count); +// map_func (chainloader_file, 1); +// efi_call_2 (b->free_pages, address, pages); + } +#undef BS + cd_boot_entry = k; + cd_boot_start = catalog[k].lba; //19*800=c800 -// if (debug > 0) -// /* wipe out debug message. */ -// printf ("\r \r"); + if (!cd_Image_disk_size) + cd_boot_size = catalog[k].sector_count; //1*200=200 + else + { + if (!v_mbr && v_bpb && catalog[k].media_type == 4) //启动扇区是硬盘格式 + cd_boot_size = (cd_Image_disk_size + 3) >> 2; + else + cd_boot_size = cd_Image_disk_size; + } + + if (v_mbr && v_mbr != 4) + cd_Image_disk_size = 0; //没有分区表,则清除 + grub_free (cache); + for (p = partition_info; p && flags; p = p->next) + { + if (p->drive == drive) + { + p->boot_start = cd_boot_start; + p->boot_size = cd_boot_size; + p->boot_entry = k; +// p->partition_start = cd_Image_part_start; + p->partition_start = (address >> 9) + cd_Image_part_start; +// p->partition_size = cd_Image_disk_size; + p->partition_size = cd_Image_disk_size - cd_Image_part_start; + *(unsigned int *)(grub_size_t)(address + (cd_Image_part_start << 9) + 0x1c) = 0; + } + } - if (errnum) { - /* No device specified. Default to the root device. */ - current_drive = saved_drive; - //current_partition = saved_partition; - filename = arg; - errnum = 0; - } + grub_free (tmp); + return 1; - if (filename == 0) - filename = arg; - - if (! chainloader_edx_set) - { - #ifdef FSYS_FB - if (current_drive == 0xFFFF || current_drive == ram_drive) - { - chainloader_edx = (saved_drive == FB_DRIVE ? (unsigned char)(fb_status >> 8) : - saved_drive | ((saved_partition >> 8) & 0xFF00)); - chainloader_edx_set=1; - } - else if (current_drive == FB_DRIVE) - { - chainloader_edx = (unsigned char)(fb_status >> 8); - chainloader_edx_set=1; - } - #else - if (current_drive == 0xFFFF || current_drive == ram_drive) - { - chainloader_edx = saved_drive | ((saved_partition >> 8) & 0xFF00); - chainloader_edx_set=1; - } - #endif - } - +fail_close_free_cache: + grub_close (); - /* check bootable cdrom */ - if (*filename == 0 || *filename == ' ' || *filename == '\t') - { - //check_bootable_cdrom (current_drive); - unsigned long i; - unsigned long tmp; - unsigned short tmp1; - unsigned short tmp2; -// struct geometry tmp_geom; - - tmp = current_drive; - /* check bootable type of drive (tmp) */ +fail_free_cache: + grub_free (cache); + grub_free (tmp); + printf_warning("bootx64.efi not found\n"); + return 0; + } +} - /* Get the geometry. This ensures that the drive is present. */ - if (get_diskinfo (tmp, &tmp_geom, 0)) - { - errnum = ERR_NO_DISK; - goto failure; - } +#if 1 //2023-04-30 +static unsigned char *initrdefi_mem; +static void *linuxefi_mem; +static unsigned long long linuxefi_size; +static unsigned int linuxefi_handover_offset; +struct linux_kernel_params *linuxefi_params; +static char *linuxefi_cmdline; +#endif +static char *initrdefi_arg = NULL; +static unsigned long long initrdefi_size; - /* open the drive */ - - grub_sprintf ((char *)SCRATCHADDR, "(0x%X)+0x%lX", tmp, (unsigned long long)tmp_geom.total_sectors); +static grub_efi_handle_t initrdefi_lf2_handle = NULL; +#if 1 //2023-04-30 +static initrd_media_device_path_t initrdefi_lf2_dp = +{ + { + { + GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, + GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE, + sizeof(grub_efi_vendor_media_device_path_t), + }, + LINUX_EFI_INITRD_MEDIA_GUID + }, + { + GRUB_EFI_END_DEVICE_PATH_TYPE, + GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, + sizeof(grub_efi_device_path_t) + } +}; - if (! grub_open ((char *)SCRATCHADDR)) - goto failure; - - /****************************************/ - /* read the EL Torito Volume Descriptor */ - /****************************************/ +static grub_efi_status_t EFIAPI +initrdefi_lf2_func(grub_efi_load_file2_t *this, + grub_efi_device_path_t *device_path, + grub_efi_boolean_t boot_policy, + grub_efi_uintn_t *buffer_size, + void *buffer); - //filemax = 0x12 * 0x800; - filepos = 0x11 * 0x800; +static grub_efi_load_file2_t initrdefi_lf2 = { initrdefi_lf2_func }; - if (grub_read ((unsigned long long)SCRATCHADDR, 512, 0xedde0d90) != 512) - goto failure_exec_format; +static grub_efi_guid_t initrdefi_lf2_guid = GRUB_EFI_LOAD_FILE2_PROTOCOL_GUID; +static grub_efi_guid_t initrdefi_lf2_dp_guid = GRUB_EFI_DEVICE_PATH_GUID; +#endif - /* check the EL Torito Volume Descriptor */ +#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) +#if 1 //2023-04-30 +typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *); - if (memcmp ((char *)SCRATCHADDR, "\0CD001\1EL TORITO SPECIFICATION\0", 31)) - goto failure_exec_format; - - /* get absolut start sector number for boot catalog */ - tmp = *(unsigned long *)((char *)SCRATCHADDR + 0x47); +static void linuxefi_boot (void *kernel_addr, grub_off_t offset, void *kernel_params); +static void +linuxefi_boot (void *kernel_addr, grub_off_t offset, + void *kernel_params) +{ + grub_efi_loaded_image_t *loaded_image = NULL; + handover_func hf; + /* + * Since the EFI loader is not calling the LoadImage() and StartImage() + * services for loading the kernel and booting respectively, it has to + * set the Loaded Image base address. + */ + loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle); + if (loaded_image) + loaded_image->image_base = kernel_addr; + hf = (handover_func)((char *)kernel_addr + offset); + hf (grub_efi_image_handle, grub_efi_system_table, kernel_params); +} +#endif - /********************************************/ - /* read the first 512 bytes of Boot Catalog */ - /********************************************/ +static void +cpio_set_field (char *field, unsigned int value) +{ + char buf[9]; + sprintf (buf, "%08x", value); + memcpy (field, buf, 8); +} - //filemax = (tmp + 1) * 0x800; - filepos = tmp * 0x800; - - if (grub_read ((unsigned long long)SCRATCHADDR, 512, 0xedde0d90) != 512) - goto failure_exec_format; +static grub_efi_status_t EFIAPI +initrdefi_lf2_func(grub_efi_load_file2_t *this, + grub_efi_device_path_t *device_path, + grub_efi_boolean_t boot_policy, + grub_efi_uintn_t *buffer_size, + void *buffer) +{ + char *name = initrdefi_arg; + errnum = 0; + grub_size_t size = 0; - /*******************************/ - /* check the Validation Entry */ - /*******************************/ + if (this != &initrdefi_lf2 || buffer_size == NULL) + return GRUB_EFI_INVALID_PARAMETER; - tmp1 = 0; - for (i = 0; i < 16; i++) - { - tmp = *(((unsigned short *)(char *)SCRATCHADDR) + i); - tmp1 += tmp; - if ((i == 0 && tmp != 1) || (i == 15 && tmp != 0xAA55)) - break; - } + if (device_path->type != GRUB_EFI_END_DEVICE_PATH_TYPE || + device_path->subtype != GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE) + return GRUB_EFI_NOT_FOUND; - if (tmp1 || i < 16) - goto failure_exec_format; + if (boot_policy) + return GRUB_EFI_UNSUPPORTED; - /* Boot Record Volume Descriptor format - * - * Offset Type Description - * ------ ---- ---------------------------------------------- - * 0 Byte Boot Record Indicator, must be 0 - * - * 1-5 Characters ISO-9660 Identifier, must be "CD001" - * - * 6 Byte Version of this descriptor, must be 1 - * - * 7-26 Characters Boot System Identifier, must be - * "EL TORITO SPECIFICATION" padded with 0's. - * - * 27-46 Characters Unused, must be 0. - * - * 47-4A Dword LBA of the first sector of Boot Catalog. - * - * 4B-7FF Characters Unused, must be 0. - * - */ - - /* Validation Entry format - * - * Offset Type Description - * ------ ---- ---------------------------------------------- - * 0 Byte Header ID, must be 01 - * - * 1 Byte Platform ID - * 0 = 80x86 - * 1 = Power PC - * 2 = Mac - * - * 2-3 Word Reserved, must be 0 - * - * 4-1B Characters ID string. This is intended to identify the - * manufacturer/developer of the CD-ROM. - * - * 1C-1D Word Checksum Word. This sum of all the words in - * this record should be 0. - * - * 1E Byte Key byte, must be 55. This value is included - * in the checksum. - * - * 1F Byte Key byte, must be AA. This value is included - * in the checksum. - * - */ - - /* Initial/Default Entry format - * - * Offset Type Description - * ------ ---- ---------------------------------------------- - * 0 Byte Boot Indicator. 88=Bootable, 00=Not Bootable - * - * 1 Byte Boot media type. - * 0 = No Emulation - * 1 = 1.2 meg diskette - * 2 = 1.44 meg diskette - * 3 = 2.88 meg diskette - * 4 = Hard Disk(drive 80) - * - * 2 Word Load Segment. 0 for 7C0 - * - * 4 Byte System Type. - * - * 5 Byte Unused, must be 0. - * - * 6 Word Sector Count. This is the number of virtual/ - * emulated sectors the system will store at Load - * Segment during the initial boot procedure. - * - * 8 DWord Load RBA. This is the start address of the - * virtual disk. CD's use Relative/Logical block - * addressing. - * - * C Bytes Unused, must be 0's. - * - */ - - /* Specification Packet format - * - * Offset Type Description - * ------ ---- ---------------------------------------------- - * 0 Byte Packet Size, currently 13 - * - * 1 Byte Boot media type. This specifies what media the - * boot image is intended to emulate in bits 0-3. - * Bits 6-7 are specific to the type of system. - * - * Bits 0-3 count as follows: - * - * 0: No Emulation - * 1: 1.2 meg diskette - * 2: 1.44 meg diskette - * 3: 2.88 meg diskette - * 4: Hard Disk (drive C) - * - * 5-F: Reserved, invalid at this time - * - * bits 4-5 - Reserved, must be 0 - * bit 6 - Image contains an ATAPI driver, - * bytes 8 & 9 refer to IDE interface - * bit 7 - Image contains SCSI drivers, - * bytes 8 & 9 refer to SCSI interface - * - * 2 Byte Drive Number. This is the drive number on - * which emulation is being initiated or - * terminated. This must be 0 for a floppy image, - * 80 for a bootable hard disk, and 81-FF for a - * "non-bootable" or "no emulation" drive. - * - * 3 Byte Controller Index. This specifies the controller - * number of the specified CD drive. - * - * 4-7 Dword Logical Block Address for the disk image to be - * emulated. - * - * 8-9 Word Device Specification. For SCSI controllers byte - * 8 is the LUN and PUN of the CD Drive, byte 9 is - * the Bus number. For IDE controllers the low - * order bit of byte 8 specifies master/slave - * device, 0 = master. - * - * A-B Word User Buffer Segment. If this field is non-zero - * it specifies the segment of a user supplied 3k - * buffer for caching CD reads. This buffer will - * begin at Segment:0. - * - * C-D Word Load Segment. This is the load address for the - * initial boot image. If this value is 0, the - * system will use the traditional segment of 7C0. - * If this value is non-zero the system will use - * the specified address. This field is only valid - * for function 4C. - * - * E-F Word Sector Count. This is the number of virtual - * sectors the system will store at Load Segment - * during the initial boot procedure. This field - * is only valid for function 4C. - * - * 10 Byte Bits 0-7 of the cylinder count. This should - * match the value returned in CH when INT 13 - * function 08 is invoked. - * - * 11 Byte This is the value returned in the CL register - * when INT 13 function 08 is invoked. Bits 0-5 - * are the sector count. Bits 6 and 7 are the high - * order 2 bits of the cylinder count. - * - * 12 Byte This is the head count, it should match the - * value in DH when INT 13 Function 08 is invoked. - * - */ - - /***********************************/ - /* check the Initial/Default Entry */ - /***********************************/ - - /* XXX: assume Initial/Default Entry is always at offset 0x20 */ - - tmp = *(unsigned char *)(SCRATCHADDR + 0x20); /* Boot Indicator. 88=Bootable, 00=Not Bootable */ - - if (tmp != 0x88) - goto failure_exec_format; + if (buffer == NULL || *buffer_size < initrdefi_size) + { + *buffer_size = (grub_efi_uintn_t) initrdefi_size; + return GRUB_EFI_BUFFER_TOO_SMALL; + } - tmp = *((unsigned char *)SCRATCHADDR + 0x25); /* Unused byte, must be 0. */ + printf ("INITRD: %s\n", initrdefi_arg); - if (tmp) - goto failure_exec_format; - - tmp2 = *((unsigned short *)((unsigned char *)SCRATCHADDR + 0x22)); /* Load Segment */ + while (*name && *name != ' ' && *name != '\t') + { + unsigned int c_namesize = 0; + char *c_name = NULL; + grub_size_t pad_size = 0; + if (*name == '@') // CPIO + { + c_name = &name[1]; + name = skip_to (SKIP_WITH_TERMINATE | 1, name); + c_namesize = name - c_name; // including NUL + } + grub_open (name); + if (errnum) + { + printf_errinfo ("Failed to open %s\n", name); + grub_close (); + return GRUB_EFI_LOAD_ERROR; + } + if (c_name) // CPIO + { + struct cpio_header *cpio = (struct cpio_header *)((char *)buffer + size); + char *c_name_ptr = (char *) (cpio + 1); + grub_memset (cpio, '0', sizeof (struct cpio_header)); + grub_memcpy (cpio->c_magic, CPIO_MAGIC, sizeof (cpio->c_magic)); + cpio_set_field (cpio->c_mode, 0100644); + cpio_set_field (cpio->c_nlink, 1); + cpio_set_field (cpio->c_filesize, filemax); + cpio_set_field (cpio->c_namesize, c_namesize); + memcpy (c_name_ptr, c_name, c_namesize); + size += cpio_image_align (sizeof(struct cpio_header) + c_namesize); + } + if (grub_read ((unsigned long long)(grub_size_t)buffer + size, + filemax, 0xedde0d90) != filemax) + { + printf_errinfo ("premature end of file %s", c_name); + grub_close (); + return GRUB_EFI_LOAD_ERROR; + } + size += filemax; + pad_size = ALIGN_UP (filemax, 4096) - filemax; + grub_memset ((char *)buffer + size, 0, pad_size); + size += pad_size; + grub_close (); + name = skip_to (0, name); + } + return GRUB_EFI_SUCCESS; +} - printf_debug0 ("\nLoad segment: 0x%X\t", (unsigned long)tmp2); +/* boot */ +int kernel_load_type; +#define KERTNEL_LOAD_HANDOVER 1 +#define KERTNEL_LOAD_LOADFILE2 2 +static int boot_func (char *arg, int flags); +static int +boot_func (char *arg, int flags) +{ + grub_efi_boot_services_t *b; + grub_efi_status_t status; + b = grub_efi_system_table->boot_services; //引导服务 - if (tmp2 == 0) - tmp2 = 0x7C0; + //sunsea报告:在图形模式下,进入没有安装好显卡驱动的PE或者新windows桌面后,会强制锁定在当前分辨率,无法修改。 + graphicsmode_func ("3", flags); //采用文本模式显示 + + if (kernel_type == KERNEL_TYPE_LINUX) + { + if (kernel_load_type == KERTNEL_LOAD_HANDOVER) + { + int offset = 0; +#if !defined(__i386__) + offset = 512; +#endif + __asm__ volatile ("cli"); + + linuxefi_boot (linuxefi_mem, linuxefi_handover_offset + offset, linuxefi_params); + /* should not return */ + if (initrdefi_mem) + efi_call_2 (b->free_pages, (grub_size_t)initrdefi_mem, + BYTES_TO_PAGES(linuxefi_params->ramdisk_size)); + if (linuxefi_cmdline) + efi_call_2 (b->free_pages, (grub_size_t)linuxefi_cmdline, + BYTES_TO_PAGES(linuxefi_params->cmdline_size + 1)); + if (linuxefi_mem) + efi_call_2 (b->free_pages, (grub_size_t)linuxefi_mem, BYTES_TO_PAGES(linuxefi_size)); + if (linuxefi_params) + efi_call_2 (b->free_pages, (grub_size_t)linuxefi_params, BYTES_TO_PAGES(16384)); + } + else if (!initrdefi_lf2_handle && initrdefi_arg) + { + status = efi_call_6(b->install_multiple_protocol_interfaces, + &initrdefi_lf2_handle, + &initrdefi_lf2_guid, + &initrdefi_lf2, + &initrdefi_lf2_dp_guid, + &initrdefi_lf2_dp, + NULL); + if (status != GRUB_EFI_SUCCESS) + printf("ERROR: Failed to install lf2 protocol.\n"); + } + } -// *(unsigned short *)&(chainloader_file[0x0C]) = tmp2; /* 0C-0D: load segment */ - - tmp = *((unsigned char *)SCRATCHADDR + 0x24); /* System Type */ + map_to_svbus(grub4dos_self_address); //为svbus复制插槽 + //不能释放,否则无法启动 + //grub_efi_fini (); + if (!image_handle) + return 0; + printf_debug ("StartImage: %x\n", image_handle); //开始映射 + //此函数要读磁盘 + status = efi_call_3 (b->start_image, image_handle, 0, NULL); //启动映像 + printf_debug ("StartImage returned 0x%lx\n", (grub_size_t) status); //开始映射返回 + status = efi_call_1 (b->unload_image, image_handle); //卸载映射 + cmain (); //如果只恢复原图形模式,则背景图和中文字符消失。 + return 1; +} - printf_debug0 ("System Type: 0x%X\t", (unsigned long)tmp); - - i = *((unsigned short *)((unsigned char *)SCRATCHADDR + 0x26)); /* Sector Count */ +static struct builtin builtin_boot = +{ + "boot", + boot_func, + BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST | BUILTIN_BOOTING, + "boot [-1]", + "Boot the OS/chain-loader which has been loaded." + "with option \"-1\" will boot to local via INT 18.", +}; +#if 0 +static grub_efi_status_t (EFIAPI *orig_open_protocol) + (grub_efi_handle_t handle, + grub_efi_guid_t *protocol, + void **interface, + grub_efi_handle_t agentHandle, + grub_efi_handle_t controllerHandle, + grub_efi_uint32_t attributes) = NULL; +grub_efi_guid_t efi_graphics_output_protocol_guid = GRUB_EFI_GOP_GUID; +/** + * Intercept OpenProtocol() 拦截OpenProtocol + * + * @v handle EFI handle 句柄 + * @v protocol Protocol GUID 协议GUID + * @v interface Opened interface 开放式接口 + * @v agent_handle Agent handle 代理句柄 + * @v controller_handle Controller handle 控制器句柄 + * @v attributes Attributes 属性 + * @ret efirc EFI status code 返回 状态代码 + */ +static grub_efi_status_t EFIAPI efi_open_protocol_wrapper (grub_efi_handle_t handle, grub_efi_guid_t *protocol, + VOID **interface, grub_efi_handle_t agent_handle, + grub_efi_handle_t controller_handle, grub_efi_uint32_t attributes); +static grub_efi_status_t EFIAPI +efi_open_protocol_wrapper (grub_efi_handle_t handle, grub_efi_guid_t *protocol, + VOID **interface, grub_efi_handle_t agent_handle, + grub_efi_handle_t controller_handle, grub_efi_uint32_t attributes) //打开协议包装器 +{ + static unsigned int count; + grub_efi_status_t status; + /* Open the protocol */ + + if ((status = orig_open_protocol (handle, protocol, interface, + agent_handle, controller_handle, + attributes)) != 0) + { + return status; + } + /* Block first attempt by bootmgfw.efi to open 阻止bootmgfw.efi首次尝试打开EFI_GRAPHICS_OUTPUT_PROTOCOL. + * EFI_GRAPHICS_OUTPUT_PROTOCOL. This forces error messages + * to be displayed in text mode (thereby avoiding the totally 这将强制以文本模式显示错误消息(从而避免在缺少字体时出现完全空白的错误屏幕) + * blank error screen if the fonts are missing). We must + * allow subsequent attempts to succeed, otherwise the OS will 我们必须允许随后的努力取得成功,否则操作系统将无法启动。 + * fail to boot. + */ + if ((memcmp ((const char *)protocol, (const char *)&efi_graphics_output_protocol_guid, + sizeof (*protocol)) == 0) && (count++ == 0) && + (cursor_state & 1)) + { + return GRUB_EFI_INVALID_PARAMETER; //参数无效 + } + return 0; +} +#endif +extern grub_efi_char16_t *cmdline; +extern grub_ssize_t cmdline_len; +extern grub_efi_handle_t dev_handle; - printf_debug0 ("Sector Count: 0x%X\n", (unsigned long)i); +/* chainloader */ +static int chainloader_func (char *arg, int flags); +static int +chainloader_func (char *arg, int flags) +{ + grub_efi_boot_services_t *b; + char *filename; + grub_efi_status_t status; + void *boot_image = 0; + b = grub_efi_system_table->boot_services; //引导服务 + static grub_efi_physical_address_t address; + static grub_efi_uintn_t pages; + grub_efi_handle_t *handle=0, *handles; + struct grub_disk_data *d = 0; + grub_efi_device_path_t *dp, *tmp_dp; + grub_efi_uintn_t count; + static grub_efi_guid_t block_io_guid = GRUB_EFI_BLOCK_IO_GUID; + image_handle = 0; + static grub_efi_handle_t temp; + + grub_memset(chainloader_file, 0, 256); + set_full_path(chainloader_file,arg,sizeof(chainloader_file)); //设置完整路径(补齐驱动器号,分区号) /efi/boot/bootx64.efi -> (hd0,0)/efi/boot/bootx64.efi + errnum = ERR_NONE; + filename = set_device (chainloader_file); //设置当前驱动器=输入驱动器号, 当前分区=输入分区号, 其余作为文件名 /efi/boot/bootx64.efi + //没有设备指定.默认到根设备 + if (errnum) + { + current_drive = saved_drive; + filename = arg; + errnum = 0; + } + + //兼容旧版本 (hd0)+1 + if (*filename == '+') + *filename = 0; -// *(unsigned short *)&(chainloader_file[0x0E]) = i; /* 0E-0F: sector count in 512-byte sectors */ - - tmp = *((unsigned long *)((unsigned char *)SCRATCHADDR + 0x28)); /* Load RBA */ + //虚拟盘类型 + if (! *filename) + { + part_data = 0; + if (current_partition == 0xFFFFFF) //如果没有指定启动分区 + part_data = get_boot_partition (current_drive); + else + part_data = get_partition_info (current_drive, current_partition); + if (!part_data) + return (!(errnum = ERR_NO_DISK)); + + printf_debug("0_part-handle=%x\n",part_data->part_handle); + if (!part_data->part_handle) + goto aaa; + dp = grub_efi_get_device_path (part_data->part_handle); + if (debug > 1) + grub_efi_print_device_path(dp); + image_handle = grub_load_image (dp, EFI_REMOVABLE_MEDIA_FILE_NAME, 0); //虚拟磁盘启动 +aaa: + if (!image_handle) + { + d = get_device_by_drive (current_drive,0); + if (!d) + return (!(errnum = ERR_NO_DISK)); - printf_debug0 ("Load RBA: 0x%X\t", (unsigned long)tmp); + printf_debug("1_dev-handle=%x\n",d->device_handle); + dp = grub_efi_get_device_path (d->device_handle); + if (debug > 1) + grub_efi_print_device_path(dp); -// *(unsigned long *)&(chainloader_file[4]) = tmp; /* 04-07: LBA of the image to be emulated */ - - tmp1 = *((unsigned char *)SCRATCHADDR + 0x21); /* Boot media type */ + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &block_io_guid, 0, &count); //定位句柄 返回句柄集及句柄数 + for (handle = handles; count--; handle++) + { + printf_debug("2_handle=%x\n",*handle); + tmp_dp = grub_efi_get_device_path (*handle); //由句柄获得路径 + if (debug > 1) + grub_efi_print_device_path(tmp_dp); + if (!grub_efi_is_child_dp (tmp_dp, dp)) //如果相等,继续 返回: 0/1=不相等或包含/相等 + continue; + image_handle = grub_load_image (tmp_dp, EFI_REMOVABLE_MEDIA_FILE_NAME, 0); //虚拟磁盘启动 + if (image_handle) //如果获得映像句柄, 退出 + break; + } + if (!image_handle) + { + printf_debug("3_dev-handle=%x\n",d->device_handle); + dp = grub_efi_get_device_path (d->device_handle); + if (debug > 1) + grub_efi_print_device_path(dp); + image_handle = grub_load_image (dp, EFI_REMOVABLE_MEDIA_FILE_NAME, 0); //虚拟磁盘启动 + } + } - if (tmp1 > 4) - goto failure_exec_format; + if (!image_handle) + goto failure_exec_format_0; + if (debug > 1) + { + grub_efi_loaded_image_t *image0 = grub_efi_get_loaded_image (image_handle); //通过映像句柄,获得加载映像 + printf_debug ("image=%x image_handle=%x\n",image0,image_handle); + } + kernel_type = KERNEL_TYPE_CHAINLOADER; + return 1; + } - printf_debug0 ("Boot Type: %s\n", - tmp1 == 0 ? "0 = No Emulation" : - tmp1 == 1 ? "1 = 1.2M floppy" : - tmp1 == 2 ? "2 = 1.44M floppy" : - tmp1 == 3 ? "3 = 2.88M floppy" : "Hard Disk"); + //文件类型 + grub_open (arg); + if (errnum) + goto failure_exec_format_0; -// chainloader_file[1] = tmp1; /* 01: boot media type */ -// chainloader_file[2] = ((tmp1 == 0) ? current_drive : (tmp1 == 4) ? 0x80 : 0x00); /* 02: drive number */ + pages = ((filemax + ((1 << 12) - 1)) >> 12); //计算页 + status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES, + GRUB_EFI_LOADER_CODE, + pages, &address); //调用(分配页面,分配类型->任意页面,存储类型->装载程序代码(1),分配页,地址) - if (tmp1 == 0) /* no-emulation mode */ + if (status != GRUB_EFI_SUCCESS) //失败退出 { - /* No emulation mode uses 2048-byte sector size. */ - if (buf_geom.sector_size != 2048) - goto failure_exec_format; - //kernel_type = KERNEL_TYPE_CHAINLOADER; - sprintf (chainloader_file, "(%d)%d+%d", current_drive, tmp, (unsigned long)((i + 3) / 4)); - chainloader_load_segment = tmp2;//0x0000; - chainloader_load_offset = 0;//0x7c00; - chainloader_load_length = i * 512;//0x200; - chainloader_skip_length = 0; - chainloader_boot_CS = tmp2;//0x0000; - chainloader_boot_IP = 0;//0x7c00; - //chainloader_ebx = 0; - //chainloader_ebx_set = 0; - chainloader_edx = current_drive; - chainloader_edx_set = 1; - //chainloader_disable_A20 = 0; - - /* update lba_cd_boot if there are any maps */ - if (! unset_int13_handler (0)) /* a successful unset */ - { - if (drive_map_slot_empty (bios_drive_map[0])) - if (atapi_dev_count == 0) - { - errnum = ERR_NO_DRIVE_MAPPED; - goto failure_exec_format; - } - lba_cd_boot = tmp; - - set_int13_handler (bios_drive_map); - } - - /* needn't clear disk buffer */ - /* buf_drive = -1; */ - /* buf_track = -1; */ - - return ! (errnum = 0); + printf_errinfo ("Failed to allocate %u pages\n",(unsigned int) pages); + goto failure_exec_format; } - /* floppy or hard drive emulation. LBA=tmp */ - - /*******************************************************/ - /* read the first 512 bytes of the image at 0000:7C00 */ - /*******************************************************/ - - filepos = tmp * 0x800; - - /* we cannot use SCRATCHADDR because map_func and geometry_func may - * use it. So we use 1 sector below 0x2B0000 instead. */ - if (grub_read ((unsigned long long)(HMA_ADDR - 0x200), 512, 0xedde0d90) != 512) + boot_image = (void *) ((grub_addr_t) address); //引导镜像地址 + if (grub_read ((unsigned long long)(grub_size_t)boot_image, filemax, 0xedde0d90) != filemax) + { + printf_errinfo ("premature end of file %s",arg); goto failure_exec_format; + } + char *arg1 = arg; + arg = skip_to(0,arg); //标记=0/1/100/200=跳过"空格,回车,换行,水平制表符"/跳过等号/跳到下一行/使用'0'替换 + if (*arg) //如果有命令行 { - unsigned long heads = 0; - unsigned long sects = 0; - - if (tmp1 == 4) - { - int err; - if ((err = probe_mbr ((struct master_and_dos_boot_sector *)(HMA_ADDR - 0x200), 0, 1, 0))) - { - printf_warning ("Warning! Partition table of HD image is faulty(err=%d).\n", err); - sects = (*(unsigned char *)(HMA_ADDR - 0x200 + 0x1C4)) & 0x3F; - probed_total_sectors = *(unsigned long *)(HMA_ADDR - 0x200 + 0x1CA); - if (sects < 2 || probed_total_sectors < 5) - { - errnum = ERR_BAD_PART_TABLE; - goto failure_exec_format; - } - heads = *(unsigned char *)(HMA_ADDR - 0x200 + 0x1C3); - //if (heads < 255) - heads++; - printf_debug0 ("Use Heads=%d, SectorsPerTrack=%d, TotalSectors=%ld for HD emulation.\n", heads, sects, (unsigned long long)probed_total_sectors); - } - } else { - if (probe_bpb((struct master_and_dos_boot_sector *)(HMA_ADDR - 0x200))) - { - probed_total_sectors = (tmp1 == 1 ? 2400 : tmp1 == 2 ? 2880 : 5760); - } - } - - /* map the image */ - sprintf (chainloader_file, "--read-only --heads=%d --sectors-per-track=%d (%d)%d+%d (%d)", - (unsigned long)heads, - (unsigned long)sects, - (unsigned long)current_drive, - (unsigned long)tmp, - (unsigned long)((probed_total_sectors + 3) / 4), //0x3FFFFFFF, - (unsigned long)((tmp1 == 4) ? 0x80 : 0x00)); + // UTF-8 转为 UCS-2 编码命令行 + grub_size_t len = grub_strlen ((const char*)arg) + 1; +// cmdline = grub_malloc (cmdline_len); //cmdline_len 未赋值,实测为0,产生内存溢出 + cmdline = grub_malloc (len*2); //避免产生内存溢出 2023-04-29 + if (! cmdline) + goto failure_exec_format; +// len = grub_utf8_to_ucs2(cmdline, len, (grub_uint8_t *)arg, len, NULL); //(ucs2地址,ucs2字节数,utf8地址,utf8字节数) + utf8_to_multimode ((void *)cmdline, (unsigned char *)arg, len, 1); + cmdline[len] = 0; + cmdline_len = len * sizeof (grub_efi_char16_t); } - tmp = ( (tmp1 == 4) ? (*(char *)0x475) : ((*(char*)0x410) & 1) ); - - /* file must be closed before calling map_func() */ - grub_close (); - - disable_map_info = 1; - map_func (chainloader_file, flags); - disable_map_info = 0; - - if (errnum) - goto failure; - - /* move the former fd0 or hd0 up. */ - if (tmp) - { - sprintf (chainloader_file, "(%d) (%d)", (unsigned long)((tmp1 == 4) ? 0x80 : 0x00), (unsigned long)((tmp1 == 4) ? (0x80 + tmp) : 0x01)); - - map_func (chainloader_file, flags); - - if (errnum) - { - printf_debug0 ("Failed 'map %s'(error=%d). But you may ignore it and continue to 'boot' the CD.\n", chainloader_file, errnum); - errnum = 0; - } - } - - /* rehook */ - unset_int13_handler (0); - if (drive_map_slot_empty (bios_drive_map[0])) - if (atapi_dev_count == 0) - { - errnum = ERR_NO_DRIVE_MAPPED; - goto failure; - } - set_int13_handler (bios_drive_map); - buf_drive = -1; - buf_track = -1; - - grub_memmove ((char *)0x7C00, (char *)(HMA_ADDR - 0x200), 512); - sprintf (chainloader_file, "(%d)+1", (unsigned long)((tmp1 == 4) ? 0x80 : 0x00)); - - chainloader_load_segment = 0;//tmp2; - chainloader_load_offset = 0x7c00; - chainloader_load_length = 512; - chainloader_skip_length = 0; - chainloader_boot_CS = 0;//tmp2; - chainloader_boot_IP = 0x7c00; - //chainloader_ebx = 0; - chainloader_ebx_set = 0; - chainloader_edx_set = 0; - chainloader_bx_set = 0; - chainloader_cx_set = 0; - //chainloader_disable_A20 = 0; - saved_drive = ((tmp1 == 4) ? 0x80 : 0x00); - chainloader_edx = saved_drive; - saved_partition = ((tmp1 == 4) ? 0x00FFFF : 0xFFFFFF); - return ! (errnum = 0); - - } - - /* Open the file. */ - grub_open (arg); - - if (errnum) - goto failure; - - /* Read the first block. */ + printf_debug("current_drive=%x, current_partition=%x\n",current_drive,current_partition); + if (current_drive == 0x21) //2023-11-24 { - unsigned long len; - len = grub_read ((unsigned long long) SCRATCHADDR, 512, 0xedde0d90); - - if (len != 512) - goto failure_exec_format; + dp = pd_dp; //网起设备路径 + temp = pd_handle; //网起设备句柄 } - - if (chainloader_skip_length > filemax) + else { - errnum = ERR_INVALID_SKIP_LENGTH; - goto failure_exec_format; +// if (current_drive >= 0xa0) //使用光盘启动镜像的句柄和路径 2023-10-14 +// current_partition = 0xffff; + //如果当前设备是(cd-1),使用光盘的路径;如果当前设备是(cd-1,0),使用光盘启动镜像的路径。 2023-10-16 + if (current_partition == 0xFFFFFF) + { + d = get_device_by_drive (current_drive,0); + if (!d || !d->device_handle) + return (!(errnum = ERR_NO_DISK)); + dp = grub_efi_get_device_path (d->device_handle); + temp = d->device_handle; } - - if (*((long *)SCRATCHADDR) == 0x49445324 /* $SDI */) - { - is_sdi = 1; - printf_debug0("SDI signature: %s\n", (char *)(SCRATCHADDR)); - } - else - if ((*(long long *)SCRATCHADDR | 0xFF00LL) == 0x4749464E4F43FFEBLL && filemax > 0x4000) - { - - if (chainloader_load_segment == -1) - chainloader_load_segment = 0x0060; -drdos: - if (chainloader_load_offset == -1) - chainloader_load_offset = 0; - if (chainloader_load_length == -1) - chainloader_load_length = filemax; - if (! chainloader_ebx_set) - { - chainloader_ebx = current_drive | ((current_partition >> 8) & 0xFF00); - chainloader_ebx_set = 1; - } - - grub_close (); - - /* FIXME: Where should the BPB be placed for FreeDOS's KERNEL.SYS? - * In the current implementation it is placed at 0000:7C00 - * but has no effect, since the KERNEL.SYS body will later - * overwrite 0000:7C00 on issuing the `boot' command. - */ - - if (((current_partition >> 8) & 0xFF00) == 0xFF00) /* check if partition number == 0xFF */ - grub_sprintf ((char *)SCRATCHADDR, "(%d)+1", (unsigned long)(unsigned char)current_drive); - else - grub_sprintf ((char *)SCRATCHADDR, "(%d,%d)+1", (unsigned long)(unsigned char)current_drive, (unsigned long)(unsigned char)(current_partition >> 16)); - - if (! grub_open ((char *)SCRATCHADDR)) - goto failure; - - /* Read the boot sector of the partition onto 0000:7C00 */ - if (grub_read ((unsigned long long) SCRATCHADDR, 512, 0xedde0d90) != 512) - goto failure_exec_format; - - /* modify the hidden sectors */ - /* FIXME: Does the boot drive number also need modifying? */ - - if (*((unsigned long *) (SCRATCHADDR + BOOTSEC_BPB_HIDDEN_SECTORS))) - *((unsigned long *) (SCRATCHADDR + BOOTSEC_BPB_HIDDEN_SECTORS)) = (unsigned long)part_start; - - if (is_pcdos||is_msdos) { - /* Set data area location to *0x7BFC, root directory entry address to *0x7BF8, root directory entry size to *0x7BDE */ - if (*((unsigned long *) (SCRATCHADDR + BOOTSEC_BPB_FAT_NAME)) == 0x31544146) { /* FAT1(2|6) */ - *(unsigned long *)0x7BF8 = *((unsigned short *) (SCRATCHADDR + BOOTSEC_BPB_RESERVED_SECTORS)) - + *((unsigned short *) (SCRATCHADDR + BOOTSEC_BPB_SECTORS_PER_FAT)) * 2; // root directory entry address - *(unsigned short *)0x7BDE = *((unsigned short *) (SCRATCHADDR + BOOTSEC_BPB_MAX_ROOT_ENTRIES)) * 32 / *((unsigned short *) (SCRATCHADDR + BOOTSEC_BPB_BYTES_PER_SECTOR)); // root directory entry size - *(unsigned long *)0x7BFC = (unsigned long)part_start - + *(unsigned long *)0x7BF8 - + *(unsigned short *)0x7BDE; - } - else if (*((unsigned long *)(SCRATCHADDR + BOOTSEC_BPB_FAT32_NAME)) == 0x33544146) { /* FAT32 */ - *(unsigned long *)0x7BF8 = *((unsigned short *) (SCRATCHADDR + BOOTSEC_BPB_RESERVED_SECTORS)) - + *((unsigned long *) (SCRATCHADDR + BOOTSEC_BPB_FAT32_SECTORS_PER_FAT)) * 2 - + (*((unsigned long *) (SCRATCHADDR + BOOTSEC_BPB_FAT32_ROOT)) - 2) * *((unsigned char *) (SCRATCHADDR + BOOTSEC_BPB_SECTORS_PER_CLUSTER)); // root directory entry address - *(unsigned short *)0x7BDE = *((unsigned char *) (SCRATCHADDR + BOOTSEC_BPB_SECTORS_PER_CLUSTER)); // root directory entry size = 1 cluster - *(unsigned long *)0x7BFC = (unsigned long)part_start + *(unsigned long *)0x7BF8; // root directory entry is in cluster 2 !! - } - else { - printf_errinfo("Error: Not FAT partition."); - goto failure_exec_format; - } - - /* copy directory entry of boot files to 0x500 */ - grub_close (); - if (((current_partition >> 8) & 0xFF00) == 0xFF00) /* check if partition number == 0xFF */ - grub_sprintf ((char *)(HMA_ADDR - 0x20), "(%d)%d+%d", (unsigned long)(unsigned char)current_drive, *(unsigned long *)0x7BF8, *(unsigned short *)0x7BDE * *((unsigned short *) (SCRATCHADDR + BOOTSEC_BPB_BYTES_PER_SECTOR)) / 512); - else - grub_sprintf ((char *)(HMA_ADDR - 0x20), "(%d,%d)%d+%d", (unsigned long)(unsigned char)current_drive, (unsigned long)(unsigned char)(current_partition >> 16), *(unsigned long *)0x7BF8, *(unsigned short *)0x7BDE * *((unsigned short *) (SCRATCHADDR + BOOTSEC_BPB_BYTES_PER_SECTOR)) / 512); - - grub_open ((char *)(HMA_ADDR - 0x20)); - grub_read ((unsigned long long)(HMA_ADDR - 0x10000), (*(unsigned short *)0x7BD8 = *(unsigned short *)0x7BDE * *((unsigned short *) (SCRATCHADDR + BOOTSEC_BPB_BYTES_PER_SECTOR))), 0xedde0d90); - - /* read 1st FAT(first 32K) to HMA_ADDR - 0x8000 */ - if (*((unsigned long *)(SCRATCHADDR + BOOTSEC_BPB_FAT32_NAME)) == 0x33544146) { /* FAT32 */ - *(unsigned short *)0x7BDC = 0; // read root directory cluster count - *(unsigned long *)0x7BD0 = *((unsigned long *) (SCRATCHADDR + BOOTSEC_BPB_FAT32_ROOT)); // last read root directory cluster - if (((current_partition >> 8) & 0xFF00) == 0xFF00) /* check if partition number == 0xFF */ - grub_sprintf ((char *)(HMA_ADDR - 0x20), "(%d)%d+%d", (unsigned long)(unsigned char)current_drive, *((unsigned short *) (SCRATCHADDR + BOOTSEC_BPB_RESERVED_SECTORS)), *((unsigned long *) (SCRATCHADDR + BOOTSEC_BPB_FAT32_SECTORS_PER_FAT))); - else - grub_sprintf ((char *)(HMA_ADDR - 0x20), "(%d,%d)%d+%d", (unsigned long)(unsigned char)current_drive, (unsigned long)(unsigned char)(current_partition >> 16), *((unsigned short *) (SCRATCHADDR + BOOTSEC_BPB_RESERVED_SECTORS)), *((unsigned long *) (SCRATCHADDR + BOOTSEC_BPB_FAT32_SECTORS_PER_FAT))); - - grub_open ((char *)(HMA_ADDR - 0x20)); /* read 1st FAT table (first 0x8000 bytes only) */ - grub_read ((unsigned long long)(HMA_ADDR - 0x8000), (*((unsigned long *) (SCRATCHADDR + BOOTSEC_BPB_FAT32_SECTORS_PER_FAT)) > 40 ? 40 : *((unsigned long *) (SCRATCHADDR + BOOTSEC_BPB_FAT32_SECTORS_PER_FAT))) * *((unsigned short *) (SCRATCHADDR + BOOTSEC_BPB_BYTES_PER_SECTOR)), 0xedde0d90); -readroot: - if ( (HMA_ADDR - 0x10000 + (1+*(unsigned short *)0x7BDC) * *(unsigned short *)0x7BD8) < HMA_ADDR && /* don't overrun */ - *(unsigned long *)0x7BD0 * sizeof(unsigned long) < 0x8000 && - (*(unsigned long *)0x7BD0 = *(unsigned long *)(HMA_ADDR - 0x8000 + *(unsigned long *)0x7BD0 * sizeof(unsigned long))) != 0xFFFFFFFF ) { /* root cluster count > 1 */ - *(unsigned long *)0x7BF8 = *((unsigned short *) (SCRATCHADDR + BOOTSEC_BPB_RESERVED_SECTORS)) - + *((unsigned long *) (SCRATCHADDR + BOOTSEC_BPB_FAT32_SECTORS_PER_FAT)) * 2 - + (*(unsigned long *)0x7BD0 - 2) * *((unsigned char *) (SCRATCHADDR + BOOTSEC_BPB_SECTORS_PER_CLUSTER)); // root directory entry address - if (((current_partition >> 8) & 0xFF00) == 0xFF00) /* check if partition number == 0xFF */ - grub_sprintf ((char *)(HMA_ADDR - 0x20), "(%d)%d+%d", (unsigned long)(unsigned char)current_drive, *(unsigned long *)0x7BF8, *(unsigned short *)0x7BDE); - else - grub_sprintf ((char *)(HMA_ADDR - 0x20), "(%d,%d)%d+%d", (unsigned long)(unsigned char)current_drive, (unsigned long)(unsigned char)(current_partition >> 16), *(unsigned long *)0x7BF8, *(unsigned short *)0x7BDE); - grub_open ((char *)(HMA_ADDR - 0x20)); - grub_read ((unsigned long long)(HMA_ADDR - 0x10000 + (1+*(unsigned short *)0x7BDC) * *(unsigned short *)0x7BD8), *(unsigned short *)0x7BD8, 0xedde0d90); - ++(*(unsigned short *)0x7BDC); - goto readroot; - } - } - grub_memmove((void *)0x7C3E, (void *)(( (*(short*)0x7A & 0xFFFF)<<4) + (*(short*)0x78 & 0xFFFF) ), 15); /* Copy DPT over PBR startup code */ - - for ( *(unsigned long *)0x7BF4 = HMA_ADDR - 0x10000, *(unsigned long *)0x7BF0 = 0x500; *(char *)(*(unsigned long *)0x7BF4) && *(unsigned long *)0x7BF4 < HMA_ADDR; *(unsigned long *)0x7BF4 += 32) { - if (*(long long *)(*(unsigned long *)0x7BF4) == *(long long *)0x7BE0) { /* BIO */ - grub_memmove((void *)*(unsigned long *)0x7BF0, (void *)*(unsigned long *)0x7BF4, 32); - *(unsigned long *)0x7BF0 += 32; - break; - } - } - for ( *(unsigned long *)0x7BF4 = HMA_ADDR - 0x10000; *(char *)(*(unsigned long *)0x7BF4) && *(unsigned long *)0x7BF4 < HMA_ADDR; *(unsigned long *)0x7BF4 += 32) { - if (*(long long *)(*(unsigned long *)0x7BF4) == *(long long *)0x7BE8) { /* DOS */ - grub_memmove((void *)*(unsigned long *)0x7BF0, (void *)*(unsigned long *)0x7BF4, 32); - *(unsigned long *)0x7BF0 += 32; - break; - } - } - if (! chainloader_bx_set) - { - chainloader_bx = *(unsigned long *)0x7BFC; - chainloader_bx_set = 1; - } - if (! chainloader_cx_set) - { - chainloader_cx = *((unsigned char *) (SCRATCHADDR + BOOTSEC_BPB_MEDIA_DESCRIPTOR)) << 8; - chainloader_cx_set = 1; - } - } - - printf_debug0("Will boot %s from drive=0x%x, partition=0x%x(hidden sectors=0x%lx)\n", - (is_pcdos ? "PC DOS" : (is_msdos ? "MS-DOS" : (is_drdos ? "DR-DOS" : (is_romdos ? "ROM-DOS" : (is_drmk ? "DRMK" : "FreeDOS"))))), current_drive, (unsigned long)(unsigned char)(current_partition >> 16), (unsigned long long)part_start); - } - else if ((*((long long *)SCRATCHADDR) == 0x501E0100122E802ELL && (is_drdos = 1)) /* packed with pack101 */ || - is_pcdos || is_msdos || - (*((long long *)(SCRATCHADDR)) == 0x0A079047EBLL && (is_pcdos = 1)) /* PC-DOS 7.1 */ || - (*((long long *)(SCRATCHADDR)) == 0x070135E9LL && (is_pcdos = 1)) /* PC-DOS 2000 */ || - (*((unsigned long *)(SCRATCHADDR)) == 0x060135E9 && (is_msdos = 1)) /* MS-DOS 6.x */ || - (*((long long *)(SCRATCHADDR+6)) == 0x646F4D206C616552LL && (is_drmk = 1)) /* DRMK */ || - ((*(long long *)SCRATCHADDR | 0xFFFF02LL) == 0x4F43000000FFFFEBLL && (*(((long long *)SCRATCHADDR)+1) == 0x706D6F435141504DLL) && (is_drdos = 1))) /* DR-DOS */ - { - /* contributor: Roy */ - if (chainloader_load_segment == -1) - chainloader_load_segment = 0x0070; - if ((is_pcdos || is_drmk || is_msdos) && chainloader_load_length == -1) - chainloader_load_length = filemax < 0x7400 ? filemax : 0x7400; - if (is_pcdos) { - *(long long *)0x7BE0 = 0x20204F49424D4249LL; /* IBMBIO.COM */ - *(long long *)0x7BE8 = 0x2020534F444D4249LL; /* IBMDOS.COM */ - } - else if (is_msdos) { - *(long long *)0x7BE0 = 0x2020202020204F49LL; /* IO.SYS */ - *(long long *)0x7BE8 = 0x202020534F44534DLL; /* MSDOS.SYS */ - } - - goto drdos; - } - else - if (filemax >= 0x40000 && *((unsigned short *) (SCRATCHADDR)) == 0x5A4D && // MZ header - *((unsigned short *) (SCRATCHADDR + 0x80)) == 0x4550 && // PE header - *((unsigned short *) (SCRATCHADDR + 0xDC)) == 0x1 //&& // PE subsystem -// (*((unsigned long *) (SCRATCHADDR + 0xA8))) == 0x1000 && // Entry address -// (*((unsigned long *) (SCRATCHADDR + 0xB4))) == 0x8000 // Base address - ) - { - if (chainloader_load_segment == -1) - chainloader_load_segment = 0; - if (chainloader_load_offset == -1) - chainloader_load_offset = (*((unsigned long *) (SCRATCHADDR + 0xB4))); - if (chainloader_load_length == -1) - chainloader_load_length = filemax; - if (chainloader_boot_IP == -1) - chainloader_boot_IP = (*((unsigned long *) (SCRATCHADDR + 0xB4))) + (*((unsigned long *) (SCRATCHADDR + 0xA8))); - if (! chainloader_edx_set) - { - chainloader_edx = current_drive | ((current_partition >> 8) & 0xFF00); - chainloader_edx_set = 1; - } - grub_close (); - - printf_debug0("Will boot FreeLDR from drive=0x%x, partition=0x%x(hidden sectors=0x%lx)\n", current_drive, (unsigned long)(unsigned char)(current_partition >> 16), (unsigned long long)part_start); - } - else - if (*(short *)SCRATCHADDR == 0x5A4D && filemax > 0x10000 && - *((unsigned short *) (SCRATCHADDR + BOOTSEC_SIG_OFFSET)) == 0 - /* && (*(long *)(SCRATCHADDR + 0xA2)) == 0 */ ) - { - - int err; - - /* Read the second sector. */ - if (grub_read ((unsigned long long) SCRATCHADDR, 512, 0xedde0d90) != 512) - goto failure_exec_format; - - err = (*(short *)SCRATCHADDR != 0x4A42); - - filepos += 0x200; /* skip the third sector */ - - /* Read the fourth sector. */ - if (grub_read ((unsigned long long) SCRATCHADDR, 512, 0xedde0d90) != 512) - goto failure_exec_format; - - err |= (*((unsigned short *) (SCRATCHADDR + BOOTSEC_SIG_OFFSET)) != 0x534D); - - /* Read the fifth sector. - * check the compress signature "CM" of IO.SYS of WinME */ - if (grub_read ((unsigned long long) SCRATCHADDR, 512, 0xedde0d90) != 512) - goto failure_exec_format; - - if (! err) - { - if (chainloader_load_segment == -1) - chainloader_load_segment = 0x0070; - if (chainloader_load_offset == -1) - chainloader_load_offset = 0; - if (chainloader_load_length == -1) - chainloader_load_length = filemax; - if (chainloader_skip_length == 0) - chainloader_skip_length = 0x0800; - - /* WinME support by bean. Thanks! */ - - // Input parameter for SYSINIT - // BX,AX: Start sector for the data area of FAT. It doesn't needs to - // be set. However, we should at least clear BX, otherwise, - // it would have some minor problem when booting WinME. - // DI: Length of the boot code, don't need to be set. - // BP: 0x7C00, boot sector pointer, don't need to be set. - // DH: Media ID (BS[0x15]) , 0xF0 for floppy, 0xF8 for harddisk - // DL: Drive number (BS[0x40] for FAT32) - - if (! chainloader_edx_set) - { - chainloader_edx = current_drive | ((current_partition >> 8) & 0xFF00); - chainloader_edx_set = 1; - } - if (! chainloader_ebx_set) - { - chainloader_ebx = 0; // clear BX for WinME - chainloader_ebx_set = 1; - } - - /* save partition number to the high word */ - chainloader_edx = (chainloader_edx & 0xFF00FFFF) | ((chainloader_edx & 0xFF00) << 8); - - // set media descriptor in DH for WinME - chainloader_edx = (chainloader_edx & 0xFFFF00FF) | 0xF000 | ((chainloader_edx & 0x80) << 4); - - grub_close (); - - /* FIXME: Where should the BPB be placed for MS-DOS's IO.SYS? - * In the current implementation it is placed at 0000:7C00 - * but has no effect, since the IO.SYS body will later - * overwrite 0000:7C00 on issuing the `boot' command. - */ - - if ((chainloader_edx & 0xFF0000) == 0xFF0000) /* check if partition number == 0xFF */ - grub_sprintf ((char *)SCRATCHADDR, "(%d)+1", (unsigned long)(unsigned char)chainloader_edx); - else - grub_sprintf ((char *)SCRATCHADDR, "(%d,%d)+1", (unsigned long)(unsigned char)chainloader_edx, (unsigned long)(unsigned char)(chainloader_edx >> 16)); - - if (! grub_open ((char *)SCRATCHADDR)) - goto failure; - - /* Read the boot sector of the partition onto 0000:7C00 */ - if (grub_read ((unsigned long long) SCRATCHADDR, 512, 0xedde0d90) != 512) - goto failure_exec_format; - - is_io = 1; - /* modify the hidden sectors */ - /* FIXME: Does the boot drive number also need modifying? */ - - if (*((unsigned long *) (SCRATCHADDR + BOOTSEC_BPB_HIDDEN_SECTORS))) - *((unsigned long *) (SCRATCHADDR + BOOTSEC_BPB_HIDDEN_SECTORS)) = (unsigned long)part_start; - printf_debug0("Will boot MS-DOS %c.x from drive=0x%x, partition=0x%x(hidden sectors=0x%lx)\n", - (unsigned long)(((*(unsigned short *) SCRATCHADDR) == 0x4D43)? '8' : '7'), - (unsigned long)current_drive, (unsigned long)(unsigned char)(current_partition >> 16), (unsigned long long)part_start); - } - } - else - if (((*(long *)SCRATCHADDR) & 0x00FF00FF) == 0x000100E9 && filemax > 0x30000 && - (*((unsigned short *) (SCRATCHADDR + BOOTSEC_SIG_OFFSET)) != BOOTSEC_SIGNATURE)) - { - if (chainloader_load_segment == -1) - chainloader_load_segment = 0x2000; - if (chainloader_load_offset == -1) - chainloader_load_offset = 0; - if (chainloader_load_length == -1) - chainloader_load_length = filemax; - if (! chainloader_edx_set) - { - chainloader_edx = current_drive | ((current_partition >> 8) & 0xFF00); - chainloader_edx_set = 1; - } - - grub_close (); - - if ((chainloader_edx & 0xFF00) == 0xFF00) - grub_sprintf ((char *)SCRATCHADDR, "(%d)+1", (unsigned long)(unsigned char)chainloader_edx); - else - grub_sprintf ((char *)SCRATCHADDR, "(%d,%d)+1", (unsigned long)(unsigned char)chainloader_edx, (unsigned long)(unsigned char)(chainloader_edx >> 8)); - - if (! grub_open ((char *)SCRATCHADDR)) - goto failure; - - /* Read the boot sector of the partition onto 0000:7C00 */ - if (grub_read ((unsigned long long) SCRATCHADDR, SECTOR_SIZE, 0xedde0d90) != SECTOR_SIZE) - goto failure_exec_format; - - /* modify the hidden sectors */ - /* FIXME: Does the boot drive number also need modifying? */ - - if (*((unsigned long *) (SCRATCHADDR + BOOTSEC_BPB_HIDDEN_SECTORS))) - *((unsigned long *) (SCRATCHADDR + BOOTSEC_BPB_HIDDEN_SECTORS)) = (unsigned long)part_start; - - /* -------- begin extra work for exFAT -------- */ - if ((unsigned char)(current_partition >> 16) != 0xFF) /* not whole drive, ie, not unpartitioned floppy/cdrom. */ - *((unsigned long *) (SCRATCHADDR + BOOTSEC_BPB_HIDDEN_SECTORS)) = (unsigned long)part_start; - - if (*((unsigned short *) (SCRATCHADDR + BOOTSEC_BPB_BYTES_PER_SECTOR)) == 0) - { - *((unsigned short *) (SCRATCHADDR + BOOTSEC_BPB_BYTES_PER_SECTOR)) = 512; - if ((buf_geom.flags & (BIOSDISK_FLAG_LBA_EXTENSION | BIOSDISK_FLAG_BIFURCATE)) && (! (buf_geom.flags & BIOSDISK_FLAG_CDROM))) - { - *((unsigned char *) (SCRATCHADDR + 0x02)) = 1; /* LBA must be supported for bootmgr of Win8. */ - } else { - /* Unfortunately LBA is not present. Win8 bootmgr may fail. */ - *((unsigned char *) (SCRATCHADDR + 0x02)) = 0; - if (! *((unsigned long *) (SCRATCHADDR + 0x18))) - { - /* Although Win8 bootmgr might fail, we do our best to - * fill the BPB with correct sectors_per_track and - * number_of_heads values. */ - *((unsigned short *) (SCRATCHADDR + 0x18)) = buf_geom.sectors; - *((unsigned short *) (SCRATCHADDR + 0x1A)) = buf_geom.heads; - } - } - } - /* -------- end extra work for exFAT -------- */ - - printf_debug0("Will boot NTLDR from drive=0x%x, partition=0x%x(hidden sectors=0x%lx)\n", current_drive, (unsigned long)(unsigned char)(current_partition >> 16), (unsigned long long)part_start); - } - else - if (filemax >= 0x4000 && (*(short *)SCRATCHADDR) == 0x3EEB && //(*(long *)(SCRATCHADDR + 0x40)) == 0x5B0000E8 && - (*((unsigned short *) (SCRATCHADDR + BOOTSEC_SIG_OFFSET)) != BOOTSEC_SIGNATURE)) - { - char tmp_buf[16]; - - filepos = 0x1FF8; /* grldr signature, pre_stage2, etc */ - - if (grub_read ((unsigned long long)(unsigned long)tmp_buf, 16, 0xedde0d90) != 16) - goto failure_exec_format; - - filepos = 0x200; - if (*(short *)tmp_buf < 0x40 || *(short *)tmp_buf > 0x1B8) - goto check_isolinux; - if (*(long *)(tmp_buf + 8) != 0x008270EA) - goto check_isolinux; - if (*(long *)(SCRATCHADDR + *(short *)tmp_buf) != *(long *)(tmp_buf + 4)) - goto check_isolinux; - if ((*(long long *)(void *)((int)*(short *)tmp_buf + (int)SCRATCHADDR - 5) & 0xFFFFFFFFFFLL) != 0xB8661FFCBBLL) - goto check_isolinux; - -// if (chainloader_load_segment == -1) -// chainloader_load_segment = 0x2000; -// if (chainloader_load_offset == -1) -// chainloader_load_offset = 0; - if (chainloader_load_length == -1) - chainloader_load_length = filemax; - if (! chainloader_edx_set) - { - chainloader_edx = current_drive | ((current_partition >> 8) & 0xFF00); - chainloader_edx_set = 1; - } - is_grldr = 1; - - grub_close (); - - printf_debug0("Will boot GRLDR from drive=0x%x, partition=0x%x(hidden sectors=0x%lx)\n", current_drive, (unsigned long)(unsigned char)(current_partition >> 16), (unsigned long long)part_start); - } else - { - -check_isolinux: - - if (filemax < 0x800) - goto check_signature; - - /* Read the 2nd, 3rd and 4th sectors. */ - - /**********************************************/ - /**** 4 sectors at SCRATCHADDR are used!!! ****/ - /**********************************************/ - - filepos = 0x200; - - if (grub_read ((unsigned long long) SCRATCHADDR+0x200, 0x600, 0xedde0d90) != 0x600) - goto check_signature; - - if (filemax >= 0x4000 && ((*(long *)SCRATCHADDR) & 0x80FFFFFF)== 0xEB5A4D && (*(long *)(SCRATCHADDR + 0x202)) == 0x53726448 && - (*((unsigned short *) (SCRATCHADDR + BOOTSEC_SIG_OFFSET)) == BOOTSEC_SIGNATURE) && - (*(unsigned char *)(SCRATCHADDR + 0x200)) == 0xEB) /* GRUB.EXE */ - { - if (chainloader_load_segment == -1) - chainloader_load_segment = 0x1000; /* use address != 0x7C00, so that PXE is automatically disabled. */ - if (chainloader_load_offset == -1) - chainloader_load_offset = 0; - if (chainloader_boot_CS == -1) - chainloader_boot_CS = chainloader_load_segment; - if (chainloader_boot_IP == -1) - chainloader_boot_IP = chainloader_load_offset + 2; /* skip "MZ" */ - if (chainloader_load_length == -1) - chainloader_load_length = filemax; - if (! chainloader_edx_set) - { - chainloader_edx = current_drive | ((current_partition >> 8) & 0xFF00); - chainloader_edx_set = 1; - } - - grub_close (); - - printf_debug0("Will boot GRUB.EXE from drive=0x%x, partition=0x%x(hidden sectors=0x%lx)\n", current_drive, (unsigned long)(unsigned char)(current_partition >> 16), (unsigned long long)part_start); - } - else - if ((*(long long *)(SCRATCHADDR + 0x200)) == 0xCB5052C03342CA8CLL && (*(long *)(SCRATCHADDR + 0x208) == 0x5441464B)) /* ROM-DOS */ - { - /* contributor: Roy */ - if (chainloader_load_segment == -1) - chainloader_load_segment = 0x1000; - if (chainloader_load_offset == -1) - chainloader_load_offset = 0; - if (chainloader_load_length == -1) - chainloader_load_length = filemax; - if (chainloader_skip_length == 0) - chainloader_skip_length = 0x0200; - *(unsigned long *)0x84 = current_drive | 0xFFFF0000; - is_romdos = 1; - goto drdos; - } - else - if (((*(long long *)SCRATCHADDR) & 0xFFFFFFFFFF00FFFFLL) == 0x909000007C00EAFALL && filemax > 0x2000 && filemax < 0x20000) /* ISOLINUX */ - { - for (p = (char *)(SCRATCHADDR + 0x40); p < (char *)(SCRATCHADDR + 0x7F3); p++) - { - if ( *(unsigned long *)p == 0xBB0201B8 && - *(unsigned long *)(p - 4) == 0 && - *(unsigned long *)(p + 4) == 0x06B97C00 && - *(unsigned long *)(p + 8) == 0x0180BA00 && - *(unsigned short *)(p + 12) == 0x9A9C) - { - goto isolinux_ok; - } - } - /* comment out old code */ - //for (p = (char *)(SCRATCHADDR + 0x40); p < (char *)(SCRATCHADDR + 0x140); p++) - //{ - // if (*(unsigned long *)p == 0xD08EC031 && - // *(unsigned short *)(p - 10) == 0x892E && - // *(unsigned short *)(p - 5) == 0x8C2E && - // *(unsigned char *)(p + 4) == 0xBC && - // *(unsigned char *)(p - 8) == 0x26 && - // *(unsigned char *)(p - 3) == 0x16) - // { - // goto isolinux_ok; - // } - //} - goto check_signature; /* it is not isolinux. */ -isolinux_ok: - if (buf_geom.sector_size != 2048) - { - printf_debug0 ("\nCannot chainload ISOLINUX from a non-CDROM device.\n"); - goto failure_exec_format; - } - - chainloader_load_segment = 0; - chainloader_load_offset = 0x7c00; - chainloader_load_length = filemax; - chainloader_edx = current_drive; - chainloader_edx_set = 1; - - is_isolinux = 1; - } - else - { -check_signature: - /* If not loading it forcibly, check for the signature. */ - if (! force - && (*((unsigned short *) (SCRATCHADDR + BOOTSEC_SIG_OFFSET)) - != BOOTSEC_SIGNATURE)) - goto failure_exec_format; - } - } - - grub_close (); - - /* if BPB exists, we can reliablly modify the hidden sectors. */ - if (! probe_bpb((struct master_and_dos_boot_sector *)SCRATCHADDR)) - if (*((unsigned long *) (SCRATCHADDR + BOOTSEC_BPB_HIDDEN_SECTORS))) - *((unsigned long *) (SCRATCHADDR + BOOTSEC_BPB_HIDDEN_SECTORS)) - = (unsigned long)part_start; + { + part_data = get_partition_info (current_drive, current_partition); + if (!part_data || !part_data->part_handle) + return (!(errnum = ERR_NO_DISK)); + dp = grub_efi_get_device_path (part_data->part_handle); + temp = part_data->part_handle; + } + } - if (chainloader_load_length == -1) - chainloader_load_length = filemax; - if (chainloader_load_length > 0xA0000) - chainloader_load_length = 0xA0000; - - grub_memmove ((char *)0x7C00, (char *)SCRATCHADDR, 512); - errnum = ERR_NONE; - + if (debug > 1) + grub_efi_print_device_path(dp); + dev_handle = temp; + image_handle = grub_load_image (dp, arg1, boot_image); + if (!image_handle) + goto failure_exec_format_0; + //当从存储器加载图像时,LoadImage不设置设备处理程序,因此有必要在这里明确设置它 + grub_efi_loaded_image_t *image1 = grub_efi_get_loaded_image (image_handle); //通过映像句柄,获得加载映像 + if (! image1) + { + printf_errinfo ("no loaded image available\n"); //"没有可用的加载图像" + goto failure_exec_format; + } + //UEFI固件已经设置了“image1->device_handle = d->handle”。他没有分区信息,启动不了某些bootmgfw.efi。必须在此填充对应分区的句柄。 +// image1->device_handle = dev_handle; +#if 0 + image1->device_handle = d->device_handle; +#else + image1->device_handle = temp; +#endif + printf_debug ("image=%x device_handle=%x\n",image1,image1->device_handle); + if (cmdline) + { + image1->load_options = cmdline; //加载选项 + image1->load_options_size = cmdline_len;//加载选项尺寸 + } + grub_close (); //关闭文件 +#if 0 + //拦截对OpenProtocol的调用 + orig_open_protocol = (void *)image1->system_table->boot_services->open_protocol; + image1->system_table->boot_services->open_protocol = (void *)efi_open_protocol_wrapper; +#endif + kernel_type = KERNEL_TYPE_CHAINLOADER; return 1; failure_exec_format: grub_close (); +failure_exec_format_0: + if (errnum == ERR_NONE) - errnum = ERR_EXEC_FORMAT; - -failure: - - chainloader_load_segment = chainloader_load_segment_orig; - chainloader_load_offset = chainloader_load_offset_orig; - chainloader_load_length = chainloader_load_length_orig; - chainloader_skip_length = chainloader_skip_length_orig; - chainloader_boot_CS = chainloader_boot_CS_orig; - chainloader_boot_IP = chainloader_boot_IP_orig; - chainloader_ebx = chainloader_ebx_orig; - chainloader_ebx_set = chainloader_ebx_set_orig; - chainloader_edx = chainloader_edx_orig; - chainloader_edx_set = chainloader_edx_set_orig; - chainloader_disable_A20 = chainloader_disable_A20_orig; - is_sdi = is_sdi_orig; - is_raw = is_raw_orig; - is_isolinux = is_isolinux_orig; - is_grldr = is_grldr_orig; - is_io = is_io_orig; - kernel_type = kernel_type_orig; - force = errnum; /* backup the errnum */ - grub_memmove ((char *)chainloader_file, (char *)chainloader_file_orig, sizeof(chainloader_file)); - errnum = force; /* restore the errnum */ - return 0; /* return failure */ + errnum = ERR_EXEC_FORMAT; + + if (address) + efi_call_2 (b->free_pages, address, pages); //释放页 + return 0; /* return failure */ } static struct builtin builtin_chainloader = @@ -2868,28 +1565,20 @@ static struct builtin builtin_chainloader = "chainloader", chainloader_func, BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST | BUILTIN_BOOTING, - "chainloader [--force] [--load-segment=LS] [--load-offset=LO]" - "\n[--load-length=LL] [--skip-length=SL] [--boot-cs=CS] [--boot-ip=IP]" - "\n[--ebx=EBX] [--edx=EDX] [--sdi] [--disable-a20] [--pcdos] [--msdos] FILE", - "Load the chain-loader FILE. If --force is specified, then load it" - " forcibly, whether the boot loader signature is present or not." - " LS:LO specifies the load address other than 0000:7C00. LL specifies" - " the length of the boot image(between 512 and 640K). CS:IP specifies" - " the address where the boot image will gain control. EBX/EDX specifies" - " the EBX/EDX register value when the boot image gets control. Use --sdi" - " if FILE is a System Deployment Image, which is of the Windows XP" - " RAM boot file format. Use --disable-a20 if you wish to turn off" - " A20 when transferring control to the boot image." - " SL specifies length in bytes at the beginning of the image to be" - " skipped when loading." + "chainloader FILE", + "Load the chain-loader FILE.\n" + "for example:\n" + " chainloader (0xff)\n" + " chainloader (hd2)\n" + " chainloader (bd)/grub.efi \"vdisk=/_ISO/LINUX/Ubuntu Mint.vdi.vtoy\"" }; - /* This function could be used to debug new filesystem code. Put a file in the new filesystem and the same file in a well-tested filesystem. Then, run "cmp" with the files. If no output is obtained, probably the code is good, otherwise investigate what's wrong... */ /* cmp FILE1 FILE2 */ +static int cmp_func (char *arg, int flags); static int cmp_func (char *arg, int flags) { @@ -2938,8 +1627,7 @@ cmp_func (char *arg, int flags) /* Read the whole data from FILE1. */ // At 6M it will be unifont. Use 64K at 1M instead. #define CMP_BUF_SIZE 0x8000ULL - addr1 = (char *) RAW_ADDR (0x100000); - addr2 = addr1 + CMP_BUF_SIZE; + if (! grub_open (file1)) return 0; @@ -2980,29 +1668,37 @@ cmp_func (char *arg, int flags) else filepos = cur_pos; - while ((size1 = grub_read ((unsigned long long)(unsigned long)addr1, CMP_BUF_SIZE, 0xedde0d90))) + addr1 = grub_malloc (0x10000); + if (!addr1) + return 0; + addr2 = addr1 + CMP_BUF_SIZE; + while ((size1 = grub_read ((unsigned long long)(grub_size_t)addr1, CMP_BUF_SIZE, 0xedde0d90))) { cur_pos = filepos; grub_close(); if (! grub_open (file2)) + { + grub_free (addr1); return 0; + } filepos = cur_pos - size1; - if (! (size2 = grub_read ((unsigned long long)(unsigned long)addr2, size1, 0xedde0d90))) + if (! (size2 = grub_read ((unsigned long long)(grub_size_t)addr2, size1, 0xedde0d90))) { grub_close (); + grub_free (addr1); return 0; } grub_close(); if (Hex) { - for (i = 0; i < size2; i+=16) + for (i = 0; i < (int)size2; i+=16) { int k,cnt; unsigned char c; - unsigned long cur_offset; - cur_offset = (unsigned long)(cur_pos - size1 + i); + grub_size_t cur_offset; + cur_offset = (grub_size_t)(cur_pos - size1 + i); if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_NORMAL); grub_printf("0x%X\t0x%lX/0x%lX\n",cur_offset, size, filemax); @@ -3010,7 +1706,7 @@ cmp_func (char *arg, int flags) current_term->setcolorstate (COLOR_STATE_STANDARD); grub_printf ("%08X: ",cur_offset); cnt = 16; - if (cnt+i > size2) + if (cnt+i > (int)size2) cnt=size2 - i; for (k=0;k= 8) -// { -// if (tmp_blinking == 0x80) -// return -1; -// tmp_blinking = 0; -// } color |= i << 4; break; } @@ -3187,7 +1875,6 @@ color_number (char *str) if (i == 16) return -1; -// blinking = tmp_blinking; return color; } @@ -3196,6 +1883,7 @@ extern int color_counting; /* Set new colors used for the menu interface. Support two methods to specify a color name: a direct integer representation and a symbolic color name. An example of the latter is "blink-light-gray/blue". */ +static int color_func (char *arg, int flags); static int color_func (char *arg, int flags) { @@ -3233,7 +1921,7 @@ color_func (char *arg, int flags) if ((int)new_normal_color < 0 && ! safe_parse_maxint (&normal, &new_normal_color)) { color_state state_t; - unsigned long state = 0; + unsigned int state = 0; int tag = 0; arg = normal; while (*arg) @@ -3306,9 +1994,6 @@ color_func (char *arg, int flags) return 1; } -// if (new_normal_color >> 8) /* disable blinking */ -// blinking = 0; - new_color[COLOR_STATE_HEADING] = new_color[COLOR_STATE_HELPTEXT] = new_color[COLOR_STATE_NORMAL] = new_normal_color; /* The second argument is optional, so set highlight_color to inverted NORMAL_COLOR. */ @@ -3332,24 +2017,9 @@ color_func (char *arg, int flags) if (!(splashimage_loaded & 2) && ((new_color[i] & 0xffffffff00000000) == 0)) new_color[i] |= (new_color[COLOR_STATE_NORMAL] & 0xffffffff00000000); - /*comment by chenall 2011-11-30 why do this? I think not need.*/ - //if (new_color[i] & 0xff00) /* disable blinking */ - //{ - // if (blinking == 0x80) - // { - // errnum = ERR_BAD_ARGUMENT; - // return 0; - // } - // blinking = 0; - //} } } - /*0x1E to set color for "normal highlight helptext heading". - (1<setcolor (0x1E,new_color); return 1; @@ -3367,24 +2037,28 @@ static struct builtin builtin_color = "If you omit HELPTEXT and/or HEADING, then NORMAL is used.\n" "1. Assign colors by target, the order can not be messed up.\n" " The color can be replaced by a placeholder n.\n" - "e.g. color 0x888800000000 0x888800ffff00 0x888800880000 0x88880000ff00. (64 bit number.)\n" + "e.g. color 0x0000888800000000 0x0000888800ffff00 0x0000888800880000 0x000088880000ff00. (64 bit number." + " The upper 32 bits are the background color, and the lower 32 bits are the foreground color.)\n" "2. Can assign colors to a specified target. NORMAL should be in the first place.\n" - "e.g. color normal=0x888800000000. (The rest is the same as NORMAL.)\n" - "e.g. color normal=0x4444440000ffff helptext=0xff0000 highlight=0x00ffff heading=0xffff00\n" - " border=0x00ff00. (Background color from NORMAL.)\n" - "e.g. color standard=0xFFFFFF. (Change the console color.)\n" + "e.g. color normal=0x00888800000000. (The rest is the same as NORMAL.)\n" + "e.g. color normal=0x004444440000ffff helptext=0x00ff0000 highlight=0x0000ffff heading=0xffff00" + " border=0x0000ff00. (Background color from NORMAL.)\n" + "e.g. color standard=0x00FFFFFF. (Change the console color.)\n" "e.g. color --64bit 0x30. (Make numbers less than 0x100 treated in 64-bit color.)\n" "Display color list if no parameters.\n" - "Use 'echo -rrggbb' to view colors." + "Use 'echo -rrggbb' to view colors.\n" + "note that if in graphics hi-res mode, the background colour for normal text and help text will be ignored and will be set to transparent." }; - + /* configfile */ +static int configfile_func (char *arg, int flags); static int configfile_func (char *arg, int flags) { errnum = 0; graphic_type = 0; + //标记为用户程序,则将配置文件保存到CMD_RUN_ON_EXIT if (flags & BUILTIN_USER_PROG) { if (! grub_open (arg)) @@ -3392,89 +2066,59 @@ configfile_func (char *arg, int flags) grub_close(); return sprintf(CMD_RUN_ON_EXIT,"\xEC configfile %.128s",arg); } + //1.其他标记,则将配置文件保存到config_file char *new_config = config_file; - - if (*arg == 0 && *config_file) - { - if (pxe_restart_config == 0) - { - if (configfile_in_menu_init == 0) - pxe_restart_config = configfile_in_menu_init = 1; - return 1; - } - /* use the original config file */ - saved_drive = boot_drive; - saved_partition = install_partition; - *saved_dir = 0; /* clear saved_dir */ - arg = config_file; - } - - if (grub_strlen(saved_dir) + grub_strlen(arg) + 20 >= sizeof(chainloader_file_orig)) + if (grub_strlen(saved_dir) + grub_strlen(arg) + 20 >= (int)sizeof(chainloader_file_orig)) //避免出界 return ! (errnum = ERR_WONT_FIT); - set_full_path(chainloader_file_orig,arg,sizeof(chainloader_file_orig)); + grub_memset(chainloader_file_orig, 0, 256); + set_full_path(chainloader_file_orig,arg,sizeof(chainloader_file_orig)); //把配置文件保存到chainloader_file_orig //chainloader_file_orig[sizeof(chainloader_file_orig) - 1] = 0; - - arg = chainloader_file_orig; - - nul_terminate (arg); - + arg = chainloader_file_orig; //arg重定向 + nul_terminate (arg); //用NUL终止字符串 /* check possible filename overflow */ - if (grub_strlen (arg) >= ((char *)0x8270 - new_config)) - return ! (errnum = ERR_WONT_FIT); - - /* Check if the file ARG is present. */ - if (! grub_open (arg)) + if (grub_strlen (arg) >= 0x49) //0x821e-0x825f 避免出界 { - if (! use_preset_menu) - return 0; - errnum = 0; - } else - { - /* Copy ARG to CONFIG_FILE. */ - while ((*new_config++ = *arg++)); - - if (current_drive == cdrom_drive) - configfile_opened = 1; - else - grub_close (); + printf_errinfo ("The full path of the configuration file should <= 72\n"); + return ! (errnum = 0x1234); } - + /* Copy ARG to CONFIG_FILE. */ + while ((*new_config++ = *arg++)); //把修改后的配置文件保存到config_file /* Force to load the configuration file. */ - use_config_file = 1; - - if (pxe_restart_config == 0) - { - pxe_restart_config = /* configfile_in_menu_init = */ 1; - return 1; - } - + //2.在main中使用配置文件 +// use_config_file = 1; /* Make sure that the user will not be authoritative. */ + //3.用户权限最低 auth = 0; - + //4.保存的项目归零 saved_entryno = 0; + //5.设置引导驱动器及引导分区 +#if 0 /* should not clear saved_dir. see issue 109 reported by ruymbeke. */ - // *saved_dir = 0; /* clear saved_dir */ - //force_cdrom_as_boot_device = 0; if (current_drive != 0xFFFF && (current_drive != ram_drive || filemax != rd_size)) { boot_drive = current_drive; install_partition = current_partition; } - ///* Restart pre_stage2. */ - //(*(char *)0x8205) |= 2; /* disable keyboard intervention */ - //chain_stage1(0, 0x8200, boot_part_addr); - /* Restart cmain. */ - asm volatile ("movl $0x7000, %esp"); /* set stack to STACKOFF */ -#ifdef HAVE_ASM_USCORE - asm volatile ("call _cmain"); - asm volatile ("jmp _stop"); -#else - asm volatile ("call cmain"); - asm volatile ("jmp stop"); #endif - + if (boot_drive == 0xFFFFFFFF) //如果引导驱动器未设置 + { + if (current_drive != 0xFFFFFFFF) + { + boot_drive = current_drive; + install_partition = current_partition; + } + else + { + boot_drive = saved_drive; + install_partition = saved_partition; + } + } + if (animated_type) + splashimage_func("\0",1); //切换菜单时.避免动画背景残留 + //6.进入菜单 + cmain (); /* Never reach here. */ return 1; } @@ -3488,8 +2132,131 @@ static struct builtin builtin_configfile = "Load FILE as the configuration file." }; - +static grub_efi_status_t +connect_all_efi (void) +{ + grub_efi_status_t status; + grub_efi_uintn_t handle_count; + grub_efi_handle_t *handle_buffer; + grub_efi_uintn_t index; + grub_efi_boot_services_t *b = grub_efi_system_table->boot_services; + status = efi_call_5 (b->locate_handle_buffer, + GRUB_EFI_ALL_HANDLES, + NULL, NULL, + &handle_count, &handle_buffer); + if (status != GRUB_EFI_SUCCESS) + return status; + for (index = 0; index < handle_count; index++) + status = efi_call_4 (b->connect_controller, + handle_buffer[index], NULL, NULL, TRUE); + if (handle_buffer) + efi_call_1 (b->free_pool, handle_buffer); + return GRUB_EFI_SUCCESS; +} + +/* load */ +static int load_func (char *arg, int flags); +static int +load_func (char *arg, int flags) +{ + int connect = 1; + grub_efi_status_t status; + grub_efi_boot_services_t *b = grub_efi_system_table->boot_services; + grub_efi_physical_address_t address; + grub_efi_uintn_t pages = 0; + grub_size_t size; + void *driver_img = NULL; + grub_efi_handle_t driver_handle; + grub_efi_loaded_image_t *loaded_image; + grub_efi_guid_t loaded_image_protocol_guid = GRUB_EFI_LOADED_IMAGE_PROTOCOL_GUID; + + if (!*arg) + goto load_fail; + if (grub_memcmp (arg, "-n", 2) == 0) + { + connect = 0; + arg = skip_to (0, arg); + } + grub_open (arg); + if (errnum) + { + printf_errinfo ("Failed to open %s\n", arg); + goto load_fail; + } + size = filemax; + pages = BYTES_TO_PAGES (size); + status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES, + GRUB_EFI_LOADER_CODE, pages, &address); + if (status != GRUB_EFI_SUCCESS) + { + grub_close (); + printf_errinfo ("Failed to allocate pages\n"); + goto load_fail; + } + driver_img = (void *) ((grub_addr_t) address); + if (grub_read ((unsigned long long)(grub_size_t)driver_img, + filemax, 0xedde0d90) != filemax) + { + grub_close (); + printf_errinfo ("premature end of file %s", arg); + goto load_fail; + } + grub_close (); + + status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, NULL, + driver_img, size, &driver_handle); + if (status != GRUB_EFI_SUCCESS) + { + printf_errinfo ("cannot load image\n"); + goto load_fail; + } + loaded_image = grub_efi_get_loaded_image (driver_handle); + if (!loaded_image) + { + printf_errinfo ("no loaded image available\n"); + goto load_fail; + } + status = efi_call_3 (b->handle_protocol, driver_handle, + &loaded_image_protocol_guid, (void **)&loaded_image); + if (status != GRUB_EFI_SUCCESS) + { + printf_errinfo ("Not a dirver\n"); + goto load_fail; + } + status = efi_call_3 (b->start_image, driver_handle, NULL, NULL); + if (status != GRUB_EFI_SUCCESS) + { + printf_errinfo ("ERROR in StartImage\n"); + goto load_fail; + } + if (connect) + { + status = connect_all_efi (); + if (status != GRUB_EFI_SUCCESS) + { + printf_errinfo ("ERROR in connect_all_efi\n"); + goto load_fail; + } + } + return 1; + +load_fail: + if (driver_img) + efi_call_2 (b->free_pages, (grub_size_t)driver_img, pages); + return 0; +} + +static struct builtin builtin_load = +{ + "load", + load_func, + BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, + "load [-n] FILE", + "Load FILE as EFI driver." +}; + /* dd if=IF of=OF */ +static int dd_func (char *arg, int flags); static int dd_func (char *arg, int flags) { @@ -3501,21 +2268,20 @@ dd_func (char *arg, int flags) unsigned long long seek = 0; unsigned long long old_part_start = part_start; unsigned long long old_part_length = part_length; -// int in_fsys_type; - unsigned long in_drive; - unsigned long in_partition; -// int out_fsys_type; - unsigned long out_drive; - unsigned long out_partition; + unsigned int in_drive; + unsigned int in_partition; + unsigned int out_drive; + unsigned int out_partition; unsigned long long in_filepos; unsigned long long in_filemax; unsigned long long out_filepos; unsigned long long out_filemax; - unsigned long long buf_addr = 0x100000ULL; /* 1M */ unsigned long long buf_size = 0x10000ULL; char tmp_in_file[16]; char tmp_out_file[16]; - + char *buf_addr = 0; + int SameFile_MoveBack = 0; + errnum = 0; for (;;) { @@ -3579,30 +2345,6 @@ dd_func (char *arg, int flags) if (! safe_parse_maxint (&p, &seek)) return 0; } - else if (grub_memcmp (arg, "buf=", 4) == 0) - { - if (buf_addr > 0x100000) /* already at above 1M, so it is set previously. */ - return !(errnum = ERR_BAD_ARGUMENT); - p = arg + 4; - if (*p == '-') /* negative */ - return !(errnum = ERR_BAD_ARGUMENT); - if (! safe_parse_maxint (&p, &buf_addr)) - return 0; - if (buf_addr < 0x100000) /* cannot set buffer at below 1M */ - return !(errnum = ERR_BAD_ARGUMENT); - } - else if (grub_memcmp (arg, "buflen=", 7) == 0) - { - if (buf_size > 0x10000) /* already above 64K, so it is set previously. */ - return !(errnum = ERR_BAD_ARGUMENT); - p = arg + 7; - if (*p == '-') /* negative */ - return !(errnum = ERR_BAD_ARGUMENT); - if (! safe_parse_maxint (&p, &buf_size)) - return 0; - if (buf_size <= 0x10000 || buf_size > 0xFFFFFFFF) /* cannot set buffer size below 64K */ - return !(errnum = ERR_BAD_ARGUMENT); - } else if (*arg) return !(errnum = ERR_BAD_ARGUMENT); else @@ -3615,20 +2357,6 @@ dd_func (char *arg, int flags) if (bs == 0) bs = 512; -// if (*in_file == '/') -// { -// in_drive = saved_drive; -// in_partition = saved_partition; -// in_file--; -// *in_file = ')'; -// in_file--; -// *in_file = '('; -// if (! grub_open (in_file)) -// goto fail; -// in_filemax = filemax; -// grub_close (); -// } -// else { p = set_device (in_file); if (errnum) @@ -3671,45 +2399,14 @@ dd_func (char *arg, int flags) } else { - //in_file--; - //*in_file = ')'; - //in_file--; - //*in_file = '('; - //current_drive = saved_drive; - //current_partition = saved_partition; - //saved_drive = in_drive; - //saved_partition = in_partition; - //in_drive = current_drive; - //in_partition = current_partition; grub_open (in_file); - //current_drive = saved_drive; - //current_partition = saved_partition; - //saved_drive = in_drive; - //saved_partition = in_partition; - //in_drive = current_drive; - //in_partition = current_partition; in_filemax = filemax; if (errnum) goto fail; grub_close (); } } -// in_fsys_type = fsys_type; - -// if (*out_file == '/') -// { -// out_drive = saved_drive; -// out_partition = saved_partition; -// out_file--; -// *out_file = ')'; -// out_file--; -// *out_file = '('; -// if (! grub_open (out_file)) -// goto fail; -// out_filemax = filemax; -// grub_close (); -// } -// else + { p = set_device (out_file); if (errnum) @@ -3752,30 +2449,13 @@ dd_func (char *arg, int flags) } else { - //out_file--; - //*out_file = ')'; - //out_file--; - //*out_file = '('; - //current_drive = saved_drive; - //current_partition = saved_partition; - //saved_drive = out_drive; - //saved_partition = out_partition; - //out_drive = current_drive; - //out_partition = current_partition; grub_open (out_file); - //current_drive = saved_drive; - //current_partition = saved_partition; - //saved_drive = out_drive; - //saved_partition = out_partition; - //out_drive = current_drive; - //out_partition = current_partition; out_filemax = filemax; if (errnum) goto fail; grub_close (); } } -// out_fsys_type = fsys_type; /* calculate in_filepos and out_filepos */ in_filepos = skip * bs; @@ -3803,7 +2483,7 @@ dd_func (char *arg, int flags) grub_memmove64 (out_filepos, in_filepos, count); part_start = tmp_part_start; part_length = tmp_part_length; - printf_debug0 ("\nMoved 0x%lX bytes from 0x%lX to 0x%lX\n", (unsigned long long)count, (unsigned long long)in_filepos, (unsigned long long)out_filepos); + printf_debug ("\nMoved 0x%lX bytes from 0x%lX to 0x%lX\n", (unsigned long long)count, (unsigned long long)in_filepos, (unsigned long long)out_filepos); errnum = 0; return count; } @@ -3814,26 +2494,26 @@ dd_func (char *arg, int flags) #if 0 if (out_drive != ram_drive && out_drive != 0xFFFF && *p != '/') { - unsigned long j; + unsigned int j; /* check if it is a mapped memdrive */ j = DRIVE_MAP_SIZE; /* real drive */ - if (! unset_int13_handler (1)) /* map is hooked */ for (j = 0; j < DRIVE_MAP_SIZE; j++) { - if (drive_map_slot_empty (hooked_drive_map[j])) + if (drive_map_slot_empty (disk_drive_map[j])) //判断驱动器映像插槽是否为空 为空,返回1 { j = DRIVE_MAP_SIZE; /* real drive */ break; } - if (out_drive == hooked_drive_map[j].from_drive && hooked_drive_map[j].to_drive == 0xFF && !(hooked_drive_map[j].to_cylinder & 0x4000)) + if (out_drive == disk_drive_map[j].from_drive && disk_drive_map[j].to_drive == 0xFF && !(disk_drive_map[j].to_log2_sector != 11)) break; /* memdrive */ } - if (j == DRIVE_MAP_SIZE) /* real drive */ + if (j == DRIVE_MAP_SIZE) /* real drive 如果不是映射驱动器)*/ { /* this command is intended for running in command line and inhibited from running in menu.lst */ + //此函数只允许在命令行运行, 禁止在菜单 if (flags & (BUILTIN_MENU | BUILTIN_SCRIPT)) { errnum = ERR_WRITE_TO_NON_MEM_DRIVE; @@ -3842,29 +2522,49 @@ dd_func (char *arg, int flags) } } #endif - { unsigned long long in_pos = in_filepos; unsigned long long out_pos = out_filepos; unsigned long long tmp_size = buf_size; + unsigned int in_count = (unsigned int)(in_filemax - in_filepos + buf_size - 1) / (unsigned int)buf_size; if (debug > 0) { count = in_filemax - in_filepos; if (count > out_filemax - out_pos) count = out_filemax - out_pos; - count = ((unsigned long)(count + buf_size - 1) / (unsigned long)buf_size); - grub_printf ("buf_size=0x%lX, loops=0x%lX. in_pos=0x%lX, out_pos=0x%lX\n", (unsigned long long)buf_size, (unsigned long long)count, (unsigned long long)in_pos, (unsigned long long)out_pos); - } - count = 0; + count = ((unsigned int)(count + buf_size - 1) / (unsigned int)buf_size); + printf_debug ("buf_size=0x%lX, loops=0x%lX. in_pos=0x%lX, out_pos=0x%lX\n", (unsigned long long)buf_size, (unsigned long long)count, (unsigned long long)in_pos, (unsigned long long)out_pos); + } + + //以终止符替换空格 + nul_terminate (in_file); + nul_terminate (out_file); + //同一文件向后移动, 可能会覆盖数据!!! 补丁修复此bug + if (substring (out_file, in_file, 0) == 0 //返回: 0/1/-1=s1与s2相等/s1不是s2的子字符串/s1是s2的子字符串 + && in_drive == out_drive + && in_partition == out_partition + && in_count + && in_pos < out_pos) + { + SameFile_MoveBack = 1; //同一文件向后移动标记 + } + +// count = 0; + buf_addr = grub_malloc (buf_size); + if (!buf_addr) + return 0; + while (in_pos < in_filemax && out_pos < out_filemax) { +#if 0 if (debug > 0) { if (!((char)count & 7)) grub_printf ("\r"); - grub_printf ("%08X ", (unsigned long)(count)); + grub_printf ("%08X ", (unsigned int)(count)); } +#endif /* open in_file */ current_drive = saved_drive; current_partition = saved_partition; @@ -3874,14 +2574,15 @@ dd_func (char *arg, int flags) in_partition = current_partition; current_drive = saved_drive; current_partition = saved_partition; -// fsys_type = in_fsys_type; + tmp_size = buf_size; if (grub_open (in_file)) { + if (SameFile_MoveBack) + in_pos = (in_count - 1) * buf_size + in_filepos; filepos = in_pos; - //tmp_size = buf_size; if (tmp_size > in_filemax - in_pos) tmp_size = in_filemax - in_pos; - if (grub_read (buf_addr, tmp_size, 0xedde0d90) != tmp_size) /* read */ + if (grub_read ((unsigned long long)(grub_size_t)buf_addr, tmp_size, 0xedde0d90) != tmp_size) /* read */ { if (errnum == 0) errnum = ERR_READ; @@ -3901,7 +2602,10 @@ dd_func (char *arg, int flags) if (errnum) goto end; - in_pos += tmp_size; + if (SameFile_MoveBack) + in_pos -= tmp_size; + else + in_pos += tmp_size; /* open out_file */ current_drive = saved_drive; @@ -3912,17 +2616,27 @@ dd_func (char *arg, int flags) out_partition = current_partition; current_drive = saved_drive; current_partition = saved_partition; -// fsys_type = out_fsys_type; if (grub_open (out_file)) { + if (SameFile_MoveBack) + { + out_pos = (in_count - 1) * buf_size + out_filepos; + if (out_pos >= out_filemax || out_pos < out_filepos) + { + out_pos = tmp_size; + goto asd; + } + } + filepos = out_pos; if (tmp_size > out_filemax - out_pos) tmp_size = out_filemax - out_pos; - if (grub_read (buf_addr, tmp_size, 0x900ddeed) != tmp_size) /* write */ + if (grub_read ((unsigned long long)(grub_size_t)buf_addr, tmp_size, 0x900ddeed) != tmp_size) /* write */ { if (errnum == 0) errnum = ERR_WRITE; } +asd: { int err = errnum; grub_close (); @@ -3938,30 +2652,37 @@ dd_func (char *arg, int flags) if (errnum) goto end; - out_pos += tmp_size; - count++; + if (SameFile_MoveBack) + out_pos -= tmp_size; + else + out_pos += tmp_size; + +// count++; + in_count--; } end: - + if (SameFile_MoveBack) + { + in_pos = in_filemax - in_filepos; + out_pos = out_filemax - out_filepos; + } + else { in_pos -= in_filepos; - out_pos -= out_filepos; + out_pos -= out_filepos;} if (debug > 0) { int err = errnum; - printf_debug0 ("\nBytes read / written = 0x%lX / 0x%lX\n", (unsigned long long)in_pos, (unsigned long long)out_pos); + printf_debug ("\nBytes read / written = 0x%lX / 0x%lX\n", (unsigned long long)in_pos, (unsigned long long)out_pos); errnum = err; } } fail: -// if (*(long *)(in_file - 1) == 0x2F292869) /* i()/ */ -// *(unsigned short *)in_file = 0x3D66; /* f= */ -// if (*(long *)(out_file - 1) == 0x2F29286F) /* o()/ */ -// *(unsigned short *)out_file = 0x3D66; /* f= */ - + if (buf_addr) + grub_free (buf_addr); return !(errnum); } @@ -3970,7 +2691,7 @@ static struct builtin builtin_dd = "dd", dd_func, BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, - "dd if=IF of=OF [bs=BS] [count=C] [skip=IN] [seek=OUT] [buf=ADDR] [buflen=SIZE]", + "dd if=IF of=OF [bs=BS] [count=C] [skip=IN] [seek=OUT]", "Copy file IF to OF. BS is blocksize, default to 512. C is blocks to copy," " default is total blocks in IF. IN specifies number of blocks to skip when" " read, default is 0. OUT specifies number of blocks to skip when write," @@ -3979,13 +2700,13 @@ static struct builtin builtin_dd = " of IF will be discarded. OF cannot be a gzipped file. If IF is a gzipped" " file, it will be decompressed automatically when copying. dd is dangerous," " use at your own risk. To be on the safe side, you should only use dd to" - " write a file in memory. ADDR and SIZE are used for user-defined buffer." - " ADDR default at 1M, and SIZE default to 64K." + " write a file in memory." }; - -/* debug */ +/* debug */ +unsigned int ctrl_c_trap = 1; +static int debug_func (char *arg, int flags); static int debug_func (char *arg, int flags) { @@ -4009,6 +2730,12 @@ debug_func (char *arg, int flags) { debug_msg = arg[4] & 7; } + else if (grub_memcmp (arg, "ctrl-c-trap=", 12) == 0) + { + arg += 12; + if (safe_parse_maxint (&arg, &tmp_debug)) + ctrl_c_trap = tmp_debug; + } else if (safe_parse_maxint (&arg, &tmp_debug)) { debug = tmp_debug; @@ -4017,9 +2744,11 @@ debug_func (char *arg, int flags) { int ret; debug_prog = 1; + debug_bat = 1; ret = command_func(arg,flags); debug_prog = 0; - debug_check_memory = 0; + debug_bat = 0; +// debug_check_memory = 0; return ret; } @@ -4031,15 +2760,17 @@ struct builtin builtin_debug = "debug", debug_func, BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, - "debug [on | off | normal | status | INTEGER]" + "debug [on | off | normal | status | ctrl-c-trap= | INTEGER]" "\ndebug Batch [ARGS]" "\ndebug msg=N", "Turn on/off or display/set the debug level or Single-step Debug for batch script" "\nmsg=N,sets the message level: 0:off,1-3:on." + "\nctrl-c-trap=0 (do not check); ctrl-c-trap=1 *(check for ctrl+c)." }; - + /* default */ +static int default_func (char *arg, int flags); static int default_func (char *arg, int flags) { @@ -4072,11 +2803,10 @@ default_func (char *arg, int flags) char buf[10]; /* This is good enough. */ p = buf; - len = grub_read ((unsigned long long)(unsigned int)buf, sizeof (buf), 0xedde0d90); + len = grub_read ((unsigned long long)(grub_size_t)buf, sizeof (buf), 0xedde0d90); printf_debug("len=%d", (unsigned long)len); if (len > 0) { - //unsigned long long ull; buf[sizeof (buf) - 1] = 0; safe_parse_maxint (&p, &ull); saved_entryno = ull; @@ -4107,7 +2837,7 @@ default_func (char *arg, int flags) return ! (errnum = ERR_DEFAULT_FILE); } - len = grub_read ((unsigned long long)(unsigned long)mbr, SECTOR_SIZE, 0xedde0d90); + len = grub_read ((unsigned long long)(grub_size_t)mbr, SECTOR_SIZE, 0xedde0d90); grub_close (); @@ -4122,7 +2852,7 @@ default_func (char *arg, int flags) return ! (errnum = ERR_DEFAULT_FILE); len = grub_strlen (arg); - if (len >= sizeof (default_file) /* DEFAULT_FILE_BUFLEN */) + if (len >= (int)sizeof (default_file) /* DEFAULT_FILE_BUFLEN */) return ! (errnum = ERR_WONT_FIT); grub_memmove (default_file, arg, len); @@ -4155,138 +2885,116 @@ static struct builtin builtin_default = " FILE." }; -static int terminal_func (char *arg, int flags); +//static int terminal_func (char *arg, int flags); #ifdef SUPPORT_GRAPHICS -extern char splashimage[128]; +char splashimage[128] = {0}; int graphicsmode_func (char *arg, int flags); -unsigned long X_offset,Y_offset; +unsigned int X_offset,Y_offset; unsigned char animated_type=0; //bit 0-3:times bit 4:repeat forever bit 7:transparent background type=00:disable unsigned short animated_delay; unsigned char animated_last_num; unsigned short animated_offset_x; unsigned short animated_offset_y; -char animated_name[57]; -unsigned long fill_color; -int splashimage_func(char *arg, int flags); +char animated_name[128]; +unsigned int fill_color; int background_transparent=0; +int splashimage_func(char *arg, int flags); int splashimage_func(char *arg, int flags) { - errnum = 0; - /* If ARG is empty, we reset SPLASHIMAGE. */ - unsigned long type = 0; - unsigned long h,w; - unsigned long long val; - int backup_x, backup_y; - X_offset=0,Y_offset=0; - fill_color = 0; - if (*arg) - { - if (strlen(arg) > 127) - return ! (errnum = ERR_WONT_FIT); - - if (grub_memcmp (arg, "--offset=", 9) == 0) //--offset=type=x=y - { - arg += 9; - if (safe_parse_maxint (&arg, &val)) - if (val & 0x80) - background_transparent=1; - arg++; - if (safe_parse_maxint (&arg, &val)) - X_offset = val; - arg++; - if (safe_parse_maxint (&arg, &val)) - Y_offset = val; - arg = skip_to (0, arg); - } - else if (grub_memcmp (arg, "--fill-color=", 13) == 0) - { - if (graphics_mode < 0xFF) - return !(errnum = ERR_NO_VBE_BIOS); - arg += 13; - if (safe_parse_maxint (&arg, &val)) - { - fill_color = val; - vbe_fill_color(fill_color); - goto fill; - } - return 0; - } - else if (grub_memcmp (arg, "--animated=", 11) == 0) - { - arg += 11; - if (safe_parse_maxint (&arg, &val)) - { - animated_type = val; - if (!animated_type) - return 1; - } - arg++; - if (safe_parse_maxint (&arg, &val)) + errnum = 0; + /* If ARG is empty, we reset SPLASHIMAGE. */ + unsigned long long val; + int backup_x, backup_y; + X_offset=0,Y_offset=0; + fill_color = 0; + if (*arg) { - if (arg[0]==':' && arg[1]=='m' && arg[2]=='s') + if (strlen(arg) > 127) + return ! (errnum = ERR_WONT_FIT); + + if (grub_memcmp (arg, "--offset=", 9) == 0) //--offset=type=x=y + { + arg += 9; + if (safe_parse_maxint (&arg, &val)) + if ((val & 0x80) == 0x80) + background_transparent=1; + arg++; + if (safe_parse_maxint (&arg, &val)) + X_offset = val; + arg++; + if (safe_parse_maxint (&arg, &val)) + Y_offset = val; + arg = skip_to (0, arg); + } + else if (grub_memcmp (arg, "--fill-color=", 13) == 0) { - animated_delay = val; - arg += 3; + if (graphics_mode < 0xFF) + return !(errnum = ERR_NO_VBE_BIOS); + arg += 13; + if (safe_parse_maxint (&arg, &val)) + { + fill_color = val; +// vbe_fill_color(fill_color); + goto fill; + } + return 0; } - else - animated_delay = val * 55; - } - arg++; - if (safe_parse_maxint (&arg, &val)) - animated_last_num = val; - arg++; - if (safe_parse_maxint (&arg, &val)) - animated_offset_x = val; - arg++; - if (safe_parse_maxint (&arg, &val)) - animated_offset_y = val; - arg = skip_to (0, arg); + else if (grub_memcmp (arg, "--animated=", 11) == 0) + { + arg += 11; + if (safe_parse_maxint (&arg, &val)) + { + animated_type = val; + if (!animated_type) + return 1; + } + arg++; + if (safe_parse_maxint (&arg, &val)) + { + if (arg[0]==':' && arg[1]=='m' && arg[2]=='s') + { + animated_delay = val; + arg += 3; + } + else + animated_delay = val * 55; + } + arg++; + if (safe_parse_maxint (&arg, &val)) + animated_last_num = val; + arg++; + if (safe_parse_maxint (&arg, &val)) + animated_offset_x = val; + arg++; + if (safe_parse_maxint (&arg, &val)) + animated_offset_y = val; + arg = skip_to (0, arg); - strcpy(animated_name, arg); - animated(); - return 1; - } - - if (! grub_open(arg)) - return 0; - grub_read((unsigned long long)(unsigned int)&type,2,GRUB_READ); - if (type == 0x4D42) - { - filepos = 18; - grub_read((unsigned long long)(unsigned int)&w,4,GRUB_READ); - grub_read((unsigned long long)(unsigned int)&h,4,GRUB_READ); - } - grub_close(); + strcpy(animated_name, arg); + animated(); + return 1; + } } + strcpy(splashimage, arg); - strcpy(splashimage, arg); - if (graphics_mode < 0xFF) - { - if (type == 0x4D42 && !graphics_inited) //BMP - { - char tmp[16]; - sprintf(tmp,"-1 %d %d",w,h); - if (graphicsmode_func(tmp,1)) - return 1; - } - else - return 0; - } - if (! animated_type && ! graphic_type ) - graphics_end(); +// if (! animated_type && ! graphic_type ) +// graphics_end(); graphics_inited = 0; fill: - current_term = term_table + 1; /* terminal graphics */ +// current_term = term_table + 1; /* terminal graphics */ backup_x = fontx; backup_y = fonty; + if (! graphics_init()) + { return ! (errnum = ERR_EXEC_FORMAT); - //graphics_cls(); + } fontx = backup_x; fonty = backup_y; - return 1; + menu_tab_ext |= 2; //已加载背景图像 + return 1; } static struct builtin builtin_splashimage = @@ -4296,76 +3004,21 @@ static struct builtin builtin_splashimage = BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_MENU | BUILTIN_HELP_LIST, "splashimage [--offset=[type]=[x]=[y]] FILE", "type: bit 7:transparent background\n" + "FILE: as the background image when in graphics mode.\n" "splashimage --fill-color=[0xrrggbb]\n" "splashimage --animated=[type]=[duration]=[last_num]=[x]=[y] START_FILE\n" - "type: bit 0-3:times(0=repeat play) bit 5:alone\n" - " bit 7:transparent background type=00:disable\n" + "type: bit 0-4: 0x01-0x0f=play n times, 0x10=infinite play.\n" + " bit 5:1=show the menu after playing , 0=Play in the menu.\n" + " bit 7:1=transparent, 0=opaque.\n" + "If type=0, stop working.\n" "duration: [10] unit is a tick. [10:ms] units are milliseconds,\n" "naming rules for START_FILE: *n.??? n: 1-9 or 01-99 or 001-999\n" - "hotkey F2,control animation: play/stop.\n" - "Load FILE as the background image when in graphics mode." -}; - - -/* foreground */ -static int -foreground_func(char *arg, int flags) -{ - errnum = 0; - if (grub_strlen(arg) == 6 && graphics_inited ) { - int r = (hex(arg[0]) << 4) | hex(arg[1]); - int g = (hex(arg[2]) << 4) | hex(arg[3]); - int b = (hex(arg[4]) << 4) | hex(arg[5]); - - foreground = (r << 16) | (g << 8) | b; - graphics_set_palette(15, foreground); - return 1; - } - - return 0; -} - -static struct builtin builtin_foreground = -{ - "foreground", - foreground_func, - BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_MENU | BUILTIN_HELP_LIST, - "foreground RRGGBB", - "Sets the foreground color when in graphics mode." - "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal." -}; - - -/* background */ -static int -background_func(char *arg, int flags) -{ - errnum = 0; - if (grub_strlen(arg) == 6 && graphics_inited) { - int r = (hex(arg[0]) << 4) | hex(arg[1]); - int g = (hex(arg[2]) << 4) | hex(arg[3]); - int b = (hex(arg[4]) << 4) | hex(arg[5]); - - background = (r << 16) | (g << 8) | b; - graphics_set_palette(0, background); - return 1; - } - - return 0; -} - -static struct builtin builtin_background = -{ - "background", - background_func, - BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_MENU | BUILTIN_HELP_LIST, - "background RRGGBB", - "Sets the background color when in graphics mode." - "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal." + "hotkey F2,control animation: play/stop." }; #endif /* SUPPORT_GRAPHICS */ +static int in_range (char *range, unsigned long long val); static int in_range (char *range, unsigned long long val) { @@ -4374,7 +3027,7 @@ in_range (char *range, unsigned long long val) for (;;) { - if (! safe_parse_maxint (&range, &start_num)) + if (! safe_parse_maxint ((char **)&range, &start_num)) break; if (val == start_num) return 1; @@ -4387,7 +3040,7 @@ in_range (char *range, unsigned long long val) break; range++; - if (! safe_parse_maxint (&range, &end_num)) + if (! safe_parse_maxint ((char **)&range, &end_num)) break; if ((long long)val > (long long)start_num && (long long)val <= (long long)end_num) return 1; @@ -4408,7 +3061,7 @@ int checkrange_func(char *arg, int flags) { struct builtin *builtin1; - unsigned long ret; + unsigned int ret; char *arg1; errnum = 0; @@ -4416,22 +3069,22 @@ checkrange_func(char *arg, int flags) builtin1 = find_command (arg1); - if ((int)builtin1 != -1) + if ((grub_size_t)builtin1 != (grub_size_t)-1) if (! builtin1 || ! (builtin1->flags & flags)) { errnum = ERR_UNRECOGNIZED; return 0; } - if ((int)builtin1 == -1 || ((builtin1->func) != errnum_func && (builtin1->func) != checkrange_func)) + if ((grub_size_t)builtin1 == (grub_size_t)-1 || ((builtin1->func) != errnum_func && (builtin1->func) != checkrange_func)) errnum = 0; - if ((int)builtin1 != -1) + if ((grub_size_t)builtin1 != (grub_size_t)-1) ret = (builtin1->func) (skip_to (1, arg1), flags); else ret = command_func (arg1, flags); - if ((int)builtin1 != -1) + if ((grub_size_t)builtin1 != (grub_size_t)-1) if ((builtin1->func) == errnum_func /*|| (builtin1->func) == checkrange_func*/) errnum = 0; if (errnum) @@ -4450,10 +3103,12 @@ static struct builtin builtin_checkrange = }; /* checktime */ +static int checktime_func(char *arg, int flags); static int checktime_func(char *arg, int flags) { - unsigned long date,time; +// unsigned long date,time; + struct grub_datetime datetime; int day, month, year, sec, min, hour, dow, ii; int limit[5][2] = {{0, 59}, {0, 23}, {1, 31}, {1, 12}, {0, 7}}; int field[5]; @@ -4470,27 +3125,13 @@ checktime_func(char *arg, int flags) return (day + y + y / 4 - y / 100 + y / 400 + (31 * m / 12)) % 7; } - get_datetime(&date, &time); - - day = ((date >> 4) & 0xF) * 10 + (date & 0xF); - date >>= 8; - - month = ((date >> 4) & 0xF) * 10 + (date & 0xF); - date >>= 8; - - year = ((date >> 4) & 0xF) * 10 + (date & 0xF); - date >>= 8; - year += (((date >> 4) & 0xF) * 10 + (date & 0xF)) * 100; - - time >>= 8; - - sec = ((time >> 4) & 0xF) * 10 + (time & 0xF); - time >>= 8; - - min = ((time >> 4) & 0xF) * 10 + (time & 0xF); - time >>= 8; - - hour = ((time >> 4) & 0xF) * 10 + (time & 0xF); + get_datetime(&datetime); + year = datetime.year; + month = datetime.month; + day = datetime.day; + hour = datetime.hour; + min = datetime.minute; + sec = datetime.second; dow = get_day_of_week(); @@ -4503,7 +3144,7 @@ checktime_func(char *arg, int flags) if (! arg[0]) { grub_printf ("%d-%02d-%02d %02d:%02d:%02d %d\n", year, month, day, hour, min, sec, dow); - return time; + return hour; } for (ii = 0; ii < 5; ii++) @@ -4541,7 +3182,7 @@ checktime_func(char *arg, int flags) m2 = m1; } - if ((m1 < limit[ii][0]) || (m2 > limit[ii][1]) || (m1 > m2)) + if ((m1 < (unsigned long long)limit[ii][0]) || (m2 > (unsigned long long)limit[ii][1]) || (m1 > m2)) return 0; if (*p == '/') @@ -4553,7 +3194,7 @@ checktime_func(char *arg, int flags) else m3 = 1; - for (j = m1; j <= m2; j+= m3) + for (j = m1; j <= (int)m2; j+= m3) { if (j == field[ii]) { @@ -4590,6 +3231,7 @@ static struct builtin builtin_checktime = }; /* clear */ +static int clear_func(); static int clear_func() { @@ -4611,90 +3253,125 @@ static struct builtin builtin_clear = }; /* displaymem */ -static int +int displaymem_func (char *arg, int flags); +int displaymem_func (char *arg, int flags) { - errnum = 0; - int sector = 0; + grub_efi_uintn_t mmap_size = 0x3000; + grub_efi_uintn_t desc_size; + grub_efi_memory_descriptor_t *memory_map; + grub_efi_memory_descriptor_t *desc; + grub_efi_status_t status; //状态 + grub_efi_boot_services_t *b; + b = grub_efi_system_table->boot_services; //系统表->引导服务 + int mm_status; //分配内存状态=1/0/-1=成功/部分/失败 + int i, mode = 0; + quit_print = 0; //满屏按“Q”退出打印 - if (grub_memcmp (arg, "--s", 3) == 0) - sector = 1; - if (!sector) - { - if (get_eisamemsize () != -1) - grub_printf (" EISA Memory BIOS Interface is present\n"); - if (get_mmap_entry ((void *) SCRATCHADDR, 0) != 0 - || *((int *) SCRATCHADDR) != 0) - grub_printf (" Address Map BIOS Interface is present\n"); - - grub_printf (" Lower memory: %uK, " - "Upper memory (to first chipset hole): %uK\n", - (unsigned long)saved_mem_lower, (unsigned long)saved_mem_upper); - } -#if 0 - if (mbi.flags & MB_INFO_MEM_MAP) - { - struct AddrRangeDesc *map = (struct AddrRangeDesc *) saved_mmap_addr; - unsigned long end_addr = saved_mmap_addr + saved_mmap_length; + if (grub_memcmp (arg, "-s", 2) == 0) //以扇区数计, 简约模式 + mode = 1; + else if (grub_memcmp (arg, "-a", 2) == 0) //以字节计, 全部显示 + mode = 2; + else if (grub_memcmp (arg, "-mem", 4) == 0) //探测4GB以上满足条件的可用内存 + mode = 3; + else if (grub_memcmp (arg, "-init", 5) == 0) //获得内存信息 + mode = 4; + else //以字节计, 简约模式(默认) + mode = 0; + +// memory_map = grub_malloc (0x3000); + status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES, + GRUB_EFI_LOADER_CODE, mmap_size >> 11, (grub_efi_physical_address_t *)&memory_map); //调用(分配页面,分配类型->任意页面,存储类型->装载程序代码(1),分配页,地址) + if (status) //如果失败 + printf_warning ("cannot allocate memory\n"); //无法分配内存 - grub_printf (" [Address Range Descriptor entries " - "immediately follow (values are 64-bit)]\n"); - while (end_addr > (unsigned long) map) + mm_status = grub_efi_get_memory_map (&mmap_size, memory_map, 0, &desc_size, 0); //获得内存映射(映射尺寸,映射页,0,描述尺寸,0) 返回1/0/-1=成功/部分/失败 + //获得内存描述符尺寸desc_size, 获得可用内存描述符集地址偏移map_size + if (mm_status == 0) //如果是部分 { - char *str; - - if (map->Type == MB_ARD_MEMORY) - str = "Usable RAM"; - else - str = "Reserved "; + efi_call_2 (b->free_pages, (grub_efi_physical_address_t)(grub_size_t)memory_map, mmap_size >> 11); //(释放页,地址,页) + mmap_size += desc_size * 32; //增大内存尺寸 + status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES, + GRUB_EFI_LOADER_CODE, mmap_size >> 11, (grub_efi_physical_address_t *)&memory_map); //调用(分配页面,分配类型->任意页面,存储类型->装载程序代码(1),分配页,地址) + if (! memory_map) //如果失败 + printf_warning ("cannot allocate memory\n"); //无法分配内存 - if (!sector ) - { - grub_printf (" %s: Base: 0x%8lX, Length: 0x%8lX\n", - str, - (unsigned long long)(map->BaseAddr), - (unsigned long long)(map->Length)); - } - else if (map->Type == MB_ARD_MEMORY) - { - grub_printf (" Usable (Hex sectors): Base: %8lX, Length: %8lX, End: %8lX\n", - (unsigned long long)(map->BaseAddr) >> 9, - (unsigned long long)(map->Length) >> 9, - (unsigned long long)(map->BaseAddr + map->Length) >> 9); - } - - map = ((struct AddrRangeDesc *) (((int) map) + 4 + map->size)); + mm_status = grub_efi_get_memory_map (&mmap_size, memory_map, 0, &desc_size, 0); //获得内存映射 } - } -#else - grub_printf (" [Address Range Descriptor entries " - "immediately follow (values are 64-bit)]\n"); + + if (mm_status < 0) //如果失败 + printf_warning ("cannot get memory map\n"); //无法分配内存 - unsigned long cont, addr; - addr = SCRATCHADDR; - cont = 0; - do + grub_efi_get_memory_map (&mmap_size, memory_map, 0, &desc_size, 0); + + for (desc = memory_map, i = 0; + desc < NEXT_MEMORY_DESCRIPTOR (memory_map, mmap_size); + desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size), i++) //下一个内存描述符(描述符,尺寸) { - cont = get_mmap_entry ((void *) addr, cont); /* int15/e820 ------ will write memory! */ - struct AddrRangeDesc *map = (struct AddrRangeDesc *) addr; - if (!sector) - { - grub_printf (" %s: Base: 0x%8lX, Length: 0x%8lX, End: 0x%8lX\n", - (map->Type == MB_ARD_MEMORY)?"Usable RAM":"Reserved ", - map->BaseAddr, - map->Length, - map->BaseAddr + map->Length); - } - else if (map->Type == MB_ARD_MEMORY) - { - grub_printf (" Usable (Hex sectors): Base: %8lX, Length: %8lX, End: %8lX\n", - map->BaseAddr / 0x200, - map->Length / 0x200, - map->BaseAddr + map->Length / 0x200); - } + switch(mode) + { + case 2: + grub_printf ("Unit_Bytes: t=%x, p=%8lx, v=%8lx, n=%8lx, a=%8lx\n", + desc->type, desc->physical_start, desc->virtual_start, + desc->num_pages, desc->attribute); + break; + case 0: + if (desc->type != GRUB_EFI_CONVENTIONAL_MEMORY) + break; + grub_printf ("Unit_Bytes: Base=%8lX, Length=%8lX, End=%8lX\n", + desc->physical_start, + desc->num_pages << 12, + desc->physical_start + (desc->num_pages << 12)); + break; + case 1: + if (desc->type != GRUB_EFI_CONVENTIONAL_MEMORY) + break; + grub_printf ("Unit_Sector: Base=%8lX, Length=%8lX, End=%8lX\n", + desc->physical_start >> 9, + desc->num_pages << 3, + (desc->physical_start >> 9) + (desc->num_pages << 3)); + break; + case 3: + if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY //可用 + && desc->physical_start >= 0x100000000 //大于等于4GB + && desc->num_pages >= blklst_num_sectors) //大于等于指定内存 + { + blklst_num_sectors = desc->physical_start; //返回内存起始地址 +// grub_free (memory_map); + efi_call_2 (b->free_pages, (grub_efi_physical_address_t)(grub_size_t)memory_map, mmap_size >> 11); //(释放页,地址,页) + return 1; + } + case 4: + if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY) //可用 + { + if (desc->physical_start < 0x100000) //常规内存(Kb) 0-a0000 + { + if (desc->num_pages > saved_mem_lower) + { + free_mem_lower_start = desc->physical_start; + saved_mem_lower = desc->num_pages; + } + } + else if (desc->physical_start < 0x100000000) //扩展内存(Mb) 1M-4G + { + if (desc->num_pages > saved_mem_upper) + saved_mem_upper = desc->num_pages; + } + else //上位内存(Mb) 4G以上 + { + if (desc->num_pages > saved_mem_higher) + saved_mem_higher = desc->num_pages; + } + } + else + break; + } + if (quit_print) + break; } - while (cont); -#endif + +// grub_free (memory_map); + efi_call_2 (b->free_pages, (grub_efi_physical_address_t)(grub_size_t)memory_map, mmap_size >> 11); //(释放页,地址,页) return 1; } @@ -4703,10 +3380,11 @@ static struct builtin builtin_displaymem = "displaymem", displaymem_func, BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, - "displaymem [--s]", + "displaymem [-s|-a]", "Display what GRUB thinks the system address space map of the" " machine is, including all regions of physical RAM installed.\n" - "--s: Display Usable RAM in units of 512-byte sectors." + "-s: Display Usable RAM in units of 512-byte sectors.\n" + "-a: Display all information." }; /* errnum */ @@ -4727,6 +3405,7 @@ static struct builtin builtin_errnum = }; /* errorcheck */ +static int errorcheck_func (char *arg, int flags); static int errorcheck_func (char *arg, int flags) { @@ -4762,10 +3441,11 @@ static struct builtin builtin_errorcheck = }; /* fallback */ +static int fallback_func (char *arg, int flags); static int fallback_func (char *arg, int flags) { - unsigned long i = 0; + unsigned int i = 0; int go=0; /* The goto command will set errnum before calling this function. * Clearing the errnum here will cause goto to not work. @@ -4779,7 +3459,7 @@ fallback_func (char *arg, int flags) while (*arg) { unsigned long long entry; - unsigned long j; + unsigned int j; unsigned char c = *arg; if (c == '+' || c == '-') ++arg; @@ -4792,7 +3472,7 @@ fallback_func (char *arg, int flags) entry -= current_entryno; /* Remove duplications to prevent infinite looping. */ for (j = 0; j < i; j++) - if (entry == fallback_entries[j]) + if (entry == (unsigned long long)fallback_entries[j]) break; if (j != i) continue; @@ -4808,9 +3488,7 @@ fallback_func (char *arg, int flags) fallback_entries[i] = -1; fallback_entryno = (i == 0) ? -1 : 0; -// if (go) return (errnum = MAX_ERR_NUM); if (go) return (errnum = 1000); -// return 1; return 0; } @@ -4828,12 +3506,14 @@ static struct builtin builtin_fallback = }; /* command */ -static char command_path[128]="(bd)/BOOT/GRUB/"; -static int command_path_len = 15; -//#define GRUB_MOD_ADDR (SYSTEM_RESERVED_MEMORY - 0x100000) -#define GRUB_MOD_ADDR (0xF00000) +//static char command_path[128]="(bd)/BOOT/GRUB/"; +//static int command_path_len = 15; +static char command_path[128]="(bd)/efi/grub/"; +static int command_path_len = 14; +//#define GRUB_MOD_ADDR (0xF00000) #define UTF8_BAT_SIGN 0x54414221BFBBEFULL #define LONG_MOD_NAME_FLAG 0xEb + struct exec_array { union @@ -4841,22 +3521,23 @@ struct exec_array char sn[12]; struct { - unsigned long flag; - unsigned long len; + unsigned int flag; + unsigned int len; } ln; } name; - unsigned long len; + unsigned int len; char data[]; } *p_exec; -unsigned int mod_end = GRUB_MOD_ADDR; +//unsigned int mod_end = GRUB_MOD_ADDR; +static struct exec_array *grub_mod_find(const char *name); static struct exec_array *grub_mod_find(const char *name) { struct exec_array *p_mod = (struct exec_array *)GRUB_MOD_ADDR; char *pn; - unsigned long mod_len; - while ((unsigned int)p_mod < mod_end) + unsigned int mod_len; + while ((grub_size_t)p_mod < (grub_size_t)mod_end) { mod_len = p_mod->len; if (p_mod->name.ln.flag == LONG_MOD_NAME_FLAG) @@ -4869,15 +3550,16 @@ static struct exec_array *grub_mod_find(const char *name) if (substring(name,pn,1) == 0) return p_mod; - p_mod = (struct exec_array *)((unsigned int)(p_mod->data + mod_len + 0xf) & ~0xf); + p_mod = (struct exec_array *)((grub_size_t)(p_mod->data + mod_len + 0xf) & ~0xf); } return 0; } +static int grub_mod_add (struct exec_array *mod); static int grub_mod_add (struct exec_array *mod) { char *name; - unsigned long data_len = 16; + unsigned int data_len = 16; if (mod->name.ln.flag == LONG_MOD_NAME_FLAG) { name = mod->data + mod->len; @@ -4888,31 +3570,33 @@ static int grub_mod_add (struct exec_array *mod) if (grub_mod_find(name) == NULL) { - printf_debug("insmod:%s...\n",name); unsigned long long rd_base_bak = rd_base; unsigned long long rd_size_bak = rd_size; - rd_base = (unsigned long long)(unsigned int)mod->data; + rd_base = (unsigned long long)(grub_size_t)mod->data; rd_size = (unsigned long long)mod->len; buf_drive = -1; grub_open("(rd)+1"); data_len += filemax; - if ((mod_end + data_len) >= GRUB_MOD_ADDR + 0x100000) + if ((mod_end + data_len) >= GRUB_MOD_ADDR + 0x800000) { grub_close(); errnum = ERR_WONT_FIT; return 0; } - struct exec_array *p_mod = (struct exec_array *)mod_end; + struct exec_array *p_mod = (struct exec_array *)(grub_size_t)mod_end; p_mod->len = filemax; - grub_read((unsigned long long)(unsigned int)p_mod->data,-1,GRUB_READ); + grub_read((unsigned long long)(grub_size_t)p_mod->data,-1,GRUB_READ); grub_close(); rd_base = rd_base_bak; rd_size = rd_size_bak; - if (*(unsigned long long *)(int)(p_mod->data + p_mod->len - 8) != 0xBCBAA7BA03051805ULL - && *(unsigned long *)(int)p_mod->data != BAT_SIGN - && (*(unsigned long long *)(int)p_mod->data & 0xFFFFFFFFFFFFFFULL) != UTF8_BAT_SIGN) //!BAT with utf-8 BOM 0xBFBBEF + unsigned long long *a = (unsigned long long *)(p_mod->data + p_mod->len - 8); + unsigned int *b = (unsigned int *)p_mod->data; + unsigned long long *c = (unsigned long long *)p_mod->data; + if (*a != (unsigned long long)0xBCBAA7BA03051805ULL + && *b != BAT_SIGN + && (*c & (unsigned long long)0xFFFFFFFFFFFFFFULL) != UTF8_BAT_SIGN) //!BAT with utf-8 BOM 0xBFBBEF { errnum = ERR_EXEC_FORMAT; return 0; @@ -4920,7 +3604,7 @@ static int grub_mod_add (struct exec_array *mod) memmove((void *)p_mod->name.sn,(void*)mod->name.sn,sizeof(mod->name)); if (p_mod->name.ln.flag == LONG_MOD_NAME_FLAG) memmove((void*)(p_mod->data + p_mod->len),(void*)(mod->data + mod->len),p_mod->name.ln.len); - mod_end = ((unsigned int)mod_end + data_len + 0xf) & ~0xf; + mod_end = (char *)(grub_size_t)(((grub_size_t)mod_end + data_len + 0xf) & ~0xf); printf_debug0("%s loaded\n",name); } else @@ -4928,13 +3612,14 @@ static int grub_mod_add (struct exec_array *mod) return 1; } +static int grub_mod_list(const char *name); static int grub_mod_list(const char *name) { struct exec_array *p_mod = (struct exec_array *)GRUB_MOD_ADDR; char *pn; - unsigned long mod_len; + unsigned int mod_len; int ret = 0; - while ((unsigned int)p_mod < mod_end) + while ((grub_size_t)p_mod < (grub_size_t)mod_end) { mod_len = p_mod->len; if (p_mod->name.ln.flag == LONG_MOD_NAME_FLAG) @@ -4948,19 +3633,20 @@ static int grub_mod_list(const char *name) if (*name == '\0' || substring(name,pn,1) == 0) { printf_debug0(" %s\n",pn); - ret = (int)p_mod->data; + ret = (grub_size_t)p_mod->data; } - p_mod = (struct exec_array *)((unsigned int)(p_mod->data + mod_len + 0xf) & ~0xf); + p_mod = (struct exec_array *)((grub_size_t)(p_mod->data + mod_len + 0xf) & ~0xf); } return ret; } +static int grub_mod_del(const char *name); static int grub_mod_del(const char *name) { struct exec_array *p_mod; char *pn; - unsigned long mod_len; - for (p_mod = (struct exec_array *)GRUB_MOD_ADDR; (unsigned int)p_mod < mod_end; p_mod = (struct exec_array *)((unsigned int)(p_mod->data + mod_len + 0xf) & ~0xf)) + grub_size_t mod_len; + for (p_mod = (struct exec_array *)GRUB_MOD_ADDR; (grub_size_t)p_mod < (grub_size_t)mod_end; p_mod = (struct exec_array *)((grub_size_t)(p_mod->data + mod_len + 0xf) & ~0xf)) { mod_len = p_mod->len; if (p_mod->name.ln.flag == LONG_MOD_NAME_FLAG) @@ -4972,13 +3658,13 @@ static int grub_mod_del(const char *name) pn = p_mod->name.sn; if (substring(name,pn,1) == 0) { - unsigned int next_mod = ((unsigned int)p_mod->data + mod_len + 0xf) & ~0xf; - if (next_mod == mod_end) - mod_end = (unsigned int)p_mod; + grub_size_t next_mod = ((grub_size_t)p_mod->data + mod_len + 0xf) & ~0xf; + if (next_mod == (grub_size_t)mod_end) + mod_end = (char *)p_mod; else { - memmove(p_mod,(char *)next_mod,mod_end - next_mod); - mod_end -= next_mod - (unsigned int)p_mod; + memmove(p_mod,(char *)next_mod,(grub_size_t)mod_end - next_mod); + mod_end -= next_mod - (grub_size_t)p_mod; } printf_debug0("%s unloaded.\n",name); return 1; @@ -4988,6 +3674,7 @@ static int grub_mod_del(const char *name) } static int grub_exec_run(char *program, char *psp, int flags); +static int test_open(char *path); static int test_open(char *path) { printf_debug ("CHECK: %s\n",path + command_path_len - 1); @@ -4998,19 +3685,22 @@ static int test_open(char *path) return 3; return 0; } + +static int command_open(char *arg,int flags); static int command_open(char *arg,int flags) { +#define t_path chainloader_file_orig if (*arg == '(' || *arg == '/') return grub_open(arg); - - if (skip_to(0,arg) - arg > 120) + if ((char *)skip_to(0,arg) - arg > 120) return 0; if (flags == 0 && (p_exec = grub_mod_find(arg))) return 2; - char t_path[512]; +// char t_path[512]; + grub_memset(t_path, 0, 256); int len = strlen(arg) + command_path_len; - if ((len + 1) >= sizeof(t_path)) + if ((len + 1) >= (int)sizeof(t_path)) { errnum = ERR_WONT_FIT; return 0; @@ -5053,11 +3743,13 @@ static int command_open(char *arg,int flags) } #endif return 0; +#undef t_path } int command_func (char *arg, int flags) { +#define file_path chainloader_file errnum = 0; while (*arg == ' ' || *arg == '\t') arg++; @@ -5073,7 +3765,7 @@ command_func (char *arg, int flags) return 1; return 0; } - + if (*arg <= ' ') { if (debug > 0) @@ -5087,7 +3779,7 @@ command_func (char *arg, int flags) return 20; } - if (*(short*)arg == 0x2d2d && *(long*)(arg+2) == 0x2d746573)// -- set- + if (*(short*)arg == 0x2d2d && *(int*)(arg+2) == 0x2d746573)// -- set- { arg += 6; if (grub_memcmp(arg,"path=",5) == 0) @@ -5095,8 +3787,9 @@ command_func (char *arg, int flags) arg += 5; if (! *arg) { - command_path_len = 15; - return grub_sprintf(command_path,"(bd)/BOOT/GRUB/"); +// command_path_len = 15; + command_path_len = 14; + return grub_sprintf(command_path,"(bd)/EFI/GRUB/"); } int j = grub_strlen(arg); @@ -5120,16 +3813,17 @@ command_func (char *arg, int flags) #endif arg -= 6; } - /* open the command file. */ - char *filename = arg; - char file_path[512]; - unsigned long arg_len = grub_strlen(arg);/*get length for build psp */ - char *cmd_arg = skip_to(SKIP_WITH_TERMINATE,arg);/* get argument of command */ + char *filename = arg; //文件名: g4e_wb abcdef +// char file_path[512]; + grub_memset(file_path, 0, 256); + unsigned int arg_len = grub_strlen(arg);/*get length for build psp */ //文件名尺寸 d + char *cmd_arg = skip_to(SKIP_WITH_TERMINATE,arg);/* get argument of command */ //命令参数: abcdef p_exec = NULL; + switch(command_open(filename,0)) { - case 2: + case 2: //grub_mod_find(arg) sprintf(file_path,"(md)/"); filemax = p_exec->len; break; @@ -5157,128 +3851,101 @@ command_func (char *arg, int flags) default: printf_errinfo ("Error: No such command: %s\n", arg); errnum = 0; /* No error, so that old menus will run smoothly. */ - //return 0; return 0;/* return 0 indicating a failure or a false case. */ } -#if 1 + if (filemax < 9ULL) { errnum = ERR_EXEC_FORMAT; goto fail; } -#endif + char *psp; - unsigned long psp_len; - unsigned long prog_len; + unsigned int psp_len; + unsigned int prog_len; char *program; - char *tmp; - prog_len = filemax; - psp_len = ((arg_len + strlen(file_path)+ 16) & ~0xF) + 0x10 + 0x20; -// psp = (char *)grub_malloc(prog_len * 2 + psp_len); - tmp = (char *)grub_malloc(prog_len + 4096 + 16 + psp_len); - -// if (psp == NULL) + char *tmp = 0, *tmp0 = 0; + prog_len = filemax; //程序(文件)尺寸 + psp_len = ((arg_len + strlen(file_path)+ 16) & ~0xF) + 0x10 + 0x20; //psp尺寸 +// tmp = (char *)grub_malloc(prog_len + 4096 + 16 + psp_len + 512); //缓存 + tmp = (char *)grub_memalign(4096, prog_len + 16 + psp_len + 512); //对齐4k分配缓存 if (tmp == NULL) { goto fail; } -// program = psp + psp_len;//(psp + psp_len) = entry point of program. - program = (char *)((int)(tmp + 4095) & ~4095); /* 4K align the program */ - psp = (char *)((int)(program + prog_len + 16) & ~0x0F); - - unsigned long long *end_signature = (unsigned long long *)(program + (unsigned long)filemax - 8); +// program = (char *)((grub_size_t)(tmp + 4095) & ~4095); /* 4K align the program 4K对齐程序*/ //程序缓存 + program = tmp; if (p_exec == NULL) { - /* read file to buff and check exec signature. */ - if ((grub_read ((unsigned long long)(int)program, -1ULL, 0xedde0d90) != filemax)) + /* read file to buff and check exec signature. 读取文件到程序缓存并检查exec签名*/ + if ((grub_read ((unsigned long long)(grub_size_t)program, -1ULL, 0xedde0d90) != filemax)) { if (! errnum) errnum = ERR_EXEC_FORMAT; } + //如果不是批处理 + if (*(unsigned int *)program != BAT_SIGN + && (*(unsigned long long *)program & 0xFFFFFFFFFFFFFFULL) != UTF8_BAT_SIGN) + { + char *p = program; + unsigned long long size = filemax; + //查找外部命令签名 + while ((long long)size > 0) + { + if (*(unsigned long long *)p == 0xBCBAA7BA03051805ULL) + break; //查到 + + size -= sizeof(grub_size_t); + p += sizeof(grub_size_t); + } + + unsigned long long len = p - program; + if ((long long)size <= 0) //没有签名,失败 + { + errnum = ERR_EXEC_FORMAT; + } + else if (len > 8) //存在尾续文件 + { + bat_md_start = (grub_size_t)(program + len + 8); //尾续文件起始 + bat_md_count = filemax - (len + 8); //尾续文件尺寸 + bat_md_count = (bat_md_count + 511) & (-512); //对齐512 + tmp0 = grub_memalign(512, bat_md_count); //给尾续文件分配新地址 + if (tmp0 == NULL) + { + grub_free(tmp); + goto fail; + } + grub_memmove64((unsigned long long)(grub_size_t)tmp0,bat_md_start,bat_md_count); //复制(未解压缩)尾续文件到新地址 + bat_md_start = (unsigned long long)(grub_size_t)tmp0 >> 9; + bat_md_count >>= 9; + + filemax = len + 8; //修正外部命令尺寸 + prog_len = filemax; //修正 + } + } +#if 0 else if (*end_signature == 0x85848F8D0C010512ULL) { if (filemax < 512 || filemax > 0x80000) errnum = ERR_EXEC_FORMAT; - else if (filemax + 0x10100 > ((*(unsigned short *)0x413) << 10)) - errnum = ERR_WONT_FIT; else { - unsigned long ret; - struct realmode_regs { - unsigned long edi; // input and output - unsigned long esi; // input and output - unsigned long ebp; // input and output - unsigned long esp; //stack pointer, input - unsigned long ebx; // input and output - unsigned long edx; // input and output - unsigned long ecx; // input and output - unsigned long eax;// input and output - unsigned long gs; // input and output - unsigned long fs; // input and output - unsigned long es; // input and output - unsigned long ds; // input and output - unsigned long ss; //stack segment, input - unsigned long eip; //instruction pointer, input - unsigned long cs; //code segment, input - unsigned long eflags; // input and output - }; - - struct realmode_regs regs; - ret = grub_strlen (cmd_arg); - /* first, backup low 640K memory to address 2M */ - grub_memmove ((char *)0x200000, 0, 0xA0000); - /* copy command-tail */ - if (ret > 126) - ret = 126; - if (ret) - grub_memmove ((char *)0x10081, cmd_arg, ret); - /* setup offset 0x80 for command-tail count */ - *(char *)0x10080 = ret; - /* end the command-tail with CR */ - *(char *)(0x10081 + ret) = 0x0D; - - /* clear the beginning word of DOS PSP. the program - * check it and see it is running under grub4dos. - * a normal DOS PSP should begin with "CD 20". - */ - *(short *)0x10000 = 0; - - /* copy program to 1000:0100 */ - grub_memmove ((char *)0x10100, (char *)program, filemax); - - /* setup DS, ES, CS:IP */ - regs.cs = regs.ds = regs.es = 0x1000; - regs.eip = 0x100; - - /* setup FS, GS, EFLAGS and stack */ - regs.ss = regs.esp = regs.fs = regs.gs = regs.eflags = -1; - - /* for 64K .com style command, setup stack */ - if (filemax < 0xFF00) - { - regs.ss = 0x1000; - regs.esp = 0xFFFE; - } grub_free(tmp); - grub_close(); - ret = realmode_run ((unsigned long)®s); - /* restore memory 0x10000 - 0xA0000 */ - grub_memmove ((char *)0x10000, (char *)0x210000, ((*(unsigned short *)0x413) << 10) - 0x10000); - return ret; + return 0; } } else if (*end_signature != 0xBCBAA7BA03051805ULL && - *(unsigned long *)program != BAT_SIGN && + *(unsigned int *)program != BAT_SIGN && (*(unsigned long long *)program & 0xFFFFFFFFFFFFFFULL) != UTF8_BAT_SIGN) { errnum = ERR_EXEC_FORMAT; } +#endif grub_close (); if (errnum) { -// grub_free(psp); grub_free(tmp); return 0; } @@ -5288,37 +3955,41 @@ command_func (char *arg, int flags) grub_memmove(program,p_exec->data,prog_len); } +// psp = (char *)((grub_size_t)(program + prog_len + 16) & ~0x0F); //psp地址 向上舍入,否则覆盖program数据 + psp = (char *)((grub_size_t)(program + prog_len + 16 + 512) & ~0x0F); //psp地址 向上舍入,否则覆盖program数据 + unsigned long long *end_signature = (unsigned long long *)(program + filemax - (unsigned long long)8); //程序结束签名地址 + if (*end_signature == 0xBCBAA7BA03051805ULL) { - if (*(unsigned long long *)(program + prog_len - 0x20) == 0x646E655F6E69616D) /* main_end New Version*/ +// if (*(unsigned long long *)(program + prog_len - 0x20) == 0x646E655F6E69616D) //bios模式:新版本标记 main_end + if (*(unsigned long long *)(program + prog_len - 0x20) == 0x646E655F69666575) //uefi模式:新版本标记 uefi_end { - char * tmp1; - char * program1; - unsigned long *bss_end = (unsigned long *)(program + prog_len - 0x24); - if (prog_len != *bss_end){ + unsigned int *prog_start = (unsigned int *)(program + prog_len - 0x3c); //.text + unsigned int *bss_end = (unsigned int *)(program + prog_len - 0x24); //end + + if (prog_len != (*bss_end - *prog_start)){ //如果bss区有数据,外部命令尺寸是filemax+bss尺寸 grub_free(tmp); - prog_len = *bss_end; - tmp1 = (char *)grub_malloc(prog_len + 4096 + 16 + psp_len); - if (tmp1 == NULL) - { + prog_len = *bss_end - *prog_start; + char *program1 = program; +// tmp = (char *)grub_malloc(prog_len + 4096 + 16 + psp_len); +// tmp = (char *)grub_malloc(prog_len + 4096 + 16 + psp_len + 512); + tmp = (char *)grub_memalign(4096, prog_len + 16 + psp_len + 512); //对齐4k分配缓存 + if (tmp == NULL) goto fail; - } - program1 = (char *)((int)(tmp1 + 4095) & ~4095); /* 4K align the program */ - if (tmp1 != tmp) - { - grub_memmove (program1, program, (unsigned long)filemax); - program = program1; - tmp = tmp1; - } - psp = (char *)((int)(program + prog_len + 16) & ~0x0F); +// program = (char *)((grub_size_t)(tmp + 4095) & ~4095); /* 4K align the program */ + program = tmp; + if (program != program1) + grub_memmove (program, program1, prog_len); +// psp = (char *)((grub_size_t)(program + prog_len + 16) & ~0x0F); + psp = (char *)((grub_size_t)(program + prog_len + 16 + 512) & ~0x0F); } } else {//the old program char *program1; printf_warning ("\nWarning! The program is outdated!\n"); psp = (char *)grub_malloc(prog_len + 4096 + 16 + psp_len); - grub_free(tmp); if (psp == NULL) { + grub_free(tmp); goto fail; } program1 = psp + psp_len; @@ -5333,22 +4004,13 @@ command_func (char *arg, int flags) grub_memmove (psp + 16, arg , arg_len + 1);/* copy args into somewhere in PSP. */ filename = psp + 16 + arg_len + 1; grub_strcpy(filename,file_path); - *(unsigned long *)psp = psp_len; -#if 0 - *(unsigned long *)(program - 4) = psp_len; /* PSP length in bytes. it is in both the starting dword and the ending dword of the PSP. */ - *(unsigned long *)(program - 8) = psp_len - 16 - (cmd_arg - arg); /* args is here. */ - *(unsigned long *)(program - 12) = flags; /* flags is here. */ - *(unsigned long *)(program - 16) = psp_len - 16;/*program filename here.*/ - *(unsigned long *)(program - 20) = prog_len;//program length - *(unsigned long *)(program - 24) = program - filename; -#else - *(unsigned long *)(psp + psp_len - 4) = psp_len; /* PSP length in bytes. it is in both the starting dword and the ending dword of the PSP. */ - *(unsigned long *)(psp + psp_len - 8) = psp_len - 16 - (cmd_arg - arg); /* args is here. */ - *(unsigned long *)(psp + psp_len - 12) = flags; /* flags is here. */ - *(unsigned long *)(psp + psp_len - 16) = psp_len - 16;/*program filename here.*/ - *(unsigned long *)(psp + psp_len - 20) = prog_len;//program length - *(unsigned long *)(psp + psp_len - 24) = psp_len - (filename - psp); -#endif + *(unsigned int *)psp = psp_len; + *(unsigned int *)(psp + psp_len - 4) = psp_len; /* PSP length in bytes. it is in both the starting dword and the ending dword of the PSP. */ + *(unsigned int *)(psp + psp_len - 8) = psp_len - 16 - (cmd_arg - arg); /* args is here. */ + *(unsigned int *)(psp + psp_len - 12) = flags; /* flags is here. */ + *(unsigned int *)(psp + psp_len - 16) = psp_len - 16;/*program filename here.*/ + *(unsigned int *)(psp + psp_len - 20) = prog_len;//program length + *(unsigned int *)(psp + psp_len - 24) = psp_len - (filename - psp); {//New psp info psp_info_t *PI = (psp_info_t*)psp; PI->proglen=prog_len; @@ -5358,11 +4020,12 @@ command_func (char *arg, int flags) /* (free_mem_start + pid - 16) is reserved for full pathname of the program file. */ int pid; ++prog_pid; - pid = grub_exec_run(program, psp, flags); /* on exit, release the memory. */ -// grub_free(psp); - grub_free(tmp); + if (tmp) + grub_free(tmp); + if (tmp0) + grub_free(tmp0); if (!(--prog_pid) && *CMD_RUN_ON_EXIT)//errnum = -1 on exit run. { errnum = 0; @@ -5374,6 +4037,7 @@ command_func (char *arg, int flags) fail: grub_close (); return 0; +#undef file_path } static struct builtin builtin_command = @@ -5387,13 +4051,27 @@ static struct builtin builtin_command = "--set-ext sets default extensions for executable files." }; +/* 模块结构 + * 首行: 16字节 05 18 05 03 BA A7 BA BC 00 00 00 00 00 00 00 00 + * 正文: + * 外部命令名称 12字节 + * 尺寸 4字节 + * 外部命令 + * 下一正文 + */ static int insmod_func(char *arg,int flags) { errnum = 0; if (arg == NULL || *arg == '\0') return 0; char *name = skip_to(1|SKIP_WITH_TERMINATE,arg); - if (substring(skip_to(0,arg) - 4,".mod",1) == 0) + + if (!GRUB_MOD_ADDR) + { + GRUB_MOD_ADDR = grub_malloc (0x800000); //模块缓存 + mod_end = GRUB_MOD_ADDR; + } + if (substring(skip_to(0,arg) - 4,".mod",1) == 0 || flags == 101) { if (!command_open(arg,1)) return 0; @@ -5403,7 +4081,7 @@ static int insmod_func(char *arg,int flags) grub_close(); return 0; } - if (grub_read((unsigned long long)(unsigned int)buff,-1,GRUB_READ) != filemax) + if (grub_read((unsigned long long)(grub_size_t)buff,-1,GRUB_READ) != filemax) { grub_close(); grub_free(buff); @@ -5415,6 +4093,11 @@ static int insmod_func(char *arg,int flags) //skip grub4dos moduld head. if (strcmp(p_mod->name.sn,"\x05\x18\x05\x03\xBA\xA7\xBA\xBC") == 0) ++p_mod; + else + { + grub_free(buff); + goto external_command; + } while ((char *)p_mod < buff_end && grub_mod_add(p_mod)) { p_mod = (struct exec_array *)(p_mod->data + p_mod->len); @@ -5422,10 +4105,12 @@ static int insmod_func(char *arg,int flags) grub_free(buff); return 1; } + +external_command: switch(command_open(arg,0)) { case 2: - printf_debug0("%s already loaded\n",arg); + printf_debug("%s already loaded\n",arg); return 1; case 0: return 0; @@ -5436,7 +4121,7 @@ static int insmod_func(char *arg,int flags) int ret = 0; if (p_mod == NULL) return 0; - if (grub_read((unsigned long long)(unsigned int)p_mod->data,-1,GRUB_READ) != filemax) + if (grub_read((unsigned long long)(grub_size_t)p_mod->data,-1,GRUB_READ) != filemax) { grub_close(); grub_free(p_mod); @@ -5476,10 +4161,11 @@ static struct builtin builtin_insmod = "insmod", insmod_func, BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST | BUILTIN_IFTITLE, - "insmod MODFILE|FILE.MOD [name]", + "insmod MODFILE|FILE.MOD", "FILE.MOD is MODFILE package, it has multiple MODFILE" }; +static int delmod_func(char *arg,int flags); static int delmod_func(char *arg,int flags) { errnum = 0; @@ -5493,6 +4179,9 @@ static int delmod_func(char *arg,int flags) if (*arg == '*') { + if (GRUB_MOD_ADDR) + grub_free (GRUB_MOD_ADDR); + GRUB_MOD_ADDR = 0; mod_end = GRUB_MOD_ADDR; return 1; } @@ -5513,11 +4202,8 @@ static struct builtin builtin_delmod = int commandline_func (char *arg, int flags) { - int forever = 0; - char *config_entries = arg; - errnum = 0; - enter_cmdline(config_entries, forever); + enter_cmdline(arg, 0); return 1; } @@ -5531,219 +4217,32 @@ static struct builtin builtin_commandline = "Enter command-line prompt mode." }; -extern int bsd_evil_hack; - -//extern unsigned long dest_partition; -//static unsigned long entry; -//static unsigned long ext_offset; -#define GPT_ATTRIBUTE_NO_DRIVE_LETTER (0x8000000000000000LL) -#define GPT_ATTRIBUTE_HIDDEN (0x4000000000000000LL) -#define GPT_ATTRIBUTE_SHADOW_COPY (0x2000000000000000LL) -#define GPT_ATTRIBUTE_READ_ONLY (0x1000000000000000LL) -#define GPT_ATTR_HIDE (0xC000000000000001LL) -#define GPT_HDR_SIZE (0x5C) -static int gpt_set_crc(P_GPT_HDR hdr) -{ - char data[SECTOR_SIZE]; - int crc; - int errnum_bak = errnum; - - if (hdr->hdr_size != GPT_HDR_SIZE) - return 0; - errnum = 0; - sprintf(data,"(0x%X)0x%lx+%u,%u",current_drive,hdr->hdr_lba_table,32,hdr->hdr_entries * hdr->hdr_entsz); - crc = grub_crc32(data,0); - if (errnum) - return 0; - hdr->hdr_crc_table = crc; - hdr->hdr_crc_self = 0; - crc = grub_crc32((char*)hdr,GPT_HDR_SIZE); - if (errnum) - return 0; - hdr->hdr_crc_self = crc; - buf_track = -1; - if (! rawread (current_drive, hdr->hdr_lba_self ,0,GPT_HDR_SIZE, (unsigned long long)(unsigned int)hdr, GRUB_WRITE)) - return 0; - errnum = errnum_bak; - return hdr->hdr_crc_table; -} - -static int gpt_set_attr(P_GPT_HDR hdr,grub_u32_t part,grub_u64_t attr) -{ - GPT_ENT ent; - if (! rawread (current_drive, hdr->hdr_lba_table + (part >> 2), (part & 3) * sizeof(GPT_ENT), sizeof(GPT_ENT), (unsigned long long)(unsigned int)&ent, GRUB_READ)) - return 0; - - if (attr & 0xFF00) - ent.ms_attr.gpt_att = (unsigned short)attr; - else - ent.attributes = attr; - - buf_track = -1; - if (! rawread (current_drive, hdr->hdr_lba_table + (part >> 2), (part & 3) * sizeof(GPT_ENT), sizeof(GPT_ENT), (unsigned long long)(unsigned int)&ent, GRUB_WRITE)) - return 0; - return gpt_set_crc(hdr); -} - -static unsigned int gpt_slic_set_attr(grub_u32_t part,grub_u64_t attr) -{ - char data[SECTOR_SIZE]; - int crc1,crc2; - if (! rawread (current_drive, 1, 0, sizeof(GPT_HDR), (unsigned long long)(unsigned int)data, GRUB_READ)) - return 0; - P_GPT_HDR hdr = (P_GPT_HDR)data; - crc1 = gpt_set_attr(hdr,part,attr); - if (!crc1) - return 0; - if (! rawread (current_drive, hdr->hdr_lba_alt, 0, sizeof(GPT_HDR), (unsigned long long)(unsigned int)data, GRUB_READ)) - return 0; - crc2 = gpt_set_attr(hdr,part,attr); - if (!crc2) - return 0; - if (debug > 1 && crc1 != crc2) - printf("Warning! Main partition table CRC mismatch!"); - return 1; -} - -static unsigned long long gpt_slic_get_attr(char *data,unsigned long part) -{ - P_GPT_ENT p = (P_GPT_ENT)data; - return p->attributes; -} - -/* Hide/Unhide CURRENT_PARTITION. */ -static int -set_partition_hidden_flag (int hidden) -{ - unsigned long part = 0xFFFFFF; - unsigned long long start, len, offset; - unsigned long type, entry1, ext_offset1; - -#if 0 - /* The drive must be a hard disk. */ - if (! (current_drive & 0x80)) - { - errnum = ERR_BAD_ARGUMENT; - return 0; - } -#endif - - /* The partition must be a PC slice. */ - if ((current_partition >> 16) == 0xFF - || (current_partition & 0xFFFF) != 0xFFFF) - { - errnum = ERR_BAD_ARGUMENT; - return 0; - } - - /* Look for the partition. */ - while (( next_partition_drive = current_drive, - next_partition_dest = current_partition, - next_partition_partition = &part, - next_partition_type = &type, - next_partition_start = &start, - next_partition_len = &len, - next_partition_offset = &offset, - next_partition_entry = &entry1, - next_partition_ext_offset = &ext_offset1, - next_partition_buf = mbr, - next_partition ())) -// while (next_partition (current_drive, 0xFFFFFF, &part, &type, -// &start, &len, &offset, &entry, -// &ext_offset, mbr)) - { - if (part == current_partition) - { - int part_num = (unsigned long)(unsigned char)(part>>16); - grub_u64_t part_attr = 0LL,is_hidden; - if (type == PC_SLICE_TYPE_GPT) - { - part_attr = gpt_slic_get_attr(mbr,part_num); - is_hidden = !!(part_attr & GPT_ATTR_HIDE); - } - else - is_hidden = PC_SLICE_TYPE (mbr, entry1) & PC_SLICE_TYPE_HIDDEN_FLAG; - /* Found. */ - if (hidden == -1) /* status only */ - { - printf_debug0 ("Partition (%cd%d,%d) is %shidden.\n", - ((current_drive & 0x80) ? 'h' : 'f'), - (current_drive & ~0x80), - part_num, - (is_hidden ? "" : "not ")); - - return is_hidden; - } - - /* Check if the hidden flag need change. */ - if ((!hidden) != (!is_hidden)) - { - if (type == PC_SLICE_TYPE_GPT) - { - if (hidden) - part_attr |= GPT_ATTR_HIDE; - else - part_attr &= ~GPT_ATTR_HIDE; - - if (!gpt_slic_set_attr(part_num,part_attr)) - return 0; - } else { - if (hidden) - PC_SLICE_TYPE (mbr, entry1) |= PC_SLICE_TYPE_HIDDEN_FLAG; - else - PC_SLICE_TYPE (mbr, entry1) &= ~PC_SLICE_TYPE_HIDDEN_FLAG; - - /* Write back the MBR to the disk. */ - buf_track = -1; - if (! rawwrite (current_drive, offset, (unsigned long long)(unsigned int)mbr)) - return 0; - } - - printf_debug0 ("Partition (%cd%d,%d) successfully set %shidden.\n", - ((current_drive & 0x80) ? 'h' : 'f'), - (current_drive & ~0x80), - part_num, - (hidden ? "" : "un")); - } else { - printf_debug0 ("Partition (%cd%d,%d) was already %shidden.\n", - ((current_drive & 0x80) ? 'h' : 'f'), - (current_drive & ~0x80), - part_num, - (hidden ? "" : "un")); - - } - - /* Succeed. */ - return 1; - } - } - - return 0; -} - - static int real_root_func (char *arg1, int attempt_mnt); /* find */ /* Search for the filename ARG in all of partitions and optionally make that * partition root("--set-root", Thanks to Chris Semler ). */ +static int find_check(char *filename,struct builtin *builtin1,char *arg,int flags); static int find_check(char *filename,struct builtin *builtin1,char *arg,int flags) { saved_drive = current_drive; saved_partition = current_partition; + int back = no_decompression; + no_decompression = 1; //无减压 执行打开命令,不探测压缩文件,即不产生读行为。 if (filename == NULL || (open_device() && grub_open (filename))) { grub_close (); + no_decompression = back; //恢复 if (builtin1) { int ret = strlen(arg) + 1; char *_tmp; if ((_tmp = grub_malloc(ret)) == NULL) return 0; - memmove(_tmp,arg,ret ); + memmove(_tmp,arg,ret); buf_drive = -1; ret = (builtin1->func) (_tmp, flags); - grub_free(_tmp); + grub_free(_tmp); if (ret == 0) return 0; } @@ -5755,7 +4254,7 @@ static int find_check(char *filename,struct builtin *builtin1,char *arg,int flag } return 1; } - + no_decompression = back; //恢复 errnum = ERR_NONE; return 0; } @@ -5764,53 +4263,47 @@ static int find_func (char *arg, int flags) { struct builtin *builtin1 = 0; -// int ret; char *filename; - unsigned long drive; - unsigned long tmp_drive = saved_drive; - unsigned long tmp_partition = saved_partition; - unsigned long got_file = 0; + unsigned int tmp_drive = saved_drive; + unsigned int tmp_partition = saved_partition; + unsigned int got_file = 0; char *set_root = 0; - unsigned long ignore_cd = 0; - unsigned long ignore_floppies = 0; - unsigned long ignore_oem = 0; + unsigned int ignore_cd = 0; + unsigned int ignore_floppies = 0; char find_devices[8]="pnuhcf";//find order:pd->nd->ud->hd->cd->fd - //char *in_drives = NULL; /* search in drive list */ -// char root_found[16]; errnum = 0; + int i = 0; + struct grub_disk_data *d; //磁盘数据 #ifdef FSYS_FB if (saved_drive == FB_DRIVE && !(unsigned char)(fb_status >> 8)) { - *(unsigned long *)&find_devices[3]=0x686366; + unsigned int *a = (unsigned int *)&find_devices[3]; +// *(unsigned long *)&find_devices[3]=0x686366; + *a=0x686366; } #endif for (;;) { if (grub_memcmp (arg, "--set-root=", 11) == 0) - { - set_root = arg + 11; - if (*set_root && *set_root != ' ' && *set_root != '\t' && *set_root != '/') - return ! (errnum = ERR_FILENAME_FORMAT); - } + { + set_root = arg + 11; + if (*set_root && *set_root != ' ' && *set_root != '\t' && *set_root != '/') + return ! (errnum = ERR_FILENAME_FORMAT); + } else if (grub_memcmp (arg, "--set-root", 10) == 0) - { - set_root = ""; - } + { + set_root = ""; + } else if (grub_memcmp (arg, "--ignore-cd", 11) == 0) - { - ignore_cd = 1; - } + { + ignore_cd = 1; + } else if (grub_memcmp (arg, "--ignore-floppies", 17) == 0) - { - ignore_floppies = 1; - } - else if (grub_memcmp (arg, "--ignore-oem", 12) == 0) - { - ignore_oem = 1; - } + { + ignore_floppies = 1; + } else if (grub_memcmp(arg, "--devices=", 10) == 0) { - int i = 0; arg += 10; while (i < 7 && *arg >= 'a') { @@ -5826,38 +4319,31 @@ find_func (char *arg, int flags) /* The filename should NOT have a DEVICE part. */ filename = set_device (arg); if (filename) - return ! (errnum = ERR_FILENAME_FORMAT); + return ! (errnum = ERR_FILENAME_FORMAT); if (*arg == '/' || *arg == '+' || (*arg >= '0' && *arg <= '9')) { - filename = arg; + filename = arg; arg = skip_to (0, arg); } else { filename = 0; } /* arg points to command. */ - -// if (*arg >= 'a' && *arg <= 'z') if (*arg) { builtin1 = find_command (arg); - if ((int)builtin1 != -1) - if (! builtin1 || ! (builtin1->flags & flags)) - { - errnum = ERR_UNRECOGNIZED; - return 0; - } - if ((int)builtin1 != -1) - arg = skip_to (1, arg); /* get argument of command */ + if ((grub_size_t)builtin1 != (grub_size_t)-1) + if (! builtin1 || ! (builtin1->flags & flags)) + { + errnum = ERR_UNRECOGNIZED; + return 0; + } + if ((grub_size_t)builtin1 != (grub_size_t)-1) + arg = skip_to (1, arg); /* get argument of command */ else - builtin1 = &builtin_command; + builtin1 = &builtin_command; } -// else if (*arg) -// { -// errnum = ERR_UNRECOGNIZED; -// return 0; -// } errnum = 0; @@ -5869,8 +4355,7 @@ find_func (char *arg, int flags) switch(*devtype) { case 'h': -// if (tmp_drive >= 0x80 && tmp_drive < 0xA0 && tmp_partition != 0xFFFFFF) - if (tmp_drive >= 0x80 && tmp_drive < 0x9F) + if (tmp_drive >= 0x80 && tmp_drive <= 0x8F) FIND_DRIVES = 1; break; case 'u': @@ -5884,13 +4369,13 @@ find_func (char *arg, int flags) case 'c': if (ignore_cd) *devtype = ' '; - else if (current_drive == cdrom_drive || (tmp_drive >= 0x9f && tmp_drive <= 0xff)) + else if (tmp_drive >= 0xa0 && tmp_drive <= 0xff) FIND_DRIVES = 1; break; case 'f': if (ignore_floppies) *devtype = ' '; - else if (tmp_drive < 8) + else if (tmp_drive <= 0x7f) FIND_DRIVES = 1; break; } @@ -5900,12 +4385,30 @@ find_func (char *arg, int flags) { current_drive = saved_drive; current_partition = saved_partition; - if (find_check(filename,builtin1,arg,flags) == 1) + if (((current_drive < 0x80 && floppies_orig) || (current_drive >= 0xa0 && cdrom_orig)) && find_check(filename,builtin1,arg,flags) == 1) { got_file = 1; if (set_root) goto found; } + else if (current_drive >= 0x80 && current_drive <= 0x8f && harddrives_orig) + { + struct grub_part_data *dp; + for (dp = partition_info; dp; dp = dp->next) + { + if (dp->drive == current_drive) + current_partition = dp->partition; + else + continue; + + if (find_check(filename,builtin1,arg,flags) == 1) + { + got_file = 1; + if (set_root) + goto found; + } + } + } } /*search other devices*/ for (devtype = find_devices; *devtype; devtype++) @@ -5922,97 +4425,154 @@ find_func (char *arg, int flags) break; #endif #ifdef FSYS_PXE - case 'p': + case 'p': if (pxe_entry) current_drive = PXE_DRIVE; else continue; + if (find_check(filename,builtin1,arg,flags) == 1) //支持pxe查询 + { + got_file = 1; + if (set_root) + goto found; + } break; #endif case 'c':/*Only search first cdrom*/ - if (cdrom_drive != GRUB_INVALID_DRIVE) - current_drive = cdrom_drive; - else if (atapi_dev_count) - current_drive = min_cdrom_id; - else - continue; + for (d = disk_data; d && cdrom_orig; d = d->next) //从设备结构起始查 + { + if (d->disk_type != DISK_TYPE_CD) + continue; + current_drive = d->drive; + if (tmp_drive == current_drive) + continue; + if (find_check(filename,builtin1,arg,flags) == 1) + { + got_file = 1; + if (set_root) + goto found; + } + } +#if 0 + for (drive = 0xa0; drive < (unsigned int)0xa0 + cdrom_orig; drive++) + { + current_drive = drive; + if (tmp_drive == current_drive) + continue; + if (find_check(filename,builtin1,arg,flags) == 1) + { + got_file = 1; + if (set_root) + goto found; + } + } +#endif break; - case 'h': case 'f': - #define FIND_HD_DRIVES (*((char *)0x475)) - #define FIND_FD_DRIVES (((*(char*)0x410) & 1)?(((*(char*)0x410) >> 6) & 3 ) + 1 : 0) - FIND_DRIVES = (*devtype == 'h') ? 0x80 + FIND_HD_DRIVES : FIND_FD_DRIVES; - for (drive = (*devtype == 'h')?0x80:0; drive < FIND_DRIVES; drive++) + for (d = disk_data; d && floppies_orig; d = d->next) //从设备结构起始查 + { + if (d->disk_type != DISK_TYPE_FD) + continue; + current_drive = d->drive; + if (tmp_drive == current_drive) + continue; + if (find_check(filename,builtin1,arg,flags) == 1) + { + got_file = 1; + if (set_root) + goto found; + } + } +#if 0 + for (drive = 0; drive < (unsigned int)floppies_orig; drive++) { - unsigned long part = 0xFFFFFF; - unsigned long long start, len, offset; - unsigned long type, entry1, ext_offset1; - - saved_drive = current_drive = drive; - saved_partition = current_partition = part; -// if ((*devtype == 'f') && open_device()) //if is a partition - biosdisk_standard (0x02, (unsigned char)drive, 0, 0, 1, 3, 0x2F00); - if (!(probe_bpb((struct master_and_dos_boot_sector *)0x2f000)) && open_device()) + current_drive = drive; + if (tmp_drive == current_drive) + continue; + if (find_check(filename,builtin1,arg,flags) == 1) + { + got_file = 1; + if (set_root) + goto found; + } + } +#endif + break; + case 'h': + for (d = disk_data; d && harddrives_orig; d = d->next) //从设备结构起始查 + { + struct grub_part_data *dp; + if (d->disk_type != DISK_TYPE_HD) + continue; + + current_drive = d->drive; + current_partition = 0xFFFFFF; + + if (tmp_drive == current_drive) + continue; + if (d->drive == (unsigned char)(fb_status >> 8) && find_check(filename,builtin1,arg,flags) == 1) + { + got_file = 1; + if (set_root) + goto found; + } + for (dp = partition_info; dp; dp = dp->next) { - if ((tmp_drive != current_drive || tmp_partition != current_partition) && find_check(filename,builtin1,arg,flags) == 1) + if (dp->drive == d->drive) + current_partition = dp->partition; + else + continue; + + if (find_check(filename,builtin1,arg,flags) == 1) { got_file = 1; if (set_root) goto found; } - if (probe_mbr((struct master_and_dos_boot_sector *)0x2f000,0,1,0)) - continue; } - - saved_drive = current_drive = drive; - while (( next_partition_drive = drive, - next_partition_dest = 0xFFFFFF, - next_partition_partition = &part, - next_partition_type = &type, - next_partition_start = &start, - next_partition_len = &len, - next_partition_offset = &offset, - next_partition_entry = &entry1, - next_partition_ext_offset = &ext_offset1, - next_partition_buf = mbr, - next_partition ())) - { - if ((start == 0) || (len == 0)) - continue; - if (/* type != PC_SLICE_TYPE_NONE - && */ ! (ignore_oem == 1 && (type & ~PC_SLICE_TYPE_HIDDEN_FLAG) == 0x02) - && ! IS_PC_SLICE_TYPE_BSD (type) - && ! IS_PC_SLICE_TYPE_EXTENDED (type)) - { - current_drive = drive; - current_partition = part; - - if ((tmp_drive != current_drive || tmp_partition != current_partition) && find_check(filename,builtin1,arg,flags) == 1) - { - got_file = 1; - if (set_root) - goto found; - } - } /*end if*/ - } /*while next_partition*/ - /* next_partition always sets ERRNUM in the last call, so clear it. */ errnum = ERR_NONE; } - #undef FIND_HD_DRIVES - #undef FIND_FD_DRIVES +#if 0 + for (drive = 0x80; drive < (unsigned int)0x80 + harddrives_orig; drive++) + { + current_drive = drive; + current_partition = 0xFFFFFF; + struct grub_part_data *dp; + + if (tmp_drive == current_drive) + continue; + if (drive == (unsigned char)(fb_status >> 8) && find_check(filename,builtin1,arg,flags) == 1) + { + got_file = 1; + if (set_root) + goto found; + } + for (dp = partition_info; dp; dp = dp->next) + { + if (dp->drive == drive) + current_partition = dp->partition; + else + continue; + + if (find_check(filename,builtin1,arg,flags) == 1) + { + got_file = 1; + if (set_root) + goto found; + } + } + /* next_partition always sets ERRNUM in the last call, so clear it. */ + errnum = ERR_NONE; + } +#endif + #undef FIND_HD_DRIVES + #undef FIND_FD_DRIVES //h,f. no break;default continue; + break; default: continue; } - if (tmp_drive == current_drive) - continue; - if (find_check(filename,builtin1,arg,flags) == 1) - { - got_file = 1; - if (set_root) - goto found; - } } saved_drive = tmp_drive; saved_partition = tmp_partition; @@ -6024,42 +4584,38 @@ find_func (char *arg, int flags) { int j; - //return real_root_func (root_found, 1); - //saved_drive = current_drive; - //saved_partition = current_partition; /* copy root prefix to saved_dir */ - for (j = 0; j < sizeof (saved_dir); j++) + for (j = 0; j < (int)sizeof (saved_dir); j++) { - char ch; + char ch; - ch = set_root[j]; - if (ch == 0 || ch == 0x20 || ch == '\t') - break; - if (ch == '\\') - { - saved_dir[j] = ch; - j++; - ch = set_root[j]; - if (! ch || j >= sizeof (saved_dir)) - { - j--; - saved_dir[j] = 0; - break; - } - } - saved_dir[j] = ch; - } + ch = set_root[j]; + if (ch == 0 || ch == 0x20 || ch == '\t') + break; + if (ch == '\\') + { + saved_dir[j] = ch; + j++; + ch = set_root[j]; + if (! ch || j >= (int)sizeof (saved_dir)) + { + j--; + saved_dir[j] = 0; + break; + } + } + saved_dir[j] = ch; + } - if (saved_dir[j-1] == '/') - { - saved_dir[j-1] = 0; - } else - saved_dir[j] = 0; - } //if set_root - - return 1; + if (saved_dir[j-1] == '/') + { + saved_dir[j-1] = 0; + } + else + saved_dir[j] = 0; + } //if set_root + return 1; } - errnum = ERR_FILE_NOT_FOUND; return 0; } @@ -6081,17 +4637,18 @@ static struct builtin builtin_find = " floppies. And --ignore-cd will skip (cd)." }; - + #ifdef SUPPORT_GRAPHICS /* * The code in function GET_NIBBLE is released to the public domain. * tinybit 2011-11-18 */ -static unsigned long -get_nibble (unsigned long c) +static unsigned int get_nibble (unsigned int c); +static unsigned int +get_nibble (unsigned int c) { - unsigned long tmp; + unsigned int tmp; tmp = ((c > '9') ? ((c & 0xdf)- 'A' + 10) : (c - '0')); if (tmp & 0xFFFFFFF0) { @@ -6100,9 +4657,9 @@ get_nibble (unsigned long c) return tmp; } -extern unsigned long ged_unifont_simp (unsigned long unicode); -extern unsigned long -ged_unifont_simp (unsigned long unicode) +extern unsigned int ged_unifont_simp (unsigned int unicode); +extern unsigned int +ged_unifont_simp (unsigned int unicode) { int i; for (i = 0; i < 8; i++) @@ -6114,51 +4671,43 @@ ged_unifont_simp (unsigned long unicode) } //static unsigned long old_narrow_char_indicator = 0; -#define old_narrow_char_indicator narrow_char_indicator -int font_func (char *arg, int flags); -//unsigned char font_type; -//unsigned char scan_mode; -//unsigned char store_mode; -int (*hotkey_func)(char *titles,int flags,int flags1); +//#define old_narrow_char_indicator narrow_char_indicator + +int (*hotkey_func)(char *titles,int flags,int flags1,int key); struct simp unifont_simp[]={{0,0xff,0},{0x2000,0x206f,0x1f00},{0x2190,0x21ff,0x2020},{0x2e80,0x303f,0x2ca0},{0x31c0,0x9fbf,0x2e20},{0xf900,0xfaff,0x8760},{0xfe30,0xffef,0x8a90}}; unsigned char unifont_simp_on; +unsigned char *UNIFONT_START = 0; +unsigned char *narrow_mem = 0; /* font */ /* load unifont to UNIFONT_START */ /* * The code and text in function FONT_FUNC is released to the public domain. * tinybit 2011-11-18 */ +int font_func (char *arg, int flags); int font_func (char *arg, int flags) { - unsigned long i, j, k; - unsigned long len; - unsigned long unicode; - unsigned long narrow_indicator; -// unsigned char buf[80]; - unsigned char buf[1024]; //64*64 - unsigned long valid_lines; - unsigned long saved_filepos; - extern unsigned char *font8x16; + unsigned int i, j, k; + unsigned int len; + unsigned int unicode=0; +// unsigned int narrow_indicator; +// unsigned char buf[870]; //48*48 + char *buf; + unsigned int valid_lines; + unsigned long long saved_filepos; unsigned long long val; unsigned char num_narrow; unsigned char tag[]={'d','o','t','s','i','z','e','='}; - unsigned long font_h_old = font_h; - unsigned long font_h_new = 0; - -// font_type = 0; -// scan_mode = 0; -// store_mode = 0; + unsigned int font_h_old = font_h; + unsigned int font_h_new = 0; valid_lines = 0; - errnum = 0; + if (arg == NULL || *arg == '\0') { - if (font_h != 16) return 0; - valid_lines--; // let valid_lines = -1, a non-zero value for TRUE. - goto build_default_VGA_font; } if (flags) @@ -6166,39 +4715,6 @@ font_func (char *arg, int flags) unifont_simp_on = 0; for (; *arg && *arg != '/' && *arg != '(' && *arg != '\n' && *arg != '\r';) { -#if 0 - if (grub_memcmp (arg, "--hex", 5) == 0) - { - arg += 5; - font_type = 0; - } - if (grub_memcmp (arg, "--bin", 5) == 0) - { - arg += 5; - font_type = 1; - } - else if (grub_memcmp (arg, "--horiz-scan", 12) == 0) - { - arg += 12; - scan_mode = 0; - } - else if (grub_memcmp (arg, "--verti-scan", 12) == 0) - { - arg += 12; - scan_mode = 1; - } - else if (grub_memcmp (arg, "--h-to-l", 8) == 0) - { - arg += 8; - store_mode = 0; - } - else if (grub_memcmp (arg, "--l-to-h", 8) == 0) - { - arg += 8; - store_mode = 1; - } - else if (grub_memcmp (arg, "--font-high=", 12) == 0) -#endif if (grub_memcmp (arg, "--font-high=", 12) == 0) { arg += 12; @@ -6249,47 +4765,25 @@ font_func (char *arg, int flags) font_h = font_h_new; font_w = font_h_new/2; } - - if (font_h_old != font_h) - { - current_term->max_lines = current_y_resolution / (font_h + line_spacing); - current_term->chars_per_line = current_x_resolution / (font_w + font_spacing); - if (hotkey_func) - memset ((char *)UNIFONT_START, 0, 0x600000); - else - memset ((char *)UNIFONT_START, 0, 0x800000); - - if (font_h == 16) - font_func (NULL, 0); } -#if 0 - if (font_type) - { - filepos =0; - len = grub_read((unsigned long long)(unsigned int)(char*)UNIFONT_START, filemax, 0xedde0d90); - grub_close(); - return 1; - } -#endif - } if (filemax >> 32) // file too long - return !(errnum = ERR_WONT_FIT); + return !(errnum = ERR_WONT_FIT); -// if (*(unsigned long *)UNIFONT_START) -// return !(errnum = ERR_UNIFONT_RELOAD); + num_wide = (font_h+7)/8; + num_narrow = ((font_h/2+7)/8)<<1; - memset ((char *)0x100000, 0, 0x10000); /* clear 64K at 1M */ + if (font_h_old != font_h) + { + current_term->max_lines = current_y_resolution / (font_h + line_spacing); + current_term->chars_per_line = current_x_resolution / (font_w + font_spacing); + } - num_wide = (font_h+7)/8; - num_narrow = ((font_h/2+7)/8)<<1; redo: - -// while (((saved_filepos = filepos), (len = grub_read((unsigned long long)(unsigned int)(char*)&buf, 38, 0xedde0d90)))) - while (((saved_filepos = filepos), (len = grub_read((unsigned long long)(unsigned int)(char*)&buf, 6+font_h*num_narrow, 0xedde0d90)))) + buf = grub_malloc (870); //48*48 +// while (((saved_filepos = filepos), (len = grub_read((unsigned long long)(grub_size_t)(char*)&buf, 6+font_h*num_narrow, 0xedde0d90)))) + while (((saved_filepos = filepos), (len = grub_read((unsigned long long)(grub_size_t)(char*)buf, 6+font_h*num_narrow, 0xedde0d90)))) { -//printf ("begin valid_lines=%d, buf=%s\n", valid_lines, buf); -// if (len != 38 || buf[4] != ':') if (len != 6+font_h*num_narrow || buf[4] != ':') { errnum = ERR_UNIFONT_FORMAT; @@ -6306,37 +4800,33 @@ font_func (char *arg, int flags) goto close_file; unicode |= (tmp << ((3 - i) << 2)); } + + if (!UNIFONT_START || font_h_old != font_h) + { + font_h_old = font_h; + if (UNIFONT_START) + grub_free (UNIFONT_START); + UNIFONT_START = grub_zalloc (num_wide * font_h * 0x10000); + if (!UNIFONT_START) +// return 0; + goto err; + if (!narrow_mem) + narrow_mem = grub_zalloc(0x2000); //宽窄字符指示器 0/1=窄/宽 + else + grub_memset (narrow_mem, 0, 0x2000); + if (!narrow_mem) +// return 0; + goto err; + } -// if (buf[37] == '\n' || buf[37] == '\r') /* narrow char */ if (buf[5+font_h*num_narrow] == '\n' || buf[5+font_h*num_narrow] == '\r') /* narrow char */ { /* discard if it is a control char(we will re-map control chars) */ -// if (unicode <= 0x1F) -// { - //valid_lines++; -// continue; -// } /* simply put the 8x16 dot matrix at the right half */ -#if 0 - for (j = 0; j < 8; j++) - { - unsigned short tmp = 0; - for (k = 0; k < 16; k++) - { - unsigned long t = 0; - t = get_nibble (buf[5+(j>>2)+(k<<1)]); - if (errnum) - goto close_file; - tmp |= ((t >> ((7-j) & 3)) & 1) << k; - } - ((unsigned short *)(UNIFONT_START + (unicode << 5) + 16))[j] = tmp; - } - /* set to the old_narrow_char_indicator */ - *(unsigned long *)(UNIFONT_START + (unicode << 5)) = old_narrow_char_indicator; -#endif if (unifont_simp_on) unicode = ged_unifont_simp (unicode); +// *(unsigned char *)(narrow_mem + unicode/8) &= ~(1 << (unicode&7)); //初始化已经清零 2023-02-22 for (j=0; j> k*8)&0xff; /* the first integer is to be checked for narrow_char_indicator */ } - *(unsigned long *)(UNIFONT_START + unicode*num_wide*font_h) = old_narrow_char_indicator; +// *(unsigned int *)(UNIFONT_START + unicode*num_wide*font_h) = old_narrow_char_indicator; } else { /* read additional 32 chars and see if it end in a LF */ -// len = grub_read((unsigned long long)(unsigned int)(char*)(buf+38), 32, 0xedde0d90); - len = grub_read((unsigned long long)(unsigned int)(char*)(buf+6+font_h*num_narrow), font_h*(num_wide*2-num_narrow), 0xedde0d90); -// if (len != 32 || (buf[69] != '\n' && buf[69] != '\r')) + len = grub_read((unsigned long long)(grub_size_t)(char*)(buf+6+font_h*num_narrow), font_h*(num_wide*2-num_narrow), 0xedde0d90); if (len != font_h*(num_wide*2-num_narrow) || (buf[5+font_h*num_wide*2] != '\n' && buf[5+font_h*num_wide*2] != '\r')) { errnum = ERR_UNIFONT_FORMAT; @@ -6367,8 +4855,8 @@ font_func (char *arg, int flags) } /* discard if it is a normal ASCII char */ - if (unicode <= 0x7F) - continue; +// if (unicode <= 0x7F) +// continue; /* discard if it is internally used INVALID chars 0xDC80 - 0xDCFF */ if (unicode >= 0xDC80 && unicode <= 0xDCFF) @@ -6376,32 +4864,10 @@ font_func (char *arg, int flags) if (unifont_simp_on) unicode = ged_unifont_simp (unicode); /* set bit 0: this unicode char is a wide char. */ - *(unsigned char *)(0x100000 + unicode) |= 1; /* bit 0 */ +// *(unsigned char *)(narrow_mem + unicode) |= 1; /* bit 0 */ + *(unsigned char *)(narrow_mem + unicode/8) |= (1 << (unicode&7)); /* put the 16x16 dot matrix */ -#if 0 - for (j = 0; j < 16; j++) - { - unsigned short tmp = 0; - for (k = 0; k < 16; k++) - { - unsigned long t = 0; - t = get_nibble (buf[5+(j>>2)+(k<<2)]); - if (errnum) - goto close_file; - tmp |= ((t >> ((15-j) & 3)) & 1) << k; - } - ((unsigned short *)(UNIFONT_START + (unicode << 5)))[j] = tmp; - /* the first integer is to be checked for narrow_char_indicator */ - if (j == 0) - { - /* set bit 4: this integer already used by this wide char, so - * it will not be used as the narrow_char_indicator. - */ - *(unsigned char *)(0x100000 + tmp) |= 16; /* bit 4 */ - } - } -#endif for (j=0; j> k*8)&0xff; - /* the first integer is to be checked for narrow_char_indicator */ - if (j == 0) - { - /* set bit 4: this integer already used by this wide char, so - * it will not be used as the narrow_char_indicator. - */ - *(unsigned char *)(0x100000 + (unsigned short)(dot_matrix & 0xffff)) |= 16; /* bit 4 */ - } } } valid_lines++; -//printf ("end valid_lines=%d, buf=%s\n", valid_lines, buf); } /* while */ close_file: - if (errnum && len) - { -// /* find next line from saved_filepos and try again */ -// grub_close (); -// if (! grub_open(arg)) -// return 0; - - filepos = saved_filepos; - i=0; - while ((len = grub_read((unsigned long long)(unsigned int)(char*)&buf, 1, 0xedde0d90))) - { - if (buf[0] == '\n' || buf[0] == '\r') - { -//printf ("goto valid_lines=%d, buf=%s\n", valid_lines, buf); - goto redo; /* try the new line */ - } - if (buf[0] == '\0') /* NULL encountered ? */ - break; /* yes, end */ - - if ((buf[0] | 0x20)== tag[i]) - i++; - else - i=0; - if (i==8) - { - grub_read((unsigned long long)(unsigned int)(char*)&buf, 10, 0xedde0d90); - char *p = (char *)buf; - i=0; - unifont_simp_on = 0; - if (safe_parse_maxint (&p, &val)) - { - if (font_h != val) - { - font_h = val; - font_w = val>>1; - current_term->max_lines = current_y_resolution / (font_h + line_spacing); - current_term->chars_per_line = current_x_resolution / (font_w + font_spacing); - memset ((char *)UNIFONT_START, 0, 0x800000); - num_wide = (font_h+7)/8; - num_narrow = ((font_h/2+7)/8)<<1; - if ((p[1]|0x20)=='s' && (p[2]|0x20)=='i' && (p[3]|0x20)=='m' && (p[4]|0x20)=='p') - unifont_simp_on = 1; - } - } - filepos -= 7; - } - } - } - - grub_close(); - - if (! valid_lines) // if no valid lines, - return valid_lines; // simply fail without loading ROM font. - - errnum = 0; - /* determine narrow_char_indicator */ - narrow_indicator = 0; - - i = 0; -loop: - i++; - if (i < 0x10000) + if (errnum && len) //如果有错误,并且长度非0. 即没有正常加载字库 与内置字库有关 { - if (((*(unsigned char *)(0x100000 + i)) & 16)) - goto loop; /* the i already used by a new wide char, failed */ - /* now the i is not used by all new wide chars */ - if (i == old_narrow_char_indicator) + filepos = saved_filepos; //从失败处重新开始查找字库 + i=0; +// while ((len = grub_read((unsigned long long)(grub_size_t)(char*)&buf, 1, 0xedde0d90))) + while ((len = grub_read((unsigned long long)(grub_size_t)(char*)buf, 1, 0xedde0d90))) { - *(unsigned long *)UNIFONT_START = i; // disable next font command. - return valid_lines; /* nothing need to change, success */ - } - /* old wide chars should not use this i as leading integer */ - for (j = 0x80; j < 0x10000; j++) - { -// if (*(unsigned long *)(UNIFONT_START + (j << 5)) == i) - if (*(unsigned long *)(UNIFONT_START + (j*num_wide*font_h)) == i) - goto loop; /* the i was used by old wide char j, failed */ - } - /* the i is not used by all wide chars, and got it! */ - narrow_indicator = i; - } + if (buf[0] == '#') //避免注释中含有'DotSize='字符串,清除已安装字库 2023-09-30 +// while (grub_read((unsigned long long)(grub_size_t)(char*)&buf, 1, 0xedde0d90) && buf[0] != '\n'); //跳过注释 + while (grub_read((unsigned long long)(grub_size_t)(char*)buf, 1, 0xedde0d90) && buf[0] != '\n'); //跳过注释 + if (buf[0] == '\n' || buf[0] == '\r') + { + goto redo; /* try the new line */ + } + if (buf[0] == '\0') /* NULL encountered ? */ + break; /* yes, end */ - if (narrow_indicator == 0) - { - errnum = ERR_INTERNAL_CHECK; - goto build_default_VGA_font; - } - /* update narrow_char_indicator for each narrow char */ - for (i = 0xFFFF; (long)i >= 0; i--) - { - if ((!((*(unsigned char *)(0x100000 + i)) & 1) /* not a new wide char */ -// && (*(unsigned long *)(UNIFONT_START + (i << 5)) - && (*(unsigned long *)(UNIFONT_START + (i*num_wide*font_h)) - == old_narrow_char_indicator) /* not an old wide char */ - ) - || i <= 0x7F - ) - { -// *(unsigned long *)(UNIFONT_START + (i << 5)) = narrow_indicator; - *(unsigned long *)(UNIFONT_START + (i*num_wide*font_h)) = narrow_indicator; + if ((buf[0] | 0x20)== tag[i]) //{'d','o','t','s','i','z','e','='} + i++; + else + i=0; + if (i==8) + { +// grub_read((unsigned long long)(grub_size_t)(char*)&buf, 10, 0xedde0d90); + grub_read((unsigned long long)(grub_size_t)(char*)buf, 10, 0xedde0d90); + char *p = (char *)buf; + i=0; + unifont_simp_on = 0; + if (safe_parse_maxint (&p, &val)) + { + if (font_h != val) + { + font_h = val; //40 + font_w = val>>1; //20 + current_term->max_lines = current_y_resolution / (font_h + line_spacing); + current_term->chars_per_line = current_x_resolution / (font_w + font_spacing); +// memset ((char *)UNIFONT_START, 0, 0x800000); + num_wide = (font_h+7)/8; //5 + num_narrow = ((font_h/2+7)/8)<<1; //6 + if ((p[1]|0x20)=='s' && (p[2]|0x20)=='i' && (p[3]|0x20)=='m' && (p[4]|0x20)=='p') + unifont_simp_on = 1; + } + } + filepos -= 7; + } } } - + grub_close(); + grub_free (buf); + if (! valid_lines) // if no valid lines, + return valid_lines; + menu_tab_ext |= 4; //已加载字库 //old_narrow_char_indicator = narrow_indicator; -#undef old_narrow_char_indicator +//#undef old_narrow_char_indicator return valid_lines; /* success */ -build_default_VGA_font: - - /* initialize ASCII chars with ROM 8x16 font. */ - - if (font8x16) - goto ROM_font_loaded; - - font8x16 = graphics_get_font (); - - /////////////////////////////////////////////////////////////////////// - // // - // ( old 3 x 5 dot matrix ) // - // // - // 0 1 2 3 4 5 6 7 // - // // - // 0 1 0 0 1 0 1 1 0 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 // - // 1 0 1 0 1 0 0 0 1 0 0 1 0 1 1 1 0 0 1 0 0 0 0 1 // - // 1 0 1 0 1 0 0 1 0 0 1 0 1 0 1 1 1 1 1 1 1 0 1 0 // - // 1 0 1 0 1 0 1 0 0 0 0 1 1 1 1 0 0 1 1 0 1 0 1 0 // - // 0 1 0 0 1 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 0 1 0 // - // // - // 8 9 A B C D E F // - // // - // 1 1 1 1 1 1 0 1 0 1 0 0 0 1 1 0 0 1 1 1 1 1 1 1 // - // 1 0 1 1 0 1 1 0 1 1 0 0 1 0 0 0 0 1 1 0 0 1 0 0 // - // 0 1 0 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 // - // 1 0 1 0 0 1 1 0 1 1 0 1 1 0 0 1 0 1 1 0 0 1 0 0 // - // 1 1 1 1 1 1 1 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 0 // - // // - /////////////////////////////////////////////////////////////////////// - // // - // ( new 3 x 7 dot matrix ) // - // // - // # # # # # // - // # # # # # # # # # # # # # # // - // # # # # # # # # # # // - // # # # # # # # # # # # # // - // # # # # # # # # # # // - // # # # # # # # # # # # # # // - // # # # // - // // - // # # # # # # // - // # # # # # # # # # # # # // - // # # # # # # # # # # # # # # // - // # # # # # # # # # # # # # # # // - // # # # # # # # # # # # # # // - // # # # # # # # # # # # # # # # // - // # # # # # # // - // // - /////////////////////////////////////////////////////////////////////// - - unsigned long dot[16] = - { - 0x1C221C,0x003E00,0x242A32,0x364922,0x3E080E,0x314927,0x32493E,0x3E0202, - 0x364936,0x3E4926,0x7C127C,0x18243F,0x22221C,0x3F2418,0x26493E,0x093E48, - }; - - for (i = 0; i < 0x10000; i++) - { - /* clear the narrow_char_indicator for each unicode char */ - *(unsigned long *)(UNIFONT_START + (i << 5)) = 0; - for (j = 0; j < 8; j++) - { - ((unsigned short *)(UNIFONT_START + (i << 5) + 16))[j] = - (((dot[((i >> (4-(j&4))) & 15)] >> ((j&3)<<3))) << 8) - | ((unsigned char)(dot[((i >> (12-(j&4))) & 15)] >> ((j&3)<<3))); - } - } - -ROM_font_loaded: - - /* copy font8x16 to RAM at 0x580000 */ - if (font8x16 != (void*)0x580000) - { - memmove ((void*)0x580000, font8x16, 0x1000); - font8x16 = (void*)0x580000; - - // re-map 6 box-drawing chars to replace 6 control-chars respectively. - /* Lower Right (0xD9) and Upper Left (0xDA) to 0x13 and 0x14 */ - memmove (font8x16 + (0x13 << 4), font8x16 + (0xD9 << 4), 32); - /* Upper Right (0xBF) and Lower Left (0xC0) to 0x15 and 0x16 */ - memmove (font8x16 + (0x15 << 4), font8x16 + (0xBF << 4), 32); - /* Vertical Line (0xB3) and Horizontal Line (0xC4) to 0x0E and 0x0F */ - memmove (font8x16 + (0x0E << 4), font8x16 + (0xB3 << 4), 16); - memmove (font8x16 + (0x0F << 4), font8x16 + (0xC4 << 4), 16); - } - - /* clear the narrow_char_indicator for the NULL char only */ -// *(unsigned long *)UNIFONT_START = 0; /* to enable the next font command */ - - /* initialize or restore the original ROM 8x16 font for each ASCII char. */ - for (i = 0; i <= 0x7F; i++) - { - for (j = 0; j < 8; j++) - { - unsigned short tmp = 0; - for (k = 0; k < 16; k++) - { - tmp |= ((font8x16[(i<<4) + k] >> (7-j)) & 1) << k; - } - ((unsigned short *)(UNIFONT_START + (i << 5) + 16))[j] = tmp; - } - } - - return valid_lines;//!(errnum); +err: + grub_free (buf); + return 0; } static struct builtin builtin_font = @@ -6689,7 +4993,7 @@ ascii_to_hex (char *arg, char *buf) } int primary; - + /* uuid */ /* List filesystem UUID in all of partitions or search for filesystem * with specified UUID and set the partition as root. @@ -6698,37 +5002,41 @@ int primary; //static void print_root_device (char *buffer); static void get_uuid (char* uuid_found, int tag); static void get_vol (char* vol_found, int tag); +static int uuid_func (char *argument, int flags); static int uuid_func (char *argument, int flags) { - unsigned long drive; - unsigned long tmp_drive = saved_drive; - unsigned long tmp_partition = saved_partition; +#define tem chainloader_file + unsigned int drive; + unsigned int tmp_drive = saved_drive; + unsigned int tmp_partition = saved_partition; char root_found[16] = ""; char uuid_found[256]; - char tem[256]; +// char tem[256]; + grub_memset(tem, 0, 256); char uuid_tag[5] = {'U','U','I','D',0}; char vol_tag[12] = {'V','o','l','u','m','e',' ','N','a','m','e',0}; char *p; char *arg = tem; int write = 0, i = 0, j = 0; primary = 0; + struct grub_disk_data *d; //磁盘数据 while (*argument && *argument != '\n' && *argument != '\r' && *argument != '(') { - if (grub_memcmp (argument, "--write", 7) == 0) - { - write = 1; - argument += 7; - } - else if (grub_memcmp (argument, "--primary", 9) == 0) - { - primary = 1; - argument += 9; - } - else - break; - argument = skip_to (0, argument); + if (grub_memcmp (argument, "--write", 7) == 0) + { + write = 1; + argument += 7; + } + else if (grub_memcmp (argument, "--primary", 9) == 0) + { + primary = 1; + argument += 9; + } + else + break; + argument = skip_to (0, argument); } if (flags) @@ -6801,107 +5109,114 @@ uuid_func (char *argument, int flags) return ! (errnum = ERR_BAD_ARGUMENT); errnum = 0; - for (drive = 0; drive <= 0xff; drive++) - { - unsigned long part = 0xFFFFFF; - unsigned long long start, len, offset; - unsigned long type, entry1, ext_offset1; - int bsd_part; - int pc_slice; + char *mem_probe = grub_malloc (0x1000); + if (!mem_probe) + return 0; -// if ((drive > 10 && drive < 0x80) || (drive > (*((char *)0x475) + 0x80) && drive < 0x9f)) -// continue; + for (drive = 0; drive <= 0xff; drive++) + { + int bsd_part = 0xff; + int pc_slice = 0xff; + + if (drive == FB_DRIVE) + continue; - for (i = 0; i < DRIVE_MAP_SIZE; i++) - { - if (drive_map_slot_empty (bios_drive_map[i])) - break; - if (bios_drive_map[i].from_drive == drive) - goto yyyyy; - } -#define FIND_HD (*((char *)0x475)) -#define FIND_FD (((*(char*)0x410) & 1)?((*(char*)0x410) >> 6) + 1 : 0) - if (drive < FIND_FD || (drive >=0x80 && drive < 0x80 + FIND_HD)) -#undef FIND_HD -#undef FIND_FD + d = get_device_by_drive (drive,0); + if (! d) //如果设备=0, 错误 + continue; +#if 0 + if (drive < (unsigned int)floppies_orig || (drive >=(unsigned int)0x80 && drive < (unsigned int)0x80 + harddrives_orig)) goto yyyyy; - if (drive < 0x9f) + if (drive < 0xa0) continue; + else if ((drive&0xf) >= (unsigned int)cdrom_orig) + break; yyyyy: - saved_drive = current_drive = drive; - saved_partition = current_partition = part; +#endif - if (drive < 0x9f && grub_memcmp(fsys_table[fsys_type].name, "iso9660", 7) != 0) + saved_drive = current_drive = drive; + saved_partition = current_partition = 0xFFFFFF; + if (drive >= (unsigned int)0x80 && drive <= (unsigned int)0x8f /*&& grub_memcmp(fsys_table[fsys_type].name, "iso9660", 7) != 0*/) { - biosdisk_standard (0x02, (unsigned char)drive, 0, 0, 1, 1, 0x2F00); - if (!(probe_bpb((struct master_and_dos_boot_sector *)0x2f000)) && open_device()) + grub_efidisk_readwrite (drive,(unsigned long long)0,0x1000,mem_probe,0xedde0d90); + if (!(fb_status && drive == (unsigned char)(fb_status >> 8)) && !(probe_bpb((struct master_and_dos_boot_sector *)mem_probe)) && open_device()) + { goto qqqqqq; - else if (probe_mbr((struct master_and_dos_boot_sector *)0x2f000,0,1,0)) + } + else if (probe_mbr((struct master_and_dos_boot_sector *)mem_probe,0,1,0)) + { continue; + } } else { if (open_device ()) + { goto qqqqqq; + } + else + continue; } - saved_drive = current_drive = drive; - while (( next_partition_drive = drive, - next_partition_dest = 0xFFFFFF, - next_partition_partition = &part, - next_partition_type = &type, - next_partition_start = &start, - next_partition_len = &len, - next_partition_offset = &offset, - next_partition_entry = &entry1, - next_partition_ext_offset = &ext_offset1, - next_partition_buf = mbr, - next_partition ())) - { - if (/* type != PC_SLICE_TYPE_NONE - && */ ! IS_PC_SLICE_TYPE_BSD (type) - && ! IS_PC_SLICE_TYPE_EXTENDED (type)) - { - current_partition = part; - if (open_device ()) - { + struct grub_part_data *q; + int max_partition = 255; + for (i=-1; i < max_partition ; i++) + { + if (i == -1) + if (open_device ()) + goto qqqqqq; + q = get_partition_info (drive, (i<<16 | 0xffff)); + if (!q) + continue; + if (/* type != PC_SLICE_TYPE_NONE + && */ ! IS_PC_SLICE_TYPE_BSD (q->partition_type) + && ! IS_PC_SLICE_TYPE_EXTENDED (q->partition_type) && q->partition_start && q->partition_size) + { + current_partition = q->partition; + if (open_device ()) + { + bsd_part = (q->partition >> 8) & 0xFF; + pc_slice = q->partition >> 16; qqqqqq: - bsd_part = (part >> 8) & 0xFF; - pc_slice = part >> 16; - if (errnum != ERR_FSYS_MOUNT && fsys_type < NUM_FSYS) - { - grub_memset(uuid_found, 0, 256); - if (flags) - get_uuid(uuid_found,0); - else - get_vol(uuid_found,0); - } - if (! *arg) - { - grub_printf ("(%s%d%c%c%c%c):", ((drive<0x80)?"fd":(drive>=0x9f)?"":"hd"),((drive<0x80 || drive>=0x9f)?drive:(drive-0x80)), ((pc_slice==0xff)?'\0':','),((pc_slice==0xff)?'\0' :(pc_slice + '0')), ((bsd_part == 0xFF) ? '\0' : ','), ((bsd_part == 0xFF) ? '\0' : (bsd_part + 'a'))); - if (*uuid_found || debug) - grub_printf("%s%s is \"%s\".\n\t", ((drive<0x80)?" ":(drive>=0x9f)?" ":" "), p, ((*uuid_found) ? uuid_found : "(unsupported)")); - print_fsys_type(); - } - else if (substring((char*)uuid_found,arg,1) == 0) - { - grub_sprintf(root_found,"(%s%d%c%c%c%c)", ((drive<0x80)?"fd":(drive>=0x9f)?"":"hd"),((drive<0x80 || drive>=0x9f)?drive:(drive-0x80)), ((pc_slice==0xff)?'\0':','),((pc_slice==0xff)?'\0' :(pc_slice + '0')), ((bsd_part == 0xFF) ? '\0' : ','), ((bsd_part == 0xFF) ? '\0' : (bsd_part + 'a'))); - goto found; - } - } - } - if (drive >= 0x9f) - break; - - /* We want to ignore any error here. */ - errnum = ERR_NONE; - } - - /* next_partition always sets ERRNUM in the last call, so clear it. */ + if (errnum != ERR_FSYS_MOUNT && fsys_type < NUM_FSYS) + { + grub_memset(uuid_found, 0, 256); + if (flags) + get_uuid(uuid_found,0); + else + get_vol(uuid_found,0); + } + if (! *arg) + { + if (drive < 0xa0) + grub_printf ("(%s%d%c%d%c%c):", ((drive<0x80)?"fd":"hd"),((drive<0x80)?drive:(drive-0x80)), ((pc_slice==0xff)?'\0':','),((pc_slice==0xff)? '\0' :pc_slice), ((bsd_part == 0xFF) ? '\0' : ','), ((bsd_part == 0xFF) ? '\0' : (bsd_part + 'a')));//2024-01-12 支持10个以上的分区 + else + grub_printf ("(0x%x):", drive); + if (*uuid_found || debug) + grub_printf("%s%s is \"%s\".\n\t", " ", p, ((*uuid_found) ? uuid_found : "(unsupported)")); + print_fsys_type(); + } + else if (substring((char*)uuid_found,arg,1) == 0) + { + if (drive < 0xa0) + grub_sprintf(root_found,"(%s%d%c%d%c%c)", ((drive<0x80)?"fd":"hd"),((drive<0x80)?drive:(drive-0x80)), ((pc_slice==0xff)?'\0':','),((pc_slice==0xff)? '\0' :pc_slice), ((bsd_part == 0xFF) ? '\0' : ','), ((bsd_part == 0xFF) ? '\0' : (bsd_part + 'a')));//2024-01-12 支持10个以上的分区 + else + grub_sprintf(root_found, "(0x%x):", drive); + goto found; + } + } + } + if (drive > (unsigned int)0x8f) + break; + /* We want to ignore any error here. */ errnum = ERR_NONE; } + /* next_partition always sets ERRNUM in the last call, so clear it. */ + errnum = ERR_NONE; + } found: + grub_free (mem_probe); saved_drive = tmp_drive; saved_partition = tmp_partition; errnum = ERR_NONE; @@ -6909,13 +5224,13 @@ uuid_func (char *argument, int flags) return 1; if (*root_found) - { - printf_debug0("setting root to %s\n", root_found); - return real_root_func(root_found,1); - } - + { + printf_debug0("setting root to %s\n", root_found); + return real_root_func(root_found,1); + }; errnum = ERR_NO_PART; return 0; +#undef tem } static struct builtin builtin_uuid = @@ -6930,7 +5245,8 @@ static struct builtin builtin_uuid = " on all devices (if UUID is not specified). If DEVICE is specified," " return true or false according to whether or not the DEVICE matches" " the specified UUID (if UUID is specified), or just list the uuid of" - " DEVICE (if UUID is not specified)." + " DEVICE (if UUID is not specified).\n" + "uuid of DEVICE is returned in temporary variables '?'." }; static void @@ -6953,13 +5269,13 @@ get_uuid (char* uuid_found, int tag) { case 12: case 16: - devread(0, 0x27, 4, (unsigned long long)(unsigned long)uuid, n); + devread(0, 0x27, 4, (unsigned long long)(grub_size_t)uuid, n); break; case 32: - devread(0, 0x43, 4, (unsigned long long)(unsigned long)uuid, n); + devread(0, 0x43, 4, (unsigned long long)(grub_size_t)uuid, n); break; case 64: - devread(0, 0x64, 4, (unsigned long long)(unsigned long)uuid, n); + devread(0, 0x64, 4, (unsigned long long)(grub_size_t)uuid, n); break; } if (!tag) @@ -6976,7 +5292,7 @@ get_uuid (char* uuid_found, int tag) uuid[i] = uuid_found[7-i]; n = 0x900ddeed; } - devread(0, 0x48, 8, (unsigned long long)(unsigned long)uuid, n); + devread(0, 0x48, 8, (unsigned long long)(grub_size_t)uuid, n); if (!tag) grub_sprintf(uuid_found, "%02X%02X%02X%02X%02X%02X%02X%02X", uuid[7], uuid[6], uuid[5], uuid[4], uuid[3], uuid[2], uuid[1], uuid[0]); return; @@ -6991,7 +5307,7 @@ get_uuid (char* uuid_found, int tag) uuid[i] = uuid_found[i]; n = 0x900ddeed; } - devread(2, 0x68, 16, (unsigned long long)(unsigned long)uuid, n); + devread(2, 0x68, 16, (unsigned long long)(grub_size_t)uuid, n); if (!tag) grub_sprintf(uuid_found, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]); return; @@ -7001,14 +5317,14 @@ get_uuid (char* uuid_found, int tag) if (grub_memcmp(fsys_table[fsys_type].name, "reiserfs", 8) == 0) { char version[9]; - devread(0x10, 52, 9, (unsigned long long)(unsigned long)version, 0xedde0d90); + devread(0x10, 52, 9, (unsigned long long)(grub_size_t)version, 0xedde0d90); if (grub_memcmp(version, "ReIsEr2Fs", 9) == 0 || grub_memcmp(version, "ReIsEr3Fs", 9) == 0) - devread(0x10, 84, 16, (unsigned long long)(unsigned long)uuid, 0xedde0d90); + devread(0x10, 84, 16, (unsigned long long)(grub_size_t)uuid, 0xedde0d90); else { - devread(0x10, 0, 7, (unsigned long long)(unsigned long)version, 0xedde0d90); + devread(0x10, 0, 7, (unsigned long long)(grub_size_t)version, 0xedde0d90); if (grub_memcmp(version, "ReIsEr4", 7) == 0) - devread(0x10, 20, 16, (unsigned long long)(unsigned long)uuid, 0xedde0d90); + devread(0x10, 20, 16, (unsigned long long)(grub_size_t)uuid, 0xedde0d90); else return; } @@ -7019,7 +5335,7 @@ get_uuid (char* uuid_found, int tag) #ifdef FSYS_JFS if (grub_memcmp(fsys_table[fsys_type].name, "jfs", 3) == 0) { - devread(0x40, 136, 16, (unsigned long long)(unsigned long)uuid, 0xedde0d90); + devread(0x40, 136, 16, (unsigned long long)(grub_size_t)uuid, 0xedde0d90); grub_sprintf(uuid_found, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]); return; } @@ -7027,7 +5343,7 @@ get_uuid (char* uuid_found, int tag) #ifdef FSYS_XFS if (grub_memcmp(fsys_table[fsys_type].name, "xfs", 3) == 0) { - devread(2, 32, 16, (unsigned long long)(unsigned long)uuid, 0xedde0d90); + devread(2, 32, 16, (unsigned long long)(grub_size_t)uuid, 0xedde0d90); grub_sprintf(uuid_found, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]); return; } @@ -7036,7 +5352,7 @@ get_uuid (char* uuid_found, int tag) if (grub_memcmp(fsys_table[fsys_type].name, "iso9660", 7) == 0) { emu_iso_sector_size_2048 = 1; - devread(0x10, 0x33e, 16, (unsigned long long)(unsigned int)(char *)uuid, 0xedde0d90); + devread(0x10, 0x33e, 16, (unsigned long long)(grub_size_t)(char *)uuid, 0xedde0d90); ascii_to_hex ((char *)uuid, (char *)buf); grub_sprintf(uuid_found, "%02x%02x-%02x-%02x-%02x-%02x-%02x-%02x", buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7]); return; @@ -7064,15 +5380,17 @@ static struct builtin builtin_vol = " return true or false according to whether or not the DEVICE matches" " the specified Volume (if VOLUME is specified), or just list the volume of" " DEVICE (if VOLUME is not specified)." - " Use --primary for ISO Primary Volume Descriptor (as used by linux)." + " Use --primary for ISO Primary Volume Descriptor (as used by linux).\n" + "vol of DEVICE is returned in temporary variables '?'." }; -int read_mft(char* buf,unsigned long mftno); +int read_mft(char* buf,unsigned int mftno); static void get_vol (char* vol_found, int flags) { int i, j, n = 0xedde0d90; - unsigned char uni[256]={0}; +// unsigned char uni[256]={0}; + char *uni = grub_zalloc (256); if (flags) n = 0x900ddeed; @@ -7082,10 +5400,10 @@ get_vol (char* vol_found, int flags) if (primary) { emu_iso_sector_size_2048 = 1; - devread(0x10, 0x28, 0x20, (unsigned long long)(unsigned int)(char *)vol_found, n); + devread(0x10, 0x28, 0x20, (unsigned long long)(grub_size_t)(char *)vol_found, n); goto pri; } -#define BUFFER (unsigned char *)(FSYS_BUF + 0x4000) //0x3E4000 +#define BUFFER (unsigned char *)(FSYS_BUF + 0x4000) if (flags && iso_type != ISO_TYPE_udf) for (i = grub_strlen(vol_found); i<0x20; i++) vol_found[i] = 0x20; @@ -7096,7 +5414,7 @@ get_vol (char* vol_found, int flags) case ISO_TYPE_9660: case ISO_TYPE_RockRidge: emu_iso_sector_size_2048 = 1; - devread(0x10, 0x28, 0x20, (unsigned long long)(unsigned int)(char *)vol_found, n); + devread(0x10, 0x28, 0x20, (unsigned long long)(grub_size_t)(char *)vol_found, n); break; case ISO_TYPE_Joliet: if (flags) @@ -7105,7 +5423,7 @@ get_vol (char* vol_found, int flags) pb[i] = vol_found[i]; } emu_iso_sector_size_2048 = 1; - devread(*(unsigned long *)FSYS_BUF, 0x28, 0x20, (unsigned long long)(unsigned int)(char *)uni, n); + devread(*(unsigned int *)FSYS_BUF, 0x28, 0x20, (unsigned long long)(grub_size_t)(char *)uni, n); if (!flags) { big_to_little ((char *)uni, 0x20); @@ -7115,7 +5433,7 @@ get_vol (char* vol_found, int flags) case ISO_TYPE_udf: if (udf_BytePerSector == 0x800) emu_iso_sector_size_2048 = 1; - devread(*(unsigned long *)FSYS_BUF, 0, udf_BytePerSector, (unsigned long long)(unsigned int)(char *)BUFFER, 0xedde0d90); + devread(*(unsigned int *)FSYS_BUF, 0, udf_BytePerSector, (unsigned long long)(grub_size_t)(char *)BUFFER, 0xedde0d90); if (!flags) { if (*(BUFFER + 0x70) == 16) @@ -7152,7 +5470,7 @@ get_vol (char* vol_found, int flags) if (udf_BytePerSector == 0x800) emu_iso_sector_size_2048 = 1; - devread(*(unsigned long *)FSYS_BUF, 0, udf_BytePerSector, (unsigned long long)(unsigned int)(char *)BUFFER, 0x900ddeed); + devread(*(unsigned int *)FSYS_BUF, 0, udf_BytePerSector, (unsigned long long)(grub_size_t)(char *)BUFFER, 0x900ddeed); } break; } @@ -7174,12 +5492,13 @@ get_vol (char* vol_found, int flags) } else if (grub_memcmp(fsys_table[fsys_type].name, "ntfs", 4) == 0) { -#define BUFFER (unsigned char *)(FSYS_BUF + 0x7000) //0x3E7000 +#define BUFFER (unsigned char *)(FSYS_BUF + 0x8000) unsigned char *pa; unsigned char *pb; read_mft((char*)BUFFER,3); - pa = BUFFER+0x38; +// pa = BUFFER+0x38; + pa = BUFFER + *(unsigned short *)(BUFFER+0x14); while (*pa != 0xFF) { if (*pa == 0x60) @@ -7205,20 +5524,23 @@ get_vol (char* vol_found, int flags) pa[4] = 0; if (*pa == 0xff || (i > pa[4] && *pa == 0x60)) { - if (i - pa[4] + *(unsigned long *)(BUFFER + 0x18) > *(unsigned long *)(BUFFER + 0x1c)) - return; + if (i - pa[4] + *(unsigned int *)(BUFFER + 0x18) > *(unsigned int *)(BUFFER + 0x1c)) + { + grub_free (uni); + return; + } if (*pa == 0xFF) { grub_memset(pa, 0, i); pa[0] = 0x60; pa[0xa] = pa[0x14] = 0x18; pa[0xe] = 4; - *(unsigned long *)&pa[i] = 0xffffffff; + *(unsigned int *)&pa[i] = 0xffffffff; } else if (j > pa[4] - 0x18) - grub_memmove (pa + i,pa + pa[4],(BUFFER + *(unsigned long *)(BUFFER + 0x18)) - (pa + pa[4])); + grub_memmove (pa + i,pa + pa[4],(BUFFER + *(unsigned int *)(BUFFER + 0x18)) - (pa + pa[4])); - *(unsigned long *)(BUFFER + 0x18) += i - pa[4]; + *(unsigned int *)(BUFFER + 0x18) += i - pa[4]; pa[4] = i; } @@ -7228,7 +5550,7 @@ get_vol (char* vol_found, int flags) for (i=0; i= *(unsigned long *)(SUPERBLOCK+0x14)) : (((filepos-32)&((1<<*(unsigned long *)(SUPERBLOCK+0x34))-1)) == 0))) + if (!i && ((*(unsigned int *)(SUPERBLOCK+0x14)) ? ((filepos-32) >= *(unsigned int *)(SUPERBLOCK+0x14)) : (((filepos-32)&((1<<*(unsigned int *)(SUPERBLOCK+0x34))-1)) == 0))) + { + grub_free (uni); return; + } if (flags) n = 0x900ddeed; @@ -7269,9 +5594,12 @@ get_vol (char* vol_found, int flags) for (i = grub_strlen(vol_found); flags && i<11; i++) vol_found[i] = 0x20; vol_found[11] = 8; - devread (*(unsigned long long *)(SUPERBLOCK+0x58)+(filepos>>9), filepos&0x1ff, 12, (unsigned long long)(unsigned long)vol_found, n); + devread (*(unsigned long long *)(SUPERBLOCK+0x58)+(filepos>>9), filepos&0x1ff, 12, (unsigned long long)(grub_size_t)vol_found, n); if (flags) + { + grub_free (uni); return; + } vol_found[11] = 0; for (i=10; i>=0; i--) { @@ -7284,7 +5612,7 @@ get_vol (char* vol_found, int flags) { if (!flags) { - devread (*(unsigned long long *)(SUPERBLOCK+0x58)+(filepos>>9), filepos&0x1ff, 32, (unsigned long long)(unsigned long)vol_found, 0xedde0d90); + devread (*(unsigned long long *)(SUPERBLOCK+0x58)+(filepos>>9), filepos&0x1ff, 32, (unsigned long long)(grub_size_t)vol_found, 0xedde0d90); for (i=0; i < vol_found[1]*2; i++) uni[i] = vol_found[2+i]; uni[i] = 0; @@ -7299,27 +5627,30 @@ get_vol (char* vol_found, int flags) uni[1] = 11; for (i = 0; i < uni[1]; i++) pb[i] = vol_found[i]; - devread (*(unsigned long long *)(SUPERBLOCK+0x58)+(filepos>>9), filepos&0x1ff, (uni[1]+1)*2, (unsigned long long)(unsigned long)uni, 0x900ddeed); + devread (*(unsigned long long *)(SUPERBLOCK+0x58)+(filepos>>9), filepos&0x1ff, (uni[1]+1)*2, (unsigned long long)(grub_size_t)uni, 0x900ddeed); } } #undef SUPERBLOCK } else if (grub_memcmp(fsys_table[fsys_type].name, "ext2fs", 6) == 0) { - devread(2, 0x78, 16, (unsigned long long)(unsigned long)vol_found, n); + devread(2, 0x78, 16, (unsigned long long)(grub_size_t)vol_found, n); } else if (grub_memcmp(fsys_table[fsys_type].name, "fb", 2) == 0) { - devread(0, 0x47, 11, (unsigned long long)(unsigned long)vol_found, n); + devread(0, 0x47, 11, (unsigned long long)(grub_size_t)vol_found, n); } else if (flags) grub_printf("Warning: No Volume in %s filesystem type.",fsys_table[fsys_type].name); + + grub_free (uni); return; } - + /* fstest */ +static int fstest_func (char *arg, int flags); static int fstest_func (char *arg, int flags) { @@ -7348,7 +5679,7 @@ fstest_func (char *arg, int flags) else errnum = ERR_BAD_ARGUMENT; - return (int)disk_read_hook; + return (grub_size_t)disk_read_hook; } static struct builtin builtin_fstest = @@ -7360,91 +5691,13 @@ static struct builtin builtin_fstest = "Turn on/off or display the fstest mode, or toggle it if no argument." }; -#ifdef SUPPORT_GFX - -/* graphics */ + +/* geometry */ +static int geometry_func (char *arg, int flags); static int -gfxmenu_func (char *arg, int flags) +geometry_func (char *arg, int flags) { - errnum = 0; - //if (*arg) - //{ - /* filename can only be 64 characters due to our buffer size */ - if (strlen(arg) > 63) - return ! (errnum = ERR_WONT_FIT); - - if (! grub_open(arg)) - return 0; - grub_close(); - //} - - strcpy(graphics_file, arg); - - //memmove(graphics_file, arg, sizeof graphics_file - 1); - //graphics_file[sizeof graphics_file - 1] = 0; - gfx_drive = saved_drive; - gfx_partition = saved_partition; - - return 1; -} - -static struct builtin builtin_gfxmenu = -{ - "gfxmenu", - gfxmenu_func, - BUILTIN_MENU | BUILTIN_HELP_LIST, - "gfxmenu FILE", - "Use the graphical menu from FILE." -}; -#endif - - -/* geometry */ -static int -geometry_func (char *arg, int flags) -{ -// struct geometry tmp_geom; - char *msg; -// char *device = arg; - - unsigned long sync = 0; - unsigned long lba1sector = 0; - - force_geometry_tune = 0; - for (;;) - { - if (grub_memcmp (arg, "--tune", 6) == 0) - { - if (force_geometry_tune) - return (errnum = ERR_BAD_ARGUMENT, 0); - force_geometry_tune = 1; - } - else if (grub_memcmp (arg, "--bios", 6) == 0) - { - if (force_geometry_tune) - return (errnum = ERR_BAD_ARGUMENT, 0); - force_geometry_tune = 2; - } - else if (grub_memcmp (arg, "--sync", 6) == 0) - { - sync = 1; - } - else if (grub_memcmp (arg, "--lba1sector", 12) == 0) - { - if (lba1sector) - return 0; /* cannot set both --lba1sector and --lba127sector */ - lba1sector = 1; - } - else if (grub_memcmp (arg, "--lba127sector", 14) == 0) - { - if (lba1sector) - return 0; /* cannot set both --lba1sector and --lba127sector */ - lba1sector = 0x80; - } - else - break; - arg = skip_to (0, arg); - } + const char *msg = "LBA"; /* Get the drive and the partition. */ if (! *arg || *arg == ' ' || *arg == '\t') @@ -7458,11 +5711,6 @@ geometry_func (char *arg, int flags) return 0; } -// /* Get the device number. */ -// set_device (device); -// if (errnum) -// return 0; - if (fb_status && current_drive == FB_DRIVE) { current_drive = (unsigned char)(fb_status >> 8); @@ -7470,193 +5718,37 @@ geometry_func (char *arg, int flags) } /* Check for the geometry. */ - if (get_diskinfo (current_drive, &tmp_geom, lba1sector)) + if (get_diskinfo (current_drive, &tmp_geom, 0)) { - force_geometry_tune = 0; errnum = ERR_NO_DISK; return 0; } - if (lba1sector) - return 1; /* success */ - force_geometry_tune = 0; - - if (tmp_geom.flags & BIOSDISK_FLAG_BIFURCATE) - msg = "BIF"; - else if (tmp_geom.flags & BIOSDISK_FLAG_LBA_EXTENSION) - { - if (tmp_geom.flags & BIOSDISK_FLAG_LBA_1_SECTOR) - msg = "1BA"; - else - msg = "LBA"; - } - else - msg = "CHS"; - grub_printf ("drive 0x%02X(%s): C/H/S=%d/%d/%d, Sector Count/Size=%ld/%d\n", +// grub_printf ("drive 0x%02X(%s): Sector Count/Size=%ld/%d\n", + grub_printf ("drive 0x%02X(%s): SectorCount/Size=%ld / %d\n", current_drive, msg, - tmp_geom.cylinders, tmp_geom.heads, tmp_geom.sectors, (unsigned long long)tmp_geom.total_sectors, tmp_geom.sector_size); - if (tmp_geom.sector_size != 512) - { - if (sync) - { - grub_printf ("Cannot sync CD-ROM.\n"); - errnum = ERR_BAD_ARGUMENT; - return 0; /* failure */ - } - return 1; /* success */ - } - - if (sync) - { -#define BS ((struct master_and_dos_boot_sector *)mbr) - - // Make sure rawread will not call get_diskinfo again after force_geometry_tune is reset. - if (buf_drive != current_drive) - { - buf_drive = current_drive; - buf_track = -1; // invalidate track buffer - } - buf_geom = tmp_geom; - - /* Read MBR or the floppy boot sector. */ - if (! rawread (current_drive, 0, 0, SECTOR_SIZE, (unsigned long long)(unsigned long)mbr, 0xedde0d90)) - return 0; - -// if (current_drive == cdrom_drive || (current_drive >= (unsigned char)min_cdrom_id && current_drive < (unsigned char)(min_cdrom_id + atapi_dev_count))) -// { -// grub_printf ("Cannot sync CD-ROM.\n"); -// errnum = ERR_BAD_ARGUMENT; -// return 0; -// } - - if (current_drive & 0x80) - { - unsigned long start_cl, start_ch, start_dh, start_lba[4]; - unsigned long end_cl, end_ch, end_dh, end_lba[4]; - unsigned long entry1; - - if (current_drive >= 0x88 || current_drive >= 0x80 + (*(unsigned char *)0x475)) - { - errnum = ERR_NO_DISK; - return 0; - } - - /* repair partition table. */ - - for (entry1 = 0; entry1 < 4; entry1++) - { - /* get absolute starting and ending sector number. */ - start_lba[entry1] = PC_SLICE_START (mbr, entry1); - end_lba[entry1] = start_lba[entry1] + PC_SLICE_LENGTH (mbr, entry1) - 1; - /* skip null entry. */ - if (! start_lba[entry1] || ! end_lba[entry1]) - continue; - /* calculate the new CHS starting and ending values. */ - lba_to_chs (start_lba[entry1], &start_cl, &start_ch, &start_dh); - lba_to_chs (end_lba[entry1], &end_cl, &end_ch, &end_dh); - /* update values of the partition table in memory */ - PC_SLICE_HEAD (mbr, entry1) = start_dh; - PC_SLICE_SEC (mbr, entry1) = start_cl; - PC_SLICE_CYL (mbr, entry1) = start_ch; - PC_SLICE_EHEAD (mbr, entry1) = end_dh; - PC_SLICE_ESEC (mbr, entry1) = end_cl; - PC_SLICE_ECYL (mbr, entry1) = end_ch; - } - printf_debug0 ("Writing MBR for drive 0x%X ... ", current_drive); - /* Write back/update the MBR. */ - if (! rawwrite (current_drive, 0, (unsigned long long)(unsigned int)mbr)) - { - printf_debug0 ("failure.\n"); - return 0; - } else { - printf_debug0 ("success.\n"); - } - - /* repair BPB of each primary partition. */ - - for (entry1 = 0; entry1 < 4; entry1++) - { - /* skip null entry. */ - if (! start_lba[entry1] || ! end_lba[entry1]) - continue; - /* Read the first sector of the partition. */ - if (! rawread (current_drive, start_lba[entry1], 0, SECTOR_SIZE, (unsigned long long)(unsigned long)mbr, 0xedde0d90)) - continue; /* on read failure, try next entry */ - - /* try to find out the filesystem type */ - if (BS->boot_signature == 0xAA55 && ! probe_bpb(BS) && filesystem_type > 0) - { - if (BS->total_heads != tmp_geom.heads || BS->sectors_per_track != tmp_geom.sectors) - { - printf_debug0 ("(hd%d,%d): Changing H/S=%d/%d to H/S=%d/%d ... ", (current_drive & 0x7F), entry1, BS->total_heads, BS->sectors_per_track, tmp_geom.heads, tmp_geom.sectors); - BS->total_heads = tmp_geom.heads; - BS->sectors_per_track = tmp_geom.sectors; - - /* Write back/update the floppy boot sector. */ - if (! rawwrite (current_drive, start_lba[entry1], (unsigned long long)(unsigned int)mbr)) - { - printf_debug0("failure.\n"); - return 0; - } else { - printf_debug0 ("success.\n"); - } - } - } - } - } - else - { - if (current_drive >= 2) - return 1; - - /* repair floppy BPB */ - - /* try to find out the filesystem type */ - if (BS->boot_signature == 0xAA55 && ! probe_bpb(BS) && filesystem_type > 0) - { - if (BS->total_heads != tmp_geom.heads || BS->sectors_per_track != tmp_geom.sectors) - { - printf_debug0 ("Floppy %d: Changing H/S=%d/%d to H/S=%d/%d ... ", current_drive, BS->total_heads, BS->sectors_per_track, tmp_geom.heads, tmp_geom.sectors); - BS->total_heads = tmp_geom.heads; - BS->sectors_per_track = tmp_geom.sectors; - - /* Write back/update the floppy boot sector. */ - if (! rawwrite (current_drive, 0, (unsigned long long)(unsigned int)mbr)) - { - printf_debug0 ("failure.\n"); - return 0; - } else { - printf_debug0 ("success.\n"); - } - } - } - } - //return 1; -#undef BS - } - errnum = 0; - if (tmp_geom.sector_size == 512) + if (tmp_geom.sector_size == 512 || tmp_geom.sector_size == 4096) { -#define BS ((struct master_and_dos_boot_sector *)mbr) +#define BS ((struct master_and_dos_boot_sector *)mbr) //主分区和dos引导扇区 0x800 // Make sure rawread will not call get_diskinfo again after force_geometry_tune is reset. - if (buf_drive != current_drive) + if (buf_drive != (int)current_drive) { buf_drive = current_drive; buf_track = -1; // invalidate track buffer } buf_geom = tmp_geom; - /* Read MBR or the floppy boot sector. */ - if (! rawread (current_drive, 0, 0, SECTOR_SIZE, (unsigned long long)(unsigned long)mbr, 0xedde0d90)) + /* Read MBR or the floppy boot sector. */ //读当前驱动器逻辑0(1扇区)到0x8000 + if (! rawread (current_drive, 0, 0, SECTOR_SIZE, (unsigned long long)(grub_size_t)mbr, 0xedde0d90)) return 0; - if (BS->boot_signature == 0xAA55 && !(probe_mbr (BS, 0, 1, 0))) - real_open_partition (1); + if (BS->boot_signature == 0xAA55 && !(probe_mbr (BS, 0, 1, 0))) //BS=0x8000 如果存在分区表 + real_open_partition (1); //则打开分区 #undef BS } @@ -7671,48 +5763,406 @@ static struct builtin builtin_geometry = "geometry", geometry_func, BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST | BUILTIN_IFTITLE, - "geometry [--tune] [--bios] [--sync] [--lba1sector] [--lba127sector] [DRIVE]", + "geometry [DRIVE]", "Print the information for drive DRIVE or the current root device if DRIVE" " is not specified." - " If --tune is specified, the geometry will change to the tuned value." - " If --bios is specified, the geometry will change to BIOS reported value." - " If --lba1sector is specified, according to the 1 sectors read and write sectors." - " If --lba127sector is specified, according to the 127 sectors read and write sectors." - " If --sync is specified, the C/H/S values in partition table" - " of DRIVE and H/S values in BPB of each primary partition of DRIVE" - "(or BPB of floppy DRIVE) will be updated according to the current" - " geometry of DRIVE in use." }; - -/* halt */ +static inline grub_uint32_t +decode_length (const grub_uint8_t *ptr, int *numlen) +{ + int num_bytes, i; + grub_uint32_t ret; + if (*ptr < 64) + { + if (numlen) + *numlen = 1; + return *ptr; + } + num_bytes = *ptr >> 6; + if (numlen) + *numlen = num_bytes + 1; + ret = *ptr & 0xf; + ptr++; + for (i = 0; i < num_bytes; i++) + { + ret |= *ptr << (8 * i + 4); + ptr++; + } + return ret; +} + +static inline grub_uint32_t +skip_name_string (const grub_uint8_t *ptr, const grub_uint8_t *end) +{ + const grub_uint8_t *ptr0 = ptr; + + while (ptr < end && (*ptr == '^' || *ptr == '\\')) + ptr++; + switch (*ptr) + { + case '.': + ptr++; + ptr += 8; + break; + case '/': + ptr++; + ptr += 1 + (*ptr) * 4; + break; + case 0: + ptr++; + break; + default: + ptr += 4; + break; + } + return ptr - ptr0; +} + +static inline grub_uint32_t +skip_data_ref_object (const grub_uint8_t *ptr, const grub_uint8_t *end) +{ + //DBG ("Data type = 0x%x\n", *ptr); + switch (*ptr) + { + case GRUB_ACPI_OPCODE_PACKAGE: + case GRUB_ACPI_OPCODE_BUFFER: + return 1 + decode_length (ptr + 1, 0); + case GRUB_ACPI_OPCODE_ZERO: + case GRUB_ACPI_OPCODE_ONES: + case GRUB_ACPI_OPCODE_ONE: + return 1; + case GRUB_ACPI_OPCODE_BYTE_CONST: + return 2; + case GRUB_ACPI_OPCODE_WORD_CONST: + return 3; + case GRUB_ACPI_OPCODE_DWORD_CONST: + return 5; + case GRUB_ACPI_OPCODE_STRING_CONST: + { + const grub_uint8_t *ptr0 = ptr; + for (ptr++; ptr < end && *ptr; ptr++); + if (ptr == end) + return 0; + return ptr - ptr0 + 1; + } + default: + if (*ptr == '^' || *ptr == '\\' || *ptr == '_' + || (*ptr >= 'A' && *ptr <= 'Z')) + return skip_name_string (ptr, end); + grub_printf ("Unknown opcode 0x%x\n", *ptr); + return 0; + } +} + +static inline grub_uint32_t +skip_term (const grub_uint8_t *ptr, const grub_uint8_t *end) +{ + grub_uint32_t add; + const grub_uint8_t *ptr0 = ptr; + + switch(*ptr) + { + case GRUB_ACPI_OPCODE_ADD: + case GRUB_ACPI_OPCODE_AND: + case GRUB_ACPI_OPCODE_CONCAT: + case GRUB_ACPI_OPCODE_CONCATRES: + case GRUB_ACPI_OPCODE_DIVIDE: + case GRUB_ACPI_OPCODE_INDEX: + case GRUB_ACPI_OPCODE_LSHIFT: + case GRUB_ACPI_OPCODE_MOD: + case GRUB_ACPI_OPCODE_MULTIPLY: + case GRUB_ACPI_OPCODE_NAND: + case GRUB_ACPI_OPCODE_NOR: + case GRUB_ACPI_OPCODE_OR: + case GRUB_ACPI_OPCODE_RSHIFT: + case GRUB_ACPI_OPCODE_SUBTRACT: + case GRUB_ACPI_OPCODE_TOSTRING: + case GRUB_ACPI_OPCODE_XOR: + /* + * Parameters for these opcodes: TermArg, TermArg Target, see ACPI + * spec r5.0, page 828f. + */ + ptr++; + ptr += add = skip_term (ptr, end); + if (!add) + return 0; + ptr += add = skip_term (ptr, end); + if (!add) + return 0; + ptr += skip_name_string (ptr, end); + break; + default: + return skip_data_ref_object (ptr, end); + } + return ptr - ptr0; +} + +static inline grub_uint32_t +skip_ext_op (const grub_uint8_t *ptr, const grub_uint8_t *end) +{ + const grub_uint8_t *ptr0 = ptr; + int add; + //DBG ("Extended opcode: 0x%x\n", *ptr); + switch (*ptr) + { + case GRUB_ACPI_EXTOPCODE_MUTEX: + ptr++; + ptr += skip_name_string (ptr, end); + ptr++; + break; + case GRUB_ACPI_EXTOPCODE_EVENT_OP: + ptr++; + ptr += skip_name_string (ptr, end); + break; + case GRUB_ACPI_EXTOPCODE_OPERATION_REGION: + ptr++; + ptr += skip_name_string (ptr, end); + ptr++; + ptr += add = skip_term (ptr, end); + if (!add) + return 0; + ptr += add = skip_term (ptr, end); + if (!add) + return 0; + break; + case GRUB_ACPI_EXTOPCODE_FIELD_OP: + case GRUB_ACPI_EXTOPCODE_DEVICE_OP: + case GRUB_ACPI_EXTOPCODE_PROCESSOR_OP: + case GRUB_ACPI_EXTOPCODE_POWER_RES_OP: + case GRUB_ACPI_EXTOPCODE_THERMAL_ZONE_OP: + case GRUB_ACPI_EXTOPCODE_INDEX_FIELD_OP: + case GRUB_ACPI_EXTOPCODE_BANK_FIELD_OP: + ptr++; + ptr += decode_length (ptr, 0); + break; + default: + grub_printf ("Unexpected extended opcode: 0x%x\n", *ptr); + return 0; + } + return ptr - ptr0; +} + static int -halt_func (char *arg, int flags) +get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, grub_uint8_t *end, + grub_uint8_t *scope, int scope_len) { - int skip_flags = 0; + grub_uint8_t *prev = table; - errnum = 0; - for (;;) + if (!ptr) + ptr = table + sizeof (struct grub_acpi_table_header); + while (ptr < end && prev < ptr) { - if (grub_memcmp (arg, "--no-apm", 8) == 0) - { - skip_flags |= 1; + int add; + prev = ptr; + //DBG ("Opcode 0x%x\n", *ptr); + //DBG ("Tell %x\n", (unsigned) (ptr - table)); + switch (*ptr) + { + case GRUB_ACPI_OPCODE_EXTOP: + ptr++; + ptr += add = skip_ext_op (ptr, end); + if (!add) + return -1; + break; + case GRUB_ACPI_OPCODE_CREATE_DWORD_FIELD: + case GRUB_ACPI_OPCODE_CREATE_WORD_FIELD: + case GRUB_ACPI_OPCODE_CREATE_BYTE_FIELD: + { + ptr += 5; + ptr += add = skip_data_ref_object (ptr, end); + if (!add) + return -1; + ptr += 4; + break; + } + case GRUB_ACPI_OPCODE_NAME: + ptr++; + if ((!scope || grub_memcmp ((void *)scope, "\\", scope_len) == 0) && + (grub_memcmp ((void *)ptr, "_S5_", 4) == 0 || grub_memcmp ((void *)ptr, "\\_S5_", 4) == 0)) + { + int ll; + grub_uint8_t *ptr2 = ptr; + //DBG ("S5 found\n"); + ptr2 += skip_name_string (ptr, end); + if (*ptr2 != 0x12) + { + grub_printf ("Unknown opcode in _S5: 0x%x\n", *ptr2); + return -1; + } + ptr2++; + decode_length (ptr2, &ll); + ptr2 += ll; + ptr2++; + switch (*ptr2) + { + case GRUB_ACPI_OPCODE_ZERO: + return 0; + case GRUB_ACPI_OPCODE_ONE: + return 1; + case GRUB_ACPI_OPCODE_BYTE_CONST: + return ptr2[1]; + default: + grub_printf ("Unknown data type in _S5: 0x%x\n", *ptr2); + return -1; + } + } + ptr += add = skip_name_string (ptr, end); + if (!add) + return -1; + ptr += add = skip_data_ref_object (ptr, end); + if (!add) + return -1; + break; + case GRUB_ACPI_OPCODE_ALIAS: + ptr++; + /* We need to skip two name strings */ + ptr += add = skip_name_string (ptr, end); + if (!add) + return -1; + ptr += add = skip_name_string (ptr, end); + if (!add) + return -1; + break; + + case GRUB_ACPI_OPCODE_SCOPE: + { + int scope_sleep_type; + int ll; + grub_uint8_t *name; + int name_len; + + ptr++; + add = decode_length (ptr, &ll); + name = ptr + ll; + name_len = skip_name_string (name, ptr + add); + if (!name_len) + return -1; + scope_sleep_type = get_sleep_type (table, name + name_len, + ptr + add, name, name_len); + if (scope_sleep_type != -2) + return scope_sleep_type; + ptr += add; + break; } - else if (grub_memcmp (arg, "--no-acpi", 9) == 0) + case GRUB_ACPI_OPCODE_IF: + case GRUB_ACPI_OPCODE_METHOD: { - skip_flags |= 2; + ptr++; + ptr += decode_length (ptr, 0); + break; } - else if (grub_memcmp (arg, "--force-sci", 11) ==0) - { - skip_flags |= 4; + default: + grub_printf ("Unknown opcode 0x%x\n", *ptr); + return -1; + } + } + return -2; +} + +static void +grub_acpi_halt (void) +{ + struct grub_acpi_rsdp_v20 *rsdp2 = NULL; + struct grub_acpi_rsdp_v10 *rsdp1 = NULL; + struct grub_acpi_table_header *rsdt; + grub_uint32_t *entry_ptr; + grub_uint32_t port = 0; + int sleep_type = -1; + unsigned i; + grub_efi_packed_guid_t acpi_guid = GRUB_EFI_ACPI_TABLE_GUID; + grub_efi_packed_guid_t acpi20_guid = GRUB_EFI_ACPI_20_TABLE_GUID; + + for (i = 0; i < grub_efi_system_table->num_table_entries; i++) + { + grub_efi_packed_guid_t *guid = + &grub_efi_system_table->configuration_table[i].vendor_guid; + if (! grub_memcmp ((void *)guid, (void *)&acpi20_guid, + sizeof (grub_efi_packed_guid_t))) + { + rsdp2 = grub_efi_system_table->configuration_table[i].vendor_table; + break; + } + } + + if (rsdp2) + rsdp1 = &(rsdp2->rsdpv1); + else + { + for (i = 0; i < grub_efi_system_table->num_table_entries; i++) + { + grub_efi_packed_guid_t *guid = + &grub_efi_system_table->configuration_table[i].vendor_guid; + if (! grub_memcmp ((void *)guid, (void *)&acpi_guid, + sizeof (grub_efi_packed_guid_t))) + { + rsdp1 = grub_efi_system_table->configuration_table[i].vendor_table; + break; } - else - break; - arg = skip_to (0, arg); + } } - - grub_halt (skip_flags); - + if (!rsdp1) + { + grub_printf ("ACPI shutdown not supported.\n"); + return; + } + + rsdt = (struct grub_acpi_table_header *) (grub_addr_t) rsdp1->rsdt_addr; + for (entry_ptr = (grub_uint32_t *) (rsdt + 1); + entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt) + rsdt->length); + entry_ptr++) + { + if (grub_memcmp ((void *) (grub_addr_t) *entry_ptr, "FACP", 4) == 0) + { + struct grub_acpi_fadt *fadt + = ((struct grub_acpi_fadt *) (grub_addr_t) *entry_ptr); + struct grub_acpi_table_header *dsdt + = (struct grub_acpi_table_header *) (grub_addr_t) fadt->dsdt_addr; + grub_uint8_t *buf = (grub_uint8_t *) dsdt; + + port = fadt->pm1a; + + //DBG ("PM1a port=%x\n", port); + + if (grub_memcmp ((void *)dsdt->signature, "DSDT", sizeof (dsdt->signature)) == 0 + && sleep_type < 0) + sleep_type = get_sleep_type (buf, NULL, buf + dsdt->length, NULL, 0); + } + else if (grub_memcmp ((void *) (grub_addr_t) *entry_ptr, "SSDT", 4) == 0 + && sleep_type < 0) + { + struct grub_acpi_table_header *ssdt + = (struct grub_acpi_table_header *) (grub_addr_t) *entry_ptr; + grub_uint8_t *buf = (grub_uint8_t *) ssdt; + + //DBG ("SSDT = 0x%x\n", (unsigned) (grub_addr_t) ssdt); + + sleep_type = get_sleep_type (buf, NULL, buf + ssdt->length, NULL, 0); + } + } + + //DBG ("SLP_TYP = %d, port = 0x%x\n", sleep_type, port); + if (port && sleep_type >= 0 && sleep_type < 8) + { + //DBG ("Sending shutdown signal\n"); + //outw (GRUB_ACPI_SLP_EN | (sleep_type << GRUB_ACPI_SLP_TYP_OFFSET), port & 0xffff); + asm volatile ("outw %w0,%w1" : :"a" ((unsigned short int) + (GRUB_ACPI_SLP_EN | (sleep_type << GRUB_ACPI_SLP_TYP_OFFSET))), + "Nd" ((unsigned short int) (port & 0xffff))); + } + + efi_call_1 (grub_efi_system_table->boot_services->stall, 1000000); + + grub_printf ("ACPI shutdown failed\n"); +} + +/* halt */ +static int halt_func (char *arg, int flags); +static int +halt_func (char *arg, int flags) +{ + grub_acpi_halt (); + grub_halt (); /* Never reach here. */ return 0; } @@ -7729,11 +6179,9 @@ static struct builtin builtin_halt = "\nif both options are specified, return to grub4dos with failure." }; - -/* help */ -//#define MAX_SHORT_DOC_LEN 39 -//#define MAX_LONG_DOC_LEN 72 +/* help */ +static void print_doc(char *doc,int left); static void print_doc(char *doc,int left) { int max_doc_len = current_term->chars_per_line; @@ -7753,17 +6201,18 @@ static void print_doc(char *doc,int left) if (grub_isspace(doc[i++])) break; } - if ((fontx+i)>max_doc_len) + if ((int)(fontx+i)>max_doc_len) { putchar('\n',255); } - while (fontx < left) + while ((int)fontx < left) grub_putchar(' ',255); doc += grub_printf("%.*s",i,doc); } grub_putchar('\n',255); } +static int help_func (char *arg, int flags); static int help_func (char *arg, int flags) { @@ -7785,29 +6234,14 @@ help_func (char *arg, int flags) for (builtin = builtin_table; *builtin != 0; builtin++) { - // int len; - // int i; /* If this cannot be used in the command-line interface, skip this. */ - if (! ((*builtin)->flags & BUILTIN_CMDLINE)) + if (! ((*builtin)->flags & BUILTIN_CMDLINE) && (*builtin)->flags) continue; /* If this doesn't need to be listed automatically and "--all" is not specified, skip this. */ - if (! all && ! ((*builtin)->flags & BUILTIN_HELP_LIST)) + if (! all && ! ((*builtin)->flags & BUILTIN_HELP_LIST) && (*builtin)->flags) continue; -#if 0 - len = grub_strlen ((*builtin)->short_doc); - /* If the length of SHORT_DOC is too long, truncate it. */ - - if (len > MAX_SHORT_DOC_LEN - 1) - len = MAX_SHORT_DOC_LEN - 1; - - for (i = 0; i < len; i++) - grub_putchar ((*builtin)->short_doc[i]); - - for (; i < MAX_SHORT_DOC_LEN; i++) - grub_putchar (' '); -#else int i,j=MAX_SHORT_DOC_LEN; for (i = 0; (i < MAX_SHORT_DOC_LEN) && ((*builtin)->short_doc[i] != 0); i++) { @@ -7817,9 +6251,8 @@ help_func (char *arg, int flags) break; } } -// printf("%-*.*s",MAX_SHORT_DOC_LEN,MAX_SHORT_DOC_LEN-1,(*builtin)->short_doc?(*builtin)->short_doc:(*builtin)->name); printf("%-*.*s",MAX_SHORT_DOC_LEN,j-1,(*builtin)->short_doc?(*builtin)->short_doc:(*builtin)->name); -#endif + if (! left) grub_putchar ('\n', 255); @@ -7878,6 +6311,7 @@ static struct builtin builtin_help = /* hiddenmenu */ +static int hiddenmenu_func (char *arg, int flags); static int hiddenmenu_func (char *arg, int flags) { @@ -7915,14 +6349,11 @@ static struct builtin builtin_hiddenmenu = "hiddenmenu", hiddenmenu_func, BUILTIN_MENU, -#if 0 - "hiddenmenu [--silent]", - "Hide the menu." -#endif }; - /* hide */ +static int set_partition_hidden_flag (int hidden); +static int hide_func (char *arg, int flags); static int hide_func (char *arg, int flags) { @@ -7952,6 +6383,7 @@ static struct builtin builtin_hide = /* hiddenflag [--set | --clear] [PARTITION] */ +static int hiddenflag_func (char *arg, int flags); static int hiddenflag_func (char *arg, int flags) { @@ -7995,31 +6427,124 @@ static struct builtin builtin_hiddenflag = " The default partition is the current root device." }; - /* initrd */ +static int initrd_func (char *arg, int flags); static int initrd_func (char *arg, int flags) { + char *name = arg; + grub_size_t arg_len = 0; errnum = 0; - switch (kernel_type) - { - case KERNEL_TYPE_LINUX: - case KERNEL_TYPE_BIG_LINUX: - if (! load_initrd (arg)) - return 0; - break; + grub_size_t size = 0; + grub_efi_boot_services_t *b = grub_efi_system_table->boot_services; - default: - errnum = ERR_NEED_LX_KERNEL; - return 0; + if (kernel_type != KERNEL_TYPE_LINUX) + { + errnum = ERR_NEED_LX_KERNEL; + return 0; + } + while (*name && *name != ' ' && *name != '\t') //确定参数占用空间 + { + if (*name == '@') // CPIO + { + unsigned int c_namesize = 1; + char *c_name = &name[1]; + name = skip_to (1, name); + c_namesize = name - c_name; // including NUL + size += cpio_image_align (sizeof(struct cpio_header) + c_namesize); } - - return 1; -} - -static struct builtin builtin_initrd = -{ - "initrd", + grub_open (name); + if (errnum) + { + printf_errinfo ("Failed to open %s\n", name); + goto fail; + } + size += ALIGN_UP (filemax, 4096); + grub_close (); + name = skip_to (0, name); + } + if (!size) //总尺寸 + { + printf_errinfo ("invalid initrd size\n"); + goto fail; + } + + if (kernel_load_type == KERTNEL_LOAD_HANDOVER) + { + initrdefi_mem = grub_efi_allocate_any_pages (BYTES_TO_PAGES(size)); + if (!initrdefi_mem) + { + printf_errinfo ("Failed to allocate initrd memory\n"); + goto fail_old; + } + grub_memset (initrdefi_mem, 0, size); + name = arg; + size = 0; + while (*name && *name != ' ' && *name != '\t') + { + grub_open (name); + if (errnum) + { + printf_errinfo ("Failed to open %s\n", arg); + goto fail_old; + } + if (grub_read ((unsigned long long)(grub_size_t)initrdefi_mem + size, + filemax, 0xedde0d90) != filemax) + { + printf_errinfo ("premature end of file %s", arg); + goto fail_old; + } + size += ALIGN_UP (filemax, 4096); + grub_close (); + name = skip_to (0, name); + } + linuxefi_params->ramdisk_size = size; + linuxefi_params->ramdisk_image = (grub_uint32_t)(grub_addr_t) initrdefi_mem; + grub_close (); + return 1; + +fail_old: + if (initrdefi_mem) + efi_call_2 (b->free_pages, (grub_size_t)initrdefi_mem, BYTES_TO_PAGES(size)); + grub_close (); + return 0; + } + + arg_len = grub_strlen (arg) + 1; //参数尺寸 + if (initrdefi_arg) //如果内存盘已经存在 + { + grub_size_t orig_len = grub_strlen ((const char *)initrdefi_arg) + 1; //内存盘尺寸 + char *str = grub_malloc (arg_len + orig_len); //重现分配内存盘地址 + if (!str) + { + printf_errinfo ("Failed to allocate initrd args\n"); + goto fail; + } + sprintf (str, "%s %s", initrdefi_arg, arg); //复制新旧参数到新内存盘 + grub_free (initrdefi_arg); //释放旧内存盘 + initrdefi_arg = str; //新内存盘地址 + } + else //如果内存盘不存在 + { + initrdefi_arg = grub_malloc (arg_len); + if (!initrdefi_arg) + { + printf_errinfo ("Failed to allocate initrd args\n"); + goto fail; + } + strcpy (initrdefi_arg, arg); + initrdefi_size += size; + return 1; + } + +fail: + grub_close (); + return 0; +} + +static struct builtin builtin_initrd = +{ + "initrd", initrd_func, BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST | BUILTIN_NO_DECOMPRESSION, "initrd [@name=]FILE [@name=][FILE ...]", @@ -8029,6 +6554,7 @@ static struct builtin builtin_initrd = }; /* is64bit */ +static int is64bit_func (char *arg, int flags); static int is64bit_func (char *arg, int flags) { @@ -8045,90 +6571,176 @@ static struct builtin builtin_is64bit = "return value bit0=PAE supported bit1=AMD64/Intel64 supported" }; - unsigned long long initrd_addr_max; /* kernel */ +static int kernel_func (char *arg, int flags); static int kernel_func (char *arg, int flags) { - int len; - char *cmd; - kernel_t suggested_type = KERNEL_TYPE_NONE; - unsigned long load_flags = 0; + int ret; + void *kernel = NULL; + grub_efi_status_t status; + grub_efi_boot_services_t *b; + struct linux_kernel_header lh; + grub_ssize_t len, start; + b = grub_efi_system_table->boot_services; + linuxefi_params = NULL; + linuxefi_cmdline = NULL; + linuxefi_mem = NULL; + linuxefi_size = 0; + linuxefi_handover_offset = 0; + initrdefi_mem = NULL; + kernel_load_type = 0; + + if (grub_memcmp (arg, "--handover", 10) == 0) //强制使用移交协议 + { + kernel_load_type = KERTNEL_LOAD_HANDOVER; + arg = skip_to (0, arg); + } + else if (grub_memcmp (arg, "--loadfile2", 11) == 0) //强制使用加载文件2协议 + { + arg = skip_to (0, arg); + goto loadfile2; + } - errnum = 0; -#ifndef AUTO_LINUX_MEM_OPT - load_flags |= KERNEL_LOAD_NO_MEM_OPTION; + grub_open (arg); + if (errnum) + { + printf_errinfo ("Failed to open %s\n", arg); + goto failure_linuxefi; + } + status = efi_call_3 (b->allocate_pool, GRUB_EFI_LOADER_CODE, + filemax, (void **)&kernel); + if (status != GRUB_EFI_SUCCESS) + { + printf_errinfo ("Failed to allocate kernel memory\n"); + goto failure_linuxefi; + } + if (grub_read ((unsigned long long)(grub_size_t)kernel, + filemax, 0xedde0d90) != filemax) + { + printf_errinfo ("premature end of file %s", arg); + goto failure_linuxefi; + } + linuxefi_params = grub_efi_allocate_any_pages (BYTES_TO_PAGES(16384)); + if (!linuxefi_params) + { + printf_errinfo ("Failed to allocate kernel params\n"); + goto failure_linuxefi; + } + memset (linuxefi_params, 0, 16384); + memcpy (&lh, kernel, sizeof (lh)); + if (lh.boot_flag != 0xaa55) + { + printf_errinfo ("Invalid magic number\n"); + goto failure_linuxefi; + } + if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS) + { + printf_errinfo ("too many setup sectors\n"); + goto failure_linuxefi; + } + printf_debug("EFI=%d, loadflags=%x, xloadflags=%x, handover_offset=%x, version=%x\n",*(char *)IMG(0x8272), lh.loadflags, lh.xloadflags, lh.handover_offset, lh.version); + //ubuntu-18.04.6,EFI=64,loadflags=1,xloadflags=3f,handover_offset=190,version=20d,只能使用旧装载方法(EFI Handover Protocol) + //ubuntu-22.04.2,EFI=64,loadflags=1,xloadflags=7f,handover_offset=190,version=20f,可以使用新旧装载方法(EFI Handover Protocol/LoadFile2) + if (kernel_load_type == KERTNEL_LOAD_HANDOVER) //强制使用移交协议 + goto EfiHandoverBoot; + if (lh.version < 0x020b) //如果版本太低,不能使用移交协议,尝试使用加载文件2协议 + { + printf_debug ("kernel too old (0x%04x < 0x020b)\n",lh.version); +// goto failure_linuxefi; + goto LoadFile2Boot; //居然有内核版本低于0x020b,不支持移交协议却支持文件2协议的,真是不可思议! 2023-10-16 + } + //如果CPU是32位,并且内核不支持EFI32 Handover协议,尝试使用加载文件2协议 由a1ive提供 + if (*(char *)IMG(0x8272) == 32 && !(lh.xloadflags & LINUX_XLF_EFI_HANDOVER_32)) + goto LoadFile2Boot; + //如果CPU是64位,并且内核不支持EFI64 Handover协议,尝试使用加载文件2协议 由a1ive提供 + if (*(char *)IMG(0x8272) == 64 && !(lh.xloadflags & LINUX_XLF_EFI_HANDOVER_64)) + goto LoadFile2Boot; + if (!lh.handover_offset) //如果不支持 Handover 协议,尝试使用加载文件2协议 由a1ive提供 + { + printf_debug ("kernel doesn't support EFI handover\n"); +// goto failure_linuxefi; + goto LoadFile2Boot; + } +EfiHandoverBoot: + kernel_load_type = KERTNEL_LOAD_HANDOVER; +#if defined(__i386__) + if ((lh.xloadflags & LINUX_XLF_KERNEL_64) && + !(lh.xloadflags & LINUX_XLF_EFI_HANDOVER_32)) //如果CPU是32位,内核是EFI64,并且不支持EFI32移交协议 + { + printf_errinfo ("kernel doesn't support 32-bit handover, xloadflags=0x%x\n", + lh.xloadflags); + goto failure_linuxefi; + } +#else + if (!(lh.xloadflags & LINUX_XLF_KERNEL_64)) //如果CPU是64位,内核不是EFI64,或者不支持EFI64移交协议 + { + printf_errinfo ("kernel doesn't support 64-bit CPUs, xloadflags=0x%x\n", + lh.xloadflags); + goto failure_linuxefi; + } #endif - /* Deal with GNU-style long options. */ - while (1) - { - /* If the option `--type=TYPE' is specified, convert the string to - a kernel type. */ - if (grub_memcmp (arg, "--type=", 7) == 0) - { - arg += 7; - - if (grub_memcmp (arg, "netbsd", 6) == 0) - suggested_type = KERNEL_TYPE_NETBSD; - else if (grub_memcmp (arg, "freebsd", 7) == 0) - suggested_type = KERNEL_TYPE_FREEBSD; - else if (grub_memcmp (arg, "openbsd", 7) == 0) - /* XXX: For now, OpenBSD is identical to NetBSD, from GRUB's - point of view. */ - suggested_type = KERNEL_TYPE_NETBSD; - else if (grub_memcmp (arg, "linux", 5) == 0) - suggested_type = KERNEL_TYPE_LINUX; - else if (grub_memcmp (arg, "biglinux", 8) == 0) - suggested_type = KERNEL_TYPE_BIG_LINUX; - else if (grub_memcmp (arg, "multiboot", 9) == 0) - suggested_type = KERNEL_TYPE_MULTIBOOT; - else - { - errnum = ERR_BAD_ARGUMENT; - return 0; - } - } - /* If the `--no-mem-option' is specified, don't pass a Linux's mem - option automatically. If the kernel is another type, this flag - has no effect. */ - else if (grub_memcmp (arg, "--no-mem-option", 15) == 0) - load_flags |= KERNEL_LOAD_NO_MEM_OPTION; - else - break; - - /* Try the next. */ - arg = skip_to (0, arg); - } - cmd = skip_to (0, arg); - len = parse_string(cmd); - cmd[len] = 0; - len += grub_strlen (kernel_option_video) + 1; - - /* Reset MB_CMDLINE. */ - mb_cmdline = (char *) MB_CMDLINE_BUF; - if (len > MB_CMDLINE_BUFLEN) - { - errnum = ERR_WONT_FIT; - return 0; - } - - /* Copy the command-line to MB_CMDLINE and append the kernel_option_video - * which might have been set by `setvbe'. - */ - - grub_sprintf (mb_cmdline, "%s%s", cmd, kernel_option_video); - - suggested_type = load_image (arg, mb_cmdline, suggested_type, load_flags); - if (suggested_type == KERNEL_TYPE_NONE) - return 0; + linuxefi_cmdline = grub_efi_allocate_any_pages (BYTES_TO_PAGES(lh.cmdline_size + 1)); + if (!linuxefi_cmdline) + { + printf_errinfo ("Failed to allocate kernel cmdline\n"); + goto failure_linuxefi; + } + grub_sprintf (linuxefi_cmdline, "%s%s", LINUX_IMAGE, arg); + lh.cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linuxefi_cmdline; + printf_debug ("cmdline: %s @0x%x\n", linuxefi_cmdline, lh.cmd_line_ptr); + + linuxefi_handover_offset = lh.handover_offset; + start = (lh.setup_sects + 1) * 512; + len = filemax - start; + + linuxefi_size = lh.init_size; + linuxefi_mem = grub_efi_allocate_fixed (lh.pref_address, BYTES_TO_PAGES(linuxefi_size)); + if (!linuxefi_mem) + linuxefi_mem = grub_efi_allocate_any_pages (BYTES_TO_PAGES(linuxefi_size)); + if (!linuxefi_mem) + { + printf_errinfo ("Failed to allocate kernel\n"); + goto failure_linuxefi; + } + memcpy (linuxefi_mem, (char *)kernel + start, len); + /* loader_set */ + lh.code32_start = (grub_uint32_t)(grub_addr_t) linuxefi_mem; + memcpy (linuxefi_params, &lh, 2 * 512); + linuxefi_params->type_of_loader = 0x21; - kernel_type = suggested_type; - mb_cmdline += len; - linux_header = (struct linux_kernel_header *) (cur_addr - LINUX_SETUP_MOVE_SIZE); - initrd_addr_max = (linux_header->header == LINUX_MAGIC_SIGNATURE && linux_header->version >= 0x0203) - ? linux_header->initrd_addr_max : LINUX_INITRD_MAX_ADDRESS; + printf_debug("Using Handover boot.\n"); + grub_close (); + efi_call_1 (b->free_pool, kernel); + kernel_type = KERNEL_TYPE_LINUX; return 1; +failure_linuxefi: + grub_close (); + if (kernel) + efi_call_1 (b->free_pool, kernel); + if (linuxefi_cmdline) + efi_call_2 (b->free_pages, (grub_size_t)linuxefi_cmdline, + BYTES_TO_PAGES(lh.cmdline_size + 1)); + if (linuxefi_params) + efi_call_2 (b->free_pages, (grub_size_t)linuxefi_params, BYTES_TO_PAGES(16384)); + if (linuxefi_mem) + efi_call_2 (b->free_pages, (grub_size_t)linuxefi_mem, BYTES_TO_PAGES(linuxefi_size)); + return 0; + +//使用加载文件2协议 +LoadFile2Boot: + printf_debug("Using LoadFile2 boot.\n"); + grub_close (); + if (kernel) + efi_call_1 (b->free_pool, kernel); + +loadfile2: + kernel_load_type = KERTNEL_LOAD_LOADFILE2; + ret = chainloader_func (arg, flags); + if (ret) + kernel_type = KERNEL_TYPE_LINUX; + return ret; } static struct builtin builtin_kernel = @@ -8136,18 +6748,17 @@ static struct builtin builtin_kernel = "kernel", kernel_func, BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST | BUILTIN_BOOTING, - "kernel [--no-mem-option] [--type=TYPE] FILE [ARG ...]", + "kernel [--handover] FILE [ARG ...]", "Attempt to load the primary boot image from FILE. The rest of the" " line is passed verbatim as the \"kernel command line\". Any modules" - " must be reloaded after using this command. The option --type is used" - " to suggest what type of kernel to be loaded. TYPE must be either of" - " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and" - " \"multiboot\". The option --no-mem-option tells GRUB not to pass a" - " Linux's mem option automatically." + " must be reloaded after using this command.\n" + "--handover Using the 'EFI Handover Protocol' loading.\n" + "--loadfile2 Using the 'loadfile2' loading." }; - + /* lock */ +static int lock_func (char *arg, int flags); static int lock_func (char *arg, int flags) { @@ -8196,12 +6807,16 @@ static struct builtin builtin_ls = "ls", ls_func, BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_MENU | BUILTIN_HELP_LIST | BUILTIN_IFTITLE, - "ls [FILE_OR_DIR]", + "ls [--test] [FILE_OR_DIR]", "List file or directory." + "test: Test whether the file or folder exists. Return 1 if present,\n" + "otherwise return 0. Not output information." + "eg: ls --test (hd0,0)/efi/grub/menu.lst" }; /* makeactive */ +static int makeactive_func (char *arg, int flags); static int makeactive_func (char *arg, int flags) { @@ -8227,15 +6842,6 @@ makeactive_func (char *arg, int flags) return 0; } -#if 0 - /* The drive must be a hard disk. */ - if (! (current_drive & 0x80)) - { - errnum = ERR_DEV_VALUES; - return 0; - } -#endif - /* The partition must be a primary partition. */ if ((part = (current_partition >> 16)) > 3 /*|| (current_partition & 0xFFFF) != 0xFFFF*/) @@ -8245,7 +6851,7 @@ makeactive_func (char *arg, int flags) } /* Read the MBR in the scratch space. */ - if (! rawread (current_drive, 0, 0, SECTOR_SIZE, (unsigned long long)(unsigned long)mbr, 0xedde0d90)) + if (! rawread (current_drive, 0, 0, SECTOR_SIZE, (unsigned long long)(grub_size_t)mbr, 0xedde0d90)) return 0; /* If the partition is an extended partition, setting the active @@ -8282,7 +6888,7 @@ makeactive_func (char *arg, int flags) PC_SLICE_FLAG (mbr, part) = PC_SLICE_FLAG_BOOTABLE; /* Write back the MBR. */ - if (! rawwrite (current_drive, 0, (unsigned long long)(unsigned int)mbr)) + if (! rawwrite (current_drive, 0, (unsigned long long)(grub_size_t)mbr)) return 0; printf_debug0 ("Partition (%cd%d,%d) successfully set active.\n", @@ -8293,7 +6899,7 @@ makeactive_func (char *arg, int flags) else { /* Check if the other 3 entries already cleared. if not, clear them. */ - unsigned long flags_changed = 0; + unsigned int flags_changed = 0; { int j; for (j = 0; j < 4; j++) @@ -8316,7 +6922,7 @@ makeactive_func (char *arg, int flags) if (flags_changed) { /* Write back the MBR. */ - if (! rawwrite (current_drive, 0, (unsigned long long)(unsigned int)mbr)) + if (! rawwrite (current_drive, 0, (unsigned long long)(grub_size_t)mbr)) return 0; printf_debug0 ("Deactivated %d Partition(s) successfully.\n", flags_changed); @@ -8337,13 +6943,13 @@ static struct builtin builtin_makeactive = }; -static unsigned long long start_sector, sector_count; -unsigned long long initrd_start_sector; +//static unsigned long long start_sector, sector_count; +//unsigned long long initrd_start_sector; /* Get the start sector number of the file. */ -static void disk_read_start_sector_func (unsigned long long sector, unsigned long offset, unsigned long long length); +static void disk_read_start_sector_func (unsigned long long sector, unsigned int offset, unsigned long long length); static void -disk_read_start_sector_func (unsigned long long sector, unsigned long offset, unsigned long long length) +disk_read_start_sector_func (unsigned long long sector, unsigned int offset, unsigned long long length) { if (sector_count < 1) { @@ -8356,38 +6962,19 @@ static void print_bios_total_drives(void); static void print_bios_total_drives(void) { - grub_printf ("\nfloppies_orig=%d, harddrives_orig=%d, floppies_curr=%d, harddrives_curr=%d\n", - ((floppies_orig & 1)?(floppies_orig >> 6) + 1 : 0), harddrives_orig, - (((*(char*)0x410) & 1)?((*(char*)0x410) >> 6) + 1 : 0), (*(char*)0x475)); + grub_printf ("\nfloppies_curr=%d, harddrives_curr=%d, cdrom_curr=%d\n", + floppies_orig, harddrives_orig, cdrom_orig); } -unsigned long probed_total_sectors; -unsigned long probed_total_sectors_round; -unsigned long probed_heads; -unsigned long probed_sectors_per_track; -unsigned long probed_cylinders; -unsigned long sectors_per_cylinder; - -#if 0 - /* matrix of coefficients of linear equations - * - * C[n] * (H_count * S_count) + H[n] * S_count = LBA[n] - S[n] + 1 - * - * where n = 1, 2, 3, 4, 5, 6, 7, 8 - */ - /* This starts at offset 0x130 */ -long long L[9]; /* L[n] == LBA[n] - S[n] + 1 */ -long H[9]; -short C[9]; -short X; -short Y; -short Cmax; -long Hmax; -short Smax; -unsigned long Z; -#endif - +unsigned int probed_total_sectors; +unsigned int probed_total_sectors_round = 0x3f * 0xff * 0x3ff; +//unsigned int probed_sector_size; +unsigned short probed_sector_size; +unsigned int probed_heads; //探测磁头数 在probe_bpb, probe_mbr赋值. +unsigned int probed_sectors_per_track; //探测每磁道扇区数 在probe_bpb, probe_mbr赋值. +unsigned int probed_cylinders; //探测柱面数 在probe_bpb, probe_mbr赋值. +unsigned int sectors_per_cylinder; //每柱面扇区数 在probe_bpb, probe_mbr赋值. /* * return: * 0 success @@ -8395,45 +6982,35 @@ unsigned long Z; * 1 no "55 AA" at the end * */ - +int probe_bpb (struct master_and_dos_boot_sector *BS); int probe_bpb (struct master_and_dos_boot_sector *BS) { - unsigned long i,j; + unsigned int i,j; /* first, check ext2 grldr boot sector */ -// probed_total_sectors = BS->total_sectors_long; if (*(unsigned short *)((char *)BS) == 0x2EEB //"jmp + 0x30" - && ((int)(char *)BS == 0x8000 && *(unsigned short *)((char *)0x2F000 + 0x438) == 0xEF53)) + && (*(int*)((char *)BS + 0x420) == 0x8000 && *(unsigned short *)((char *)BS + 0x438) == 0xEF53)) { /* at 0D: (byte)Sectors per block. Valid values are 2, 4, 8, 16 and 32. */ -// if (BS->sectors_per_cluster < 2 || 32 % BS->sectors_per_cluster) - i = 2 << *(unsigned long *)((char *)0x2F000 + 0x418); + i = 2 << *(unsigned int *)((char *)BS + 0x418); if (i < 2 || 32 % i) goto failed_ext2_grldr; /* at 0E: (word)Bytes per block. * Valid values are 0x400, 0x800, 0x1000, 0x2000 and 0x4000. */ -// if (BS->reserved_sectors != BS->sectors_per_cluster * 0x200) -// goto failed_ext2_grldr; - -// i = *(unsigned long *)((char *)BS + 0x2C); -// if (BS->reserved_sectors == 0x400 && i != 2) j = i << 9; - i = *(unsigned long *)((char *)0x2F000 + 0x414) + 1; + i = *(unsigned int *)((char *)BS + 0x414) + 1; if (j == 0x400 && i != 2) goto failed_ext2_grldr; -// if (BS->reserved_sectors != 0x400 && i != 1) if (j != 0x400 && i != 1) goto failed_ext2_grldr; /* at 14: Pointers per block(number of blocks covered by an indirect block). * Valid values are 0x100, 0x200, 0x400, 0x800, 0x1000. */ - -// i = *(unsigned long *)((char *)BS + 0x14); i = j >> 2; if (i < 0x100 || 0x1000 % i) goto failed_ext2_grldr; @@ -8443,26 +7020,8 @@ probe_bpb (struct master_and_dos_boot_sector *BS) * Valid values are 0x10000, 0x40000, 0x100000, 0x400000 and 0x1000000. */ -// if (*(unsigned long *)((char *)BS + 0x10) != i * i) -// goto failed_ext2_grldr; - -// if (! BS->sectors_per_track || BS->sectors_per_track > 63) -// goto failed_ext2_grldr; - -// if (BS->total_heads > 256 /* (BS->total_heads - 1) >> 8 */) -// goto failed_ext2_grldr; - -// probed_heads = BS->total_heads; -// probed_sectors_per_track = BS->sectors_per_track; -// sectors_per_cylinder = probed_heads * probed_sectors_per_track; -// probed_cylinders = (probed_total_sectors + sectors_per_cylinder - 1) / sectors_per_cylinder; - probed_heads = 0xff; - probed_sectors_per_track = 0x3f; - sectors_per_cylinder = probed_heads * probed_sectors_per_track; - probed_total_sectors = *(unsigned long *)((char *)0x2F000 + 0x404); - probed_cylinders = (probed_total_sectors + sectors_per_cylinder - 1) / sectors_per_cylinder; - filesystem_type = 5; + probed_sector_size = 512; /* BPB probe success */ return 0; } @@ -8472,16 +7031,11 @@ probe_bpb (struct master_and_dos_boot_sector *BS) /* Second, check exfat grldr boot sector */ if (*(unsigned long long *)((char *)BS + 03) != 0x2020205441465845) //'EXFAT ' goto failed_exfat_grldr; - if (*(unsigned char *)((char *)BS + 0x6c) != 9) - goto failed_exfat_grldr; if (*(unsigned char *)((char *)BS + 0x6e) != 1) goto failed_exfat_grldr; - probed_heads = 0xff; - probed_sectors_per_track = 0x3f; - sectors_per_cylinder = probed_heads * probed_sectors_per_track; - probed_total_sectors = *(unsigned long *)((char *)BS + 0x48); - probed_cylinders = (probed_total_sectors + sectors_per_cylinder - 1) / sectors_per_cylinder; + probed_sector_size = *(unsigned short *)((char *)BS + 0x0b); + probed_total_sectors = *(unsigned long long *)((char *)BS + 0x48); filesystem_type = 6; return 0; @@ -8490,2951 +7044,1655 @@ probe_bpb (struct master_and_dos_boot_sector *BS) if (*(unsigned short *)((char *)BS + 0x16) == 0x6412) //'12 64' { - probed_total_sectors = *(unsigned long *)((char *)BS + 0x20); + probed_sector_size = *(unsigned short *)((char *)BS + 0x0b); + probed_total_sectors = *(unsigned int *)((char *)BS + 0x20); filesystem_type = 7; //fat12-64 return 0; } - if (*(unsigned long *)((char *)BS + 0x1b4) == 0x46424246) //'FBBF' + if (*(unsigned int *)((char *)BS + 0x1b4) == 0x46424246) //'FBBF' { + probed_sector_size = 512; filesystem_type = 8; return 0; } - /* Second, check FAT12/16/32/NTFS grldr boot sector */ - probed_total_sectors = BS->total_sectors_short ? BS->total_sectors_short : (BS->total_sectors_long ? BS->total_sectors_long : (unsigned long)BS->total_sectors_long_long); -#if 0 - if (probed_total_sectors != sector_count && sector_count != 1 && (! (probed_total_sectors & 1) || probed_total_sectors != sector_count - 1)) - goto failed_probe_BPB; -#endif - if (BS->bytes_per_sector != 0x200) - return 1; + probed_total_sectors = BS->total_sectors_short ? BS->total_sectors_short : (BS->total_sectors_long ? BS->total_sectors_long : (unsigned int)BS->total_sectors_long_long); if (! BS->sectors_per_cluster || 128 % BS->sectors_per_cluster) return 1; -// if (! BS->reserved_sectors) /* NTFS reserved_sectors is 0 */ -// goto failed_probe_BPB; if (BS->number_of_fats > (unsigned char)2 /* BS->number_of_fats && ((BS->number_of_fats - 1) >> 1) */) return 1; - if (! BS->sectors_per_track || BS->sectors_per_track > 63) - return 1; - if (BS->total_heads > 256 /* (BS->total_heads - 1) >> 8 */) - return 1; if (BS->media_descriptor < (unsigned char)0xF0) return 1; if (! BS->root_dir_entries && ! BS->total_sectors_short && ! BS->sectors_per_fat) /* FAT32 or NTFS */ + { if (BS->number_of_fats && BS->total_sectors_long && BS->sectors_per_fat32) - { filesystem_type = 3; - } else if (! BS->number_of_fats && ! BS->total_sectors_long && ! BS->reserved_sectors && BS->total_sectors_long_long) - { filesystem_type = 4; - } else + else return 1; /* unknown NTFS-style BPB */ + } else if (BS->number_of_fats && BS->sectors_per_fat) /* FAT12 or FAT16 */ + { if ((probed_total_sectors - BS->reserved_sectors - BS->number_of_fats * BS->sectors_per_fat - (BS->root_dir_entries * 32 + BS->bytes_per_sector - 1) / BS->bytes_per_sector) / BS->sectors_per_cluster < 0x0ff8 ) - { filesystem_type = 1; - } else { + else filesystem_type = 2; } else return 1; /* unknown BPB */ - probed_heads = BS->total_heads; - probed_sectors_per_track = BS->sectors_per_track; - sectors_per_cylinder = probed_heads * probed_sectors_per_track; - probed_cylinders = (probed_total_sectors + sectors_per_cylinder - 1) / sectors_per_cylinder; + probed_sector_size = *(unsigned short *)((char *)BS + 0x0b); /* BPB probe success */ return 0; } -#if 0 + /* on call: * BS points to the bootsector - * start_sector1 is the start_sector of the bootimage in the real disk, if unsure, set it to 0 - * sector_count1 is the sector_count of the bootimage in the real disk, if unsure, set it to 1 - * part_start1 is the part_start of the partition in which the bootimage resides, if unsure, set it to 0 + * start_sector1 is the start_sector of the bootimage in the + * real disk, if unsure, set it to 0 + * sector_count1 is the sector_count of the bootimage in the + * real disk, if unsure, set it to 1 + * part_start1 is the part_start of the partition in which + * the bootimage resides, if unsure, set it to 0 * * on return: * 0 success * otherwise failure * */ - +int probe_mbr (struct master_and_dos_boot_sector *BS, unsigned int start_sector1, unsigned int sector_count1, unsigned int part_start1); int -probe_mbr (struct master_and_dos_boot_sector *BS, unsigned long start_sector1, unsigned long sector_count1, unsigned long part_start1) +probe_mbr (struct master_and_dos_boot_sector *BS, unsigned int start_sector1, unsigned int sector_count1, unsigned int part_start1) { unsigned long i, j; - unsigned long lba_total_sectors = 0; - - /* probe the partition table */ - - Cmax = 0; Hmax = 0; Smax = 0; + unsigned long non_empty_entries; + unsigned long ret_val; + unsigned long active_partitions = 0; + unsigned long long L[8]; + unsigned long X; + unsigned long Y; + + /* check boot indicator (0x80 or 0) */ + non_empty_entries = 0; /* count non-empty entries */ for (i = 0; i < 4; i++) + { + int *part_entry; + /* the boot indicator must be 0x80 (bootable) or 0 (non-bootable) */ + if ((unsigned char)(BS->P[i].boot_indicator << 1))/* if neither 0x80 nor 0 */ { - int *part_entry; - /* the boot indicator must be 0x80 (for bootable) or 0 (for non-bootable) */ - if ((unsigned char)(BS->P[i].boot_indicator << 1))/* if neither 0x80 nor 0 */ - return 1; - /* check if the entry is empty, i.e., all the 16 bytes are 0 */ - part_entry = (int *)&(BS->P[i].boot_indicator); - if (*part_entry++ || *part_entry++ || *part_entry++ || *part_entry) - //if (*(long long *)&BS->P[i] || ((long long *)&BS->P[i])[1]) - { - /* valid partitions never start at 0, because this is where the MBR - * lives; and more, the number of total sectors should be non-zero. - */ - if (! BS->P[i].start_lba || ! BS->P[i].total_sectors) - return 2; - if (lba_total_sectors < BS->P[i].start_lba+BS->P[i].total_sectors) - lba_total_sectors = BS->P[i].start_lba+BS->P[i].total_sectors; - /* the partitions should not overlap each other */ - for (j = 0; j < i; j++) - { - if ((BS->P[j].start_lba <= BS->P[i].start_lba) && (BS->P[j].start_lba + BS->P[j].total_sectors >= BS->P[i].start_lba + BS->P[i].total_sectors)) - continue; - if ((BS->P[j].start_lba >= BS->P[i].start_lba) && (BS->P[j].start_lba + BS->P[j].total_sectors <= BS->P[i].start_lba + BS->P[i].total_sectors)) - continue; - if ((BS->P[j].start_lba < BS->P[i].start_lba) ? - (BS->P[i].start_lba - BS->P[j].start_lba < BS->P[j].total_sectors) : - (BS->P[j].start_lba - BS->P[i].start_lba < BS->P[i].total_sectors)) - return 3; - } - /* the cylinder number */ - C[i] = (BS->P[i].start_sector_cylinder >> 8) | ((BS->P[i].start_sector_cylinder & 0xc0) << 2); - if (Cmax < C[i]) - Cmax = C[i]; - H[i] = BS->P[i].start_head; - if (Hmax < H[i]) - Hmax = H[i]; - X = BS->P[i].start_sector_cylinder & 0x3f;/* the sector number */ - if (Smax < X) - Smax = X; - /* the sector number should not be 0. */ - ///* partitions should not start at the first track, the MBR-track */ - if (! X /* || BS->P[i].start_lba < Smax */) - return 4; - L[i] = BS->P[i].start_lba - X + 1; - if (start_sector1 == part_start1)/* extended partition is pretending to be a whole drive */ - L[i] +=(unsigned long) part_start1; - - C[i+4] = (BS->P[i].end_sector_cylinder >> 8) | ((BS->P[i].end_sector_cylinder & 0xc0) << 2); - if (Cmax < C[i+4]) - Cmax = C[i+4]; - H[i+4] = BS->P[i].end_head; - if (Hmax < H[i+4]) - Hmax = H[i+4]; - Y = BS->P[i].end_sector_cylinder & 0x3f; - if (Smax < Y) - Smax = Y; - if (! Y) - return 5; - L[i+4] = BS->P[i].start_lba + BS->P[i].total_sectors; - if (L[i+4] < Y) - return 6; - L[i+4] -= Y; - if (start_sector1 == part_start1)/* extended partition is pretending to be a whole drive */ - L[i+4] +=(unsigned long) part_start1; - - /* C[n] * (H_count * S_count) + H[n] * S_count = LBA[n] - S[n] + 1 = L[n] */ - - /* C[n] * (H * S) + H[n] * S = L[n] */ - - /* Check the large disk partition -- Win98 */ - if (Y == 63 && H[i+4] == Hmax && C[i+4] == Cmax - && (Hmax >= 254 || Cmax >= 1022) - /* && C[i+4] == 1023 */ - && (Cmax + 1) * (Hmax + 1) * 63 < L[i+4] + Y - /* && C[i] * (Hmax + 1) * 63 + H[i] * 63 + X - 1 == BS->P[i].start_lba */ - ) - { - if (C[i] * (Hmax+1) * 63 + H[i] * 63 > L[i]) - return 7; - if (C[i] * (Hmax+1) * 63 + H[i] * 63 < L[i]) - { - /* calculate CHS numbers from start LBA */ - if (X != ((unsigned long)L[i] % 63)+1 && X != 63) - return 8; - if (H[i]!=((unsigned long)L[i]/63)%(Hmax+1) && H[i]!=Hmax) - return 9; - if (C[i] != (((unsigned long)L[i]/63/(Hmax+1)) & 0x3ff) && C[i] != Cmax) - return 10; - } - C[i] = 0; - H[i] = 1; - L[i] = 63; - C[i+4] = 1; - H[i+4] = 0; - L[i+4] = (Hmax + 1) * 63; - } - - /* Check the large disk partition -- Win2K */ - else if (Y == 63 && H[i+4] == Hmax /* && C[i+4] == Cmax */ - && (C[i+4] + 1) * (Hmax + 1) * 63 < L[i+4] + Y - && ! (((unsigned long)L[i+4] + Y) % ((Hmax + 1) * 63)) - && ((((unsigned long)L[i+4] + Y) / ((Hmax + 1) * 63) - 1) & 0x3ff) == C[i+4] - ) - { - if (C[i] * (Hmax+1) * 63 + H[i] * 63 > L[i]) - return 11; - if (C[i] * (Hmax+1) * 63 + H[i] * 63 < L[i]) - { - if (((unsigned long)L[i] - H[i] * 63) % ((Hmax+1) * 63)) - return 12; - if (((((unsigned long)L[i] - H[i] * 63) / ((Hmax+1) * 63)) & 0x3ff) != C[i]) - return 13; - } - C[i] = 0; - H[i] = 1; - L[i] = 63; - C[i+4] = 1; - H[i+4] = 0; - L[i+4] = (Hmax + 1) * 63; - } - - /* Maximum of C[n] * (H * S) + H[n] * S = 1023 * 255 * 63 + 254 * 63 = 0xFB03C1 */ - - else if (L[i+4] > 0xFB03C1) /* Large disk */ - { - /* set H/S to max */ - if (Hmax < 254) - Hmax = 254; - Smax = 63; - if ((unsigned long)L[i+4] % Smax) - return 114; - if (H[i+4]!=((unsigned long)L[i+4]/63)%(Hmax+1) && H[i+4]!=Hmax) - return 115; - if (C[i+4] != (((unsigned long)L[i+4]/63/(Hmax+1)) & 0x3ff) && C[i+4] != Cmax) - return 116; - - if (C[i] * (Hmax+1) * 63 + H[i] * 63 > L[i]) - return 117; - if (C[i] * (Hmax+1) * 63 + H[i] * 63 < L[i]) - { - /* calculate CHS numbers from start LBA */ - if (X != ((unsigned long)L[i] % 63)+1 && X != 63) - return 118; - if (H[i]!=((unsigned long)L[i]/63)%(Hmax+1) && H[i]!=Hmax) - return 119; - if (C[i] != (((unsigned long)L[i]/63/(Hmax+1)) & 0x3ff) && C[i] != Cmax) - return 120; - } - C[i] = 0; - H[i] = 1; - L[i] = 63; - C[i+4] = 1; - H[i+4] = 0; - L[i+4] = (Hmax + 1) * 63; - } - } - else - { - /* empty entry, zero all the coefficients */ - C[i] = 0; - H[i] = 0; - L[i] = 0; - C[i+4] = 0; - H[i+4] = 0; - L[i+4] = 0; - } + printf_debug ("Error: invalid boot indicator(0x%X) for entry %d.\n", (unsigned char)(BS->P[i].boot_indicator), i); + ret_val = 2; + goto err_print_hex; } - -// for (i = 0; i < 4; i++) -// { -//grub_printf ("%d \t%d \t%d\n%d \t%d \t%d\n", C[i], H[i],(int)(L[i]), C[i+4], H[i+4],(int)(L[i+4])); -// } - for (i = 0; i < 8; i++) + if ((unsigned char)(BS->P[i].boot_indicator) == 0x80) + active_partitions++; + if (active_partitions > 1) { - if (C[i]) - break; + printf_debug ("Error: duplicate active flag at entry %d.\n", i); + ret_val = 3; + goto err_print_hex; } - if (i == 8) /* all C[i] == 0 */ + /* check if the entry is empty, i.e., all the 16 bytes are 0 */ + part_entry = (int *)&(BS->P[i].boot_indicator); + if (*part_entry++ || *part_entry++ || *part_entry++ || *part_entry) { - for (i = 0; i < 8; i++) - { - if (H[i]) - break; - } - if (i == 8) /* all H[i] == 0 */ - return 14; + non_empty_entries++; + /* valid partitions never start at 0, because this is where the MBR + * lives; and more, the number of total sectors should be non-zero. + */ + if (! BS->P[i].start_lba) + { + printf_warning ("Warning: partition %d should not start at sector 0(the MBR sector).\n", i); + ret_val = 4; + goto err_print_hex; + } + if (! BS->P[i].total_sectors) + { + printf_debug ("Error: number of total sectors in partition %d should not be 0.\n", i); + ret_val = 5; + goto err_print_hex; + } + /* the partitions should not overlap each other */ for (j = 0; j < i; j++) - if (L[j]) - return 15; - if (! L[i]) - return 16; - //if (*(long *)((char *)&(L[i]) + 4)) - if (L[i] > 0x7fffffff) - return 17; - if ((long)L[i] % H[i]) - return 18; - probed_sectors_per_track = (long)L[i] / H[i]; - if (probed_sectors_per_track > 63 || probed_sectors_per_track < Smax) - return 19; - Smax = probed_sectors_per_track; - for (j = i + 1; j < 8; j++) + { + if ((BS->P[j].start_lba <= BS->P[i].start_lba) && (BS->P[j].start_lba + BS->P[j].total_sectors >= BS->P[i].start_lba + BS->P[i].total_sectors)) + continue; + if ((BS->P[j].start_lba >= BS->P[i].start_lba) && (BS->P[j].start_lba + BS->P[j].total_sectors <= BS->P[i].start_lba + BS->P[i].total_sectors)) + continue; + if ((BS->P[j].start_lba < BS->P[i].start_lba) ? + (BS->P[i].start_lba - BS->P[j].start_lba < BS->P[j].total_sectors) : + (BS->P[j].start_lba - BS->P[i].start_lba < BS->P[i].total_sectors)) { - if (H[j]) - { - if (probed_sectors_per_track * H[j] != L[j]) - return 20; - } - else if (L[j]) - return 21; - } - probed_heads = Hmax + 1; -#if 0 - if (sector_count1 == 1) - probed_cylinders = 1; + printf_debug ("Error: overlapped partitions %d and %d.\n", j, i); + ret_val = 6; + goto err_print_hex; + } + } + /* the starting cylinder number */ + X = ((BS->P[i].start_sector_cylinder) & 0x3f); + /* the sector number should not be 0. */ + ///* partitions should not start at the first track, the MBR-track */ + if (! X /* || BS->P[i].start_lba < Smax */) + { + printf_debug ("Error: starting S of entry %d should not be 0.\n", i); + ret_val = 7; + goto err_print_hex; + } + Y = ((BS->P[i].end_sector_cylinder) & 0x3f); + if (! Y) + { + printf_debug ("Error: ending S of entry %d should not be 0.\n", i); + ret_val = 8; + goto err_print_hex; + } + if (BS->P[i].total_sectors != 0xffffffff) + L[i+4] = BS->P[i].start_lba + BS->P[i].total_sectors; else -#endif - { - L[8] = sector_count1; /* just set to a number big enough */ - Z = sector_count1 / probed_sectors_per_track; - for (j = probed_heads; j <= 256; j++) - { - H[8] = Z % j;/* the remainder */ - if (L[8] > H[8]) - { - L[8] = H[8];/* the least residue */ - probed_heads = j;/* we got the optimum value */ - } - } - probed_cylinders = Z / probed_heads; - if (! probed_cylinders) - probed_cylinders = 1; - } - sectors_per_cylinder = probed_heads * probed_sectors_per_track; - probed_total_sectors_round = sectors_per_cylinder * probed_cylinders; - probed_total_sectors = lba_total_sectors; + L[i+4] = 0xffffffff; + if (start_sector1 == part_start1 && L[i+4] != 0xffffffff)/* extended partition is pretending to be a whole drive */ + L[i+4] +=(unsigned long) part_start1; + if (L[i+4] < Y) + { + printf_debug ("Error: partition %d ended too near.\n", i); + ret_val = 9; + goto err_print_hex; + } + if (L[i+4] > 0x100000000ULL) + { + printf_debug ("Error: partition %d ended too far.\n", i); + ret_val = 10; + goto err_print_hex; + } } - else + } /* end for */ + if (non_empty_entries == 0) + { + printf_debug ("Error: partition table is empty.\n"); + ret_val = 11; + goto err_print_hex; + } + return 0; + +err_print_hex: + /* print the partition table in Hex */ + if (debug > 1) + for (i = 0; i < 4; i++) { - if (i > 0) - { - C[8] = C[i]; H[8] = H[i]; L[8] = L[i]; - C[i] = C[0]; H[i] = H[0]; L[i] = L[0]; - C[0] = C[8]; H[0] = H[8]; L[0] = L[8]; - } - H[8] = 0; /* will store sectors per track */ - for (i = 1; i < 8; i++) - { - H[i] = C[0] * H[i] - C[i] * H[0]; - L[i] = C[0] * L[i] - C[i] * L[0]; - if (H[i]) - { - if (H[i] < 0) - { - H[i] = - H[i];/* H[i] < 0x080000 */ - L[i] = - L[i]; - } - /* Note: the max value of H[i] is 1024 * 256 * 2 = 0x00080000, - * so L[i] should be less than 0x00080000 * 64 = 0x02000000 */ - if (L[i] <= 0 || L[i] > 0x7fffffff) - return 22; - L[8] = ((long)L[i]) / H[i]; /* sectors per track */ - if (L[8] * H[i] != L[i]) - return 23; - if (L[8] > 63 || L[8] < Smax) - return 24; - Smax = L[8]; - if (H[8]) - { - /* H[8] is the old L[8] */ - if (L[8] != H[8]) - return 25; - } - else /* H[8] is empty, so store L[8] for the first time */ - H[8] = L[8]; - } - else if (L[i]) - return 26; - } - if (H[8]) - { - /* H[8] is sectors per track */ - L[0] -= H[0] * H[8]; - /* Note: the max value of H[8] is 63, the max value of C[0] is 1023, - * so L[0] should be less than 64 * 1024 * 256 = 0x01000000 */ - if (L[0] <= 0 || L[0] > 0x7fffffff) - return 27; - - /* L[8] is number of heads */ - L[8] = ((long)L[0]) / H[8] / C[0]; - if (L[8] * H[8] * C[0] != L[0]) - return 28; - if (L[8] > 256 || L[8] <= Hmax) - return 29; - probed_sectors_per_track = H[8]; - } - else /* fail to set L[8], this means all H[i]==0, i=1,2,3,4,5,6,7 */ - { - /* Now the only equation is: C[0] * H * S + H[0] * S = L[0] */ - for (i = 63; i >= Smax; i--) - { - L[8] = L[0] - H[0] * i; - if (L[8] <= 0 || L[8] > 0x7fffffff) - continue; - Z = L[8]; - if (Z % (C[0] * i)) - continue; - L[8] = Z / (C[0] * i); - if (L[8] <= 256 && L[8] > Hmax) - break;/* we have got the PROBED_HEADS */ - } - if (i < Smax) - return 30; - probed_sectors_per_track = i; - } - probed_heads = L[8]; - sectors_per_cylinder = probed_heads * probed_sectors_per_track; - probed_cylinders = (sector_count1 + sectors_per_cylinder - 1) / sectors_per_cylinder; - if (probed_cylinders < Cmax + 1) - probed_cylinders = Cmax + 1; - probed_total_sectors_round = sectors_per_cylinder * probed_cylinders; - probed_total_sectors = lba_total_sectors; + printf ("%02X, %02X %02X %02X %02X, %02X %02X %02X %08X %08X\n" + , (unsigned char)(BS->P[i].boot_indicator) + , BS->P[i].start_head + , (unsigned char)(BS->P[i].start_sector_cylinder) + , (unsigned char)(BS->P[i].start_sector_cylinder >> 8) + , (unsigned char)(BS->P[i].system_indicator) + , BS->P[i].end_head + , (unsigned char)(BS->P[i].end_sector_cylinder) + , (unsigned char)(BS->P[i].end_sector_cylinder >> 8) + , BS->P[i].start_lba + , BS->P[i].total_sectors); } - - filesystem_type = 0; /* MBR device */ - - /* partition table probe success */ - return 0; + return ret_val; } -#endif -static unsigned long long L[8]; -static unsigned long S[8]; -static unsigned long H[8]; -static unsigned long C[8]; -static unsigned long X; -static unsigned long Y; -static unsigned long Cmax; -static unsigned long Hmax; -static unsigned long Smax; -static unsigned long Lmax; +static struct fragment_map_slot *fragment_map_slot_empty(struct fragment_map_slot *q); +static struct fragment_map_slot * +fragment_map_slot_empty(struct fragment_map_slot *q) //查找碎片空槽 返回=0/非0=没有空槽/空槽位置 +{ + int n = FRAGMENT_MAP_SLOT_SIZE; + while (n > 0) + { + if (!q->slot_len) + return q; + n -= q->slot_len; +// q += q->slot_len; + q = (struct fragment_map_slot *)((char *)q + q->slot_len); + } + return 0; +} -/* on call: - * BS points to the bootsector - * start_sector1 is the start_sector of the bootimage in the - * real disk, if unsure, set it to 0 - * sector_count1 is the sector_count of the bootimage in the - * real disk, if unsure, set it to 1 - * part_start1 is the part_start of the partition in which - * the bootimage resides, if unsure, set it to 0 - * - * on return: - * 0 success - * otherwise failure - * - */ -int -probe_mbr (struct master_and_dos_boot_sector *BS, unsigned long start_sector1, unsigned long sector_count1, unsigned long part_start1) +struct fragment_map_slot *fragment_map_slot_find(struct fragment_map_slot *q, unsigned int from); +struct fragment_map_slot * +fragment_map_slot_find(struct fragment_map_slot *q, unsigned int from) //在碎片插槽中查找包含from驱动器的插槽 返回=0/非0=没有找到/插槽位置 { - unsigned long i, j; -// unsigned long lba_total_sectors = 0; - unsigned long non_empty_entries; - unsigned long HPC; - unsigned long SPT; - unsigned long solutions = 0; - unsigned long ret_val; - unsigned long active_partitions = 0; - unsigned long best_HPC = 0; - unsigned long best_SPT = 0; - unsigned long best_bad_things = 0xFFFFFFFF; - - /* probe the partition table */ - - Cmax = 0; Hmax = 0; Smax = 0; Lmax = 0; + int n = FRAGMENT_MAP_SLOT_SIZE; -#if 0 - if (filemax < 512) + while (n > 0) { - printf_debug ("Error: filesize(=%d) less than 512.\n", (unsigned long)filemax); - return 1; + if (!q->slot_len) + return 0; + if (q->from == (unsigned char)from) + return q; + n -= q->slot_len; +// q += q->slot_len; + q = (struct fragment_map_slot *)((char *)q + q->slot_len); } -#endif + return 0; +} -#if 0 - /* check signature */ - if (BS->boot_signature != 0xAA55) +void unload_fragment_slot (unsigned int from); +void +unload_fragment_slot (unsigned int from) //卸载碎片插槽 +{ + struct fragment_map_slot *q; +// char *filename; + void *start; + int len; + +// q = (struct fragment_map_slot *)&disk_fragment_map; //q=碎片映射插槽起始位置 *q=插槽尺寸 b6e0 + q = (struct fragment_map_slot *)disk_fragment_map; //q=碎片映射插槽起始位置 *q=插槽尺寸 b6e0 +// filename = (char *)q + FRAGMENT_MAP_SLOT_SIZE; //碎片映射插槽终止位置 +// grub_size_t size = (grub_size_t)&disk_fragment_map + FRAGMENT_MAP_SLOT_SIZE; + grub_size_t size = (grub_size_t)disk_fragment_map + FRAGMENT_MAP_SLOT_SIZE; + q = fragment_map_slot_find(q, from); //q=from驱动器在碎片映射插槽起始位置 + if (q) //0/1=没有找到驱动器/找到驱动器位置 { - printf_warning ("Warning!!! No boot signature 55 AA.\n"); +// start = filename - q->slot_len; + start = (char *)size - q->slot_len; + len = q->slot_len; +// grub_memmove (q, (char *)q + q->slot_len, filename - (char *)q - q->slot_len); + grub_memmove (q, (char *)q + q->slot_len, (char *)size - (char *)q - q->slot_len); + grub_memset (start, 0, len); } -#endif +} - /* check boot indicator (0x80 or 0) */ - non_empty_entries = 0; /* count non-empty entries */ - for (i = 0; i < 4; i++) - { - int *part_entry; - /* the boot indicator must be 0x80 (bootable) or 0 (non-bootable) */ - if ((unsigned char)(BS->P[i].boot_indicator << 1))/* if neither 0x80 nor 0 */ - { - printf_debug ("Error: invalid boot indicator(0x%X) for entry %d.\n", (unsigned char)(BS->P[i].boot_indicator), i); - ret_val = 2; - goto err_print_hex; - } - if ((unsigned char)(BS->P[i].boot_indicator) == 0x80) - active_partitions++; - if (active_partitions > 1) - { - printf_debug ("Error: duplicate active flag at entry %d.\n", i); - ret_val = 3; - goto err_print_hex; - } - /* check if the entry is empty, i.e., all the 16 bytes are 0 */ - part_entry = (int *)&(BS->P[i].boot_indicator); - if (*part_entry++ || *part_entry++ || *part_entry++ || *part_entry) - { - non_empty_entries++; - /* valid partitions never start at 0, because this is where the MBR - * lives; and more, the number of total sectors should be non-zero. - */ - if (! BS->P[i].start_lba) - { - printf_warning ("Warning: partition %d should not start at sector 0(the MBR sector).\n", i); - ret_val = 4; - goto err_print_hex; - } - if (! BS->P[i].total_sectors) - { - printf_debug ("Error: number of total sectors in partition %d should not be 0.\n", i); - ret_val = 5; - goto err_print_hex; - } -// if (lba_total_sectors < BS->P[i].start_lba+BS->P[i].total_sectors) -// lba_total_sectors = BS->P[i].start_lba+BS->P[i].total_sectors; - /* the partitions should not overlap each other */ - for (j = 0; j < i; j++) - { - if ((BS->P[j].start_lba <= BS->P[i].start_lba) && (BS->P[j].start_lba + BS->P[j].total_sectors >= BS->P[i].start_lba + BS->P[i].total_sectors)) - continue; - if ((BS->P[j].start_lba >= BS->P[i].start_lba) && (BS->P[j].start_lba + BS->P[j].total_sectors <= BS->P[i].start_lba + BS->P[i].total_sectors)) - continue; - if ((BS->P[j].start_lba < BS->P[i].start_lba) ? - (BS->P[i].start_lba - BS->P[j].start_lba < BS->P[j].total_sectors) : - (BS->P[j].start_lba - BS->P[i].start_lba < BS->P[i].total_sectors)) - { - printf_debug ("Error: overlapped partitions %d and %d.\n", j, i); - ret_val = 6; - goto err_print_hex; - } - } - /* the starting cylinder number */ - C[i] = (BS->P[i].start_sector_cylinder >> 8) | ((BS->P[i].start_sector_cylinder & 0xc0) << 2); - if (Cmax < C[i]) - Cmax = C[i]; - /* the starting head number */ - H[i] = BS->P[i].start_head; - if (Hmax < H[i]) - Hmax = H[i]; - /* the starting sector number */ - X = ((BS->P[i].start_sector_cylinder) & 0x3f); - if (Smax < X) - Smax = X; - /* the sector number should not be 0. */ - ///* partitions should not start at the first track, the MBR-track */ - if (! X /* || BS->P[i].start_lba < Smax */) - { - printf_debug ("Error: starting S of entry %d should not be 0.\n", i); - ret_val = 7; - goto err_print_hex; - } - S[i] = X; - L[i] = BS->P[i].start_lba;// - X + 1; - if (start_sector1 == part_start1)/* extended partition is pretending to be a whole drive */ - L[i] +=(unsigned long) part_start1; - if (Lmax < L[i]) - Lmax = L[i]; - - /* the ending cylinder number */ - C[i+4] = (BS->P[i].end_sector_cylinder >> 8) | ((BS->P[i].end_sector_cylinder & 0xc0) << 2); - if (Cmax < C[i+4]) - Cmax = C[i+4]; - /* the ending head number */ - H[i+4] = BS->P[i].end_head; - if (Hmax < H[i+4]) - Hmax = H[i+4]; - /* the ending sector number */ - Y = ((BS->P[i].end_sector_cylinder) & 0x3f); - if (Smax < Y) - Smax = Y; - if (! Y) - { - printf_debug ("Error: ending S of entry %d should not be 0.\n", i); - ret_val = 8; - goto err_print_hex; - } - S[i+4] = Y; - if (BS->P[i].total_sectors != 0xffffffff) - L[i+4] = BS->P[i].start_lba + BS->P[i].total_sectors; - else - L[i+4] = 0xffffffff; - if (start_sector1 == part_start1 && L[i+4] != 0xffffffff)/* extended partition is pretending to be a whole drive */ - L[i+4] +=(unsigned long) part_start1; - if (L[i+4] < Y) - { - printf_debug ("Error: partition %d ended too near.\n", i); - ret_val = 9; - goto err_print_hex; - } - if (L[i+4] > 0x100000000ULL) - { - printf_debug ("Error: partition %d ended too far.\n", i); - ret_val = 10; - goto err_print_hex; - } - //L[i+4] -= Y; - //L[i+4] ++; - L[i+4] --; - if (Lmax < L[i+4]) - Lmax = L[i+4]; - } - else - { - /* empty entry, zero out all the coefficients */ - C[i] = 0; - H[i] = 0; - S[i] = 0; - L[i] = 0; - C[i+4] = 0; - H[i+4] = 0; - S[i+4] = 0; - L[i+4] = 0; - } - } /* end for */ - if (non_empty_entries == 0) - { +#if VHD_DIFFERENCE +int GetSectorSequence (char* Utf8Name, struct fragment_map_slot** SectorSeq, int exist); +int +GetSectorSequence (char* Utf8Name, struct fragment_map_slot** SectorSeq, int exist) //获得父VHD文件的扇区序列 +{ + if (exist) + { + errnum = 0; + goto aaa; + } + int i = no_decompression; + query_block_entries = -1; //仅请求块列表*/ + no_decompression = 1; + blocklist_func (Utf8Name, 1); //请求块列表 执行成功后,将设置query_block_entries=1,设置errnum=0 + no_decompression = i; +aaa: + if (errnum || query_block_entries > DRIVE_MAP_FRAGMENT || query_block_entries <= 0) + return 0; + *SectorSeq = grub_zalloc (((blklst_num_entries + 1) << 4) + 4); + struct fragment_map_slot* q = *SectorSeq; - printf_debug ("Error: partition table is empty.\n"); - ret_val = 11; - goto err_print_hex; +// struct fragment *p = (struct fragment *)&q->fragment_data; + int offse = offsetof(struct fragment_map_slot, fragment_data); + struct fragment *p = (struct fragment *)((char *)q + offse); + if (!p) + return 0; + for (i = 0; i < blklst_num_entries; i++) + { + p[i].start_sector = map_start_sector[i]; + p[i].sector_count = map_num_sectors[i]; } + p[i].start_sector = 0; + p[i].sector_count = 0; - /* This can serve as a solution if there would be no solution. */ - printf_debug ("Initial estimation: Cmax=%d, Hmax=%d, Smax=%d\n", Cmax, Hmax, Smax); + return blklst_num_entries; +} - /* Try each HPC in Hmax+1 .. 256 and each SPT in Smax .. 63 */ +char *vhd_file_name = 0; +char vhd_file_path [128]; +int GetParentUtf8Name (char *dest, grub_uint16_t *src); +int +GetParentUtf8Name (char *dest, grub_uint16_t *src) //获得utf8格式的父VHD文件名 +{ + char *d = chainloader_file_orig; + grub_uint16_t *s = src; + int count = 0; - for (SPT = Smax; SPT <= 63; SPT++) + while (*s) { - for (HPC = (Hmax == 255) ? Hmax : Hmax + 1; HPC <= 256; HPC++) - { - unsigned long bad_things = 0; + *d++ = (*s++ >> 8); + count++; + } + *d = 0; + + d = chainloader_file_orig + count; + while (*d-- != '\\') ; + d += 2; - /* Check if this combination of HPC and SPT is OK */ - for (i = 0; i < 8; i++) - { - if (L[i]) - { - unsigned long C1, H1, S1; + grub_sprintf (dest, "%s%s", vhd_file_path, d); + count = grub_strlen (dest); - /* Calculate C/H/S from LBA */ - S1 = (((unsigned long)L[i]) % SPT) + 1; - H1 = (((unsigned long)L[i]) / SPT) % HPC; - C1 = ((unsigned long)L[i]) / (SPT * HPC); - /* check sanity */ -#if 1 - if (C1 <= 1023) - { - if (C1 == C[i] && H1 == H[i] && S1 == S[i]) - { - continue; /* this is OK */ - } - if (/*C1 > C[i]*/ C1 == C[i]+1 && C[i] == Cmax && L[i] == Lmax && (H1 != HPC-1 || S1 != SPT) && (((H[i] == HPC-1 || (HPC == 255 && H[i] == 255)) && S[i] == SPT) || (H[i] == H1 && S[i] == S1))) - { - /* HP USB Disk Storage Format Tool. Bad!! */ - bad_things++; - continue; /* accept it. */ - } - } - else - { - if ((((C1 & 1023) == C[i] || 1023 == C[i]) && (S1 == S[i] || SPT == S[i]) && (H1 == H[i] || (HPC-1) == H[i])) || (1023 == C[i] && 255 == H[i] && 63 == S[i])) - continue; /* this is OK */ - } -#else - if ((C1 <= 1023) ? - ((C1 == C[i] && H1 == H[i] && S1 == S[i]) || (/*C1 > C[i]*/ C1 == C[i]+1 && C[i] == Cmax && (((H[i] == HPC-1 || (HPC == 255 && H[i] == 255)) && S[i] == SPT) || (H[i] == H1 && S[i] == S1))) ) - : - ((((C1 & 1023) == C[i] || 1023 == C[i]) && (S1 == S[i] || SPT == S[i]) && (H1 == H[i] || (HPC-1) == H[i])) || (1023 == C[i] && 255 == H[i] && 63 == S[i]))) - continue; /* this is OK */ + return count; +} #endif - /* failed, try next combination */ - break; - } - } - if (i >= 8) /* passed */ - { - solutions++; - if (HPC == 256) - bad_things += 16; /* not a good solution. */ - printf_debug ("Solution %d(bad_things=%d): H=%d, S=%d.\n", solutions, bad_things, HPC, SPT); - if (bad_things <= best_bad_things) - { - best_HPC = HPC; - best_SPT = SPT; - best_bad_things = bad_things; - } - } - } - } - ret_val = 0; /* initial value: partition table probe success */ - if (solutions == 0) - { - if ((Hmax == 254 || Hmax == 255) && Smax == 63) - { - printf_debug ("Partition table is NOT GOOD and there is no solution.\nBut there is a fuzzy solution: H=255, S=63.\n"); - best_HPC = 255; - best_SPT = 63; - } - else - { - printf_debug ("Sorry! No solution. Bad! Please report it.\n"); - ret_val = -1; /* non-zero: partition table probe failure */ - goto err_print_decimal; /* will not touch filesystem_type */ - } - } - else if (solutions == 1) + +void add_part_data (int drive); +void +add_part_data (int drive) +{ + struct grub_part_data *p; //efi分区数据 + struct grub_part_data *p_final; //efi分区数据 + unsigned int back_saved_drive = saved_drive; + unsigned int back_current_drive = current_drive; + unsigned int back_saved_partition = saved_partition; + unsigned int back_current_partition = current_partition; + struct grub_disk_data *d = get_device_by_drive(drive,0); + if (!d) + return; + + //查找分区数据结束 + p_final = partition_info; + while (p_final->next) + p_final = p_final->next; + + if (drive < 0x90) { - if (debug > 1) - { - if (best_bad_things == 0) - { - printf ("Perfectly Good!\n"); - //filesystem_type = 0; /* MBR device */ - //return 0; /* partition table probe success */ + unsigned int part = 0xFFFFFF; + unsigned long long start, len, offset; + unsigned int type, entry1, ext_offset1; + saved_drive = current_drive = drive; + saved_partition = current_partition = part; + while (( next_partition_drive = drive, //虽然大部分参数可以由vdisk_install获得,但是map之后,vdisk_install之前需要参数时还的在此获取。 + next_partition_dest = 0xFFFFFF, + next_partition_partition = &part, + next_partition_type = &type, + next_partition_start = &start, + next_partition_len = &len, + next_partition_offset = &offset, + next_partition_entry = &entry1, + next_partition_ext_offset = &ext_offset1, + next_partition_buf = mbr, + next_partition ())) + { + if (*next_partition_type == 0 || *next_partition_type == 5 || *next_partition_type == 0xf) + continue; + //如果分区已经存在,则跳过 + p = get_partition_info (current_drive, *next_partition_partition); //2023-03-26 + if (p && p->partition_start) + continue; + + p = grub_zalloc (sizeof (*p)); //分配内存 + if(! p) //如果分配内存失败 + return; + + //填充设备结构 + p->drive = drive; + p->partition = *next_partition_partition; + p->partition_type = *next_partition_type; + p->partition_start = *next_partition_start; + p->partition_size = *next_partition_len; + p->partition_offset = *next_partition_offset; + p->partition_entry = *next_partition_entry; + p->partition_ext_offset = *next_partition_ext_offset; + p->partition_activity_flag = partition_activity_flag; + grub_memcpy (&p->partition_signature, &partition_signature, 16); + + p->next = 0; + if (!partition_info) + { + partition_info = p; + p_final = p; } else { - printf ("Found 1 solution, but the partition table has problems.\n"); + p_final->next = p; + p_final = p; } } + if (get_efi_device_boot_path (drive, 1)) + { + part_data = get_partition_info (drive, part_data->partition); + if (part_data) //2023-03-26 + part_data->partition_boot = 1; + } + + saved_drive = back_saved_drive; + current_drive = back_current_drive; + saved_partition = back_saved_partition; + current_partition = back_current_partition; } else { - printf_debug ("Total solutions: %d (too many). The best one is:\n" - "H=%d, S=%d.\n", solutions, best_HPC, best_SPT); + p = grub_zalloc (sizeof (*p)); //分配内存 + if(! p) //如果分配内存失败 + return; + p->drive = drive; + p->partition = 0xffff; +// p->partition_start = cd_Image_part_start; +// p->partition_size = cd_Image_disk_size; +// p->boot_start = cd_boot_start; +// p->boot_size = cd_boot_size; +// p->partition_activity_flag = 0x60 + cd_map_count; //光盘启动镜像的驱动器号 + p->partition_boot = 1; + p->next = 0; + if (!partition_info) //使用 'if (!p_final)' 会判断错误。 当 partition_info=bp=0 时,if (!partition_info) 返回1;而 if (!p_final) 返回0。 + partition_info = p; + else + p_final->next = p; + get_efi_device_boot_path(drive, 1); } - - probed_sectors_per_track = best_SPT; - probed_heads = best_HPC; - sectors_per_cylinder = probed_heads * probed_sectors_per_track; - probed_cylinders = (Lmax / sectors_per_cylinder) + 1; -// if (probed_cylinders < Cmax + 1) -// probed_cylinders = Cmax + 1; - probed_total_sectors_round = sectors_per_cylinder * probed_cylinders; - probed_total_sectors = Lmax + 1; - - filesystem_type = 0; /* MBR device */ - if (solutions == 1 && best_bad_things == 0) - return 0; /* partition table probe success */ - -err_print_decimal: - - /* print the partition table in calculated decimal LBA C H S */ - if (debug > 1) - for (i = 0; i < 4; i++) - { - printf ("%10ld %4d %3d %2d %10ld %4d %3d %2d\n" - , (unsigned long long)L[i], C[i], H[i], S[i] - , (unsigned long long)L[i+4], C[i+4], H[i+4], S[i+4]); - } - -err_print_hex: - - /* print the partition table in Hex */ - if (debug > 1) - for (i = 0; i < 4; i++) - { - printf ("%02X, %02X %02X %02X %02X, %02X %02X %02X %08X %08X\n" - , (unsigned char)(BS->P[i].boot_indicator) - , BS->P[i].start_head - , (unsigned char)(BS->P[i].start_sector_cylinder) - , (unsigned char)(BS->P[i].start_sector_cylinder >> 8) - , (unsigned char)(BS->P[i].system_indicator) - , BS->P[i].end_head - , (unsigned char)(BS->P[i].end_sector_cylinder) - , (unsigned char)(BS->P[i].end_sector_cylinder >> 8) - , BS->P[i].start_lba - , BS->P[i].total_sectors); - } - - return ret_val; -} - -static char * -fragment_map_slot_empty(char *p) -{ - unsigned long n = FRAGMENT_MAP_SLOT_SIZE; - while (n) - { - if (!(*(unsigned short *)p)) - return p; - n -= *(unsigned short *)p; - p += *(unsigned short *)p; - } - - return 0; -} - -static char * -fragment_map_slot_find(char *p, unsigned long from) -{ - unsigned long n = FRAGMENT_MAP_SLOT_SIZE; - while (n) - { - if (!(*(unsigned short *)p)) - return 0; - if (*(p+2) == (char)from) - return p; - n -= *(unsigned short *)p; - p += *(unsigned short *)p; - } - - return 0; -} - -unsigned long analysis (char *arg, int flags); -unsigned long -analysis (char *arg, int flags) -{ - unsigned long drive; - unsigned long long tmp; - char *p = arg + 3; - - if (*arg == '(' && *(arg+1) == 'h' && *(arg+2) == 'd') - { - if (*(arg+3) == ')') - tmp = (unsigned char)(0x80 + (*(unsigned char *)0x475)); - else if (*(arg+3) == '-' && *(arg+4) == '1') - tmp = (unsigned char)(0x80 + (*(unsigned char *)0x475 - 1)); - else if (safe_parse_maxint_with_suffix (&p, &tmp, 9)) - tmp += 0x80; - else - return 0; - } - else if (*arg == '(' && *(arg+1) == ')') - tmp = saved_drive; - else if (! safe_parse_maxint_with_suffix (&arg, &tmp, 9)) - return 0; - return drive = tmp; } -unsigned long map_image_HPC, map_image_SPT; -static unsigned long long map_mem_min = 0x100000; -static unsigned long long map_mem_max = (-4096ULL); +unsigned long long tmp; +#if VHD_DIFFERENCE +unsigned long long vhd_start_sector; +#endif +unsigned int ext_num; +unsigned int ext_start_lba; +unsigned int ext_total_sectors; +/* +网起: +1. 如果执行http协议(cur_pxe_type=1),并且支持断点续传(http_feature=1),则可以不加载到内存。要加载到内存,使用 --mem 参数,并且在本模块分配内存。 +2. 如果执行tftp协议(cur_pxe_type=0),或者不支持断点续传(http_feature=0),则强制加载到内存,使用固定缓存(efi_pxe_buf),不在本模块分配内存。 +*/ -/* map */ -/* Map FROM_DRIVE to TO_DRIVE. */ +//映射 FROM 驱动器到 TO 驱动器 int -map_func (char *arg, int flags) +map_func (char *arg, int flags) //对设备进行映射 返回: 0/1=失败/成功 { char *to_drive; char *from_drive; - unsigned long to, from, /*to_o = -1,*/ i = 0, primeval_to, m; - int j = 0xff, k, l; + unsigned int to, from,primeval_to; + int k, l, m; char *filename; char *p; struct fragment_map_slot *q; - unsigned long extended_part_start; - unsigned long extended_part_length; - int err; + int prefer_top = 0; + int no_hook = 0; + int alloc_only = 0; + int no_alloc = 0; +#if VHD_DIFFERENCE + int vhd_disk = 0; + vhd_start_sector = 0; +#endif + map_pd = 0; - //struct master_and_dos_boot_sector *BS = (struct master_and_dos_boot_sector *) RAW_ADDR (0x8000); #define BS ((struct master_and_dos_boot_sector *)mbr) - unsigned long long mem = -1ULL; - int read_Only = 0; - int fake_write = 0; - int unsafe_boot = 0; - int disable_lba_mode = 0; - int disable_chs_mode = 0; - unsigned long long sectors_per_track = -1ULL; - unsigned long long heads_per_cylinder = -1ULL; - unsigned long long to_filesize = 0; - unsigned long BPB_H = 0; - unsigned long BPB_S = 0; - unsigned long in_situ = 0; - unsigned long in_situ_flags = 0; - unsigned short in_situ_id = -1; - int add_mbt = -1; - unsigned long long tmp_mem_max = map_mem_max; - /* prefer_top now means "enable blocks above address of 4GB". - * By default, prefer_top = 0, meaning that only 32-bit addressable - * memory is allowed for the specified virtual mem-drive. - -- tinybit 2017-01-24 */ - int prefer_top = 0; + unsigned long long mem = -1ULL; //0=加载到内存 -1=不加载到内存 + int read_only = 0; //只读 若read_Only=1,则同时unsafe_boot=1 + unsigned char from_log2_sector = 9; + unsigned char partmap_type = 0; + int add_mbt = 0; + char system_indicator; + char* buffer; unsigned long long skip_sectors = 0; - unsigned long long max_sectors = -1ULL; filesystem_type = -1; start_sector = sector_count = 0; - map_image_HPC = 0; map_image_SPT = 0; blklst_num_entries = 0; - -#if MAP_NUM_16 - /* backup hooked_drive_map_1[0] onto hooked_drive_map[0] */ - grub_memmove ((char *) &hooked_drive_map[0], (char *) &hooked_drive_map_1[0], sizeof (struct drive_map_slot)*8); - /* backup hooked_drive_map_2[0] onto hooked_drive_map[8] */ - grub_memmove ((char *) &hooked_drive_map[8], (char *) &hooked_drive_map_2[0], sizeof (struct drive_map_slot)*9); -#endif - + grub_efi_status_t status; //状态 + grub_efi_boot_services_t *b; //引导服务 + b = grub_efi_system_table->boot_services; //系统表->引导服务 + char *cache = 0; + struct grub_disk_data *df, *dt=0, *de; + //处理入口参数 errnum = 0; + for (;;) { - - if (grub_memcmp (arg, "--status", 8) == 0) - { - int byte = 0; - arg += 8; - if (grub_memcmp (arg, "-byte", 5) == 0) - byte = 1; - arg = skip_to(1,arg); - if (*arg>='0' && *arg <='9') + if (grub_memcmp (arg, "--status", 8) == 0) //1. 状况 按扇区显示 { - if (unset_int13_handler (1) || !safe_parse_maxint(&arg,&mem)) - return 0; - for (i = 0; i < DRIVE_MAP_SIZE && !drive_map_slot_empty (hooked_drive_map[i]); i++) + int byte = 0; + arg += 8; + if (grub_memcmp (arg, "-byte", 5) == 0) //按字节显示 --status-byte + byte = 1; + arg = skip_to(1,arg); //标记=0: 跳过"空格,回车,换行,水平制表符"; 标记=1: 跳过"空格,回车,换行,水平制表符,等号" + + if ((unsigned char)*arg>='0' /*&& *arg <='9'*/) //--status= { - if (hooked_drive_map[i].from_drive != (unsigned char)mem) - continue; -// sprintf(tmp,"0x%lX",(unsigned long long)hooked_drive_map[i].start_sector); - *(unsigned long *)ADDR_RET_STR = (unsigned long)hooked_drive_map[i].start_sector; - return hooked_drive_map[i].sector_count; + if (!safe_parse_maxint(&arg,&mem)) //分析十进制或十六进制ASCII输人字符,转换到64位整数 + return 0; //分析错误 + + df = get_device_by_drive ((unsigned int)mem,1); + if (df) + { + *(unsigned int *)ADDR_RET_STR = df->start_sector; //2024-12-12 + return df->sector_count; //返回起始扇区(32位) + } + return 0; //没有查到from驱动器号 } - return 0; - } -// if (debug > 0) - { - print_bios_total_drives(); - printf ("\nNumber of ATAPI CD-ROMs: %d\n", atapi_dev_count); - } - if (rd_base != -1ULL) - grub_printf ("\nram_drive=0x%X, rd_base=0x%lX, rd_size=0x%lX\n", ram_drive, rd_base, rd_size); - if (unset_int13_handler (1) && drive_map_slot_empty (bios_drive_map[0])) - { - grub_printf ("\nThe int13 hook is off. The drive map table is currently empty.\n"); - return 1; - } + print_bios_total_drives(); //打印软盘数,硬盘数 + if (rd_base != -1ULL) //如果rd基地址被赋值 + grub_printf ("\nram_drive=0x%X, rd_base=0x%lX, rd_size=0x%lX\n", ram_drive, rd_base, rd_size); -//struct drive_map_slot -//{ - /* Remember to update DRIVE_MAP_SLOT_SIZE once this is modified. - * The struct size must be a multiple of 4. - */ +/* +svbus插槽 +typedef struct _GRUB4DOS_DRIVE_MAP_SLOT +{ + UCHAR from_drive; //1字节 + UCHAR to_drive; //1字节 0xFF indicates a memdrive + UCHAR max_head; //1字节 + UCHAR max_sector:6; //位0-5 未使用 + UCHAR disable_lba:1; //位6: disable lba 未使用 + UCHAR read_only:1; //位7: read only 未使用 + USHORT to_cylinder:13; //位0-12: max cylinder of the TO drive 未使用 + USHORT from_cdrom:1; //位13: FROM drive is CDROM(with big 2048-byte sector) + USHORT to_cdrom:1; //位14: TO drive is CDROM(with big 2048-byte sector) 未使用 + USHORT to_support_lba:1; //位15: TO drive support LBA 未使用 + UCHAR to_head; //1字节 max head of the TO drive 未使用 + UCHAR to_sector:6; //位0-5: max sector of the TO drive + UCHAR fake_write:1; //位6: fake-write or safe-boot 未使用 + UCHAR in_situ:1; //位7: in-situ 未使用 + ULONGLONG start_sector; //8字节 + ULONGLONG sector_count; //8字节 +}GRUB4DOS_DRIVE_MAP_SLOT,*PGRUB4DOS_DRIVE_MAP_SLOT; +*/ +/* +现在: +struct drive_map_slot +{ + Remember to update DRIVE_MAP_SLOT_SIZE once this is modified. + The struct size must be a multiple of 4. + unsigned char from_drive; + unsigned char to_drive; 0xFF indicates a memdrive + unsigned char max_head; //旧svbus使用,否则蓝屏。支持碎片的新版本不需要。 + + unsigned char :7; + unsigned char read_only:1; //位7 + + unsigned short to_log2_sector:4; //位0-3 + unsigned short from_log2_sector:4; //位4-7 + unsigned short :2; + unsigned short fragment:1; //位10 + unsigned short :2; + unsigned short from_cdrom:1; //位13 + unsigned short to_cdrom:1; //位14 + unsigned short :1; + + unsigned char to_head; + unsigned char to_sector; //旧svbus使用,否则蓝屏。支持碎片的新版本不需要。 + unsigned long long start_sector; + unsigned long long sector_count; +}; +*/ - /* X=max_sector bit 7: read only or fake write */ - /* Y=to_sector bit 6: safe boot or fake write */ +//过去: + /* X=max_sector bit 7: read only or fake write */ //只读或假写 read_Only | fake_write + /* Y=to_sector bit 6: safe boot or fake write */ //安全或假写 !unsafe_boot | fake_write /* ------------------------------------------- */ - /* X Y: meaning of restrictions imposed on map */ + /* X Y: meaning of restrictions imposed on map */ //约束映射的意义.不能只看X或Y,应当组合来看. /* ------------------------------------------- */ - /* 1 1: read only=0, fake write=1, safe boot=0 */ - /* 1 0: read only=1, fake write=0, safe boot=0 */ - /* 0 1: read only=0, fake write=0, safe boot=1 */ - /* 0 0: read only=0, fake write=0, safe boot=0 */ - -// unsigned char from_drive; -// unsigned char to_drive; /* 0xFF indicates a memdrive */ -// unsigned char max_head; -// unsigned char max_sector; /* bit 7: read only */ - /* bit 6: disable lba */ - -// unsigned short to_cylinder; /* max cylinder of the TO drive */ - /* bit 15: TO drive support LBA */ - /* bit 14: TO drive is CDROM(with big 2048-byte sector) */ - /* bit 13: FROM drive is CDROM(with big 2048-byte sector) */ + /* 1 1: read only=0, fake write=1, safe boot=0 */ //假写 + /* 1 0: read only=1, fake write=0, safe boot=0 */ //只读 + /* 0 1: read only=0, fake write=0, safe boot=1 */ //安全 + /* 0 0: read only=0, fake write=0, safe boot=0 */ //未知 + +// unsigned char from_drive; //0 from驱动器 映射驱动器 +// unsigned char to_drive; /* 0xFF indicates a memdrive */ //1 to驱动器 宿主驱动器 0xff是内存驱动器 +// unsigned char max_head; //2 from最大磁头号 来源: BPB探测磁道数-1 如果chs无效,让MAX_HEAD非0,避免空槽 +// unsigned char max_sector; /* bit 7: read-only or fake-write*/ //3 from最大扇区号 位7:只读 or 假写 位6:禁止lba + /* bit 6: disable lba */ // 来源: 禁止chs模式=0; 在原处=1; 其他=每磁道扇区数; +// 如果FROM是cdrom但TO不是cdrom,则=大于1的任意数,表示仿真. + //前4字节为零, 就是空插槽!!! +// unsigned short to_cylinder; /* max cylinder of the TO drive */ //4,5 to最大柱面号 位15:to支持lba 位14:to驱动器是cdrom 位13:from驱动器是cdrom + // 位12:to是分叉 位11:to引导扇区类型已知 位10:有碎片 + // 位9-0:最大柱面号 0-0x3ff; to是分叉时,0x80代表真实分叉 + /* bit 15: TO drive support LBA */ // 来源: 由几何探测计数 + /* bit 14: TO drive is CDROM(with big 2048-byte sector) */ // 如果in_situ!=0,则to_c含义: 位8=in_situ_flags,位0-7=分区类型 + /* bit 13: FROM drive is CDROM(with big 2048-byte sector) */ // 位7-4:from_log2_sector 位3-0:to_log2_sector /* bit 12: TO drive is BIFURCATE */ /* bit 11: TO drive has a known boot sector type */ /* bit 10: TO drive has Fragment */ - -// unsigned char to_head; /* max head of the TO drive */ -// unsigned char to_sector; /* max sector of the TO drive */ - /* bit 7: in-situ */ + +// unsigned char to_head; /* max head of the TO drive */ //6 to最大磁头号 来源: 几何探测磁头数-1 +// unsigned char to_sector; /* max sector of the TO drive */ //7 to扇区数 位7:在原处 位6:假写 or 安全 + /* bit 7: in-situ */ // 来源: 几何探测每磁道扇区数 /* bit 6: fake-write or safe-boot */ -// unsigned long start_sector; -// unsigned long start_sector_hi; /* hi dword of the 64-bit value */ -// unsigned long sector_count; -// unsigned long sector_count_hi; /* hi dword of the 64-bit value */ +// unsigned long start_sector; //8 to起始扇区低 来源: 块列表.映射起始扇区 0表示整体映射 +// unsigned long start_sector_hi; /* hi dword of the 64-bit value */ //12 to起始扇区高 +// unsigned long sector_count; //16 to扇区计数低 来源: grub_open.文件最大/0x200 或者 分区长度 0或1表示整体映射 +// unsigned long sector_count_hi; /* hi dword of the 64-bit value */ //20 to扇区计数高 加载到内存时=1 + //}; - /* From To MaxHead MaxSector ToMaxCylinder ToMaxHead ToMaxSector StartLBA_lo StartLBA_hi Sector_count_lo Sector_count_hi Hook Type */ -// if (debug > 0) - grub_printf ("\nFr To Hm Sm To_C _H _S Start_Sector Sector_Count DHR" - "\n-- -- -- -- ---- -- -- ---------------- ---------------- ---\n"); - if (! unset_int13_handler (1)) - for (i = 0; i < DRIVE_MAP_SIZE; i++) - { - if (drive_map_slot_empty (hooked_drive_map[i])) - break; - for (j = 0; j < DRIVE_MAP_SIZE; j++) - { - if (drive_map_slot_equal(bios_drive_map[j], hooked_drive_map[i])) - break; - } -// if (debug > 0) - grub_printf ("%02X %02X %02X %02X %04X %02X %02X %016lX %016lX %c%c%c\n", hooked_drive_map[i].from_drive, hooked_drive_map[i].to_drive, hooked_drive_map[i].max_head, hooked_drive_map[i].max_sector, hooked_drive_map[i].to_cylinder, hooked_drive_map[i].to_head, hooked_drive_map[i].to_sector, byte?(((unsigned long long)hooked_drive_map[i].start_sector)*0x200):((unsigned long long)hooked_drive_map[i].start_sector), byte?(((unsigned long long)hooked_drive_map[i].sector_count)*0x200):((unsigned long long)hooked_drive_map[i].sector_count), ((hooked_drive_map[i].to_cylinder & 0x4000) ? 'C' : hooked_drive_map[i].to_drive < 0x80 ? 'F' : hooked_drive_map[i].to_drive == 0xFF ? 'M' : 'H'), ((j < DRIVE_MAP_SIZE) ? '=' : '>'), ((hooked_drive_map[i].max_sector & 0x80) ? ((hooked_drive_map[i].to_sector & 0x40) ? 'F' : 'R') :((hooked_drive_map[i].to_sector & 0x40) ? 'S' : 'U'))); - } - for (i = 0; i < DRIVE_MAP_SIZE; i++) - { - if (drive_map_slot_empty (bios_drive_map[i])) - break; - if (! unset_int13_handler (1)) - { - for (j = 0; j < DRIVE_MAP_SIZE; j++) - { - if (drive_map_slot_equal(hooked_drive_map[j], bios_drive_map[i])) - break; - } - if (j < DRIVE_MAP_SIZE) - continue; - } -// if (debug > 0) - grub_printf ("%02X %02X %02X %02X %04X %02X %02X %016lX %016lX %c<%c\n", bios_drive_map[i].from_drive, bios_drive_map[i].to_drive, bios_drive_map[i].max_head, bios_drive_map[i].max_sector, bios_drive_map[i].to_cylinder, bios_drive_map[i].to_head, bios_drive_map[i].to_sector, byte?(((unsigned long long)bios_drive_map[i].start_sector)*0x200):((unsigned long long)bios_drive_map[i].start_sector), byte?(((unsigned long long)bios_drive_map[i].start_sector)*0x200):((unsigned long long)bios_drive_map[i].sector_count), ((bios_drive_map[i].to_cylinder & 0x4000) ? 'C' : bios_drive_map[i].to_drive < 0x80 ? 'F' : bios_drive_map[i].to_drive == 0xFF ? 'M' : 'H'), ((bios_drive_map[i].max_sector & 0x80) ? ((bios_drive_map[i].to_sector & 0x40) ? 'F' : 'R') :((bios_drive_map[i].to_sector & 0x40) ? 'S' : 'U'))); - } - return 1; - } - else if (grub_memcmp (arg, "--hook", 6) == 0) - { - unsigned long long first_entry = -1ULL; +// TO: 200 800 1000 +//-------------------------------------------------------- +//FORM: +//200 不变 /4... /8... +//800 *4 不变 /2... +//1000 *8 *2 不变 - p = arg + 6; - if (*p == '=') - { - p++; - if (! safe_parse_maxint (&p, &first_entry)) - return 0; - if (first_entry > 0xFF) - return ! (errnum = ERR_BAD_ARGUMENT); - } - unset_int13_handler (0); - //if (! unset_int13_handler (1)) - // return ! (errnum = ERR_INT13_ON_HOOK); - if (drive_map_slot_empty (bios_drive_map[0])) - if (atapi_dev_count == 0) - return ! (errnum = ERR_NO_DRIVE_MAPPED); - if (first_entry <= 0xFF) - { - /* setup first entry */ - /* find first_entry in bios_drive_map */ - for (i = 0; i < DRIVE_MAP_SIZE - 1; i++) - { - if (drive_map_slot_empty (bios_drive_map[i])) - break; /* not found */ - if (bios_drive_map[i].from_drive == first_entry) - { - /* found */ - /* nothing to do if it is already the first entry */ - if (i == 0) - break; - /* backup this entry onto hooked_drive_map[0] */ - grub_memmove ((char *) &hooked_drive_map[0], (char *) &bios_drive_map[i], sizeof (struct drive_map_slot)); - /* move top entries downward */ - grub_memmove ((char *) &bios_drive_map[1], (char *) &bios_drive_map[0], sizeof (struct drive_map_slot) * i); - /* restore this entry onto bios_drive_map[0] from hooked_drive_map[0] */ - grub_memmove ((char *) &bios_drive_map[0], (char *) &hooked_drive_map[0], sizeof (struct drive_map_slot)); - break; - } - } - } - set_int13_handler (bios_drive_map); - buf_drive = -1; - buf_track = -1; - return 1; - } - else if (grub_memcmp (arg, "--unhook", 8) == 0) + grub_printf ("\nFd Td Fs Ts Fg Ro Start_Sector Sector_Count" + "\n-- -- -- -- ---- -- -- -- ---------------- ----------------\n"); + for (df = disk_data; df; df = df->next) //从设备结构起始查 { - //if (unset_int13_handler (1)) - // return ! (errnum = ERR_INT13_OFF_HOOK); - unset_int13_handler (0); -// int13_on_hook = 0; - buf_drive = -1; - buf_track = -1; - return 1; + if(df->sector_count) + { + grub_printf ("%02X %02X %02X %02X %02X %02X %016lX %016lX\n", df->drive, df->to_drive, + df->from_log2_sector, df->to_log2_sector, df->fragment, df->read_only, + byte?(df->start_sector << df->to_log2_sector):df->start_sector, + byte?((unsigned long long)df->sector_count) + << df->to_log2_sector:(unsigned long long)df->sector_count); + } } - else if (grub_memcmp (arg, "--unmap=", 8) == 0) - { - int drive; - char map_tmp[32]; - - p = arg + 8; - for (drive = 0xFF; drive >= 0; drive--) - { - if (drive != INITRD_DRIVE && in_range (p, drive) - #ifdef FSYS_FB - && drive != FB_DRIVE - #endif - ) - { - /* unmap drive */ - sprintf (map_tmp, "(0x%X) (0x%X)", drive, drive); - map_func (map_tmp, flags); + return 1; } - } - buf_drive = -1; - buf_track = -1; - return 1; + else if (grub_memcmp (arg, "--hook", 6) == 0) + { + buf_drive = -1; + buf_track = -1; + return 1; + } + else if (grub_memcmp (arg, "--no-hook", 9) == 0) + { + no_hook = 1; + } + else if (grub_memcmp (arg, "--unhook", 8) == 0) + { + buf_drive = -1; + buf_track = -1; + return 1; + } + else if (grub_memcmp (arg, "--unmap=", 8) == 0) + { +#if UNMAP + int drive; + p = arg + 8; + for (drive = 0xFF; drive >= 0; drive--) //从0xff到0 + { + if (drive != INITRD_DRIVE && in_range (p, drive)) //如果驱动器不是0x22及0x23,并且排列存在 + { + df = get_device_by_drive (drive,0); + if (!df) //避免驱动器不存在时死机 2023-03-26 + continue; + if (df->drive == drive && df->sector_count) //是映射驱动器 + { + //卸载碎片插槽 + if (df->fragment == 1) //有碎片 + unload_fragment_slot (drive); + //卸载映射磁盘,卸载映射分区 + uninstall (drive, df); //2023-03-28 + } + } } +#endif + buf_drive = -1; + buf_track = -1; + return 1; + } else if (grub_memcmp (arg, "--rehook", 8) == 0) - { - //if (unset_int13_handler (1)) - // return ! (errnum = ERR_INT13_OFF_HOOK); - unset_int13_handler (0); -// int13_on_hook = 0; - if (drive_map_slot_empty (bios_drive_map[0])) - if (atapi_dev_count == 0) - return 1;//! (errnum = ERR_NO_DRIVE_MAPPED); -// set_int13_handler (bios_drive_map); /* backup bios_drive_map onto hooked_drive_map */ -// unset_int13_handler (0); /* unhook it to avoid further access of hooked_drive_map by the call to map_func */ -// /* delete all memory mappings in hooked_drive_map */ -// for (i = 0; i < DRIVE_MAP_SIZE - 1; i++) -// { -// while (hooked_drive_map[i].to_drive == 0xFF && !(hooked_drive_map[i].to_cylinder & 0x4000)) -// { -// grub_memmove ((char *) &hooked_drive_map[i], (char *) &hooked_drive_map[i + 1], sizeof (struct drive_map_slot) * (DRIVE_MAP_SIZE - i)); -// } -// } - /* clear hooked_drive_map */ - grub_memset ((char *) hooked_drive_map, 0, sizeof (struct drive_map_slot) * (DRIVE_MAP_SIZE)); - - /* re-create (topdown) all memory map entries in hooked_drive_map from bios_drive_map */ - for (j = 0; j < DRIVE_MAP_SIZE - 1; j++) - { - unsigned long long top_start = 0; - unsigned long top_entry = DRIVE_MAP_SIZE; - /* find the top memory mapping in bios_drive_map */ - for (i = 0; i < DRIVE_MAP_SIZE - 1; i++) - { - if (bios_drive_map[i].to_drive == 0xFF && !(bios_drive_map[i].to_cylinder & 0x4000)) + { + buf_drive = -1; + buf_track = -1; + return 1; + } + else if (grub_memcmp (arg, "--floppies=", 11) == 0) + { + return 1; + } + else if (grub_memcmp (arg, "--harddrives=", 13) == 0) + { + return 1; + } + else if (grub_memcmp (arg, "--ram-drive=", 12) == 0) //8. 内存盘 设置rd驱动器号,默认0x7f,设置区间:0-0xfe { - if (top_start < bios_drive_map[i].start_sector) - { - top_start = bios_drive_map[i].start_sector; - top_entry = i; - } - } - } - if (top_entry >= DRIVE_MAP_SIZE) /* not found */ - break; /* end */ - /* move it to hooked_drive_map, by a copy and a delete */ - grub_memmove ((char *) &hooked_drive_map[j], (char *) &bios_drive_map[top_entry], sizeof (struct drive_map_slot)); - grub_memmove ((char *) &bios_drive_map[top_entry], (char *) &bios_drive_map[top_entry + 1], sizeof (struct drive_map_slot) * (DRIVE_MAP_SIZE - top_entry)); - } - /* now there should be no memory mappings in bios_drive_map. */ - -#if MAP_NUM_16 - /* backup hooked_drive_map[0] onto hooked_drive_map_1[0]*/ - grub_memmove ((char *) &hooked_drive_map_1[0], (char *) &hooked_drive_map[0], sizeof (struct drive_map_slot)*8); - /* backup hooked_drive_map[8] onto hooked_drive_map_2[0] */ - grub_memmove ((char *) &hooked_drive_map_2[0], (char *) &hooked_drive_map[8], sizeof (struct drive_map_slot)*9); -#endif + p = arg + 12; + if (! safe_parse_maxint (&p, &tmp)) + return 0; + if (tmp > 254) + return ! (errnum = ERR_INVALID_RAM_DRIVE); + ram_drive = tmp; -// /* delete all memory mappings in bios_drive_map */ -// for (i = 0; i < DRIVE_MAP_SIZE - 1; i++) -// { -// while (bios_drive_map[i].to_drive == 0xFF && !(bios_drive_map[i].to_cylinder & 0x4000)) -// { -// grub_memmove ((char *) &bios_drive_map[i], (char *) &bios_drive_map[i + 1], sizeof (struct drive_map_slot) * (DRIVE_MAP_SIZE - i)); -// } -// } - /* re-create all memory mappings stored in hooked_drive_map */ - for (i = 0; i < DRIVE_MAP_SIZE - 1; i++) - { - if (hooked_drive_map[i].to_drive == 0xFF && !(hooked_drive_map[i].to_cylinder & 0x4000)) - { - char tmp[128]; -#ifndef NO_DECOMPRESSION - int no_decompression_bak = no_decompression; -#endif - //int is64bit_bak = is64bit; - sprintf (tmp, "--add-mbt=0 %s --heads=%d --sectors-per-track=%d (md)0x%lX+0x%lX (0x%X)", ((((unsigned long long)hooked_drive_map[i].start_sector >= 0x800000ULL) && (hooked_drive_map[i].from_drive != INITRD_DRIVE))? "--top" : ""), (hooked_drive_map[i].max_head + 1), ((hooked_drive_map[i].max_sector) & 63), (unsigned long long)hooked_drive_map[i].start_sector, (unsigned long long)hooked_drive_map[i].sector_count, hooked_drive_map[i].from_drive); - - printf_debug ("Re-map the memdrive (0x%X):\n\tmap %s\n", hooked_drive_map[i].from_drive, tmp); - errnum = 0; - disable_map_info = 1; - - /* because we are "rehooking", we should not decompress the - * sector data in memory. i.e., no_decompression for all - * mem-drives, not only for the INITRD_DRIVE. - * tinybit 2017-01-24 */ - - //if (hooked_drive_map[i].from_drive == INITRD_DRIVE) - { -#ifndef NO_DECOMPRESSION - no_decompression = 1; -#endif - //is64bit = 0; /* Don't touch is64bit. Instead, we now use --top to control it. -- tinybit 2017-01-24 */ + return 1; } - map_func (tmp, flags); - //if (hooked_drive_map[i].from_drive == INITRD_DRIVE) + else if (grub_memcmp (arg, "--rd-base=", 10) == 0) //9. rd基址 { -#ifndef NO_DECOMPRESSION - no_decompression = no_decompression_bak; -#endif - //is64bit = is64bit_bak; - } - disable_map_info = 0; + p = arg + 10; + if (! safe_parse_maxint_with_suffix (&p, &tmp, 9)) + return 0; + rd_base = tmp; - if (errnum) - { - printf_errinfo ("Fatal: Error %d occurred while 'map %s'. Please report this bug.\n", errnum, tmp); - return 0; + return 1; } - - if (hooked_drive_map[i].from_drive == INITRD_DRIVE) - linux_header->ramdisk_image = RAW_ADDR (initrd_start_sector << 9); - /* change the map options */ - for (j = 0; j < DRIVE_MAP_SIZE - 1; j++) + else if (grub_memcmp (arg, "--rd-size=", 10) == 0) //10. rd尺寸 { - if (bios_drive_map[j].from_drive == hooked_drive_map[i].from_drive && bios_drive_map[j].to_drive == 0xFF && !(bios_drive_map[j].to_cylinder & 0x4000)) - { - bios_drive_map[j].max_head = hooked_drive_map[i].max_head; - bios_drive_map[j].max_sector = hooked_drive_map[i].max_sector; - bios_drive_map[j].to_cylinder = hooked_drive_map[i].to_cylinder; - bios_drive_map[j].to_head = hooked_drive_map[i].to_head; - bios_drive_map[j].to_sector = hooked_drive_map[i].to_sector; - break; - } + p = arg + 10; + if (! safe_parse_maxint_with_suffix (&p, &tmp, 9)) + return 0; + rd_size = tmp; + return 1; } - } - } - set_int13_handler (bios_drive_map); /* hook it */ - buf_drive = -1; - buf_track = -1; - return 1; - } - else if (grub_memcmp (arg, "--floppies=", 11) == 0) - { - unsigned long long floppies; - p = arg + 11; - if (! safe_parse_maxint (&p, &floppies)) - return 0; - if (floppies > 2) - return ! (errnum = ERR_INVALID_FLOPPIES); - *((char *)0x410) &= 0x3e; - if (floppies) - *((char *)0x410) |= (floppies == 1) ? 1 : 0x41; - return 1; - } - else if (grub_memcmp (arg, "--harddrives=", 13) == 0) - { - unsigned long long harddrives; - p = arg + 13; - if (! safe_parse_maxint (&p, &harddrives)) - return 0; - if (harddrives > 127) - return ! (errnum = ERR_INVALID_HARDDRIVES); - *((char *)0x475) = harddrives; - return 1; - } - else if (grub_memcmp (arg, "--ram-drive=", 12) == 0) - { - unsigned long long tmp; - p = arg + 12; - if (! safe_parse_maxint (&p, &tmp)) - return 0; - if (tmp > 254) - return ! (errnum = ERR_INVALID_RAM_DRIVE); - ram_drive = tmp; - - return 1; - } - else if (grub_memcmp (arg, "--rd-base=", 10) == 0) - { - unsigned long long tmp; - p = arg + 10; - if (! safe_parse_maxint_with_suffix (&p, &tmp, 9)) - return 0; -// if (tmp == 0xffffffff) -// return ! (errnum = ERR_INVALID_RD_BASE); - rd_base = tmp; - - return 1; - } - else if (grub_memcmp (arg, "--rd-size=", 10) == 0) - { - unsigned long long tmp; - p = arg + 10; - if (! safe_parse_maxint_with_suffix (&p, &tmp, 9)) - return 0; -// if (tmp == 0) -// return ! (errnum = ERR_INVALID_RD_SIZE); - rd_size = tmp; - - return 1; - } else if (grub_memcmp (arg, "--e820cycles=", 13) == 0) - { - unsigned long long tmp; - p = arg + 13; - if (! safe_parse_maxint (&p, &tmp)) - return 0; - e820cycles = tmp; - return 1; - } + { + return 1; + } else if (grub_memcmp (arg, "--int15nolow=", 13) == 0) - { - unsigned long long tmp; - p = arg + 13; - if (! safe_parse_maxint (&p, &tmp)) - return 0; - int15nolow = tmp; - return 1; - } + { + return 1; + } else if (grub_memcmp (arg, "--memdisk-raw=", 14) == 0) - { - unsigned long long tmp; - p = arg + 14; - if (! safe_parse_maxint (&p, &tmp)) - return 0; - memdisk_raw = tmp; - return 1; - } + { + return 1; + } else if (grub_memcmp (arg, "--a20-keep-on=", 14) == 0) - { - unsigned long long tmp; - p = arg + 14; - if (! safe_parse_maxint (&p, &tmp)) - return 0; - a20_keep_on = tmp; - return 1; - } + { + return 1; + } else if (grub_memcmp (arg, "--safe-mbr-hook=", 16) == 0) - { - unsigned long long tmp; - p = arg + 16; - if (! safe_parse_maxint (&p, &tmp)) - return 0; - safe_mbr_hook = tmp; - return 1; - } + { + return 1; + } else if (grub_memcmp (arg, "--int13-scheme=", 15) == 0) - { - unsigned long long tmp; - p = arg + 15; - if (! safe_parse_maxint (&p, &tmp)) - return 0; - int13_scheme = tmp; - return 1; - } + { + return 1; + } else if (grub_memcmp (arg, "--mem-max=", 10) == 0) - { - unsigned long long num; - p = arg + 10; - if (! safe_parse_maxint_with_suffix (&p, &num, 9)) - return 0; - map_mem_max = (num<<9) & (-4096ULL); // convert to bytes, 4KB alignment, round down - if (is64bit) { - if (map_mem_max==0) - map_mem_max = (-4096ULL); - } else { - if (map_mem_max==0 || map_mem_max>(1ULL<<32)) - map_mem_max = (1ULL<<32); // 4GB - }\ - printf_debug0("map_mem_max = 0x%lX sectors = 0x%lX bytes\n",map_mem_max>>9,map_mem_max); - return 1; - } + { + return 1; + } else if (grub_memcmp (arg, "--mem-min=", 10) == 0) - { - unsigned long long num; - p = arg + 10; - if (! safe_parse_maxint_with_suffix (&p, &num, 9)) - return 0; - map_mem_min = (((num<<9)+4095)&(-4096ULL)); // convert to bytes, 4KB alignment, round up - if (map_mem_min < (1ULL<<20)) - map_mem_min = (1ULL<<20); // 1MB - printf_debug0("map_mem_min = 0x%lX sectors = 0x%lX bytes\n",map_mem_min>>9,map_mem_min); - return 1; - } - else if (grub_memcmp (arg, "--mem=", 6) == 0) - { - p = arg + 6; - if (! safe_parse_maxint_with_suffix (&p, &mem, 9)) - return 0; - if (mem == -1ULL) - mem = -2ULL;//return errnum = ERR_INVALID_MEM_RESERV; - } - else if (grub_memcmp (arg, "--mem", 5) == 0) - { - mem = 0; - } - else if (grub_memcmp (arg, "--top", 5) == 0) - { - prefer_top = 1; - } + { + return 1; + } + else if (grub_memcmp (arg, "--mem=", 6) == 0) //19. 指定mem的位置(扇区数)) + { + p = arg + 6; + if (! safe_parse_maxint_with_suffix (&p, &mem, 9)) + return 0; + } + else if (grub_memcmp (arg, "--mem", 5) == 0) //20. 使用内存映射 + { + mem = 0; //0=加载到内存 -1=不加载到内存 + } + else if (grub_memcmp (arg, "--top", 5) == 0) //21. 内存映射置顶 + { + //有人反映:UEFI固件不会自动分配内存到4GB以上,必须强制加载到4GB以上内存。 + prefer_top = 1; + mem = 0; + } else if (grub_memcmp (arg, "--read-only", 11) == 0) - { - if (read_Only || fake_write || unsafe_boot) - return !(errnum = ERR_SPECIFY_RESTRICTION); - read_Only = 1; - unsafe_boot = 1; - } + { + read_only = 1; + } else if (grub_memcmp (arg, "--fake-write", 12) == 0) - { - if (read_Only || fake_write || unsafe_boot) - return !(errnum = ERR_SPECIFY_RESTRICTION); - fake_write = 1; - unsafe_boot = 1; - } - else if (grub_memcmp (arg, "--unsafe-boot", 13) == 0) - { - if (unsafe_boot) - return !(errnum = ERR_SPECIFY_RESTRICTION); - unsafe_boot = 1; - } + { + } + else if (grub_memcmp (arg, "--fake-write", 12) == 0) + { + } else if (grub_memcmp (arg, "--disable-chs-mode", 18) == 0) - { - disable_chs_mode = 1; - } + { + } else if (grub_memcmp (arg, "--disable-lba-mode", 18) == 0) - { - disable_lba_mode = 1; - } + { + } else if (grub_memcmp (arg, "--in-place=", 11) == 0) - { - unsigned long long tmp; - p = arg + 11; - if (! safe_parse_maxint (&p, &tmp)) - return 0; - in_situ_flags = (unsigned char)tmp; - in_situ = 2; - } + { + } else if (grub_memcmp (arg, "--in-situ=", 10) == 0) - { - unsigned long long tmp; - p = arg + 10; - if (! safe_parse_maxint (&p, &tmp)) - return 0; - in_situ_flags = (unsigned char)tmp; - if (*(arg + 10) == '0' && *(arg + 11) == 'x') - in_situ_id = (unsigned short)tmp >> 8; - in_situ = 1; - } + { + } else if (grub_memcmp (arg, "--in-place", 10) == 0) - { - in_situ = 2; - } + { + } else if (grub_memcmp (arg, "--in-situ", 9) == 0) - { - in_situ = 1; - } + { + } else if (grub_memcmp (arg, "--heads=", 8) == 0) - { - p = arg + 8; - if (! safe_parse_maxint (&p, &heads_per_cylinder)) - return 0; - if ((unsigned long long)heads_per_cylinder > 256) - return ! (errnum = ERR_INVALID_HEADS); - } + { + } else if (grub_memcmp (arg, "--sectors-per-track=", 20) == 0) - { - p = arg + 20; - if (! safe_parse_maxint (&p, §ors_per_track)) - return 0; - if ((unsigned long long)sectors_per_track > 63) - return ! (errnum = ERR_INVALID_SECTORS); - } - else if (grub_memcmp (arg, "--add-mbt=", 10) == 0) - { - unsigned long long num; - p = arg + 10; - if (! safe_parse_maxint (&p, &num)) - return 0; - add_mbt = num; - if (add_mbt < -1 || add_mbt > 1) - return 0; - } - else if (grub_memcmp (arg, "--skip-sectors=", 15) == 0) - { - p = arg + 15; - if (! safe_parse_maxint_with_suffix (&p, &skip_sectors, 9)) - return 0; - } - else if (grub_memcmp (arg, "--max-sectors=", 14) == 0) - { - p = arg + 14; - if (! safe_parse_maxint_with_suffix (&p, &max_sectors, 9)) - return 0; - if (max_sectors < 8ULL) - max_sectors = 8ULL; - } - else if (grub_memcmp (arg, "--swap-drive=", 13) == 0) + { + } + else if (grub_memcmp (arg, "--add-mbt=", 10) == 0) //33. 增加存储块 -1,0,1 { - p = arg + 13; - unsigned long drive1, drive2; - char tmp[128]; - k = 0; - l = 0; - if (!(drive1 = analysis (p, 1))) - return 0; - while (*p != '=') - p++; - p++; - if (!(drive2 = analysis (p, 1))) + } + else if (grub_memcmp (arg, "--skip-sectors=", 15) == 0) //34. 跳过扇区 + { + p = arg + 15; + if (! safe_parse_maxint_with_suffix (&p, &skip_sectors, 9)) return 0; - for (i = 0; i < DRIVE_MAP_SIZE; i++) //bios_drive_map - { - if (bios_drive_map[i].from_drive == drive1) - { - bios_drive_map[i].from_drive = drive2; - j = i; - break; - } - } - if (i == DRIVE_MAP_SIZE) - k = 1; - - for (i = 0; i < DRIVE_MAP_SIZE; i++) //bios_drive_map - { - if (i == j) - continue; - if (bios_drive_map[i].from_drive == drive2) - { - bios_drive_map[i].from_drive = drive1; - break; - } - } - if (i == DRIVE_MAP_SIZE) - l = 1; - if (k) - { - sprintf (tmp, "(0x%x) (0x%x)", drive1, drive2); - map_func (tmp, flags); - } - if (l) - { - sprintf (tmp, "(0x%x) (0x%x)", drive2, drive1); - map_func (tmp, flags); - } - return 1; } - else - break; - arg = skip_to (0, arg); - } - - to_drive = arg; - from_drive = skip_to (0, arg); - -// if (grub_memcmp (from_drive, "(hd+)", 5) == 0) -// { -// from = (unsigned char)(0x80 + (*(unsigned char *)0x475)); -// } -// else -// { - /* Get the drive number for FROM_DRIVE. */ - set_device (from_drive); - if (errnum) - return 0; - from = current_drive; -// } - - if (! (from & 0x80) && in_situ) - return ! (errnum = ERR_IN_SITU_FLOPPY); - /* Get the drive number for TO_DRIVE. */ - filename = set_device (to_drive); - - if (errnum) { - /* No device specified. Default to the root device. */ - current_drive = saved_drive; - //current_partition = saved_partition; - filename = 0; - errnum = 0; - } - - to = current_drive; - if (to == FB_DRIVE) - to = (unsigned char)(fb_status >> 8)/* & 0xff*/; - if (! (to & 0x80) && in_situ) - return ! (errnum = ERR_IN_SITU_FLOPPY); - - primeval_to = to; - - /* if mem device is used, assume the --mem option */ - if (to == 0xffff || to == ram_drive || from == ram_drive) - { - if (mem == -1ULL) - mem = 0; - } - - if (mem != -1ULL && in_situ) - return ! (errnum = ERR_IN_SITU_MEM); - - if (in_situ == 1) - { - unsigned long current_partition_bak; - char *filename_bak; - char buf[16]; - - current_partition_bak = current_partition; - filename_bak = filename; - - /* read the first sector of drive TO */ - grub_sprintf (buf, "(%d)+1", to); - if (! grub_open (buf)) - return 0; - - if (grub_read ((unsigned long long)SCRATCHADDR, SECTOR_SIZE, 0xedde0d90) != SECTOR_SIZE) - { - grub_close (); - - /* This happens, if the file size is less than 512 bytes. */ - if (errnum == ERR_NONE) - errnum = ERR_EXEC_FORMAT; - - return 0; - } - grub_close (); - - current_partition = current_partition_bak; - filename = filename_bak; - - /* try to find an empty entry in the partition table */ - for (i = 0; i < 4; i++) - { - //if (! *(((char *)SCRATCHADDR) + 0x1C2 + i * 16)) - // break; /* consider partition type 00 as empty */ - if (! (*(((char *)SCRATCHADDR) + 0x1C0 + i * 16) & 63)) - break; /* invalid start sector number of 0 */ - if (! (*(((char *)SCRATCHADDR) + 0x1C4 + i * 16) & 63)) - break; /* invalid end sector number of 0 */ - if (! *(unsigned long *)(((char *)SCRATCHADDR) + 0x1C6 + i * 16)) - break; /* invalid start LBA of 0 */ - if (! *(unsigned long *)(((char *)SCRATCHADDR) + 0x1CA + i * 16)) - break; /* invalid sector count of 0 */ - } - - if (i >= 4) /* No empty entry. The partition table is full. */ - return ! (errnum = ERR_PARTITION_TABLE_FULL); - } - - if ((current_partition == 0xFFFFFF || (to >= 0x80 && to <= 0xFF)) && filename && (*filename == 0x20 || *filename == 0x09)) - { - if (to == 0xffff /* || to == ram_drive */) - { - if (((long long)mem) <= 0) - { - //grub_printf ("When mapping whole mem device at a fixed location, you must specify --mem to a value > 0.\n"); - return ! (errnum = ERR_MD_BASE); - } - start_sector = (unsigned long long)mem; - sector_count = 1; - //goto map_whole_drive; - }else if (to == ram_drive) - { - /* always consider this to be a fixed memory mapping */ - if ((rd_base & 0x1ff) || ! rd_base) - return ! (errnum = ERR_RD_BASE); - to = 0xffff; - mem = (rd_base >> SECTOR_BITS); - start_sector = (unsigned long long)mem; - sector_count = 1; - //goto map_whole_drive; - }else{ - /* when whole drive is mapped, the geometry should not be specified. */ - if ((long long)heads_per_cylinder > 0 || (long long)sectors_per_track > 0) - return ! (errnum = ERR_SPECIFY_GEOM); - /* when whole drive is mapped, the mem option should not be specified. - * but when we delete a drive map slot, the mem option means force. - */ - if (mem != -1ULL && to != from) - return ! (errnum = ERR_SPECIFY_MEM); - - sectors_per_track = 1;/* 1 means the specified geometry will be ignored. */ - heads_per_cylinder = 1;/* can be any value but ignored since #sectors==1. */ - /* Note: if the user do want to specify geometry for whole drive map, then - * use a command like this: - * - * map --heads=H --sectors-per-track=S (hd0)+1 (hd1) - * - * where S > 1 - */ - goto map_whole_drive; - } - } - - if (mem == -1ULL) - { - query_block_entries = -1; /* query block list only */ -// query_block_entries = 4; - blocklist_func (to_drive, flags); - if (errnum) - return 0; - -// if (query_block_entries != 1 && mem == -1ULL) - if (query_block_entries <= 0 || query_block_entries > DRIVE_MAP_FRAGMENT) - return ! (errnum = ERR_MANY_FRAGMENTS); - -// start_sector = map_start_sector; /* in big 2048-byte sectors */ - start_sector = map_start_sector[0]; - //sector_count = map_num_sectors; - sector_count = (filemax + 0x1ff) >> SECTOR_BITS; /* in small 512-byte sectors */ - - if (start_sector == part_start && part_start && sector_count == 1) - sector_count = part_length; - } - - if ((to == 0xffff /* || to == ram_drive */) && sector_count == 1) - { - /* fixed memory mapping */ - grub_memmove64 ((unsigned long long)(unsigned long) 0x2F000, (start_sector << 9), 0x800); - grub_memmove64 ((unsigned long long)(unsigned long) BS, (start_sector << 9), SECTOR_SIZE); - }else{ - if (! grub_open (to_drive)) - return 0; - if (skip_sectors > (filemax >> 9)) - return !(errnum = ERR_EXEC_FORMAT); - /* disk_read_start_sector_func() will set start_sector and sector_count */ - start_sector = sector_count = 0; - rawread_ignore_memmove_overflow = 1; - disk_read_hook = disk_read_start_sector_func; - filepos = (skip_sectors << 9); - /* Read the first sector of the emulated disk. */ - unsigned long long a = filepos; - grub_read ((unsigned long long)(unsigned long) 0x2F000, 0x800, 0xedde0d90); - filepos = a; - err = grub_read ((unsigned long long)(unsigned long) BS, SECTOR_SIZE, 0xedde0d90); - disk_read_hook = 0; - rawread_ignore_memmove_overflow = 0; - if (err != SECTOR_SIZE && from != ram_drive) + else if (grub_memcmp (arg, "--max-sectors=", 14) == 0) { - grub_close (); - /* This happens, if the file size is less than 512 bytes. */ - if (errnum == ERR_NONE) - errnum = ERR_EXEC_FORMAT; - return 0; } - - to_filesize = gzip_filemax; - sector_count = (filemax + 0x1ff) >> SECTOR_BITS; /* in small 512-byte sectors */ - if (part_length - && (buf_geom.sector_size == 2048 ? (start_sector - (skip_sectors >> 2)) : (start_sector - skip_sectors)) == part_start - /* && part_start */ - && (buf_geom.sector_size == 2048 ? (sector_count == 4) : (sector_count == 1))) + else if (grub_memcmp (arg, "--swap-drive=", 13) == 0) { - // Fixed issue 107 by doing it early before part_length changed. - sector_count = (buf_geom.sector_size == 2048 ? (part_length << 2) : part_length); - if (mem != -1ULL) - { - char buf[32]; - - grub_close (); - //sector_count = part_length; - grub_sprintf (buf, "(%d)%ld+%ld", to, (unsigned long long)part_start, (unsigned long long)part_length); - if (! grub_open (buf)) // This changed part_length, causing issue 107. - return 0; - filepos = (skip_sectors + 1) << 9; - }// else if (part_start) - //sector_count = (buf_geom.sector_size == 2048 ? (part_length << 2) : part_length); + return 1; } - sector_count -= skip_sectors; - - if (mem == -1ULL) - grub_close (); - if (to == 0xffff && sector_count == 1) + else if (grub_memcmp (arg, "--alloc-only", 12) == 0) //仅分配内存,不用复制 2024-09-01 { - grub_printf ("For mem file in emulation, you should not specify sector_count to 1.\n"); - errnum = ERR_BAD_ARGUMENT; - return 0; + alloc_only = 1; } - if (sector_count > max_sectors) - sector_count = max_sectors; - /* measure start_sector in small 512-byte sectors */ - if (buf_geom.sector_size == 2048) + else if (grub_memcmp (arg, "--no-alloc", 10) == 0) //0/1=正常分配内存/使用rd,md,efi_pxe_buf的值 2024-11-21 { - start_sector *= 4; - start_sector += (((unsigned long)skip_sectors) % 4); + no_alloc = 1; } + else + break; + arg = skip_to (0, arg); //跳到空格后 + } //入口参数处理完毕 + //1. 初始化from、to、pd驱动器 + to_drive = arg; //to驱动器地址 + from_drive = skip_to (0, arg); //from驱动器地址 + set_device (from_drive); //设置from驱动器的当前驱动器号 返回: 0/非0=失败/成功 - } - - if ((filemax >= (skip_sectors << 9 ) && filemax - (skip_sectors << 9) < 512) || BS->boot_signature != 0xAA55) - goto geometry_probe_failed; - - /* probe the BPB */ - - if (probe_bpb(BS)) - goto failed_probe_BPB; - - if (debug > 0 && ! disable_map_info) - grub_printf ("%s BPB found %s 0xEB (jmp) leading the boot sector.\n", - filesystem_type == 1 ? "FAT12" : - filesystem_type == 2 ? "FAT16" : - filesystem_type == 3 ? "FAT32" : - filesystem_type == 4 ? "NTFS" : - filesystem_type == 6 ? "exFAT" : - /*filesystem_type == 5 ?*/ "EXT2 GRLDR", - (BS->dummy1[0] == (char)0xEB ? "with" : "but WITHOUT")); + if (errnum) + return 0; + from = current_drive; //from=当前驱动器 - if (sector_count != 1) - { - if (debug > 0 && ! disable_map_info) - { - if (probed_total_sectors > sector_count) - printf_warning ("Warning: BPB total_sectors(%ld) is greater than the number of sectors in the whole disk image (%ld). The int13 handler will disable any read/write operations across the image boundary. That means you will not be able to read/write sectors (in absolute address, i.e., lba) %ld - %ld, though they are logically inside your file system.\n", (unsigned long long)probed_total_sectors, (unsigned long long)sector_count, (unsigned long long)sector_count, (unsigned long long)(probed_total_sectors - 1)); - else if (probed_total_sectors < sector_count && ! disable_map_info) - grub_printf ("info: BPB total_sectors(%ld) is less than the number of sectors in the whole disk image(%ld).\n", (unsigned long long)probed_total_sectors, (unsigned long long)sector_count); - } - } - - if (mem == -1ULL && (from & 0x80) && (to & 0x80) && (start_sector == part_start && part_start && sector_count == part_length)/* && BS->hidden_sectors >= probed_sectors_per_track */) + if (from >= 0xa0) { - if (BS->hidden_sectors <= probed_sectors_per_track) - BS->hidden_sectors = (unsigned long)part_start; - extended_part_start = BS->hidden_sectors - probed_sectors_per_track; - extended_part_length = probed_total_sectors + probed_sectors_per_track; - if (debug > 0 && ! disable_map_info) - grub_printf ("\nBPB probed C/H/S = %d/%d/%d, BPB probed total sectors = %ld\n", probed_cylinders, probed_heads, probed_sectors_per_track, (unsigned long long)probed_total_sectors); - BPB_H = probed_heads; - BPB_S = probed_sectors_per_track; - if (in_situ) - { - //start_sector += probed_sectors_per_track; - //sector_count -= probed_sectors_per_track; - goto geometry_probe_ok; - } - - if (debug > 0 && ! disable_map_info) - grub_printf ("Try to locate extended partition (hd%d)%d+%d for the virtual (hd%d).\n", (to & 0x7f), extended_part_start, extended_part_length, (from & 0x7f)); - grub_sprintf ((char *)BS, "(hd%d)%d+%d", (to & 0x7f), extended_part_start, extended_part_length); - //j = filesystem_type; /* save filesystem_type */ - if (! grub_open ((char *)BS)) - return 0; - - //filesystem_type = j; /* restore filesystem_type */ - /* Read the first sector of the emulated disk. */ - if (grub_read ((unsigned long long)(unsigned int) BS, SECTOR_SIZE, 0xedde0d90) != SECTOR_SIZE) - { - grub_close (); - - /* This happens, if the file size is less than 512 bytes. */ - if (errnum == ERR_NONE) - errnum = ERR_EXEC_FORMAT; - - return 0; - } - grub_close (); - for (i = 0; i < 4; i++) - { - unsigned char sys = BS->P[i].system_indicator; - if (sys == 0x05 || sys == 0x0f || sys == 0) - { - *(long long *)&(BS->P[i].boot_indicator) = 0LL; - //*(long long *)&(BS->P[i].start_lba) = 0LL; - ((long long *)&(BS->P[i]))[1] = 0LL; - } - } - part_start = extended_part_start; - part_length = extended_part_length; - start_sector = extended_part_start; - sector_count = extended_part_length; - - /* when emulating a hard disk using a logical partition, the geometry should not be specified. */ - if ((long long)heads_per_cylinder > 0 || (long long)sectors_per_track > 0) - return ! (errnum = ERR_SPECIFY_GEOM); - - goto failed_probe_BPB; - //if (probe_mbr (BS, start_sector, sector_count, (unsigned long)part_start) > 0) - // goto geometry_probe_failed; + grub_memset(chainloader_file_orig, 0, 256); + set_full_path(chainloader_file_orig,to_drive,sizeof(chainloader_file_orig)); + skip_to (SKIP_WITH_TERMINATE,chainloader_file_orig); } - //if (probed_cylinders * sectors_per_cylinder == probed_total_sectors) - goto geometry_probe_ok; - -failed_probe_BPB: - /* probe the partition table */ - - if (probe_mbr (BS, start_sector, sector_count, (unsigned long)part_start)) - goto geometry_probe_failed; - - if (sector_count != 1) - { - if (probed_total_sectors < probed_total_sectors_round && probed_total_sectors_round <= sector_count) - probed_total_sectors = probed_total_sectors_round; - if (debug > 0 && ! disable_map_info) - { - if (probed_total_sectors > sector_count) - printf_warning ("Warning: total_sectors calculated from partition table(%ld) is greater than the number of sectors in the whole disk image (%ld). The int13 handler will disable any read/write operations across the image boundary. That means you will not be able to read/write sectors (in absolute address, i.e., lba) %ld - %ld, though they are logically inside your emulated virtual disk(according to the partition table).\n", (unsigned long long)probed_total_sectors, (unsigned long long)sector_count, (unsigned long long)sector_count, (unsigned long long)(probed_total_sectors - 1)); - else if (probed_total_sectors < sector_count) - grub_printf ("info: total_sectors calculated from partition table(%ld) is less than the number of sectors in the whole disk image(%ld).\n", (unsigned long long)probed_total_sectors, (unsigned long long)sector_count); - } - } - goto geometry_probe_ok; + de = get_device_by_drive (from, 1); //de非0,则存在重名驱动器 + if (de && de->fragment) //如果存在碎片插槽,删除它 + unload_fragment_slot (from); -geometry_probe_failed: - - if (map_image_HPC && map_image_SPT) { - heads_per_cylinder = map_image_HPC; - sectors_per_track = map_image_SPT; - goto geometry_probe_ok; - } - - if (BPB_H || BPB_S) - { - if (mem != -1ULL) - grub_close (); - return ! (errnum = ERR_EXTENDED_PARTITION); + filename = set_device (to_drive); //设置to驱动器的当前驱动器号 + if (errnum) //如果错误 + { + //未指定设备。默认为根设备。 + current_drive = saved_drive; //则当前驱动器=根驱动器 + filename = 0; //驱动器号=0 + errnum = 0; //错误号=0 } - - /* possible ISO9660 image */ - if ((filemax >= (skip_sectors << 9 ) && filemax - (skip_sectors << 9) < 512) - || BS->boot_signature != 0xAA55 || (unsigned char)from >= (unsigned char)0x9F) + + to = current_drive; //to=当前驱动器 + primeval_to = to; //保存原始to + /* if mem device is used, assume the --mem option 如果使用mem驱动器,假设--mem已选择*/ +//printf ("from-0,%x,%x,%x,%x\n",from,to,current_drive,saved_drive); +//a0,21,21,21; 60,ffff,ffff,21; map (http)/imgs/ifu352.iso (cd) +//a0,21,21,21; 60,ffff,ffff,21; map --mem (http)/imgs/ifu352.iso (cd) +//81,ffff,ffff.21; 82,7f,7f,81; ntboot (http)/imgs/boot.wim + if (to == 0xffff || to == ram_drive || from == ram_drive || (to == 0x21 && (!cur_pxe_type || !http_feature))) //如果to=md,或to=rd,或from=rd,或网络驱动器 { - if ((long long)heads_per_cylinder < 0) - heads_per_cylinder = 0; - if ((long long)sectors_per_track < 0) - sectors_per_track = 0; + if (mem == -1ULL) //如果mem=-1ULL=0xffffffffffffffff 不加载到内存 + mem = 0; //则为零 修改为加载到内存 to=md,或to=rd,或from=rd,则一定是mem=0,即一定加载到内存 } - if ((long long)heads_per_cylinder < 0) - { - if (from & 0x80) - { - if (mem != -1ULL) - grub_close (); - return ! (errnum = ERR_NO_HEADS); - } - /* floppy emulation */ - switch (sector_count) - { - /* for the 5 standard floppy disks, offer a value */ - case 720: /* 360K */ - case 1440: /* 720K */ - case 2400: /* 1200K */ - case 2880: /* 1440K */ - case 5760: /* 2880K */ - heads_per_cylinder = 2; break; - default: - if (sector_count > 1 && sector_count < 5760 ) - { - heads_per_cylinder = 2; break; - } - else - { - if (mem != -1ULL) - grub_close (); - return ! (errnum = ERR_NO_HEADS); - } - } - if (debug > 0 && ! disable_map_info) - grub_printf ("\nAutodetect number-of-heads failed. Use default value %d\n", heads_per_cylinder); - } - else if (heads_per_cylinder == 0) - { - if (from & 0x80) - { - /* hard disk emulation */ - heads_per_cylinder = 255; /* 256 */ - } - else - { - /* floppy emulation */ - switch (sector_count) - { - case 320: /* 160K */ - case 360: /* 180K */ - case 500: /* 250K */ - heads_per_cylinder = 1; break; - case 1: /* a whole-disk emulation */ - heads_per_cylinder = 255; break; - default: - if (sector_count <= 63 * 1024 * 2 + 1) - heads_per_cylinder = 2; - else - heads_per_cylinder = 255; - } - } - if (debug > 0 && ! disable_map_info) - if (from < 0x9F) - grub_printf ("\nAutodetect number-of-heads failed. Use default value %d\n", heads_per_cylinder); - } - else - { - if (debug > 0 && ! disable_map_info) - grub_printf ("\nAutodetect number-of-heads failed. Use the specified %d\n", heads_per_cylinder); - } - - if ((long long)sectors_per_track < 0) - { - if (from & 0x80) + if ((current_partition == 0xFFFFFF || (to >= 0x80 && to <= 0xFF)) && filename && (*filename == 0x20 || *filename == 0x09)) { - if (mem != -1ULL) - grub_close (); - return ! (errnum = ERR_NO_SECTORS); - } - /* floppy emulation */ - switch (sector_count) - { - /* for the 5 standard floppy disks, offer a value */ - case 720: /* 360K */ - case 1440: /* 720K */ - sectors_per_track = 9; break; - case 2400: /* 1200K */ - sectors_per_track = 15; break; - case 2880: /* 1440K */ - sectors_per_track = 18; break; - case 5760: /* 2880K */ - sectors_per_track = 36; break; - default: - if (sector_count > 1 && sector_count < 2880 ) - { - sectors_per_track = 18; break; - } - else if (sector_count > 2880 && sector_count < 5760 ) - { - sectors_per_track = 36; break; - } - else - { - if (mem != -1ULL) - grub_close (); - return ! (errnum = ERR_NO_SECTORS); - } - } - if (debug > 0 && ! disable_map_info) - grub_printf ("\nAutodetect sectors-per-track failed. Use default value %d\n", sectors_per_track); - } - else if (sectors_per_track == 0) - { - if (sector_count == 1) - sectors_per_track = 1; - else if (from & 0x80) - { - /* hard disk emulation */ - sectors_per_track = 63; - } - else - { - /* floppy emulation */ - switch (sector_count) - { - case 400: /* 200K */ - sectors_per_track = 5; break; - case 320: /* 160K */ - case 640: /* 320K */ - case 1280: /* 640K */ - sectors_per_track = 8; break; - case 360: /* 180K */ - case 720: /* 360K */ - case 1440: /* 720K */ - case 1458: /* 729K */ - case 1476: /* 738K */ - case 1494: /* 747K */ - case 1512: /* 756K */ - sectors_per_track = 9; break; - case 500: /* 250K */ - case 800: /* 400K */ - case 840: /* 420K */ - case 1000: /* 500K */ - case 1600: /* 800K */ - case 1620: /* 810K */ - case 1640: /* 820K */ - case 1660: /* 830K */ - case 1680: /* 840K */ - sectors_per_track = 10; break; - case 1804: /* 902K */ - sectors_per_track = 11; break; - case 1968: /* 984K */ - sectors_per_track = 12; break; - case 2132: /* 1066K */ - sectors_per_track = 13; break; - case 2400: /* 1200K */ - case 2430: /* 1215K */ - case 2460: /* 1230K */ - case 2490: /* 1245K */ - case 2520: /* 1260K */ - sectors_per_track = 15; break; - case 2720: /* 1360K */ - case 2754: /* 1377K */ - case 2788: /* 1394K */ - case 2822: /* 1411K */ - case 2856: /* 1428K */ - sectors_per_track = 17; break; - case 2880: /* 1440K */ - case 2916: /* 1458K */ - case 2952: /* 1476K */ - case 2988: /* 1494K */ - case 3024: /* 1512K */ - sectors_per_track = 18; break; - case 3116: /* 1558K */ - sectors_per_track = 19; break; - case 3200: /* 1600K */ - case 3240: /* 1620K */ - case 3280: /* 1640K */ - case 3320: /* 1660K */ - sectors_per_track = 20; break; - case 3360: /* 1680K */ - case 3402: /* 1701K */ - case 3444: /* 1722K */ - case 3486: /* 1743K */ - case 3528: /* 1764K */ - sectors_per_track = 21; break; - case 3608: /* 1804K */ - sectors_per_track = 22; break; - case 3772: /* 1886K */ - sectors_per_track = 23; break; - case 5760: /* 2880K */ - sectors_per_track = 36; break; - case 6396: /* 3198K */ - sectors_per_track = 39; break; - case 7216: /* 3608K */ - sectors_per_track = 44; break; - case 7380: /* 3690K */ - sectors_per_track = 45; break; - case 7544: /* 3772K */ - sectors_per_track = 46; break; - default: - if (sector_count <= 2881) - sectors_per_track = 18; - else if (sector_count <= 5761) - sectors_per_track = 36; - else - sectors_per_track = 63; - } - } - if (debug > 0 && ! disable_map_info) - if (from < 0x9F) - grub_printf ("\nAutodetect sectors-per-track failed. Use default value %d\n", sectors_per_track); - } - else - { - if (debug > 0 && ! disable_map_info) - grub_printf ("\nAutodetect sectors-per-track failed. Use the specified %d\n", sectors_per_track); - } - goto map_whole_drive; - -geometry_probe_ok: - -// if (! disable_map_info) -// { - if (debug > 0 && ! disable_map_info) - grub_printf ("\nprobed C/H/S = %d/%d/%d, probed total sectors = %ld\n", probed_cylinders, probed_heads, probed_sectors_per_track, (unsigned long long)probed_total_sectors); - if (mem != -1ULL && ((long long)mem) <= 0) - { - if (((unsigned long long)(-mem)) < probed_total_sectors && probed_total_sectors > 1 && sector_count >= 1/* filemax >= 512 */) - mem = - (unsigned long long)probed_total_sectors; - } -// } - if (BPB_H || BPB_S) - if (BPB_H != probed_heads || BPB_S != probed_sectors_per_track) + return 0; + } +#if VHD_DIFFERENCE + //保存to驱动器的路径文件名 + if (*(to_drive) == '/' || *(to_drive) == '(') { - //if (debug > 0) - // printf_warning ("\nWarning!!! geometry (H/S=%d/%d) from the (extended) partition table\nconflict with geometry (H/S=%d/%d) in the BPB. The boot could fail!\n", probed_heads, probed_sectors_per_track, BPB_H, BPB_S); - if (mem != -1ULL) - grub_close (); - return ! (errnum = ERR_EXTENDED_PARTITION); + grub_memmove (chainloader_file, to_drive, grub_strlen (to_drive) + 1); + p = skip_to (0, chainloader_file); + *(p - 1) = 0; + + vhd_file_name = grub_zalloc(256); + grub_memmove (vhd_file_name, chainloader_file, grub_strlen (chainloader_file) + 1); + //获得并保存to驱动器的路径 + p--; + while (*p-- != '/') ; + *(p + 2) = 0; + + grub_memmove (vhd_file_path, chainloader_file, grub_strlen (chainloader_file) + 1); } - - if ((long long)heads_per_cylinder <= 0) - heads_per_cylinder = probed_heads; - else if (heads_per_cylinder != probed_heads) - { - if (debug > 0 && ! disable_map_info) - printf_warning ("\nWarning!! Probed number-of-heads(%d) is not the same as you specified.\nThe specified value %d takes effect.\n", probed_heads, heads_per_cylinder); - } +#endif +//printf ("from-1,%x,%x,%x,%x\n",from,to,current_drive,saved_drive); +//a0,21,21,21; 60,ffff,ffff,21; +//a0,21,21,21; 60,ffff,ffff,21; +//81,ffff,ffff.21; 82,7f,7f,81; + if (to == 0x21 && (!cur_pxe_type || !http_feature)) + { + map_pd = 1; + if (! grub_open (to_drive)) //从服务器复制文件到efi_pxe_buf + goto fail_free; + rd_base = (unsigned long long)(grub_size_t)efi_pxe_buf; + rd_size = (unsigned long long)filemax; + to_drive = "(rd)+1"; //将获得的文件映射为rd, 作为to驱动器 +// efi_pxe_buf = 0; + if (!compressed_file) //如果未压缩 + no_alloc = 1; //则使用efi_pxe_buf,不再分配内存 + grub_close (); + } - if ((long long)sectors_per_track <= 0) - sectors_per_track = probed_sectors_per_track; - else if (sectors_per_track != probed_sectors_per_track) - { - if (debug > 0 && ! disable_map_info) - printf_warning ("\nWarning!! Probed sectors-per-track(%d) is not the same as you specified.\nThe specified value %d takes effect.\n", probed_sectors_per_track, sectors_per_track); - } + //2. 获取to驱动器扇区序列(填充碎片信息) + query_block_entries = -1; /* query block list only 仅请求块列表*/ + int c = compressed_file; + k = no_decompression; + no_decompression = 1; + putchar_hooked = (unsigned char*)1; //禁止显示 + //第一次读to驱动器,建立扇区序列 + blocklist_func (to_drive, flags); //请求块列表 执行成功后,将设置query_block_entries=1,设置errnum=0 + putchar_hooked = 0; + no_decompression = k; + compressed_file = c; + if (errnum) + return 0; +#if VHD_DIFFERENCE + vhd_start_sector = map_start_sector[0]; + if (map_pd) + vhd_start_sector += rd_base; +#endif + cache = grub_zalloc (0x800); //分配缓存 + if (!cache) + return 0; +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//printf ("from-2,%x,%x,%x,%x\n",from,to,current_drive,saved_drive); +//a0,21,7f,21; 60,ffff,ffff,21; +//a0,21,7f,21; 60,ffff,ffff,21; +//81,ffff,ffff.21; 82,7f,7f,81; + //3. 获取to驱动器参数 + //第二次读获取,建立form驱动器映射 + if (! grub_open (to_drive)) //打开to驱动器 + goto fail_free; + + if (mem == -1ULL && (compressed_file || (query_block_entries > DRIVE_MAP_FRAGMENT))) //如果不加载到内存,并且是压缩文件, 或者碎片太多,强制加载到内存 + { + mem = 0; + if (compressed_file) //如果是压缩文件 + printf_warning ("Compressed file needs to be loaded into memory."); + else + printf_warning ("Too many fragments, needs to be loaded into memory."); + } -map_whole_drive: + if (skip_sectors > (filemax >> 9)) //如果跳过扇区>文件最大扇区 + { + errnum = ERR_EXEC_FORMAT; + goto fail_free; + } - if (from != ram_drive) - { - /* Search for an empty slot in BIOS_DRIVE_MAP. */ - for (i = 0; i < DRIVE_MAP_SIZE; i++) + //disk_read_start_sector_func()函数将设置开始扇区和扇区计数 + start_sector = sector_count = 0; //开始扇区=扇区计数=0 + rawread_ignore_memmove_overflow = 1; //读忽视内存移动溢出=1 + + //disk_read_start_sector_func将挂钩在grub_read。当运行grub_read时,同时运行disk_read_start_sector_func。 + //disk_read_start_sector_func设置start_sector和sector_count。 + //此处的start_sector是绝对扇区数,含分区起始扇区。是首次设置!!! + //此处的sector_count没有用,即不是碎片数,也不是文件扇区数。 + disk_read_hook = disk_read_start_sector_func; //磁盘读挂钩=磁盘读开始扇区功能 + filepos = (skip_sectors << 9); //文件位置指针=跳过扇区*0x200 skip_sectors一般为零 + /* Read the first sector of the emulated disk. */ + //读to驱动器分区的首扇区到 cache + unsigned long long a = filepos; + grub_read ((unsigned long long)(grub_size_t) cache, 0x800, 0xedde0d90); + filepos = a; + err = grub_read ((unsigned long long)(grub_size_t) BS, SECTOR_SIZE, 0xedde0d90); + disk_read_hook = 0; //磁盘读挂钩=0 + rawread_ignore_memmove_overflow = 0; //读忽视内存移动溢出=0 + + if (err != SECTOR_SIZE && from != ram_drive) //如果错误号不是0x200,并且from不是rd { - /* Perhaps the user wants to override the map. */ - if ((bios_drive_map[i].from_drive == from)) - { - if ((hooked_drive_map[i].to_cylinder & (1 << 10)) != 0) - { - p = (char *)&hooked_fragment_map; - filename = p + FRAGMENT_MAP_SLOT_SIZE; - p = fragment_map_slot_find(p, from); - if (p) - { - void *start = filename - *(unsigned short *)p; - int len = *(unsigned short *)p; - grub_memmove (p, p + *(unsigned short *)p, filename - p - *(unsigned short *)p); - grub_memset (start, 0, len); - } - } - break; - } - - if (drive_map_slot_empty (bios_drive_map[i])) - break; + //如果文件大小小于512字节,则会发生这种情况。 + if (errnum == ERR_NONE) //如果错误号是0 + errnum = ERR_EXEC_FORMAT; //则设置错误号为ram_drive + goto fail_close_free; } - if (i == DRIVE_MAP_SIZE) + //此处重新设置了 sector_count, 将扇区计数更改为按每扇区0x200字节计的小扇区!!! + sector_count = (filemax + buf_geom.sector_size - 1) >> buf_geom.log2_sector_size; +#if VHD_DIFFERENCE + if (!start_sector) + start_sector = vhd_start_sector; +#endif + //此处又修改sector_count + sector_count -= skip_sectors; //扇区计数=扇区计数-跳过扇区 +#if 0 //重名from前面已经排除,现在的from还没有建立。 + if (from != ram_drive) //如果from不等于rd + { + df = get_device_by_drive (from,1); + if (df && df->fragment == 1) //有碎片 { - if (mem != -1ULL) - grub_close (); - errnum = ERR_WONT_FIT; - return 0; + q = (struct fragment_map_slot *)disk_fragment_map; //碎片插槽起始 + grub_size_t size = (grub_size_t)disk_fragment_map + FRAGMENT_MAP_SLOT_SIZE; + q = fragment_map_slot_find(q, from); //从碎片插槽查找from驱动器 + if (q) //q=0/非0=没有找到/from驱动器在碎片插槽位置 + { + void *start = (char *)size - q->slot_len; + int len = q->slot_len; + grub_memmove (q, (char *)q + q->slot_len, (char *)size - (char *)q - q->slot_len); + grub_memset (start, 0, len); + } } - - /* If TO == FROM and whole drive is mapped, and, no map options occur, then delete the entry. */ - if (to == from && read_Only == 0 && fake_write == 0 && disable_lba_mode == 0 - && disable_chs_mode == 0 && start_sector == 0 && (sector_count == 0 || - /* sector_count == 1 if the user uses a special method to map a whole drive, e.g., map (hd1)+1 (hd0) */ - (sector_count == 1 && (long long)heads_per_cylinder <= 0 && (long long)sectors_per_track <= 1))) - goto delete_drive_map_slot; - } - + } +#endif +//检查to是否存在父映射 在 disk_drive_map 查找from,是否等于当前to /* check whether TO is being mapped */ - //if (mem == -1) - if ( mem == -1ULL && ! unset_int13_handler (1)) /* hooked */ + if (mem == -1ULL) //如果不加载到内存 + { + //查找父插槽 + dt = get_device_by_drive (to,1); + if (dt) + { + //to改变!!!! + to = dt->to_drive; //设置当前to等于父插槽的to + if (to == 0xFF && !(dt->to_log2_sector == 11)) //如果to=0xFF,并且to不是cdrom + to = 0xFFFF; /* memory device 内存驱动器*/ + //确定起时扇区 + if (! dt->fragment) + { + //起始扇区=起始扇区+父起始扇区 + start_sector = (start_sector << dt->from_log2_sector) >> dt->to_log2_sector; + start_sector += dt->start_sector; + //扇区计数 + sector_count = (sector_count << dt->from_log2_sector) >> dt->to_log2_sector; + } + //如果to有碎片,调整各碎片起始扇区。起始扇区由blocklist_func获得。 + else + { + for (k = 0; (k < DRIVE_MAP_FRAGMENT) && (map_start_sector[k] != 0); k++) + { + map_start_sector[k] = (map_start_sector[k] << dt->from_log2_sector) >> dt->to_log2_sector; + map_start_sector[k] += dt->start_sector; + map_num_sectors[k] = (map_num_sectors[k] << dt->from_log2_sector) >> dt->to_log2_sector; + } + } + } + } +//至此,start_sector与sector_count最终确定!!!! +//j=from驱动器的父插槽号 也就是说,to不是原生磁盘,是映射盘 dt是from的父驱动器设备 +//i=from驱动器的插槽号 df是from驱动器的设备 +//==================================================================================================================== +//printf ("from-3,%x,%x,%x,%x,%x\n",from,to,current_drive,saved_drive,alloc_only); +//a0,21,7f,21; 60,ffff,ffff,21; +//a0,21,7f,21; 60,ffff,ffff,21; +//81,ffff,ffff.21; 82,7f,7f,81; + //4. 探测及设置from参数 + if (from != ram_drive && from != 0xffff && !alloc_only) + { + //获取to驱动器,虚拟分区信息 +// disk_drive_map[i].start_sector = start_sector; +// disk_drive_map[i].sector_count = sector_count; + + if (from >= 0xa0) //光盘 { - for (j = 0; j < DRIVE_MAP_SIZE; j++) - { -// if (to != hooked_drive_map[j].from_drive) - if (to != hooked_drive_map[j].from_drive || (to == 0xFF && (hooked_drive_map[j].to_cylinder & 0x4000))) - continue; - #if 0 - if (! (hooked_drive_map[j].max_sector & 0x3F)) - disable_chs_mode = 1; - - /* X=max_sector bit 7: read only or fake write */ - /* Y=to_sector bit 6: safe boot or fake write */ - /* ------------------------------------------- */ - /* X Y: meaning of restrictions imposed on map */ - /* ------------------------------------------- */ - /* 1 1: read only=0, fake write=1, safe boot=0 */ - /* 1 0: read only=1, fake write=0, safe boot=0 */ - /* 0 1: read only=0, fake write=0, safe boot=1 */ - /* 0 0: read only=0, fake write=0, safe boot=0 */ - - if (!(read_Only | fake_write | unsafe_boot)) /* no restrictions specified */ - switch ((hooked_drive_map[j].max_sector & 0x80) | (hooked_drive_map[j].to_sector & 0x40)) - { - case 0xC0: read_Only = 0; fake_write = 1; unsafe_boot = 1; break; - case 0x80: read_Only = 1; fake_write = 0; unsafe_boot = 1; break; - case 0x00: read_Only = 0; fake_write = 0; unsafe_boot = 1; break; - /*case 0x40:*/ - default: read_Only = 0; fake_write = 0; unsafe_boot = 0; - } + from_log2_sector = 11; + } + else if (from >= 0x80) //硬盘 + { + struct master_and_dos_boot_sector *mbr1 = (struct master_and_dos_boot_sector *)cache; + grub_efi_uint32_t active = -1; + ext_start_lba = 0; - if (hooked_drive_map[j].max_sector & 0x40) - disable_lba_mode = 1; - #endif - //to_o = to; - to = hooked_drive_map[j].to_drive; - if (to == 0xFF && !(hooked_drive_map[j].to_cylinder & 0x4000)) - { - /* to_o = */ to = 0xFFFF; /* memory device */ - } - if (! ((hooked_drive_map[j].to_sector) & 0x80)) // The TO drive is not in-situ - { - if (start_sector == 0 && (sector_count == 0 || (sector_count == 1 && (long long)heads_per_cylinder <= 0 && (long long)sectors_per_track <= 1))) + if (probe_mbr (mbr1, 0, 1, 0)) //没有mbr,是软盘,需增加mbr + { + add_mbt = 1; + + if (grub_memcmp ((char*)mbr1 + 0x36, "FAT12", 5) == 0) + system_indicator = 1; + else if (grub_memcmp ((char*)mbr1 + 0x36, "FAT16", 5) == 0) + system_indicator = 0xe; + else if (grub_memcmp ((char*)mbr1 + 0x52, "FAT32", 5) == 0) + system_indicator = 0xc; + else + goto fail_close_free; + + active = 3; + from_log2_sector = 9; + mem = 0; + part_addr = *(int*)((char*)mbr1 + 0x20); + buffer = grub_zalloc (512); + *(int*)(buffer+0x1b8) = 0x11223344; + *(int*)(buffer) = 0xd08ec033; + *(int*)(buffer+0x1ee) = 0x00010180; + *(char*)(buffer+0x1f2) = system_indicator; + *(int*)(buffer+0x1f3) = 0x00fefefe; + *(int*)(buffer+0x1f6) = 0x00000001; + *(int*)(buffer+0x1fa) = part_addr + 1; + *(short*)(buffer+0x1fe) = 0xaa55; + goto get_info_ok; + } + + for (k = 0; k < 4; k++) //判断分区类型 mbr/gpt + { + if(mbr1->P[k].system_indicator == GRUB_PC_PARTITION_TYPE_GPT_DISK) //如果系统标识是EFI分区 + goto get_gpt_info; + else if (mbr1->P[k].system_indicator == 0x5 || mbr1->P[k].system_indicator == 0xf) //获取扩展分区信息 { - sector_count = hooked_drive_map[j].sector_count; - heads_per_cylinder = hooked_drive_map[j].max_head + 1; - sectors_per_track = (hooked_drive_map[j].max_sector) & 0x3F; + ext_num = k; + ext_start_lba = mbr1->P[k].start_lba; + ext_total_sectors = mbr1->P[k].total_sectors; } - start_sector += hooked_drive_map[j].start_sector; - for (k = 0; (k < DRIVE_MAP_FRAGMENT) && (map_start_sector[k] != 0); k++) - map_start_sector[k] += hooked_drive_map[j].start_sector; - } - - /* If TO == FROM and whole drive is mapped, and, no map options occur, then delete the entry. */ - if (to == from && read_Only == 0 && fake_write == 0 && disable_lba_mode == 0 - && disable_chs_mode == 0 && start_sector == 0 && (sector_count == 0 || - /* sector_count == 1 if the user uses a special method to map a whole drive, e.g., map (hd1)+1 (hd0) */ - (sector_count == 1 && (long long)heads_per_cylinder <= 0 && (long long)sectors_per_track <= 1))) + partmap_type = 1; //MBR + } + for (k = 0; k < 4; k++) //查找活动分区 + { + if(mbr1->P[k].boot_indicator == ACTIVE_PARTITION) { - /* yes, delete the FROM drive(with slot[i]), not the TO drive(with slot[j]) */ - if (from != ram_drive) - goto delete_drive_map_slot; + active = k; + break; } -#if 0 - for (j = 0; j < DRIVE_MAP_SIZE; j++) + } + if (active == (grub_efi_uint32_t)-1) //如果没有活动分区,寻找第一个非0分区起始 + { + for(k = 0; k < 4; k++) { - if (to == hooked_drive_map[j].from_drive) + if(mbr1->P[k].start_lba != 0) { + active = k; break; } } - if (j == DRIVE_MAP_SIZE) - to_o = -1; -#endif - break; } - } - m = j; - j = i; /* save i into j */ -//grub_printf ("\n debug 4 start_sector=%lX, part_start=%lX, part_length=%lX, sector_count=%lX, filemax=%lX\n", start_sector, part_start, part_length, sector_count, filemax); - - /* how much memory should we use for the drive emulation? */ - if (mem != -1ULL) - { - unsigned long long start_byte; - unsigned long long bytes_needed; - unsigned long long base; - unsigned long long top_end; - - bytes_needed = base = top_end = 0ULL; -//if (to == 0xff) -//{ -// -//}else{ - if (start_sector == part_start && part_start == 0 && sector_count == 1) - sector_count = part_length; - - /* For GZIP disk image if uncompressed size >= 4GB, - high bits of filemax is wrong, sector_count is also wrong. */ - #if 0 - if ( compressed_file && (sector_count < probed_total_sectors) && filesystem_type > 0 ) - { /* adjust high bits of filemax and sector_count */ - unsigned long sizehi = (unsigned long)(probed_total_sectors >> (32-SECTOR_BITS)); - if ( (unsigned long)filemax < (unsigned long)(probed_total_sectors << SECTOR_BITS) ) - ++sizehi; - fsmax = filemax += (unsigned long long)sizehi << 32; - sector_count = filemax >> SECTOR_BITS; - grub_printf("Uncompressed size is probably %ld sectors\n",sector_count); - } - #endif - if ( (long long)mem < 0LL && sector_count < (-mem) ) - bytes_needed = (-mem) << SECTOR_BITS; - else - bytes_needed = sector_count << SECTOR_BITS; - - /* filesystem_type - * 0 an MBR device - * 1 FAT12 - * 2 FAT16 - * 3 FAT32 - * 4 NTFS - * -1 unknown filesystem(do not care) - * - * Note: An MBR device is a whole disk image that has a partition table. - */ - - if (add_mbt<0) - add_mbt = (filesystem_type > 0 && (from & 0x80) && (from < 0x9F))? 1: 0; /* known filesystem without partition table */ - - if (add_mbt) - bytes_needed += sectors_per_track << SECTOR_BITS; /* build the Master Boot Track */ - - bytes_needed = ((bytes_needed+4095)&(-4096ULL)); /* 4KB alignment */ -//} - if ((to == 0xffff || to == ram_drive) && sector_count == 1) - /* mem > 0 */ - bytes_needed = 0; - //base = 0; - - start_byte = start_sector << SECTOR_BITS; - if (to == ram_drive) - start_byte += rd_base; - /* we can list the total memory thru int15/E820. on the other hand, we can - * see thru our drive map slots how much memory have already been used for - * drive emulation. */ - /* the available memory can be calculated thru int15 and the slots. */ - /* total memory can always be calculated thru unhooked int15 */ - /* used memory can always be calculated thru drive map slots */ - /* the int15 handler: - * if not E820, return to the original int15 - * for each E820 usable memory, check how much have been used in slot, - * and return the usable memory minus used memory. - */ - /* once int13 hooked and at least 1 slot uses mem==1, also hook int15 - */ - - if (tmp_mem_max > 0x100000000ULL && (! is64bit || ! prefer_top)) - tmp_mem_max = 0x100000000ULL; - if (map_mem_min < 0x100000ULL) - map_mem_min = 0x100000ULL; - //fix initrd error by chenall 2020-01-04 http://bbs.wuyou.net/forum.php?mod=viewthread&tid=417786&extra=page%3D1&page=5 - if (from == INITRD_DRIVE && to == 0xffff && tmp_mem_max > initrd_addr_max){ //INITRD_DRIVE - tmp_mem_max = initrd_addr_max; - } - if (mbi.flags & MB_INFO_MEM_MAP) - { - struct AddrRangeDesc *map = (struct AddrRangeDesc *) saved_mmap_addr; - unsigned long end_addr = saved_mmap_addr + saved_mmap_length; - for (; end_addr > (unsigned long) map; map = (struct AddrRangeDesc *) (((int) map) + 4 + map->size)) - { - unsigned long long tmpbase, tmpend, tmpmin, sum; - if (map->Type != MB_ARD_MEMORY) - continue; - if (map->Length == 0) - continue; - tmpmin = (map->BaseAddr > map_mem_min) ? - map->BaseAddr : map_mem_min; - tmpmin = ((tmpmin+4095)&(-4096ULL));/* 4KB alignment, round up */ - /* consider the case when map->BaseAddr + map->Length overflows. - * It happens if and only if the sum is less than both addends. - tinybit 2017-01-24 */ - sum = map->BaseAddr + map->Length; - tmpend = tmp_mem_max; - if (sum >= map->BaseAddr && sum >= map->Length) // no overflow + if (active == (grub_efi_uint32_t)-1) //失败 + goto fail_close_free; + from_log2_sector = 9; + part_addr = mbr1->P[active].start_lba; //分区起始扇区 + filepos = part_addr << 9; //指向dbr + grub_read ((unsigned long long)(grub_size_t) cache, 0x800, 0xedde0d90); + if (probe_bpb(mbr1)) //没有bpb { - if (sum < tmp_mem_max) - tmpend = sum; + from_log2_sector = 12; + filepos = part_addr << 12; //指向dbr 是原生4k磁盘 + grub_read ((unsigned long long)(grub_size_t) cache, 0x800, 0xedde0d90); + if (probe_bpb(mbr1)) //没有bpb + goto fail_close_free; } - tmpend &= (-4096ULL); /* 4KB alignment, round down */ - if (tmpend < bytes_needed) - continue; - tmpbase = tmpend - bytes_needed; // maximum possible base for this region - //grub_printf("range b %lx l %lx -- tm %lx te %lx tb %lx\n",map->BaseAddr,map->Length,tmpmin,tmpend,tmpbase); - if (((long long)mem) > 0)//force the base value - { - if (tmpbase >= (mem << 9)) - tmpbase = (mem << 9); // move tmpbase down to forced value - else // mem base exceed maximum possible base for this region - continue; - } - if (tmpbase < tmpmin) // base fall below minimum address for this region - continue; - - for (i = 0; i < DRIVE_MAP_SIZE; i++) - { - - if (drive_map_slot_empty (bios_drive_map[i])) - break; - - /* TO_DRIVE == 0xFF indicates a MEM map */ - if (bios_drive_map[i].to_drive == 0xFF && !(bios_drive_map[i].to_cylinder & 0x4000)) - { - unsigned long long drvbase, drvend; - drvbase = (bios_drive_map[i].start_sector << SECTOR_BITS); - drvend = (bios_drive_map[i].sector_count << SECTOR_BITS) + drvbase; - drvend = ((drvend+4095)&(-4096ULL));/* 4KB alignment, round up */ - drvbase &= (-4096ULL); /* 4KB alignment, round down */ - //grub_printf("drv %02x: db %lx de %lx -- tb %lx te %lx\n",bios_drive_map[i].from_drive,drvbase,drvend,tmpbase,tmpend); - if (tmpbase < drvend && drvbase < tmpend) - { // overlapped address, move tmpend and tmpbase down - tmpend = drvbase; - if (tmpend >= bytes_needed) - { - if ((long long)mem <= 0) - { // decrease tmpbase - tmpbase = tmpend - bytes_needed; - if (tmpbase >= tmpmin) - { // recheck new tmpbase - i = -1; continue; - } - } - else - { // force base value, cannot decrease tmpbase - /* changed "<" to "<=". -- tinybit */ - if (tmpbase <= tmpend - bytes_needed) - { // there is still enough space below drvbase - continue; - } - } - } - /* not enough room for this memory area */ - // grub_printf("region can't be used bn %lx te %lx tb %lx\n",bytes_needed,tmpend,tmpbase); - tmpbase = 0; break; - } - } - } /* for (i = 0; i < DRIVE_MAP_SIZE; i++) */ + goto get_info_ok; + +get_gpt_info: - if (tmpbase >= tmpmin) - { - /* check if the memory area overlaps the (md)... or (rd)... file. */ - if ( (to != 0xffff && to != ram_drive) /* TO is not in memory */ - || ((long long)mem) > 0 /* TO is in memory but is mapped at a fixed location */ - || !compressed_file /* TO is in memory and is normally mapped and uncompressed */ - /* Now TO is in memory and is normally mapped and compressed */ - || tmpbase + bytes_needed <= start_byte /* XXX: destination is below the gzip image */ - || tmpbase >= start_byte + to_filesize) /* XXX: destination is above the gzip image */ + partmap_type = 2; //GPT + from_log2_sector = 9; + P_GPT_HDR gpt = (P_GPT_HDR)cache; + /* "EFI PART" */ + filepos = 1 << 9; //读逻辑1扇区, 普通磁盘 + grub_read ((unsigned long long)(grub_size_t) cache, 0x800, 0xedde0d90); + if (gpt->hdr_sig != GPT_HDR_SIG) //如果签名不符 { - /* Comment out. Now we always prefer top. -- tinybit, 2016-12-21 */ - //if (prefer_top) - { - if (base < tmpbase) - { - base = tmpbase; top_end = tmpend; - } - continue; // find available region with highest address - } - //else - //{ - //base = tmpbase; top_end = tmpend; - //break; // use the first available region - //} + from_log2_sector = 12; + filepos = 1 << 12; //读逻辑1扇区, 是原生4k磁盘 + grub_read ((unsigned long long)(grub_size_t) cache, 0x800, 0xedde0d90); + if (gpt->hdr_sig != GPT_HDR_SIG) //如果签名不符 + goto fail_close_free; } + goto get_info_ok; + } + else //软盘 + { + from_log2_sector = 9; + } + } + +get_info_ok: + grub_free (cache); + cache = 0; +#if VHD_DIFFERENCE + if (compressed_file && decomp_type == DECOMP_TYPE_VHD) //vhd动态磁盘 + { + if (mem == -1ULL) //不加载到内存 + vhd_disk |= 1; + else //加载到内存 + vhd_disk |= 2; + } +#endif + if (mem == -1ULL) //如果不加载到内存 + grub_close (); //关闭to驱动器 +//==================================================================================================================== +//printf ("from-4,%x,%x,%x,%x,%x\n",from,to,current_drive,saved_drive,no_alloc); +//a0,21,7f,21; 60,ffff,ffff,21; +//a0,21,7f,21; 60,ffff,ffff,21; +//81,ffff,ffff.21; 82,7f,7f,81; + //5. 处理加载到内存 + if (mem != -1ULL && !no_alloc) //如果加载到内存 + { + unsigned long long start_byte; //起始字节 + unsigned long long bytes_needed; //需要字节 + bytes_needed = 0ULL; //初始化: 需要字节=基地址=顶端=0 + grub_efi_physical_address_t alloc; //分配 动态地址,变化 + + if (start_sector == part_start && part_start == 0 && sector_count == 1) //如果起始扇区=分区起始,并且分区起始=0,并且扇区计数=1 + sector_count = part_length; //扇区计数=分区长度 + if ( (long long)mem < 0LL && sector_count < (-mem) ) //如果mem<0,并且扇区计数<(-mem) + bytes_needed = (-mem) << buf_geom.log2_sector_size; else - /* destination overlaps the gzip image */ - /* fail and try next memory block. */ - continue; - } - //if (to == 0xff) - //bytes_needed = 0; + bytes_needed = sector_count << buf_geom.log2_sector_size; - } /* for (; end_addr > (int) map; map = (struct AddrRangeDesc *) (((int) map) + 4 + map->size)) */ + if (add_mbt) //如果增加分配块=1, 需要字节0x200 + bytes_needed += 512; - } /* if (mbi.flags & MB_INFO_MEM_MAP) */ - else - grub_printf ("\nFatal: Your BIOS has no support for System Memory Map(INT15/EAX=E820h).\nAs a result you cannot use the --mem option.\n"); + bytes_needed = ((bytes_needed+4095)&(-4096ULL)); /* 4KB alignment 4k对齐*/ - if (base < map_mem_min) + start_byte = start_sector << buf_geom.log2_sector_size; //起始字节 + if (to == ram_drive) //如果to=rd + start_byte += rd_base; //起始字节+rd基址 + if (to == 0x21 && (!cur_pxe_type || !http_feature)) //网络驱动器 + { + start_sector = ((unsigned long long)(grub_size_t)(char*)efi_pxe_buf); //此处是内存起始字节!!! + start_byte = rd_base; + } +/////////////////////////////////////////////////////////////////////////////////////////////////////以下插入分配内存 + if (prefer_top) //分配4GB以上内存 { - grub_close (); - return ! (errnum = ERR_WONT_FIT); + //在此借用一下 blklst_num_sectors 全局变量 + blklst_num_sectors = (grub_efi_uintn_t)bytes_needed >> 12; //需求页数 + displaymem_func ((char *)"-mem", 1); //探测4GB以上内存 + if (blklst_num_sectors != (grub_efi_uintn_t)bytes_needed >> 12) //有满足条件的内存 + { + status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ADDRESS, +// GRUB_EFI_RUNTIME_SERVICES_DATA, + GRUB_EFI_RESERVED_MEMORY_TYPE, //保留内存类型 0 + (grub_efi_uintn_t)bytes_needed >> 12, &blklst_num_sectors); //调用(分配页面,分配类型->指定页面,存储类型->运行时服务数据(6),分配页,地址) + if (status == GRUB_EFI_SUCCESS) + { + alloc = blklst_num_sectors; + goto mem_ok; + } + } } - - if (((long long)mem) > 0) - { - base = ((unsigned long long)mem << 9); - sector_count = (top_end - base) >> SECTOR_BITS; - }else{ - sector_count = bytes_needed >> SECTOR_BITS; - // now sector_count may be > part_length, reading so many sectors could cause failure +/* +通过g4e或者grub2作为一个UEFI引导器,加载镜像到内存盘,并且做好了与svbus驱动的对接,然后启动windows,进入桌面。 +当内存类型为GRUB_EFI_RUNTIME_SERVICES_DATA时,有的系统可以成功启动,而有的windows系统报错误0xc0000225和0xc0000017. +“c0000225”或“c0000017”错误发生在您试图在运行Windows 7或Windows Server 2008 R2的启用了UEFI的计算机上启动Windows PE RAM磁盘映像时. +看微软的意思是“内存状态不同步,一个内存管理器使用的一些内存仍然被另一个内存管理器标记为可用. +改用内存类型GRUB_EFI_RESERVED_MEMORY_TYPE,完美解决. +*/ + status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES, +// GRUB_EFI_RUNTIME_SERVICES_DATA, + GRUB_EFI_RESERVED_MEMORY_TYPE, //保留内存类型 0 + (grub_efi_uintn_t)bytes_needed >> 12, &alloc); //调用(分配页面,分配类型->任意页面,存储类型->运行时服务数据(6),分配页,地址) + if (status != GRUB_EFI_SUCCESS) //如果失败 + { + printf_errinfo ("out of map memory: %d\n",(int)status); + errnum = ERR_WONT_FIT; //2024-09-01 + return 0; } - bytes_needed = base; - if (add_mbt) /* no partition table */ - bytes_needed += sectors_per_track << SECTOR_BITS; /* build the Master Boot Track */ - - /* bytes_needed points to the first partition, base points to MBR */ - -//#undef MIN_EMU_BASE - // if (! grub_open (filename1)) - // return 0; - - /* the first sector already read at BS */ -#if 0 - if ((to != 0xffff && to != ram_drive) || ((long long)mem) <= 0) - { -#endif +/////////////////////////////////////////////////////////////////////////////////////////////////////以上插入分配内存 +/* +VHD测试 +镜像:qbus_gd.vhd 716Mb(包含qbus);qbus_dt.vhd 642Mb;hdd_boot_gd.vhd(无qbus) +环境:QEMU虚拟机; VirtualBox虚拟机; 笔记本电脑。 +条件1:不加载到内存/加载到内存 +条件2:使用grub_read读文件簇/使用read_blocks读碎片块 +条件3:U盘/SSD固态盘 +-------------------------------------------------------------------------------------------------------------- +环境 镜像 条件1 条件2 条件3 启动时间(秒) 说明 +-------------------------------------------------------------------------------------------------------------- +QEMU hdd_boot_gd.vhd map 可以正常启动 +QEMU qbus_gd.vhd map 可以正常启动 +QEMU qbus_gd.vhd map --mem grub_read U盘 167 +QEMU qbus_gd.vhd map --mem read_blocks U盘 94 +QEMU qbus_dt.vhd map 不能启动 +QEMU qbus_dt.vhd map --mem grub_read U盘 93 +-------------------------------------------------------------------------------------------------------------- +VirtualBox hdd_boot_gd.vhd map 可以正常启动 +VirtualBox qbus_gd.vhd map 不能启动(一直转圈) +VirtualBox qbus_gd.vhd map --mem grub_read U盘 503 +VirtualBox qbus_gd.vhd map --mem read_blocks U盘 150 +-------------------------------------------------------------------------------------------------------------- +笔记本电脑 hdd_boot_gd.vhd map 可以正常启动 +笔记本电脑 qbus_gd.vhd map 不能启动(转圈之后重启) +笔记本电脑 qbus_gd.vhd map --mem grub_read U盘 85 +笔记本电脑 qbus_gd.vhd map --mem read_blocks U盘 82 +笔记本电脑 qbus_gd.vhd map --mem grub_read SSD固态盘 2 +笔记本电脑 qbus_gd.vhd map --mem read_blocks SSD固态盘 1 +-------------------------------------------------------------------------------------------------------------- + +结论: +1. 加载速度取决于UEFI固件。实机区别不大,虚拟机有改进。 +2. 静态VHD映射为硬盘,可以是内存盘,也可以不是。可以使用chainloader加载,也可以使用ntboot加载。 +3. 动态/差分VHD使用chainloader加载,必须映射为内存盘。 +4. 动态/差分VHD使用ntboot加载,内部必须包含BCD。 +*/ +mem_ok: + sector_count = bytes_needed >> 9; //扇区计数=加载到内存的扇区数,每扇区0x200字节 + start_sector = alloc >> 9; + + if (add_mbt) + { + grub_memmove64 (alloc, (unsigned long long)(grub_size_t)buffer, 512); + grub_free (buffer); + alloc += 512; + } + if (alloc_only) + { + from_log2_sector = 9; + grub_close (); //关闭to驱动器 + to = 0xFFFF; + goto no_fragment; + } + //向内存移动映像 第一扇区已经读到了BS /* if image is in memory and not compressed, we can simply move it. */ - if ((to == 0xffff || to == ram_drive) && !compressed_file) - { - if (bytes_needed != start_byte) - grub_memmove64 (bytes_needed, start_byte, (max_sectors >= filemax) ? filemax : (sector_count << SECTOR_BITS)); - } else { - unsigned long long read_result; - grub_memmove64 (bytes_needed, (unsigned long long)(unsigned int)BS, SECTOR_SIZE); - /* read the rest of the sectors */ - if (sector_count > 1) - { - unsigned long long read_size = ((sector_count - 1) << 9); - if (read_size > filemax - ((skip_sectors + 1) << 9)) - read_size = filemax - ((skip_sectors + 1) << 9); - read_result = grub_read ((bytes_needed + SECTOR_SIZE), read_size, 0xedde0d90); - if (read_result != read_size) - { - //if ( !probed_total_sectors || read_result<(probed_total_sectors<= read_size - || ( (filepos = ((skip_sectors + 1) << 9)), /* re-read from the second sector. */ - grub_read (bytes_needed + SECTOR_SIZE, required, 0xedde0d90) != required - ) - ) - { - grub_close (); - if (errnum == ERR_NONE) - errnum = ERR_READ; - return 0; - } - //} - } - } - } - grub_close (); -#if 0 - } - else if (/*(to == 0xffff || to == ram_drive) && */!compressed_file) - { - if (bytes_needed != start_byte) - grub_memmove64 (bytes_needed, start_byte, filemax); - grub_close (); - } - else - { - grub_memmove64 (bytes_needed, (unsigned long long)(unsigned int)BS, SECTOR_SIZE); - grub_read (bytes_needed + SECTOR_SIZE, -1ULL, 0xedde0d90); - grub_close (); - } -#endif - start_sector = base >> SECTOR_BITS; - to = 0xFFFF/*GRUB_INVALID_DRIVE*/; - - if (add_mbt) /* no partition table */ - { - unsigned long sectors_per_cylinder1, cylinder, sector_rem; - unsigned long head, sector; +//printf ("from-5,%x,%x,%x,%x,%x\n",from,to,current_drive,saved_drive,compressed_file); +//a0,21,7f,21; 60,ffff,ffff,21; +//a0,21,7f,21; 60,ffff,ffff,21; +//81,ffff,ffff.21; + if ((to == 0xffff || to == ram_drive/* || (to == 0x21 && type != 260)*/) && !compressed_file) //如果映像在内存中,并且没有压缩,我们可以简单地移动它。 + { + printf ("Copying data from memory, please wait......\n"); + grub_memmove64 (alloc, start_byte, filemax); + } + else if (!compressed_file && to != 0x21) //如果映像不在内存,而且没有压缩(img,iso,静态vhd),使用读碎片块方法 2024-09-01 加快静态vhd的读取速度 + { + //在QEMU虚拟机测试qbus_gd.vhd,716Mb,用时94秒。如果使用grub_read函数,用时167秒。94/167=56% + //在QEMU虚拟机测试qbus_dt.vhd,642Mb,用时93秒。 + //在实机测试qbus_gd.vhd(ssd固态硬盘),716Mb,用时1秒。如果使用grub_read函数,用时2秒。 + //在实机测试qbus_gd.vhd(2.0启动U盘),716Mb,用时82秒。如果使用grub_read函数,用时85秒。 + //在Qracle VM虚拟机测试qbus_gd.vhd,716Mb,用时150秒。如果使用grub_read函数,用时503秒。150/503=30% + //静态VHD(内涵qbus)不加载到内存,QEMU虚拟机可以启动成功,Qracle VM虚拟机一直转圈,实机转圈后重启。 + unsigned long long add = alloc; //内存扇区地址 + filepos = skip_sectors << 9; + + printf ("Copying data from sector sequence, please wait......\n"); + for (k = 0; k < blklst_num_entries; k++) + { + struct grub_disk_data *d = 0; + grub_efi_block_io_t *bio = 0; + d = get_device_by_drive (to,0); + if (!d) + return (!(errnum = ERR_NO_DISK)); + bio = d->block_io; //块io + status = efi_call_5 (bio->read_blocks, bio, bio->media->media_id, (grub_efi_uint64_t) map_start_sector[k], + (grub_efi_uintn_t) map_num_sectors[k] << 9, (char *)(grub_size_t)add); //读写(读,本身块io,media_id,扇区,字节尺寸,缓存) + if (status) //如果错误 + { + grub_close (); //关闭to驱动器 + errnum = ERR_READ; + return 0; + } - /* First sector of disk image has already been read to buffer BS/mbr */ - - /* modify the BPB drive number. required for FAT12/16/32/NTFS */ - if (filesystem_type != -1) - if (!*(char *)((int)BS + ((filesystem_type == 3) ? 0x41 : 0x25))) - *(char *)((int)BS + ((filesystem_type == 3) ? 0x40 : 0x24)) = from; - - /* modify the BPB hidden sectors. required for FAT12/16/32/NTFS/EXT2 */ - if (filesystem_type != -1 || *(unsigned long *)((int)BS + 0x1c) == (unsigned long)part_start) - *(unsigned long *)((int)BS + 0x1c) = sectors_per_track; - - grub_memmove64 (bytes_needed, (unsigned long long)(unsigned int)BS, SECTOR_SIZE); - - /* clear BS/mbr buffer */ - grub_memset(mbr, 0, SECTOR_SIZE); - - /* clear MS magic number */ - //*(long *)((int)mbr + 0x1b8) = 0; - /* Let MS magic number = virtual BIOS drive number */ - *(long *)((int)mbr + 0x1b8) = (unsigned char)from; - /* build the partition table */ - *(long *)((int)mbr + 0x1be) = 0x00010180L; - *(char *)((int)mbr + 0x1c2) = //((filesystem_type == -1 || filesystem_type == 5)? 0x83 : filesystem_type == 4 ? 0x07 : 0x0c); - filesystem_type == 1 ? 0x0E /* FAT12 */ : - filesystem_type == 2 ? 0x0E /* FAT16 */ : - filesystem_type == 3 ? 0x0C /* FAT32 */ : - filesystem_type == 4 ? 0x07 /* NTFS */ : - filesystem_type == 6 ? 0x07 /* exFAT */ : - /*filesystem_type == 5 ?*/ 0x83 /* EXT2 */; - - //sector_count += sectors_per_track; /* already incremented above */ - - /* calculate the last sector's C/H/S value */ - sectors_per_cylinder1 = sectors_per_track * heads_per_cylinder; - cylinder = ((unsigned long)(sector_count - 1)) / sectors_per_cylinder1; /* XXX: 64-bit div */ - sector_rem = ((unsigned long)(sector_count - 1)) % sectors_per_cylinder1; /* XXX: 64-bit mod */ - head = sector_rem / (unsigned long)sectors_per_track; - sector = sector_rem % (unsigned long)sectors_per_track; - sector++; - *(char *)((int)mbr + 0x1c3) = head; - *(unsigned short *)((int)mbr + 0x1c4) = sector | (cylinder << 8) | ((cylinder >> 8) << 6); - *(unsigned long *)((int)mbr + 0x1c6) = sectors_per_track; /* start LBA */ - *(unsigned long *)((int)mbr + 0x1ca) = sector_count - sectors_per_track; /* sector count */ - *(long long *)((int)mbr + 0x1ce) = 0LL; - *(long long *)((int)mbr + 0x1d6) = 0LL; - *(long long *)((int)mbr + 0x1de) = 0LL; - *(long long *)((int)mbr + 0x1e6) = 0LL; - *(long long *)((int)mbr + 0x1ee) = 0LL; - *(long long *)((int)mbr + 0x1f6) = 0LL; - *(unsigned short *)((int)mbr + 0x1fe) = 0xAA55; - - /* compose a master boot record routine */ - *(char *)((int)mbr) = 0xFA; /* cli */ - *(unsigned short *)((int)mbr + 0x01) = 0xC033; /* xor AX,AX */ - *(unsigned short *)((int)mbr + 0x03) = 0xD08E; /* mov SS,AX */ - *(long *)((int)mbr + 0x05) = 0xFB7C00BC; /* mov SP,7C00 ; sti */ - *(long *)((int)mbr + 0x09) = 0x07501F50; /* push AX; pop DS */ - /* push AX; pop ES */ - *(long *)((int)mbr + 0x0d) = 0x7C1CBEFC; /* cld; mov SI,7C1C */ - *(long *)((int)mbr + 0x11) = 0x50061CBF; /* mov DI,061C ; push AX */ - *(long *)((int)mbr + 0x15) = 0x01E4B957; /* push DI ; mov CX, 01E4 */ - *(long *)((int)mbr + 0x19) = 0x1ECBA4F3; /* repz movsb;retf;push DS */ - *(long *)((int)mbr + 0x1d) = 0x537C00BB; /* mov BX,7C00 ; push BX */ - *(long *)((int)mbr + 0x21) = 0x520180BA; /* mov DX,0180 ; push DX */ - *(long *)((int)mbr + 0x25) = 0x530201B8; /* mov AX,0201 ; push BX */ - *(long *)((int)mbr + 0x29) = 0x5F13CD41; /* inc CX; int 13; pop DI */ - *(long *)((int)mbr + 0x2d) = 0x5607BEBE; /* mov SI,07BE ; push SI */ - *(long *)((int)mbr + 0x31) = 0xCBFA5A5D; /* pop BP;pop DX;cli;retf */ - grub_memmove64 (base, (unsigned long long)(unsigned int)mbr, SECTOR_SIZE); - } - else if ((from & 0x80) && (from < 0x9F)) /* the virtual drive is hard drive */ - { - /* First sector of disk image has already been read to buffer BS/mbr */ - if (*(long *)((int)mbr + 0x1b8) == 0) - /* Let MS magic number = virtual BIOS drive number */ - *(long *)((int)mbr + 0x1b8) = (unsigned char)from; - else if ((*(long *)((int)mbr + 0x1b8) & 0xFFFFFF00) == 0) - *(long *)((int)mbr + 0x1b8) |= (from << 8); - grub_memmove64 (base, (unsigned long long)(unsigned int)mbr, SECTOR_SIZE); - } + add += map_num_sectors[k] << 9; + filepos += map_num_sectors[k] << 9; + } + blklst_num_entries = 1; //如果文件有碎片,加载到内存后就连续了。避免后续设置碎片。 + } + else //如果映像不在内存,而且被压缩,使用读文件簇方法 + { + unsigned long long read_result; //读结果 + unsigned long long read_size = bytes_needed; //读尺寸 + //修正读尺寸 + if (read_size > filemax - (skip_sectors << 9)) + read_size = filemax - (skip_sectors << 9); + filepos = skip_sectors << 9; + unsigned long long asdf = part_start; +#if VHD_DIFFERENCE + if (vhd_disk & 2) + part_start = vhd_start_sector; +#endif + printf ("Copying data from compressed file, please wait......\n"); + read_result = grub_read (alloc, read_size, 0xedde0d90); //读结果=返回读尺寸 + part_start = asdf; - /* if FROM is (rd), no mapping is established. but the image will be - * loaded into memory, and (rd) will point to it. Note that Master - * Boot Track and MBR code have been built as above when needed + if (read_result != read_size) //如果读结果!=读尺寸 + { + grub_close (); //关闭to驱动器 + if (errnum == ERR_NONE) + errnum = ERR_READ; + return 0; + } + blklst_num_entries = 1; //如果文件有碎片,加载到内存后就连续了。避免后续设置碎片。 + } + + if (add_mbt) + { + *(int*)((grub_size_t)alloc + 0x1c) = 1; + add_mbt = 0; + } + grub_close (); //关闭to驱动器 + to = 0xFFFF/*GRUB_INVALID_DRIVE*/; +//printf ("from-6,%x,%x,%x,%x\n",from,to,current_drive,saved_drive); +//a0,ffff,7f,21; 60,ffff,ffff,21; +//a0,ffff,7f,21; 60,ffff,ffff,21; +//81,ffff,ffff.21; + /* if FROM is (rd), no mapping is established. but the image will be //如果FROM是rd,没有建立映射 + * loaded into memory, and (rd) will point to it. Note that Master //但是映像将装载到内存,并且rd指向它. + * Boot Track and MBR code have been built as above when needed //注意主引导磁道和MBR代码已经建立,需要ram_drive是硬盘. * for ram_drive > 0x80. */ - if (from == ram_drive) + if (from == ram_drive) //如果from是rd + { + rd_base = alloc; //rd基址 + rd_size = filemax; + return 1; + } + } //if (mem != -1ULL)结束 //如果加载到内存结束 +//printf ("from-7,%x,%x,%x,%x,%x\n",from,to,current_drive,saved_drive,no_alloc); +//a0,ffff,7f,21; 60,ffff,ffff,21; +//a0,ffff,7f,21; 60,ffff,ffff,21; +//81,ffff,ffff.21; 82,7f,7f,81; + if (no_alloc) + { + if (current_drive == 0x21) + { + start_sector = (grub_size_t)efi_pxe_buf >> 9; +// efi_pxe_buf = 0; + } + else if (current_drive == ram_drive) + { + start_sector = rd_base >> 9; + } + grub_close (); //关闭to驱动器 + to = 0xFFFF; + } + //加载到内存结束 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ buf_geom 是 primeval_to 的信息 + //6. 处理不加载到内存 + if (primeval_to != to) + if (get_diskinfo (to, &buf_geom, 0)) //如果'获得磁盘信息'返回非0, 错误 + return !(errnum = ERR_NO_DISK); + +//有碎片 +// │ Virtual_sector │ 虚拟扇区(假设连续) +// │ │ +// │ To_count(0) To_count(1) │ To_count(2) │ To_count(3) │ +// ├─────────┼────────────┼──────────┼───────────────────┤ To驱动器(父) 有碎片 +//To_start(0) To_start(1) To_start(2) To_start(3) +// │ Form_len +// ├--------------------├------------------------------------┤ Form驱动器(子) 可能有碎片 +// │ Form_statr + + //Determine the start fragment + //不加载到内存,并且to不是光盘,并且((原始to != to,并且有碎片) 或者块列表数大于1) +// if ((mem == -1ULL) && (to < 0x9f) && (((primeval_to != to) && (disk_drive_map[j].fragment == 1)) || (blklst_num_entries > 1))) + if ((mem == -1ULL) && (to < 0x9f) && (((primeval_to != to) && (dt->fragment == 1)) || (blklst_num_entries > 1))) + { + //如果是2次映射,并且有碎片 + if ((primeval_to != to) && (dt->fragment == 1)) //如果是2次映射,并且有碎片 + { + //临时缓存子程序碎片信息 + char *p1 = grub_zalloc (DRIVE_MAP_FRAGMENT * 8); + if (!p1) + return 0; + char *p2 = grub_zalloc (DRIVE_MAP_FRAGMENT * 8); + if (!p2) + return 0; + unsigned long long *map_start_sector_back = (unsigned long long *)p1; + unsigned long long *map_num_sectors_back = (unsigned long long *)p2; + grub_memmove64 ((unsigned long long)(grub_size_t)p1, (unsigned long long)(grub_size_t)map_start_sector, DRIVE_MAP_FRAGMENT * 8); + grub_memmove64 ((unsigned long long)(grub_size_t)p2, (unsigned long long)(grub_size_t)map_start_sector, DRIVE_MAP_FRAGMENT * 8); + //查找父插槽To_ + q = (struct fragment_map_slot *)disk_fragment_map; + q = fragment_map_slot_find(q, primeval_to); + +// struct fragment *to_ = (struct fragment *)&q->fragment_data; + int offse = offsetof(struct fragment_map_slot, fragment_data); + struct fragment *to_ = (struct fragment *)((char *)q + offse); + for (m = 0; *map_start_sector_back && m < DRIVE_MAP_FRAGMENT; map_start_sector_back += 8, map_num_sectors_back += 8) { - rd_base = base; - rd_size = (max_sectors >= filemax) ? filemax : (sector_count << SECTOR_BITS); - if (add_mbt) - rd_size += sectors_per_track << SECTOR_BITS; /* build the Master Boot Track */ - return 1; + unsigned long long Virtual_sector = 0; //虚拟扇区终点(假设扇区连续) 以To_start(0)为起点,把各碎片依序逐次拼接的终端值。 + unsigned long long Form_len = *map_num_sectors_back; //Form扇区计数 + unsigned long long Form_statr = *map_start_sector_back; //Form起始扇区 + Virtual_sector = to_[0].start_sector; //虚拟扇区终端,以To_start(0)为起点 + + for (k = 0; (k+m < DRIVE_MAP_FRAGMENT) && (to_[k].start_sector != 0); k++) + { + //确定Form_statr在父驱动器的物理地址 + Virtual_sector += to_[k].sector_count; //拼接第k段后的虚拟扇区终点 + if (Form_statr < Virtual_sector) //如果Form起始扇区小于虚拟扇区终点,说明Form起始扇区位于碎片段k + { + map_start_sector[m] = to_[k].start_sector + to_[k].sector_count - (Virtual_sector - Form_statr); //Form_statr在父驱动器的物理地址 + start_sector = map_start_sector[m]; + break; + } + } + //确定碎片尺寸(也可能只有一段) + l = 0; + if ((Form_len + Form_statr) <= Virtual_sector) //如果父碎片段k可容纳Form_len + goto set_ok; //完成 + else + { + //确定子碎片段0尺寸 + map_num_sectors[m] = Virtual_sector - Form_statr; //碎片段k剩余尺寸,作为子碎片段0的尺寸 + Form_len -= map_num_sectors[m]; //Form扇区计数剩余值 + //确定子碎片段l尺寸 + for (l = 1; ((k+l+m < DRIVE_MAP_FRAGMENT) && (to_[k+l].start_sector != 0)); l++) + { + blklst_num_entries = l + 2; + // + if (Form_len <= to_[k+l].sector_count) //如果父碎片段k可容纳Form_len + { + map_num_sectors[l+m] = Form_len; //Form扇区计数剩余值,作为子碎片段l的尺寸 + map_start_sector[l+m] = to_[k+l].start_sector;//父碎片段k+l的起时扇区,作为子碎片段l的起时扇区 + goto set_ok; //完成 + } + else //如果父碎片段k不能容纳Form_len + { + map_num_sectors[l+m] = to_[k+l].sector_count; //父碎片段k+l的起时扇区,作为子碎片段l的起时扇区 + map_start_sector[l+m] = to_[k+l].start_sector;//父碎片段k+l的扇区尺寸,作为子碎片段l的扇区尺寸 + Form_len -= to_[k+l].sector_count; //Form扇区计数剩余值 + } + } + } +set_ok: + m += l + 1; } + map_num_sectors[m] = 0; + map_start_sector[m] = 0; + grub_free (p1); + grub_free (p2); } - if (in_situ) - bios_drive_map[j].to_cylinder = (in_situ_flags << 8) | ( - in_situ_id != 0xffff ? in_situ_id : - filesystem_type == 1 ? 0x0E /* FAT12 */ : - filesystem_type == 2 ? 0x0E /* FAT16 */ : - filesystem_type == 3 ? 0x0C /* FAT32 */ : - filesystem_type == 4 ? 0x07 /* NTFS */ : - filesystem_type == 6 ? 0x07 /* exFAT */ : - /*filesystem_type == 5 ?*/ 0x83 /* EXT2 */ - ); - - /* if TO_DRIVE is whole floppy, skip the geometry lookup. */ - if (start_sector == 0 && sector_count == 0 && to < 0x04) - { - tmp_geom.flags &= ~BIOSDISK_FLAG_LBA_EXTENSION; - tmp_geom.sector_size = 512; - tmp_geom.cylinders = 80; /* does not care */ - tmp_geom.heads = 2; /* does not care */ - tmp_geom.sectors = 18; /* does not care */ - } - else - { - /* Using variable TO_O here is wrong! we must get_diskinfo of TO. - * tmp_geom of TO will be used later. - * It is just this which caused problem of issue 97. - */ - //if (to_o == -1) - // to_o = to; - /* Get the geometry. This ensures that the drive is present. */ - //if (to_o != PXE_DRIVE && get_diskinfo (to_o, &tmp_geom)) - if (to != PXE_DRIVE && get_diskinfo (to, &tmp_geom, 0)) - { - return ! (errnum = ERR_NO_DISK); - } - } - i = j; /* restore i from j */ - - - -// j_count(0) j_count(1) j_count(2) j_count(3) -// ├──────────────┼───────────────────┼───────────────────┼───────────────────┤ -// j_start(0) j_start(1) j_start(2) j_start(3) -// To_len -// ┇┅┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄├───────────────────────┤ -// 0 To_statr - - //Determine the start fragment - if ((mem == -1ULL) && (to < 0x9f) && (((primeval_to != to) && ((hooked_drive_map[m].to_cylinder & (1 << 10)) != 0)) || (blklst_num_entries > 1))) - { - if (primeval_to >= 0x9f) - { - for (k = 0; (k < DRIVE_MAP_FRAGMENT) && (map_start_sector[k] != 0); k++) - { - map_start_sector[k] *= 4; - map_num_sectors[k] *= 4; - } - } -// if (part_start) -// { -// for (k = 0; (k < DRIVE_MAP_FRAGMENT) && (map_start_sector[k] != 0); k++) -// { -// map_start_sector[k] += part_start; -// } -// } - if ((primeval_to != to) && ((hooked_drive_map[m].to_cylinder & (1 << 10)) != 0)) - { - unsigned long long a = 0; //Sum(j_count(k)) - unsigned long long b = map_num_sectors[0]; //Residual(To_len) - unsigned long long c = map_start_sector[0]; //To_statr - p = (char *)&hooked_fragment_map; - p = fragment_map_slot_find(p, primeval_to); - q = (struct fragment_map_slot *)p; - for (k = 0; (k < DRIVE_MAP_FRAGMENT) && (q->fragment_data[k] != 0); k++) - { - a += q->fragment_data[k*2+1]; //Sum(j_count(k)) - if (map_start_sector[0] < a) //To_statr < Sum(j_count(k)) - { - map_start_sector[0] += q->fragment_data[k*2] + q->fragment_data[k*2+1] - a; - //To_statr = To_statr + j_start(k) + j_count(k) - Sum(j_count(k)) - break; //ok - } - } - //Determine the length - if ((b + c) <= a ) //Residual(To_len) <= Sum(j_count(k)) - j_start(0) - goto set_ok; //j_count(k) = To_len - else - { - map_num_sectors[0] = a - c; //j_count(k) = Sum(j_count(k)) - To_statr - map_start_sector[1] = q->fragment_data[k*2+2]; //j_start(k+1) - b -= (a - c); //Residual(To_len) - (Sum(j_count(k)) - To_statr) - for (l = 0; ((l < DRIVE_MAP_FRAGMENT - k) && (q->fragment_data[(k+l)*2+3] != 0)); l++) - { - blklst_num_entries = l + 2; - if (b <= q->fragment_data[(k+l)*2+3]) //Residual(To_len) <= j_count(k+1) - { - map_num_sectors[l+1] = b; //Residual(To_len) - goto set_ok; - } - else - { - map_num_sectors[l+1] = q->fragment_data[(k+l)*2+3]; //j_count(k+1) - map_start_sector[l+2] = q->fragment_data[(k+l)*2+4];//j_start(k+2) - b -= q->fragment_data[(k+l)*2+3]; //Residual(To_len) - j_count(k+1) - } - } - } - } - -set_ok: if (blklst_num_entries < 2) { - start_sector = map_start_sector[0]; goto no_fragment; } - - p = (char *)&hooked_fragment_map; - filename = p; - p = fragment_map_slot_empty(p); - if ((p + blklst_num_entries*16 + 4 - filename) > FRAGMENT_MAP_SLOT_SIZE) + //查找空槽 + q = (struct fragment_map_slot *)disk_fragment_map; + filename = (char *)q; + q = fragment_map_slot_empty(q); + //出界检查 + if (((char *)q + blklst_num_entries*16 + 4 - filename) > FRAGMENT_MAP_SLOT_SIZE) return ! (errnum = ERR_MANY_FRAGMENTS); - q = (struct fragment_map_slot *)p; - + //建立碎片映射 q->from = from; q->to = to; +// struct fragment *f = (struct fragment *)&q->fragment_data; + int offse = offsetof(struct fragment_map_slot, fragment_data); + struct fragment *f = (struct fragment *)((char *)q + offse); for (k = 0; map_start_sector[k] != 0; k++) { - q->fragment_data[k*2] = map_start_sector[k]; - q->fragment_data[k*2+1] = map_num_sectors[k]; + f[k].start_sector = map_start_sector[k]; + f[k].sector_count = map_num_sectors[k]; } + q->slot_len = k*16 + 4; } - -no_fragment: - - bios_drive_map[i].from_drive = from; - bios_drive_map[i].to_drive = (unsigned char)to; /* to_drive = 0xFF if to == 0xffff */ - - /* if CHS disabled, let MAX_HEAD != 0 to ensure a non-empty slot */ - bios_drive_map[i].max_head = disable_chs_mode | (heads_per_cylinder - 1); -// bios_drive_map[i].max_sector = (disable_chs_mode ? 0 : in_situ ? 1 : sectors_per_track) | ((read_Only | fake_write) << 7) | (disable_lba_mode << 6); - bios_drive_map[i].max_sector = (disable_chs_mode ? 0 : sectors_per_track) | ((read_Only | fake_write) << 7) | (disable_lba_mode << 6); - if (from >= 0x9F && tmp_geom.sector_size != 2048) /* FROM is cdrom and TO is not cdrom. */ - bios_drive_map[i].max_sector |= 0x0F; /* can be any value > 1, indicating an emulation. */ - - /* bit 12 is for "TO drive is bifurcate" */ - - if (! in_situ) - bios_drive_map[i].to_cylinder = - ((tmp_geom.flags & BIOSDISK_FLAG_BIFURCATE) ? ((to & 0x100) >> 1) : - ((tmp_geom.flags & BIOSDISK_FLAG_LBA_EXTENSION) << 15)) | - ((tmp_geom.sector_size == 2048) << 14) | - ((from >= 0x9F) << 13) | /* assume cdrom if from_drive is 0xA0 or greater */ - ((!!(tmp_geom.flags & BIOSDISK_FLAG_BIFURCATE)) << 12) | - ((filesystem_type > 0) << 11) | /* has a known boot sector type */ - ((blklst_num_entries > 1) << 10) | - ((tmp_geom.cylinders - 1 > 0x3FF) ? 0x3FF : (tmp_geom.cylinders - 1)); - bios_drive_map[i].to_head = tmp_geom.heads - 1; +//无碎片 +no_fragment: +#undef BS - bios_drive_map[i].to_sector = tmp_geom.sectors | ((fake_write | ! unsafe_boot) << 6); - if (in_situ) - bios_drive_map[i].to_sector |= 0x80; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //7. 填充映射结构 + buf_drive = -1; + buf_track = -1; + struct grub_disk_data *d; + struct grub_disk_data *d1; + if (de) + d = de; + else + d = grub_zalloc (sizeof (*d)); //分配内存, 并清零 - bios_drive_map[i].start_sector = start_sector; - //bios_drive_map[i].start_sector_hi = 0; /* currently only low 32 bits are used. */ - initrd_start_sector = start_sector; - - bios_drive_map[i].sector_count = sector_count;//(sector_count & 0xfffffffe) | fake_write | ! unsafe_boot; - //bios_drive_map[i].sector_count_hi = 0; /* currently only low 32 bits are used. */ +//填充磁盘数据 + d->drive = from; + d->to_drive = (unsigned char)to; + d->from_log2_sector = from_log2_sector; + d->to_log2_sector = buf_geom.log2_sector_size; + d->start_sector = start_sector; + ext_data_0 = start_sector; + d->sector_count = sector_count; + d->total_sectors = (filemax + (1 << from_log2_sector) - 1) >> from_log2_sector; + d->to_block_size = buf_geom.sector_size; + d->partmap_type = partmap_type; + d->fragment = (blklst_num_entries > 1); + d->read_only = read_only; +//printf ("from-8,%x,%x,%x,%x\n",from,to,current_drive,saved_drive); +//a0,ffff,7f,21; 60,ffff,ffff,21; +//a0,ffff,7f,21; 60,ffff,ffff,21; +//81,ffff,ffff.21; 82,ffff,7f,81; +#if VHD_DIFFERENCE + d->vhd_disk = vhd_disk; + if (vhd_file_name) + { + grub_free (vhd_file_name); + vhd_file_name = 0; + } +#endif + if (de) + return 1; - /* increase the floppies or harddrives if needed */ - if (from & 0x80) + d->next = 0; + if (d->drive >= 0xa0) + { + cdrom_orig++; + d->disk_type = DISK_TYPE_CD; + } + else if (d->drive >= 0x80) + { + harddrives_orig++; + d->disk_type = DISK_TYPE_HD; + } + else { - if (*((char *)0x475) == (char)(from - 0x80)) - { - *((char *)0x475) = (char)(from - 0x80 + 1); - if (debug > 0 && ! disable_map_info) - print_bios_total_drives(); - } - }else{ - if ((((*(char*)0x410) & 1)?((*(char*)0x410) >> 6) + 1 : 0) == ((char)from)) - { - *((char *)0x410) &= 0x3e; - *((char *)0x410) |= (((char)from) ? 0x41 : 1); - if (debug > 0 && ! disable_map_info) - print_bios_total_drives(); - } + floppies_orig++; + d->disk_type = DISK_TYPE_FD; } - return 1; - -delete_drive_map_slot: - -// if (bios_drive_map[i].to_drive == 0xFF && !(bios_drive_map[i].to_cylinder & 0x4000)) -// for (j = DRIVE_MAP_SIZE - 1; j > i ; j--) -// { -// if (bios_drive_map[j].to_drive == 0xFF && !(bios_drive_map[j].to_cylinder & 0x4000)) -// { -// if (mem == -1) -// return ! (errnum = ERR_DEL_MEM_DRIVE); -// else /* force delete all subsequent MEM map slots */ -// grub_memmove ((char *) &bios_drive_map[j], (char *) &bios_drive_map[j + 1], sizeof (struct drive_map_slot) * (DRIVE_MAP_SIZE - j)); -// } -// } - - grub_memmove ((char *) &bios_drive_map[i], (char *) &bios_drive_map[i + 1], sizeof (struct drive_map_slot) * (DRIVE_MAP_SIZE - i)); - if ((hooked_drive_map[i].to_cylinder & (1 << 10)) != 0) - { - p = (char *)&hooked_fragment_map; - filename = p + FRAGMENT_MAP_SLOT_SIZE; - p = fragment_map_slot_find(p, from); - if (p) - { - void *start = filename - *(unsigned short *)p; - int len = *(unsigned short *)p; - grub_memmove (p, p + *(unsigned short *)p, filename - p - *(unsigned short *)p); - grub_memset (start, 0, len); - } - } + if (!disk_data) //网起时如果没有硬盘则为零,会引起错误。 + disk_data = d; + d1 = disk_data; - if (mem != -1ULL) - grub_close (); - -#undef BS + if (d1 != d) + { + for (; d1->next; d1 = d1->next); + d1->next = d; + } - /* Search for the Max floppy drive number in the drive map table. */ - from = 0; - for (i = 0; i < DRIVE_MAP_SIZE; i++) - { - if (drive_map_slot_empty (bios_drive_map[i])) - break; - if (! (bios_drive_map[i].from_drive & 0xE0) && from < bios_drive_map[i].from_drive + 1) - from = bios_drive_map[i].from_drive + 1; + if (d->drive >= 0x80) + { + //第三次读to驱动器,探测引导扇区 + add_part_data (d->drive); //填充分区数据 + //8. 安装虚拟磁盘 + if (!no_hook) + { + current_drive = d->drive; + part_data = get_boot_partition (current_drive); + if (!part_data) + return (int)(!(errnum = ERR_NO_DISK)); + current_partition = part_data->partition; + status = vdisk_install (current_drive, current_partition); //安装虚拟磁盘 + if (status != GRUB_EFI_SUCCESS) //如果安装失败 + { + printf_errinfo ("Failed to install vdisk.(%d)\n",(int)status); //未能安装vdisk + return 0; + } } + } +//printf ("from-9,%x,%x,%x,%x\n",from,to,current_drive,saved_drive); +//; 60,ffff,ffff,21; a0,ffff,a0,21; +//; 60,ffff,ffff,21; a0,ffff,a0,21; +//81,ffff,ffff.21; 82,ffff,82,81; +//getkey(); + map_pd = 0; + return 1; - /* max possible floppies that can be handled in BIOS Data Area is 4 */ - if (from > 4) - from = 4; - if (from <= ((floppies_orig & 1) ? (floppies_orig >> 6) + 1 : 0)) - if ((((*(char*)0x410) & 1) ? ((*(char*)0x410) >> 6) + 1 : 0) > ((floppies_orig & 1) ? (floppies_orig >> 6) + 1 : 0)) - { - /* decrease the floppies */ - (*(char*)0x410) = floppies_orig; - if (debug > 0) - print_bios_total_drives(); - } - - /* Search for the Max hard drive number in the drive map table. */ - from = 0; - for (i = 0; i < DRIVE_MAP_SIZE; i++) - { - if (drive_map_slot_empty (bios_drive_map[i])) - break; - if ((bios_drive_map[i].from_drive & 0xE0) == 0x80 && from < bios_drive_map[i].from_drive - 0x80 + 1) - from = bios_drive_map[i].from_drive - 0x80 + 1; - } +fail_close_free: + grub_close (); - if (from <= harddrives_orig) - if ((*(char*)0x475) > harddrives_orig) +fail_free: + if (cache) + grub_free (cache); +#if VHD_DIFFERENCE + if (vhd_file_name) { - /* decrease the harddrives */ - (*(char*)0x475) = harddrives_orig; - if (debug > 0) - print_bios_total_drives(); + grub_free (vhd_file_name); + vhd_file_name = 0; } - - return 1; +#endif + return 0; } static struct builtin builtin_map = @@ -11442,33 +8700,29 @@ static struct builtin builtin_map = "map", map_func, BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST | BUILTIN_IFTITLE, - "map [--status[-byte]] [--mem[=RESERV]] [--hook] [--unhook] [--unmap=DRIVES]\n [--rehook] [--floppies=M] [--harddrives=N] [--memdisk-raw=RAW]\n [--a20-keep-on=AKO] [--safe-mbr-hook=SMH] [--int13-scheme=SCH]\n [--ram-drive=RD] [--rd-base=ADDR] [--rd-size=SIZE] [[--read-only]\n [--fake-write] [--unsafe-boot] [--disable-chs-mode] [--disable-lba-mode]\n [--heads=H] [--sectors-per-track=S] [--swap-drivs=DRIVE1=DRIVE2] [--in-situ=FLAGS_AND_ID] TO_DRIVE FROM_DRIVE]", - "Map the drive FROM_DRIVE to the drive TO_DRIVE. This is necessary" - " when you chain-load some operating systems, such as DOS, if such an" - " OS resides at a non-first drive. TO_DRIVE can be a disk file, this" - " indicates a disk emulation." + "map [--status[-byte]] [--mem] [--top] [--no-hook] [--unmap=DRIVES] [--ram-drive=RD]\n [--rd-base=ADDR] [--rd-size=SIZE] [--read-only] TO_DRIVE FROM_DRIVE", + "Map the drive FROM_DRIVE to the drive TO_DRIVE." + "\nTO_DRIVE can be a disk file, this indicates a disk emulation." "\nIf --read-only is given, the emulated drive will be write-protected." - "\nIf --fake-write is given, any write operations to the emulated drive are allowed but the data" - " written will be discarded." - "\nThe --unsafe-boot switch enables the write to the Master and DOS boot sectors of the emulated disk." - "\nIf --disable-chs-mode is given, CHS access to the emulated drive will be refused." - "\nIf --disable-lba-mode is given, LBA access to the emulated drive will be refused." - "\nIf RAW=1, all memdrives will be accessed without using int15/ah=87h." - "\nIf RAW=0, then int15/ah=87h will be used to access memdrives." - "\nIf one of --status, --hook, --unhook, --rehook, --floppies, --harddrives, --memdisk-raw, --a20-keep-on, --safe-mbr-hook, --int13-scheme," - " --ram-drive, --rd-base or --rd-size is given, then any other command-line arguments will be ignored." + "\nIf one of --status, --ram-drive, --rd-base or --rd-size is given,\n" + " then any other command-line arguments will be ignored." "\nThe --mem option indicates a drive in memory(0-4Gb)." "\nThe --mem --top option indicates a drive in memory(>4Gb)." - "\nif RESERV is used and <= 0, the minimum memory occupied by the memdrive is (-RESERV) in 512-byte-sectors." - "\nif RESERV is used and > 0,the memdrive will occupy the mem area starting at absolute physical address RESERV in 512-byte-sectors and ending at the end of this mem" + "\nThe --no-hook option indicates FROM_DRIVE is not mounted to UEFI firmware." + "\nif RESERV is used and <= 0, the minimum memory occupied by the memdrive\n" + " is (-RESERV) in 512-byte-sectors." + "\nif RESERV is used and > 0,the memdrive will occupy the mem area starting\n" + " at absolute physical address RESERV in 512-byte-sectors and ending at the end of this mem" "\nIf --swap-drivs=DRIVE1=DRIVE2 is given, swap DRIVE1 and DRIVE2 for FROM_DRIVE." " block(usually the end of physical mem)." - "\nIf --in-situ=FLAGS_AND_ID is given, the low byte is FLAGS(default 0) and the high byte is partition type ID(use 0xnnnn to specify)." + "\nIf --in-situ=FLAGS_AND_ID is given, the low byte is FLAGS(default 0) and the high byte\n" + " is partition type ID(use 0xnnnn to specify)." }; - + #ifdef USE_MD5_PASSWORDS /* md5crypt */ +static int md5crypt_func (char *arg, int flags); static int md5crypt_func (char *arg, int flags) { @@ -11488,7 +8742,10 @@ md5crypt_func (char *arg, int flags) grub_memmove (crypted, "$1$", 3); /* Create the length of a salt. */ - seed = *(unsigned int *)0x46C; +// seed = *(unsigned int *)0x46C; //0x46C是DOS系统的时间滴答 1滴答= 1/18.2秒 此处一般为零。 + struct grub_datetime datetime; + get_datetime (&datetime); + seed = (datetime.day << 24) | (datetime.hour << 16) | (datetime.minute << 8) | datetime.second; /* Generate a salt. */ for (i = 0; i < 8 && seed; i++) @@ -11533,6 +8790,7 @@ static struct builtin builtin_md5crypt = "Generate a password in MD5 format." }; +static int crc32_func(char *arg, int flags); static int crc32_func(char *arg, int flags) { int crc = grub_crc32(arg,0); @@ -11550,8 +8808,9 @@ static struct builtin builtin_crc32 = }; #endif /* USE_MD5_PASSWORDS */ - + /* module */ +static int module_func (char *arg, int flags); static int module_func (char *arg, int flags) { @@ -11561,7 +8820,8 @@ module_func (char *arg, int flags) switch (kernel_type) { case KERNEL_TYPE_MULTIBOOT: - if (mb_cmdline + len + 1 > (char *) MB_CMDLINE_BUF + MB_CMDLINE_BUFLEN) +// if (mb_cmdline + len + 1 > (char *) MB_CMDLINE_BUF + MB_CMDLINE_BUFLEN) + if (len + 1 > MB_CMDLINE_BUFLEN) { errnum = ERR_WONT_FIT; return 0; @@ -11599,8 +8859,9 @@ static struct builtin builtin_module = " the `kernel' command." }; - + /* modulenounzip */ +static int modulenounzip_func (char *arg, int flags); static int modulenounzip_func (char *arg, int flags) { @@ -11618,8 +8879,9 @@ static struct builtin builtin_modulenounzip = }; #ifdef SUPPORT_GRAPHICS - +#if 0 /* outline [on | off | status] */ +static int outline_func (char *arg, int flags); static int outline_func (char *arg, int flags) { @@ -11650,10 +8912,12 @@ static struct builtin builtin_outline = "outline [on | off | status]", "Turn on/off or display the outline mode, or toggle it if no argument." }; +#endif #endif /* SUPPORT_GRAPHICS */ - + /* pager [on|off] */ +static int pager_func (char *arg, int flags); static int pager_func (char *arg, int flags) { @@ -11688,61 +8952,67 @@ static struct builtin builtin_pager = "Turn on/off or display the pager mode, or toggle it if no argument." }; - /* Convert a LBA address to a CHS address in the INT 13 format. */ +void lba_to_chs (unsigned int lba, unsigned int *cl, unsigned int *ch, unsigned int *dh); void -lba_to_chs (unsigned long lba, unsigned long *cl, unsigned long *ch, unsigned long *dh) +lba_to_chs (unsigned int lba, unsigned int *cl, unsigned int *ch, unsigned int *dh) { - unsigned long cylinder, head, sector; - - sector = lba % buf_geom.sectors + 1; - head = (lba / buf_geom.sectors) % buf_geom.heads; - cylinder = lba / (buf_geom.sectors * buf_geom.heads); - - if (cylinder > 0x3FF) - cylinder = 0x3FF; + unsigned int cylinder, head, sector; - if (cylinder >= buf_geom.cylinders) - cylinder = buf_geom.cylinders - 1; - - *cl = sector | ((cylinder & 0x300) >> 2); - *ch = cylinder & 0xFF; - *dh = head; + if (lba >= 0xfb03ff) //如果超过8GB,则应将1023、254、63用于CHS。issues#374 + { + sector = 63; + head = 254; + cylinder = 1023; + } + else + { + sector = lba % 0x3f + 1; + head = (lba / 0x3f) % 0xff; + cylinder = lba / (0x3f * 0xff); + + if (cylinder > 0x3FF) + cylinder = 0x3FF; + } + *cl = sector | ((cylinder & 0x300) >> 2); + *ch = cylinder & 0xFF; + *dh = head; } - + /* partnew PART TYPE START LEN */ +static int partnew_func (char *arg, int flags); static int partnew_func (char *arg, int flags) { unsigned long long new_type, new_start, new_len; - unsigned long start_cl, start_ch, start_dh; - unsigned long end_cl, end_ch, end_dh; - unsigned long current_drive_bak; - unsigned long current_partition_bak; + unsigned int start_cl, start_ch, start_dh; + unsigned int end_cl, end_ch, end_dh; + unsigned int current_drive_bak; + unsigned int current_partition_bak; char *filename; - unsigned long entry1, i; - unsigned long active = -1; + unsigned int entry1, i; + unsigned int active = -1; + int force = 0; errnum = 0; +resume: if (grub_memcmp (arg, "--active", 8) == 0) { active = 0x80; arg = skip_to (0, arg); + goto resume; + } + if (grub_memcmp (arg, "--force", 7) == 0) + { + force = 1; + arg = skip_to (0, arg); + goto resume; } /* Get the drive and the partition. */ if (! set_device (arg)) return 0; -#if 0 - /* The drive must be a hard disk. */ - if (! (current_drive & 0x80)) - { - errnum = ERR_BAD_ARGUMENT; - return 0; - } -#endif - entry1 = current_partition >> 16; /* The partition must a primary partition. */ @@ -11815,14 +9085,14 @@ partnew_func (char *arg, int flags) if (new_start == part_start && part_start && new_len == 1) new_len = part_length; - if (new_start < part_start || new_start + new_len > (unsigned long)(part_start + part_length)) + if (new_start < part_start || new_start + new_len > (unsigned int)(part_start + part_length)) { printf_debug0 ("Cannot create a partition that exceeds the partition boundary.\n"); return ! (errnum = ERR_BAD_ARGUMENT); } /* Read the first sector. */ - if (! rawread (current_drive, new_start, 0, SECTOR_SIZE, (unsigned long long)(unsigned int)mbr, 0xedde0d90)) + if (! rawread (current_drive, new_start, 0, SECTOR_SIZE, (unsigned long long)(grub_size_t)mbr, 0xedde0d90)) return 0; #define BS ((struct master_and_dos_boot_sector *)mbr) @@ -11855,7 +9125,7 @@ partnew_func (char *arg, int flags) printf_debug0 ("Changing hidden sectors 0x%X to 0x%lX... ", BS->hidden_sectors, (unsigned long long)new_start); BS->hidden_sectors = new_start; /* Write back/update the boot sector. */ - if (! rawwrite (current_drive, new_start, (unsigned long long)(unsigned int)mbr)) + if (! rawwrite (current_drive, new_start, (unsigned long long)(grub_size_t)mbr)) { printf_debug0 ("failure.\n"); return 0; @@ -11869,23 +9139,12 @@ partnew_func (char *arg, int flags) current_drive = current_drive_bak; current_partition = current_partition_bak; } -#if 0 - else - { - /* this command is intended for running in command line and inhibited from running in menu.lst */ - if (flags & (BUILTIN_MENU | BUILTIN_SCRIPT)) - { - printf_debug0 ("This form of partnew is inhibited from running in a script.\n"); - return ! (errnum = ERR_BAD_ARGUMENT); - } - } -#endif /* Read the MBR. */ - if (! rawread (current_drive, 0, 0, SECTOR_SIZE, (unsigned long long)(unsigned int)mbr, 0xedde0d90)) + if (! rawread (current_drive, 0, 0, SECTOR_SIZE, (unsigned long long)(grub_size_t)mbr, 0xedde0d90)) return 0; - if (current_drive_bak) /* creating a partition from a file */ + if (current_drive_bak && !force) /* creating a partition from a file */ { /* if the entry is not empty, it should be a part of another * partition, that is, it should be covered by another partition. */ @@ -11905,115 +9164,325 @@ partnew_func (char *arg, int flags) if (i >= 4) { /* not found */ - printf_debug0 ("Cannot overwrite an independent partition.\n"); + printf_debug0 ("Cannot overwrite an independent partition. Can use the parameter '--force' to enforce\n"); return ! (errnum = ERR_BAD_ARGUMENT); } } } -#if 0 - /* Do not check this. The total_sectors might be too small - * for some buggy BIOSes. */ - /* Check if the new partition will fit in the disk. */ - if (new_start + new_len > buf_geom.total_sectors) + if (new_type == 0 && new_start == 0 && new_len == 0) + { + /* empty the entry */ + start_dh = start_cl = start_ch = end_dh = end_cl = end_ch = 0; + }else{ + if (new_start == 0 || new_len == 0) { - errnum = ERR_GEOM; + errnum = ERR_BAD_PART_TABLE; return 0; } -#endif + /* Store the partition information in the MBR. */ + lba_to_chs (new_start, &start_cl, &start_ch, &start_dh); + lba_to_chs (new_start + new_len - 1, &end_cl, &end_ch, &end_dh); + } - if (new_type == 0 && new_start == 0 && new_len == 0) + if (active == 0x80) + { + /* Activate this partition */ + PC_SLICE_FLAG (mbr, entry1) = 0x80; + } else { + if (PC_SLICE_FLAG (mbr, entry1) != 0x80) + PC_SLICE_FLAG (mbr, entry1) = 0; + } + + /* Deactivate other partitions */ + if (PC_SLICE_FLAG (mbr, entry1) == 0x80) + { + for (i = 0; i < 4; i++) + { + if (i == entry1) + continue; + if (PC_SLICE_FLAG (mbr, i) != 0) + { + if (debug > 0) + { + if (PC_SLICE_FLAG (mbr, i) == 0x80) + { + grub_printf ("The active flag(0x80) of partition %d was changed to 0.\n", (unsigned int)i); + } else { + grub_printf ("The invalid active flag(0x%X) of partition %d was changed to 0.\n", (unsigned int)(PC_SLICE_FLAG (mbr, i)), (unsigned int)i); + } + } + + PC_SLICE_FLAG (mbr, i) = 0; + } + } + } + PC_SLICE_HEAD (mbr, entry1) = start_dh; + PC_SLICE_SEC (mbr, entry1) = start_cl; + PC_SLICE_CYL (mbr, entry1) = start_ch; + PC_SLICE_TYPE (mbr, entry1) = new_type; + PC_SLICE_EHEAD (mbr, entry1) = end_dh; + PC_SLICE_ESEC (mbr, entry1) = end_cl; + PC_SLICE_ECYL (mbr, entry1) = end_ch; + PC_SLICE_START (mbr, entry1) = new_start; + PC_SLICE_LENGTH (mbr, entry1) = new_len; + + /* Make sure that the MBR has a valid signature. */ + PC_MBR_SIG (mbr) = PC_MBR_SIGNATURE; + + /* Write back the MBR to the disk. */ + buf_track = -1; + if (! rawwrite (current_drive, 0, (unsigned long long)(grub_size_t)mbr)) + return 0; + + if (new_type == 0 && new_start == 0 && new_len == 0) //删除分区 2023-03-26 + { + struct grub_part_data *p, *p_previous = 0; + for (p = partition_info; p; p_previous = p, p = p->next) + { + if (p->drive != current_drive || p->partition != current_partition) + continue; + + if (p == partition_info) //首位 + { + if (p->next == 0) + partition_info = 0; + else + partition_info = p->next; + } + else if (p_previous) //其他 + p_previous->next = p->next; + } + } + else + add_part_data (current_drive); //使立即生效 2023-03-26 + return 1; +} + +static struct builtin builtin_partnew = +{ + "partnew", + partnew_func, + BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_MENU | BUILTIN_HELP_LIST | BUILTIN_NO_DECOMPRESSION, + "partnew [--active] [--force] PART TYPE START [LEN]", + "Create a primary partition at the starting address START with the" + " length LEN, with the type TYPE. START and LEN are in sector units." + " If --active is used, the new partition will be active." + " If --force is used, can overwrite an independent partition. START can be" + " a contiguous file that will be used as the content/data of the new" + " partition, in which case the LEN parameter is ignored, and TYPE can" + " be either 0x00 for auto or 0x10 for hidden-auto." +}; + +#define GPT_ATTRIBUTE_NO_DRIVE_LETTER (0x8000000000000000LL) +#define GPT_ATTRIBUTE_HIDDEN (0x4000000000000000LL) +#define GPT_ATTRIBUTE_SHADOW_COPY (0x2000000000000000LL) +#define GPT_ATTRIBUTE_READ_ONLY (0x1000000000000000LL) +#define GPT_ATTR_HIDE (0xC000000000000001LL) +#define GPT_HDR_SIZE (0x5C) +static int gpt_set_crc(P_GPT_HDR hdr) +{ +// char data[SECTOR_SIZE]; + char *data = grub_malloc (SECTOR_SIZE); + int crc; + int errnum_bak = errnum; + + if (hdr->hdr_size != GPT_HDR_SIZE) + return 0; + errnum = 0; + sprintf(data,"(0x%X)0x%lx+%u,%u",current_drive,hdr->hdr_lba_table,32,hdr->hdr_entries * hdr->hdr_entsz); + crc = grub_crc32(data,0); + if (errnum) + { + grub_free (data); + return 0; + } + grub_free (data); + hdr->hdr_crc_table = crc; + hdr->hdr_crc_self = 0; + crc = grub_crc32((char*)hdr,GPT_HDR_SIZE); + if (errnum) + return 0; + hdr->hdr_crc_self = crc; + buf_track = -1; + if (! rawread (current_drive, hdr->hdr_lba_self ,0,GPT_HDR_SIZE, (unsigned long long)(grub_size_t)hdr, GRUB_WRITE)) + return 0; + errnum = errnum_bak; + return hdr->hdr_crc_table; +} + +static int gpt_set_attr(P_GPT_HDR hdr,grub_u32_t part,grub_u64_t attr) +{ +// GPT_ENT ent; + GPT_ENT *ent = grub_malloc (sizeof(GPT_ENT)); +// if (! rawread (current_drive, hdr->hdr_lba_table + (part >> 2), (part & 3) * sizeof(GPT_ENT), sizeof(GPT_ENT), (unsigned long long)(grub_size_t)&ent, GRUB_READ)) + if (! rawread (current_drive, hdr->hdr_lba_table + (part >> 2), (part & 3) * sizeof(GPT_ENT), sizeof(GPT_ENT), (unsigned long long)(grub_size_t)ent, GRUB_READ)) + { + grub_free (ent); + return 0; + } + + if (attr & 0xFF00) +// ent.ms_attr.gpt_att = (unsigned short)attr; + ent->ms_attr.gpt_att = (unsigned short)attr; + else +// ent.attributes = attr; + ent->attributes = attr; + + buf_track = -1; +// if (! rawread (current_drive, hdr->hdr_lba_table + (part >> 2), (part & 3) * sizeof(GPT_ENT), sizeof(GPT_ENT), (unsigned long long)(grub_size_t)&ent, GRUB_WRITE)) + if (! rawread (current_drive, hdr->hdr_lba_table + (part >> 2), (part & 3) * sizeof(GPT_ENT), sizeof(GPT_ENT), (unsigned long long)(grub_size_t)ent, GRUB_WRITE)) + { + grub_free (ent); + return 0; + } + + grub_free (ent); + return gpt_set_crc(hdr); +} + +static unsigned int gpt_slic_set_attr(grub_u32_t part,grub_u64_t attr) +{ +// char data[SECTOR_SIZE]; + char *data = grub_malloc (SECTOR_SIZE); + int crc1,crc2; + if (! rawread (current_drive, 1, 0, sizeof(GPT_HDR), (unsigned long long)(grub_size_t)data, GRUB_READ)) + { + grub_free (data); + return 0; + } + P_GPT_HDR hdr = (P_GPT_HDR)data; + crc1 = gpt_set_attr(hdr,part,attr); + if (!crc1) + { + grub_free (data); + return 0; + } + if (! rawread (current_drive, hdr->hdr_lba_alt, 0, sizeof(GPT_HDR), (unsigned long long)(grub_size_t)data, GRUB_READ)) + { + grub_free (data); + return 0; + } + grub_free (data); + crc2 = gpt_set_attr(hdr,part,attr); + if (!crc2) + return 0; + if (debug > 1 && crc1 != crc2) + printf("Warning! Main partition table CRC mismatch!"); + return 1; +} + +static unsigned long long gpt_slic_get_attr(char *data,unsigned int part) +{ + P_GPT_ENT p = (P_GPT_ENT)data; + return p->attributes; +} + +/* Hide/Unhide CURRENT_PARTITION. */ +static int +set_partition_hidden_flag (int hidden) +{ + struct grub_part_data *q; + +#if 0 + /* The drive must be a hard disk. */ + if (! (current_drive & 0x80)) + { + errnum = ERR_BAD_ARGUMENT; + return 0; + } +#endif + + /* The partition must be a PC slice. */ + if ((current_partition >> 16) == 0xFF + || (current_partition & 0xFFFF) != 0xFFFF) { - /* empty the entry */ - start_dh = start_cl = start_ch = end_dh = end_cl = end_ch = 0; - }else{ - if (new_start == 0 || new_len == 0) - { - errnum = ERR_BAD_PART_TABLE; - return 0; - } - /* Store the partition information in the MBR. */ - lba_to_chs (new_start, &start_cl, &start_ch, &start_dh); - lba_to_chs (new_start + new_len - 1, &end_cl, &end_ch, &end_dh); + errnum = ERR_BAD_ARGUMENT; + return 0; } - if (active == 0x80) + q = get_partition_info (current_drive, current_partition); + if (!q) + return 0; + + int part_num = (unsigned int)(unsigned char)(q->partition>>16); + grub_u64_t part_attr = 0LL,is_hidden; + if (q->partition_type == PC_SLICE_TYPE_GPT) { - /* Activate this partition */ - PC_SLICE_FLAG (mbr, entry1) = 0x80; - } else { - if (PC_SLICE_FLAG (mbr, entry1) != 0x80) - PC_SLICE_FLAG (mbr, entry1) = 0; + part_attr = gpt_slic_get_attr(mbr,part_num); + is_hidden = !!(part_attr & GPT_ATTR_HIDE); + } + else + is_hidden = PC_SLICE_TYPE (mbr, q->partition_entry) & PC_SLICE_TYPE_HIDDEN_FLAG; + /* Found. */ + if (hidden == -1) /* status only */ + { + printf_debug0 ("Partition (%cd%d,%d) is %shidden.\n", + ((current_drive & 0x80) ? 'h' : 'f'), + (current_drive & ~0x80), + part_num, + (is_hidden ? "" : "not ")); + + return is_hidden; } - /* Deactivate other partitions */ - if (PC_SLICE_FLAG (mbr, entry1) == 0x80) + /* Check if the hidden flag need change. */ + if ((!hidden) != (!is_hidden)) { - for (i = 0; i < 4; i++) - { - if (i == entry1) - continue; - if (PC_SLICE_FLAG (mbr, i) != 0) - { - if (debug > 0) - { - if (PC_SLICE_FLAG (mbr, i) == 0x80) - { - grub_printf ("The active flag(0x80) of partition %d was changed to 0.\n", (unsigned long)i); - } else { - grub_printf ("The invalid active flag(0x%X) of partition %d was changed to 0.\n", (unsigned long)(PC_SLICE_FLAG (mbr, i)), (unsigned long)i); - } - } + if (q->partition_type == PC_SLICE_TYPE_GPT) + { + if (hidden) + part_attr |= GPT_ATTR_HIDE; + else + part_attr &= ~GPT_ATTR_HIDE; - PC_SLICE_FLAG (mbr, i) = 0; + if (!gpt_slic_set_attr(part_num,part_attr)) + return 0; + } + else + { + if (hidden) + PC_SLICE_TYPE (mbr, q->partition_entry) |= PC_SLICE_TYPE_HIDDEN_FLAG; + else + PC_SLICE_TYPE (mbr, q->partition_entry) &= ~PC_SLICE_TYPE_HIDDEN_FLAG; + + /* Write back the MBR to the disk. */ + buf_track = -1; + if (! rawwrite (current_drive, q->partition_offset, (unsigned long long)(grub_size_t)mbr)) + return 0; } - } - } - PC_SLICE_HEAD (mbr, entry1) = start_dh; - PC_SLICE_SEC (mbr, entry1) = start_cl; - PC_SLICE_CYL (mbr, entry1) = start_ch; - PC_SLICE_TYPE (mbr, entry1) = new_type; - PC_SLICE_EHEAD (mbr, entry1) = end_dh; - PC_SLICE_ESEC (mbr, entry1) = end_cl; - PC_SLICE_ECYL (mbr, entry1) = end_ch; - PC_SLICE_START (mbr, entry1) = new_start; - PC_SLICE_LENGTH (mbr, entry1) = new_len; - /* Make sure that the MBR has a valid signature. */ - PC_MBR_SIG (mbr) = PC_MBR_SIGNATURE; - - /* Write back the MBR to the disk. */ - buf_track = -1; - if (! rawwrite (current_drive, 0, (unsigned long long)(unsigned int)mbr)) - return 0; + printf_debug0 ("Partition (%cd%d,%d) successfully set %shidden.\n", + ((current_drive & 0x80) ? 'h' : 'f'), + (current_drive & ~0x80), + part_num, + (hidden ? "" : "un")); + } + else + { + printf_debug0 ("Partition (%cd%d,%d) was already %shidden.\n", + ((current_drive & 0x80) ? 'h' : 'f'), + (current_drive & ~0x80), + part_num, + (hidden ? "" : "un")); + } + + /* Succeed. */ return 1; } -static struct builtin builtin_partnew = -{ - "partnew", - partnew_func, - BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_MENU | BUILTIN_HELP_LIST | BUILTIN_NO_DECOMPRESSION, - "partnew [--active] PART TYPE START [LEN]", - "Create a primary partition at the starting address START with the" - " length LEN, with the type TYPE. START and LEN are in sector units." - " If --active is used, the new partition will be active. START can be" - " a contiguous file that will be used as the content/data of the new" - " partition, in which case the LEN parameter is ignored, and TYPE can" - " be either 0x00 for auto or 0x10 for hidden-auto." -}; - + /* parttype PART TYPE */ static int parttype_func (char *arg, int flags) { unsigned long long new_type = -1; - unsigned long part = 0xFFFFFF; - unsigned long long start, len, offset; - unsigned long type, entry1, ext_offset1; - +// unsigned int part = 0xFFFFFF; +// unsigned long long start, len, offset; +// unsigned int type, entry1, ext_offset1; + struct grub_part_data *q; /* Get the drive and the partition. */ errnum = 0; @@ -12021,13 +9490,16 @@ parttype_func (char *arg, int flags) { current_drive = saved_drive; current_partition = saved_partition; - } else if (! set_device (arg)) + } + else if (! set_device (arg)) { if (! safe_parse_maxint (&arg, &new_type)) return 0; current_drive = saved_drive; current_partition = saved_partition; - } else { + } + else + { /* Get the new partition type. */ arg = skip_to (0, arg); if (*arg && *arg != ' ' && *arg != '\t') @@ -12035,15 +9507,6 @@ parttype_func (char *arg, int flags) return 0; } -#if 0 - /* The drive must be a hard disk. */ - if (! (current_drive & 0x80)) - { - errnum = ERR_BAD_ARGUMENT; - return 0; - } -#endif - /* The partition must be a PC slice. */ if ((current_partition >> 16) == 0xFF || (current_partition & 0xFFFF) != 0xFFFF) @@ -12052,38 +9515,27 @@ parttype_func (char *arg, int flags) return 0; } - /* Look for the partition. */ - while (( next_partition_drive = current_drive, - next_partition_dest = current_partition, - next_partition_partition = &part, - next_partition_type = &type, - next_partition_start = &start, - next_partition_len = &len, - next_partition_offset = &offset, - next_partition_entry = &entry1, - next_partition_ext_offset = &ext_offset1, - next_partition_buf = mbr, - next_partition ())) - { - if (part == current_partition) - { - /* Found. */ - + rawread (current_drive, 0, 0, SECTOR_SIZE, (unsigned long long)(grub_size_t)mbr, 0xedde0d90); //mbr可能存储的是其他分区信息,必需更新一下。2022-11-29 + q = get_partition_info (current_drive, current_partition); + if (!q) + return 0; + errnum = 0; if (new_type == -1) /* return the current type */ { - new_type = (type == PC_SLICE_TYPE_GPT)?0xEE:PC_SLICE_TYPE (mbr, entry1); +// new_type = (q->partition_type == PC_SLICE_TYPE_GPT)?0xEE:PC_SLICE_TYPE (mbr, q->partition_entry); + new_type = q->partition_type; if (debug > 0) printf ("Partition type for (%cd%d,%d) is 0x%02X.\n", ((current_drive & 0x80) ? 'h' : 'f'), (current_drive & ~0x80), - (unsigned long)(unsigned char)(current_partition >> 16), - (unsigned long)new_type); + (unsigned int)(unsigned char)(current_partition >> 16), + (unsigned int)new_type); return new_type; } - if (type == PC_SLICE_TYPE_GPT) /* set gpt partition attributes*/ - return gpt_slic_set_attr(part>>16,new_type); + if (q->partition_type == PC_SLICE_TYPE_GPT) /* set gpt partition attributes*/ + return gpt_slic_set_attr(q->partition>>16,new_type); /* The partition type is unsigned char. */ if (new_type > 0xFF) @@ -12092,27 +9544,22 @@ parttype_func (char *arg, int flags) return 0; } /* Set the type to NEW_TYPE. */ - PC_SLICE_TYPE (mbr, entry1) = new_type; - + PC_SLICE_TYPE (mbr, q->partition_entry) = new_type; + /* Write back the MBR to the disk. */ buf_track = -1; - if (! rawwrite (current_drive, offset, (unsigned long long)(unsigned int)mbr)) - break; /* failure */ + if (! rawwrite (current_drive, q->partition_offset, (unsigned long long)(grub_size_t)mbr)) + return 0; /* failure */ if (debug > 0) printf ("Partition type for (%cd%d,%d) set to 0x%02X successfully.\n", ((current_drive & 0x80) ? 'h' : 'f'), (current_drive & ~0x80), - (unsigned long)(unsigned char)(current_partition >> 16), - (unsigned long)new_type); + (unsigned int)(unsigned char)(current_partition >> 16), + (unsigned int)new_type); /* Succeed. */ errnum = 0; return 1; - } - } - - /* The partition was not found. ERRNUM was set by next_partition. */ - return 0; } static struct builtin builtin_parttype = @@ -12126,8 +9573,8 @@ static struct builtin builtin_parttype = "default to the current root device." }; - /* password */ +static int password_func (char *arg, int flags); static int password_func (char *arg, int flags) { @@ -12150,19 +9597,6 @@ password_func (char *arg, int flags) if ((flags & (BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_BAT_SCRIPT)) != 0) { -#if 0 - /* Do password check! */ - char entered[32]; - - /* Wipe out any previously entered password */ - entered[0] = 0; - get_cmdline_str.prompt = msg_password; - get_cmdline_str.maxlen = sizeof (entered) - 1; - get_cmdline_str.echo_char = '*'; - get_cmdline_str.readline = 0; - get_cmdline_str.cmdline = entered; - get_cmdline (); -#endif nul_terminate (arg); if ((len = check_password (arg, type)) != 0) { @@ -12175,7 +9609,7 @@ password_func (char *arg, int flags) len = grub_strlen (arg); /* PASSWORD NUL NUL ... */ - if (len + 2 > sizeof (password_str)/* PASSWORD_BUFLEN */) + if (len + 2 > (int)sizeof (password_str)/* PASSWORD_BUFLEN */) { errnum = ERR_WONT_FIT; return 0; @@ -12207,8 +9641,9 @@ static struct builtin builtin_password = " md5crypt." }; - + /* pause */ +static int pause_func (char *arg, int flags); static int pause_func (char *arg, int flags) { @@ -12242,25 +9677,24 @@ pause_func (char *arg, int flags) /* Get current time. */ int ret = 1; while ((time2 = getrtsecs ()) == 0xFF); - while (wait != 0) + while (wait != 0) { /* Check if there is a key-press. */ - if (checkkey () != -1) + if ((ret = checkkey ()) != (int)-1) { - ret = getkey (); if (testkey) { printf_debug0("%04x",ret); return ret; } - ret &= 0xFF; +// ret &= 0xFF; /* Check the special ESC key */ - if (ret == '\e') + if ((unsigned short)ret == 0x011b) return 0; /* abort this entry */ break; } - if (wait != -1 && (time1 = getrtsecs ()) != time2 && time1 != 0xFF) + if (wait != (unsigned long long)-1 && (time1 = getrtsecs ()) != time2 && time1 != 0xFF) { printf_debug0("\t%d\t\r",wait); time2 = time1; @@ -12280,7 +9714,7 @@ static struct builtin builtin_pause = "--test-key display keyboard code." }; - +#if 1 #ifdef FSYS_PXE /* pxe */ static struct builtin builtin_pxe = @@ -12288,9 +9722,14 @@ static struct builtin builtin_pxe = "pxe", pxe_func, BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST | BUILTIN_BOOTING | BUILTIN_IFTITLE, - "pxe [cmd] [parameters]", - "Call PXE command." + "pxe #Return network interface information.\n", + "pxe init #Enable network functionality.\n" + "pxe open /path/file #Open files.\n" + "pxe read /path/file range_start - range_end #Read files." }; +#endif +#endif +#if 0 #ifdef FSYS_IPXE /* pxe */ static struct builtin builtin_ipxe = @@ -12304,104 +9743,8 @@ static struct builtin builtin_ipxe = #endif #endif - -/* quit */ -static int -quit_func (char *arg, int flags) -{ - unsigned long i; - register long Sum; - - errnum = 0; - /* check if we were launched from DOS. */ - if (*(long *)0x2A0000 != 0x50554B42) /* "BKUP" */ - { - return ! (errnum = ERR_DOS_BACKUP); - } - - for (i = 0, Sum = 0; i < (0xA0000 + 16) / 4; i++) - { - Sum += *(long *)(0x200000 + (i << 2)); - } - - if (Sum) - return ! (errnum = ERR_DOS_BACKUP); - - chainloader_disable_A20 = 0; - //grub_memmove((char *)0x110000, (char *)0x200000, 0xA0000); - - for (;;) - { - if (grub_memcmp (arg, "--disable-a20", 13) == 0) - { - chainloader_disable_A20 = 1; - } - else - break; - arg = skip_to (0, arg); - } - chain_load_segment = 0; - chain_load_offset = 0; - chain_boot_CS = *(unsigned short*)(0x2A0000 + 10); - chain_boot_IP = *(unsigned short*)(0x2A0000 + 8); - chain_load_length = 0xA0000; - chain_ebx = 0; - chain_ebx_set = 0; - chain_edx = 0; - chain_edx_set = 0; - chain_bx = 0; - chain_bx_set = 0; - chain_cx = 0; - chain_cx_set = 0; - chain_enable_gateA20 = ((*(short *)(0x2A0000 + 4)) != 0); - if (chainloader_disable_A20) - chain_enable_gateA20 = 0; - - /* move the code to a safe place at 0x2B0000 */ - grub_memmove((char *)HMA_ADDR, HMA_start, 0x200/*0xfff0*/); - - /* Turn off A20 here if the DOS image told us to do so. Note: we won't have - * access to the odd megas of the memory when A20 is off. - */ - if (!chain_enable_gateA20) - { - if (gateA20 (0)) - { - printf_debug0("\nGate A20 is turned off successfully.\n"); - } - else { - /* to asure A20 is on when we return to grub. */ - gateA20 (1); /* turn on A20 in case it is off */ - if (chainloader_disable_A20) - return ! (errnum = ERR_DISABLE_A20); - else - { - printf_debug0("\nFailed to turn off Gate A20!\n"); - chain_enable_gateA20 = 1; - } - } - } - - /* Jump to high memory area. This will move boot code at - * 0x110000 to the destination load-segment:load-offset; - * setup edx and ebx registers; switch to real mode; - * and jump to boot-cs:boot-ip. - */ - ((void (*)(void))HMA_ADDR)(); /* no return */ - - return 0; -} - -static struct builtin builtin_quit = -{ - "quit", - quit_func, - BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST | BUILTIN_BOOTING, - "quit [--disable-a20]", - "Go back to DOS if GRUB was previously launched from DOS." -}; - #ifndef NO_DECOMPRESSION +static int raw_func(char *arg, int flags); static int raw_func(char *arg, int flags) { return run_line(arg,flags); @@ -12417,33 +9760,49 @@ static struct builtin builtin_raw = }; #endif +static int read_func (char *arg, int flags); static int read_func (char *arg, int flags) { unsigned long long addr, val; - int bytes=0; + int bytes=0, mem=0; errnum = 0; - if (*(long *)arg == 0x2E524156)//VAR. + if (*(int *)arg == 0x2E524156)//VAR. {//for Fast access to system variables.(defined in asm.s) - arg += sizeof(long); + arg += sizeof(int); if (! safe_parse_maxint (&arg, &addr)) return 0; - return (*(long **)0x8304)[addr]; + return (*(grub_size_t **)IMG(0x8308))[addr]; } + + for (;;) + { if (grub_memcmp (arg, "--8", 3) == 0) { bytes=1; arg += 3; - arg = skip_to (0, arg); } + else if (grub_memcmp (arg, "--mem", 5) == 0) + { + mem=1; //强制使用普通内存,否则0x8200-0x8400(不含)特指G4E头部固定数据区。 + arg += 5; + } + else + break; + arg = skip_to (0, arg); + } + if (! safe_parse_maxint (&arg, &addr)) return 0; + if (!mem && addr >= 0x8200 && addr < 0x8400) + addr += (grub_size_t)g4e_data - 0x8200; + if (!bytes) - val = *(unsigned long *)(unsigned long)(RAW_ADDR (addr)); + val = *(unsigned int *)(grub_size_t)addr; else - val = *(unsigned long long *)(unsigned long)(RAW_ADDR (addr)); + val = *(unsigned long long *)(grub_size_t)addr; printf_debug0 ("Address 0x%lx: Value 0x%lx\n", addr, val); return val; } @@ -12453,22 +9812,21 @@ static struct builtin builtin_read = "read", read_func, BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST | BUILTIN_IFTITLE, - "read [--8] ADDR", - "Read a 32-bit or 64-bit value from memory at address ADDR and" - " display it in hex format." + "read [--8] [--mem] ADDR", + "Read a 32-bit or 64-bit value from memory at address ADDR and display it in hex format.\n" + "--mem Force normal memory, \n" + " otherwise, 0x8200-0x8400(not included) specifically refers to G4e head fixed data area." }; - +int parse_string (char *arg); int parse_string (char *arg) { int len; char *p; char ch; - //int quote; //nul_terminate (arg); - #if 1 for (len = 0,p = arg;(ch = *p);p++) { if (ch == '\\' && (ch = *++p)) @@ -12582,155 +9940,25 @@ parse_string (char *arg) len++; } - #else - for (quote = len = 0, p = arg; (ch = *p); p++) - { - if (ch == '\\') - { - if (quote) - { - *arg++ = ch; - len++; - quote = 0; - continue; - } - quote = 1; - continue; - } - if (quote) - { - if (ch == 't') - { - *arg++ = '\t'; - len++; - quote = 0; - continue; - } - if (ch == 'r') - { - *arg++ = '\r'; - len++; - quote = 0; - continue; - } - if (ch == 'n') - { - *arg++ = '\n'; - len++; - quote = 0; - continue; - } - if (ch == 'a') - { - *arg++ = '\a'; - len++; - quote = 0; - continue; - } - if (ch == 'b') - { - *arg++ = '\b'; - len++; - quote = 0; - continue; - } - if (ch == 'f') - { - *arg++ = '\f'; - len++; - quote = 0; - continue; - } - if (ch == 'v') - { - *arg++ = '\v'; - len++; - quote = 0; - continue; - } - if (ch >= '0' && ch <= '7') - { - /* octal */ - int val = ch - '0'; - if (p[1] >= '0' && p[1] <= '7') - { - val *= 8; - p++; - val += *p -'0'; - if (p[1] >= '0' && p[1] <= '7') - { - val *= 8; - p++; - val += *p -'0'; - } - } - *arg++ = val; - len++; - quote = 0; - continue; - } - if (ch == 'x') - { - /* hex */ - int val; - - p++; - ch = *p; - if (ch >= '0' && ch <= '9') - val = ch - '0'; - else if (ch >= 'A' && ch <= 'F') - val = ch - 'A' + 10; - else if (ch >= 'a' && ch <= 'f') - val = ch - 'a' + 10; - else - return len; /* error encountered */ - p++; - ch = *p; - if (ch >= '0' && ch <= '9') - val = val * 16 + ch - '0'; - else if (ch >= 'A' && ch <= 'F') - val = val * 16 + ch - 'A' + 10; - else if (ch >= 'a' && ch <= 'f') - val = val * 16 + ch - 'A' + 10; - else - p--; - *arg++ = val; - len++; - quote = 0; - continue; - } - if (ch) - { - *arg++ = ch; - len++; - quote = 0; - continue; - } - return len; - } - *arg++ = ch; - len++; - quote = 0; - } - #endif -// if (*arg) *arg = 0; return len; } +static int write_func (char *arg, int flags); static int write_func (char *arg, int flags) { unsigned long long addr; unsigned long long val; char *p; - unsigned long tmp_drive; - unsigned long tmp_partition; + unsigned int tmp_drive; + unsigned int tmp_partition; unsigned long long offset; unsigned long long len; unsigned long long bytes = 0; char tmp_file[16]; - //int block_file = 0; + int mem = 0; +// int block_file = 0; errnum = 0; tmp_drive = saved_drive; @@ -12739,19 +9967,24 @@ write_func (char *arg, int flags) for (;;) { if (grub_memcmp (arg, "--offset=", 9) == 0) - { - p = arg + 9; - if (! safe_parse_maxint (&p, &offset)) - return 0; - } + { + p = arg + 9; + if (! safe_parse_maxint (&p, &offset)) + return 0; + } else if (grub_memcmp (arg, "--bytes=", 8) == 0) { - p = arg + 8; - if (! safe_parse_maxint (&p, &bytes)) - return 0; + p = arg + 8; + if (! safe_parse_maxint (&p, &bytes)) + return 0; } + else if (grub_memcmp (arg, "--mem", 5) == 0) + { + mem = 1; + arg += 5; + } else - break; + break; arg = skip_to (0, arg); } @@ -12761,95 +9994,92 @@ write_func (char *arg, int flags) { /* destination is device or file. */ if (*arg == '(') - { - p = set_device (arg); - if (errnum) - goto fail; - if (! p) - { - if (errnum == 0) - errnum = ERR_BAD_ARGUMENT; - goto fail; - } - //if (*p != '/') - // block_file = 1; - saved_drive = current_drive; - saved_partition = current_partition; - /* if only the device portion is specified */ - if ((unsigned char)*p <= ' ') - { - p = tmp_file; - *p++ = '('; - *p++ = ')'; - *p++ = '+'; - *p++ = '1'; - *p = 0; - p = tmp_file; - grub_open (p); - if (errnum) - goto fail; - grub_sprintf (p + 3, "0x%lx", (unsigned long long)part_length); - grub_close (); - } - } - if (p != tmp_file) + { + p = set_device (arg); + if (errnum) + goto fail; + if (! p) + { + if (errnum == 0) + errnum = ERR_BAD_ARGUMENT; + goto fail; + } +// if (*p != '/') +// block_file = 1; + saved_drive = current_drive; + saved_partition = current_partition; + /* if only the device portion is specified */ + if ((unsigned char)*p <= ' ') + { + p = tmp_file; + *p++ = '('; + *p++ = ')'; + *p++ = '+'; + *p++ = '1'; + *p = 0; + p = tmp_file; + grub_open (p); + if (errnum) + goto fail; + grub_sprintf (p + 3, "0x%lx", (unsigned long long)part_length); + grub_close (); + } + } + if (p != tmp_file) p = arg; - grub_open (p); - current_drive = saved_drive; - current_partition = saved_partition; - if (errnum) - goto fail; - + grub_open (p); + current_drive = saved_drive; + current_partition = saved_partition; + if (errnum) + goto fail; #if 0 - if (current_drive != ram_drive && current_drive != 0xFFFF && block_file) - { - unsigned long j; + if (current_drive != ram_drive && current_drive != 0xFFFF && block_file) + { + unsigned int j; - /* check if it is a mapped memdrive */ - j = DRIVE_MAP_SIZE; /* real drive */ - if (! unset_int13_handler (1)) /* map is hooked */ - for (j = 0; j < DRIVE_MAP_SIZE; j++) - { - if (drive_map_slot_empty (hooked_drive_map[j])) - { - j = DRIVE_MAP_SIZE; /* real drive */ - break; - } + /* check if it is a mapped memdrive */ + j = DRIVE_MAP_SIZE; /* real drive */ + for (j = 0; j < DRIVE_MAP_SIZE; j++) + { + if (drive_map_slot_empty (disk_drive_map[j])) //判断驱动器映像插槽是否为空 为空,返回1 + { + j = DRIVE_MAP_SIZE; /* real drive */ + break; + } - if (current_drive == hooked_drive_map[j].from_drive && hooked_drive_map[j].to_drive == 0xFF && !(hooked_drive_map[j].to_cylinder & 0x4000)) - break; /* memdrive */ - } + if (current_drive == disk_drive_map[j].from_drive && disk_drive_map[j].to_drive == 0xFF && !(disk_drive_map[j].to_log2_sector != 11)) + break; /* memdrive */ + } - if (j == DRIVE_MAP_SIZE) /* real drive */ - { + if (j == DRIVE_MAP_SIZE) /* real drive */ + { /* this command is intended for running in command line and inhibited from running in menu.lst */ if (flags & (BUILTIN_MENU | BUILTIN_SCRIPT)) { - grub_close (); - errnum = ERR_WRITE_TO_NON_MEM_DRIVE; - goto fail; + grub_close (); + errnum = ERR_WRITE_TO_NON_MEM_DRIVE; + goto fail; } - } - } + } + } #endif - - filepos = offset; + filepos = offset; } else { - /* destination is memory address. */ - if (*arg < '0' || *arg > '9') - { - errnum = ERR_BAD_ARGUMENT; - goto fail; - } - if (! safe_parse_maxint (&arg, &addr)) - goto fail; - if (addr == -1) - { - errnum = ERR_BAD_ARGUMENT; - goto fail; - } + /* destination is memory address. */ + if (*arg < '0' || *arg > '9') + { + errnum = ERR_BAD_ARGUMENT; + goto fail; + } + if (! safe_parse_maxint (&arg, &addr)) + goto fail; + if (addr == -1) + { + errnum = ERR_BAD_ARGUMENT; + goto fail; + } } /* destination is device or file if addr == -1 */ @@ -12857,72 +10087,75 @@ write_func (char *arg, int flags) arg = skip_to (0, arg); /* INTEGER_OR_STRING */ - if (addr == -1) + if (addr == (unsigned long long)-1) { - /* string */ - if (! *arg) - { - grub_close (); - errnum = ERR_BAD_ARGUMENT; - goto fail; - } - len = parse_string (arg); + /* string */ + if (! *arg) + { + grub_close (); + errnum = ERR_BAD_ARGUMENT; + goto fail; + } + len = parse_string (arg); - if (bytes && bytes < len) len = bytes; + if (bytes && bytes < len) len = bytes; - if (saved_drive == 0xFFFF && p == tmp_file) /* (md) */ - { - grub_close (); - grub_memmove64 (offset, (unsigned long long)(unsigned int)arg, len); - if ((unsigned long)&saved_drive + 3 >= offset && (unsigned long)&saved_drive < offset + len) - tmp_drive = saved_drive; - if ((unsigned long)&saved_partition + 3 >= offset && (unsigned long)&saved_partition < offset + len) - tmp_partition = saved_partition; - errnum = 0; - goto succ; - } - /* write file */ - if (len > filemax - filepos) + if (saved_drive == 0xFFFF && p == tmp_file) /* (md) */ + { + grub_close (); + grub_memmove64 (offset, (unsigned long long)(grub_size_t)arg, len); + if ((grub_size_t)&saved_drive + 3 >= offset && (grub_size_t)&saved_drive < offset + len) + tmp_drive = saved_drive; + if ((grub_size_t)&saved_partition + 3 >= offset && (grub_size_t)&saved_partition < offset + len) + tmp_partition = saved_partition; + errnum = 0; + goto succ; + } + /* write file */ + if (len > filemax - filepos) len = filemax - filepos; - if (grub_read ((unsigned long long)(unsigned int)arg, len, 0x900ddeed) != len) /* write */ - { - if (errnum == 0) - errnum = ERR_WRITE; - } - { - int err = errnum; - grub_close (); - errnum = err; - } + if (grub_read ((unsigned long long)(grub_size_t)arg, len, 0x900ddeed) != len) /* write */ + { + if (errnum == 0) + errnum = ERR_WRITE; + } + { + int err = errnum; + grub_close (); + errnum = err; + } succ: - if (errnum == 0) - printf_debug0 ("0x%lX bytes written at offset 0x%lX.\n", (unsigned long long)len, (unsigned long long)offset); + if (errnum == 0) + printf_debug0 ("0x%lX bytes written at offset 0x%lX.\n", (unsigned long long)len, (unsigned long long)offset); } else { - if (bytes > 8) bytes = 8; - else if (bytes == 0) bytes = 4; - - /* integer */ - p = arg; - if (! safe_parse_maxint (&p, &val)) - goto fail; - addr += offset; - arg = (char*)(unsigned int)addr; - p = (char*)(unsigned int)&val; + if (bytes > 8) bytes = 8; + else if (bytes == 0) bytes = 4; + + /* integer */ + p = arg; + if (! safe_parse_maxint (&p, &val)) + goto fail; + addr += offset; + + if (!mem && addr >= 0x8200 && addr < 0x8400) + addr += (grub_size_t)g4e_data - 0x8200; + + arg = (char*)(grub_size_t)addr; + p = (char*)(grub_size_t)&val; - while(bytes--) - { - *arg++ = *p++; - } -// *((unsigned *)(unsigned int) RAW_ADDR (addr)) = (unsigned)val; - printf_debug0 ("Address 0x%lx: Value 0x%x\n", (unsigned long long)addr, (*((unsigned *)(unsigned int) RAW_ADDR (addr)))); - if (addr != (int)&saved_drive) - saved_drive = tmp_drive; - if (addr != (int)&saved_partition) - saved_partition = tmp_partition; - errnum = 0; - return val; + while(bytes--) + { + *arg++ = *p++; + } + printf_debug0 ("Address 0x%lx: Value 0x%x\n", (unsigned long long)addr, *(unsigned *)(grub_size_t)addr); + if (addr != (grub_size_t)&saved_drive) + saved_drive = tmp_drive; + if (addr != (grub_size_t)&saved_partition) + saved_partition = tmp_partition; + errnum = 0; + return val; } fail: @@ -12937,15 +10170,18 @@ static struct builtin builtin_write = "write", write_func, BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST | BUILTIN_IFTITLE, - "write [--offset=SKIP] [--bytes=N] ADDR_OR_FILE INTEGER_OR_STRING", + "write [--offset=SKIP] [--bytes=N] [#]ADDR_OR_FILE INTEGER_OR_STRING", "Write a 32-bit INTEGER to memory ADDR or write a STRING to FILE(or device!)\n" "To memory ADDR: default N=4, otherwise N<=8. Use 0xnnnnnnnn form.\n" "To FILE(or device): default STRING size.\n" " UTF-8(or hex values) use \\xnn form, UTF-16(big endian) use \\Xnnnn form." + "--mem Force normal memory, \n" + " otherwise, 0x8200-0x8400(not included) specifically refers to G4e head fixed data area." }; - + /* reboot */ +static int reboot_func (char *arg, int flags); static int reboot_func (char *arg, int flags) { @@ -12965,18 +10201,25 @@ static struct builtin builtin_reboot = "Reboot your system." }; - + /* Print the root device information to buffer. flag 0 saved device. flag 1 current device. */ - +void print_root_device (char *buffer,int flag); void print_root_device (char *buffer,int flag) { - unsigned long tmp_drive = flag?current_drive:saved_drive; - unsigned long tmp_partition = flag?current_partition:saved_partition; + unsigned int no_partition = 0; + if (flag & 0x100) + { + no_partition = 1; + flag &= 0xff; + } + unsigned int tmp_drive = flag?current_drive:saved_drive; + unsigned int tmp_partition = flag?current_partition:saved_partition; unsigned char *tmp_hooked = NULL; + if (buffer) { tmp_hooked = set_putchar_hook((unsigned char*)buffer); @@ -12992,21 +10235,18 @@ print_root_device (char *buffer,int flag) #endif /* FSYS_FB */ #ifdef FSYS_PXE case PXE_DRIVE: + #if 0 #ifdef FSYS_IPXE if (tmp_partition == IPXE_PART) grub_printf("(wd)"); else #endif + #endif grub_printf("(pd)"); break; #endif /* PXE drive. */ default: - if (tmp_drive == cdrom_drive) - { - grub_printf("(cd)"); - break; - } - else if (tmp_drive == 0xFFFF) + if (tmp_drive == 0xFFFF) { grub_printf("(md"); if (md_part_base) grub_printf(",0x%lx,0x%lx",md_part_base,md_part_size); @@ -13030,36 +10270,38 @@ print_root_device (char *buffer,int flag) grub_printf("(fd%d", tmp_drive); } - if ((tmp_partition & 0xFF0000) != 0xFF0000) - grub_printf(",%d", (unsigned long)(unsigned char)(tmp_partition >> 16)); + if (tmp_drive < 0x9f && (tmp_partition & 0xFF0000) != 0xFF0000 && !no_partition) + grub_printf(",%d", (unsigned int)(unsigned char)(tmp_partition >> 16)); - if ((tmp_partition & 0x00FF00) != 0x00FF00) - grub_printf(",%c", (unsigned long)(unsigned char)((tmp_partition >> 8) + 'a')); + if (tmp_drive < 0x9f && (tmp_partition & 0x00FF00) != 0x00FF00) + grub_printf(",%c", (unsigned int)(unsigned char)((tmp_partition >> 8) + 'a')); putchar(')',1); break; } if (buffer) set_putchar_hook(tmp_hooked); + return; } -void print_vol (unsigned long drive); +void print_vol (unsigned int drive); void -print_vol (unsigned long drive) +print_vol (unsigned int drive) { char uuid_found[256] = {0}; get_vol (uuid_found,0); if (*uuid_found) - grub_printf (" Volume Name is \"%s\".", uuid_found); + grub_printf (" Volume Name is \"%s\".\n", uuid_found); } +static int real_root_func (char *arg, int attempt_mnt); static int real_root_func (char *arg, int attempt_mnt) { char *next; - unsigned long i, tmp_drive = 0; - unsigned long tmp_partition = 0; + unsigned int i, tmp_drive = 0; + unsigned int tmp_partition = 0; char ch; errnum = 0; @@ -13072,46 +10314,25 @@ real_root_func (char *arg, int attempt_mnt) } else if (grub_memcmp (arg, "endpart", 7) == 0) { - unsigned long part = 0xFFFFFF; - unsigned long long start, len, offset; - unsigned long type, entry1, ext_offset1; - /* find MAX/END partition of the current root drive */ - -#if 0 - if (! (saved_drive & 0x80)) - { - grub_printf ("Cannot use 'endpart' with the current root device (fd%d).\n", saved_drive); - errnum = ERR_DEV_VALUES; - return 0; - } -#endif - tmp_partition = saved_partition; tmp_drive = saved_drive; current_partition = saved_partition; current_drive = saved_drive; next = arg + 7; - - while ((next_partition_drive = current_drive, - next_partition_dest = 0xFFFFFF, - next_partition_partition = &part, - next_partition_type = &type, - next_partition_start = &start, - next_partition_len = &len, - next_partition_offset = &offset, - next_partition_entry = &entry1, - next_partition_ext_offset = &ext_offset1, - next_partition_buf = mbr, - next_partition ())) + struct grub_part_data *q; + for (i=0; i < 16 ; i++) { + q = get_partition_info (current_drive, (i<<16 | 0xffff)); + if (!q) + continue; if (/* type != PC_SLICE_TYPE_NONE - && */ ! IS_PC_SLICE_TYPE_BSD (type) - && ! IS_PC_SLICE_TYPE_EXTENDED (type)) + && */ ! IS_PC_SLICE_TYPE_BSD (q->partition_type) + && ! IS_PC_SLICE_TYPE_EXTENDED (q->partition_type)) { saved_partition = current_partition; - current_partition = part; + current_partition = q->partition; if (attempt_mnt) { if (! open_device ()) @@ -13141,7 +10362,6 @@ real_root_func (char *arg, int attempt_mnt) if (! (next = set_device (arg))) return 0; } - if (next) { /* check the length of the root prefix, i.e., NEXT */ @@ -13152,13 +10372,11 @@ real_root_func (char *arg, int attempt_mnt) break; if (ch == '\\') { - //saved_dir[i] = ch; i++; ch = next[i]; if (! ch || i >= sizeof (saved_dir)) { i--; - //saved_dir[i] = 0; break; } } @@ -13182,7 +10400,6 @@ real_root_func (char *arg, int attempt_mnt) if (! open_device () && errnum != ERR_FSYS_MOUNT) return 0; -#if 1 if (next) { unsigned long long hdbias = 0; @@ -13195,9 +10412,7 @@ real_root_func (char *arg, int attempt_mnt) bootdev = set_bootdev (hdbias); } if (errnum) - return 0; -#endif - + return 0; if (fsys_type != NUM_FSYS || ! next) /* Print the type of the filesystem. */ { @@ -13209,9 +10424,8 @@ real_root_func (char *arg, int attempt_mnt) else return ! (errnum = ERR_FSYS_MOUNT); } -#if 1 else if (next) - { + { /* This is necessary, because the location of a partition table must be set appropriately. */ if (open_partition ()) @@ -13221,43 +10435,10 @@ real_root_func (char *arg, int attempt_mnt) return 0; } } -#endif - if (next) { - if (kernel_type == KERNEL_TYPE_CHAINLOADER) - { - if (is_io) - { - /* DL=drive, DH=media descriptor: 0xF0=floppy, 0xF8=harddrive */ - chainloader_edx = (tmp_drive & 0xFF) | 0xF000 | ((tmp_drive & 0x80) << 4); - chainloader_edx_set = 1; - - /* the user might wrongly set these argument, so force them to be correct */ - - chainloader_ebx = 0; // clear BX for WinME - chainloader_ebx_set = 1; - chainloader_load_segment = 0x0070; - chainloader_load_offset = 0; - chainloader_skip_length = 0x0800; - } else { - if (chainloader_edx_set) - { - chainloader_edx &= 0xFFFF0000; - chainloader_edx |= tmp_drive | ((tmp_partition >> 8) & 0xFF00); - } - - if (chainloader_ebx_set && chainloader_ebx) - { - chainloader_ebx &= 0xFFFF0000; - chainloader_ebx |= tmp_drive | ((tmp_partition >> 8) & 0xFF00); - } - } - } - saved_partition = tmp_partition; saved_drive = tmp_drive; - /* copy root prefix to saved_dir */ for (i = 0; i < sizeof (saved_dir); i++) { @@ -13279,12 +10460,15 @@ real_root_func (char *arg, int attempt_mnt) saved_dir[i] = ch; } + if (i && *saved_dir) + { if (saved_dir[i-1] == '/') { saved_dir[i-1] = 0; } else saved_dir[i] = 0; } + } if (debug > 0 && *saved_dir) grub_printf (" The current working directory (relative path) is %s\n", saved_dir); @@ -13296,6 +10480,7 @@ real_root_func (char *arg, int attempt_mnt) return next ? 1 : (saved_drive & 0x80); } +static int root_func (char *arg, int flags); static int root_func (char *arg, int flags) { @@ -13320,8 +10505,9 @@ static struct builtin builtin_root = " FreeBSD root partition is on the SCSI disk, then use a `1' for HDBIAS." }; - + /* rootnoverify */ +static int rootnoverify_func (char *arg, int flags); static int rootnoverify_func (char *arg, int flags) { @@ -13341,24 +10527,23 @@ static struct builtin builtin_rootnoverify = " derived from attempting the mount will NOT work correctly." }; - + static int time1; static int time2; char default_file[60]; static unsigned long long saved_sectors[2]; -static unsigned long saved_offsets[2]; -static unsigned long saved_lengths[2]; +static unsigned int saved_offsets[2]; +static unsigned int saved_lengths[2]; static unsigned long long wait; static unsigned long long entryno; -//static int c; static int deny_write; /* Save sector information about at most two sectors. */ -static void disk_read_savesect_func1 (unsigned long long sector, unsigned long offset, unsigned long long length); +static void disk_read_savesect_func1 (unsigned long long sector, unsigned int offset, unsigned long long length); static void -disk_read_savesect_func1 (unsigned long long sector, unsigned long offset, unsigned long long length) +disk_read_savesect_func1 (unsigned long long sector, unsigned int offset, unsigned long long length) { if (blklst_num_sectors < 2) { @@ -13370,12 +10555,12 @@ disk_read_savesect_func1 (unsigned long long sector, unsigned long offset, unsig } static void prompt_user (void); - static void prompt_user (void) { int wait1; - int c; + int c1; + unsigned short c; wait1 = wait; printf("\nAbout to write the entry number %d to file %s\n\n" @@ -13387,9 +10572,9 @@ prompt_user (void) for (;;) { /* Check if ESC is pressed. */ - if (checkkey () != -1 /*&& ASCII_CHAR (getkey ()) == '\e'*/) + if ((c1 = checkkey ()) != (int)-1 /*&& ASCII_CHAR (getkey ()) == '\e'*/) { - if ((c = ASCII_CHAR (getkey ())) == '\e') + if ((c = c1) == 0x011b) { deny_write = 2; /* abort this entry */ break; @@ -13428,28 +10613,19 @@ prompt_user (void) /* savedefault */ +static int savedefault_func (char *arg, int flags); static int savedefault_func (char *arg, int flags) { - unsigned long tmp_drive = saved_drive; - unsigned long tmp_partition = saved_partition; + unsigned int tmp_drive = saved_drive; + unsigned int tmp_partition = saved_partition; char *p; -// int ignore_error = 0; - errnum = 0; blklst_num_sectors = 0; wait = 0; time2 = -1; deny_write = 0; - - /* This command is only useful when you boot an entry from the menu - interface. */ -// if (! (flags & BUILTIN_SCRIPT)) -// { -// errnum = ERR_UNRECOGNIZED; -// return 0; -// } if (grub_memcmp (arg, "--wait=", 7) == 0) { @@ -13508,7 +10684,7 @@ savedefault_func (char *arg, int flags) saved_partition = install_partition; if (grub_open (default_file)) { - unsigned long len, len1; + unsigned int len, len1; char buf[12]; if (compressed_file) @@ -13519,10 +10695,9 @@ savedefault_func (char *arg, int flags) saved_lengths[0] = 0; disk_read_hook = disk_read_savesect_func1; - len = grub_read ((unsigned long long)(unsigned int)mbr, 512, 0xedde0d90); + len = grub_read ((unsigned long long)(grub_size_t)mbr, 512, 0xedde0d90); disk_read_hook = 0; - grub_close (); - + grub_close (); if (len != ((filemax <= 512) ? filemax : 512)) { /* Read file failure */ @@ -13559,11 +10734,8 @@ savedefault_func (char *arg, int flags) //grub_memset (mbr, '\n', 11); len = grub_sprintf (buf, "%d", entryno); len++; /* including the ending null. */ - -// if (saved_lengths[0] < len) -// { - //char sect[512]; - if (! rawread (current_drive, saved_sectors[0], 0, SECTOR_SIZE, (unsigned long long)(unsigned int)mbr, 0xedde0d90)) + + if (! rawread (current_drive, saved_sectors[0], 0, SECTOR_SIZE, (unsigned long long)(grub_size_t)mbr, 0xedde0d90)) goto fail; len1 = saved_lengths[0] < len ? saved_lengths[0] : len; @@ -13584,21 +10756,19 @@ savedefault_func (char *arg, int flags) if (deny_write <= 0 ) { - if (! rawwrite (current_drive, saved_sectors[0], (unsigned long long)(unsigned int)mbr)) + if (! rawwrite (current_drive, saved_sectors[0], (unsigned long long)(grub_size_t)mbr)) goto fail; } } /* The file is anchored to another file and the first few bytes are spanned in two sectors. Uggh... */ - - //len = strlen(buf) + 1; /* entryno and the ending NULL */ /* only LEN bytes need to be written */ if (saved_lengths[0] < len) { /* write the rest bytes to the second sector */ - if (! rawread (current_drive, saved_sectors[1], 0, 512, (unsigned long long)(unsigned int)mbr, 0xedde0d90)) + if (! rawread (current_drive, saved_sectors[1], 0, 512, (unsigned long long)(grub_size_t)mbr, 0xedde0d90)) goto fail; /* skip the write if possible. */ @@ -13618,22 +10788,11 @@ savedefault_func (char *arg, int flags) if (deny_write <= 0 ) { - if (! rawwrite (current_drive, saved_sectors[1], (unsigned long long)(unsigned int)mbr)) + if (! rawwrite (current_drive, saved_sectors[1], (unsigned long long)(grub_size_t)mbr)) goto fail; } } } -// } -// else -// { -// /* This is a simple case. It fits into a single sector. */ -// if (! rawread (current_drive, saved_sectors[0], 0, SECTOR_SIZE, -// sect)) -// goto fail; -// grub_memmove (sect + saved_offsets[0], buf, len); -// if (! rawwrite (current_drive, saved_sectors[0], sect)) -// goto fail; -// } /* Clear the cache. */ buf_track = -1; @@ -13656,481 +10815,247 @@ savedefault_func (char *arg, int flags) static struct builtin builtin_savedefault = { "savedefault", - savedefault_func, - BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, - "savedefault [--wait=T] [[+/-]NUM | `fallback']", - "Save the current entry as the default boot entry if no argument is" - " specified. If a number is specified, this number is saved. If" - " `fallback' is used, next fallback entry is saved." - " If T is not 0, prompt the user to confirm the write operation by" - " pressing the Y key, and if no key-press detected within T seconds," - " the write will be discarded." -}; - - -#ifdef SUPPORT_SERIAL -/* serial */ -static int -serial_func (char *arg, int flags) -{ - unsigned short port = serial_hw_get_port (0); - unsigned int speed = 9600; - int word_len = UART_8BITS_WORD; - int parity = UART_NO_PARITY; - int stop_bit_len = UART_1_STOP_BIT; - - errnum = 0; - /* Process GNU-style long options. - FIXME: We should implement a getopt-like function, to avoid - duplications. */ - while (1) - { - if (grub_memcmp (arg, "--unit=", sizeof ("--unit=") - 1) == 0) - { - char *p = arg + sizeof ("--unit=") - 1; - unsigned long long unit; - - if (! safe_parse_maxint (&p, &unit)) - return 0; - - if (unit < 0 || unit > 3) - { - errnum = ERR_DEV_VALUES; - return 0; - } - - port = serial_hw_get_port (unit); - } - else if (grub_memcmp (arg, "--speed=", sizeof ("--speed=") - 1) == 0) - { - char *p = arg + sizeof ("--speed=") - 1; - unsigned long long num; - - if (! safe_parse_maxint (&p, &num)) - return 0; - - speed = (unsigned int) num; - } - else if (grub_memcmp (arg, "--port=", sizeof ("--port=") - 1) == 0) - { - char *p = arg + sizeof ("--port=") - 1; - unsigned long long num; - - if (! safe_parse_maxint (&p, &num)) - return 0; - - port = (unsigned short) num; - } - else if (grub_memcmp (arg, "--word=", sizeof ("--word=") - 1) == 0) - { - char *p = arg + sizeof ("--word=") - 1; - unsigned long long len; - - if (! safe_parse_maxint (&p, &len)) - return 0; - - switch (len) - { - case 5: word_len = UART_5BITS_WORD; break; - case 6: word_len = UART_6BITS_WORD; break; - case 7: word_len = UART_7BITS_WORD; break; - case 8: word_len = UART_8BITS_WORD; break; - default: - errnum = ERR_BAD_ARGUMENT; - return 0; - } - } - else if (grub_memcmp (arg, "--stop=", sizeof ("--stop=") - 1) == 0) - { - char *p = arg + sizeof ("--stop=") - 1; - unsigned long long len; - - if (! safe_parse_maxint (&p, &len)) - return 0; - - switch (len) - { - case 1: stop_bit_len = UART_1_STOP_BIT; break; - case 2: stop_bit_len = UART_2_STOP_BITS; break; - default: - errnum = ERR_BAD_ARGUMENT; - return 0; - } - } - else if (grub_memcmp (arg, "--parity=", sizeof ("--parity=") - 1) == 0) - { - char *p = arg + sizeof ("--parity=") - 1; - - if (grub_memcmp (p, "no", sizeof ("no") - 1) == 0) - parity = UART_NO_PARITY; - else if (grub_memcmp (p, "odd", sizeof ("odd") - 1) == 0) - parity = UART_ODD_PARITY; - else if (grub_memcmp (p, "even", sizeof ("even") - 1) == 0) - parity = UART_EVEN_PARITY; - else - { - errnum = ERR_BAD_ARGUMENT; - return 0; - } - } - else - break; - - arg = skip_to (0, arg); - } - - /* Initialize the serial unit. */ - if (! serial_hw_init (port, speed, word_len, parity, stop_bit_len)) - { - errnum = ERR_BAD_ARGUMENT; - return 0; - } - - return 1; -} - -static struct builtin builtin_serial = -{ - "serial", - serial_func, - BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, - "serial [--unit=UNIT] [--port=PORT] [--speed=SPEED] [--word=WORD]\n [--parity=PARITY] [--stop=STOP] [--device=DEV]", - "Initialize a serial device. UNIT is a digit that specifies which serial" - " device is used (e.g. 0 == COM1). If you need to specify the port number," - " set it by --port. SPEED is the DTE-DTE speed. WORD is the word length," - " PARITY is the type of parity, which is one of `no', `odd' and `even'." - " STOP is the length of stop bit(s). The option --device can be used only" - " in the grub shell, which specifies the file name of a tty device. The" - " default values are COM1, 9600, 8N1." -}; -#endif /* SUPPORT_SERIAL */ - - -/* setkey */ -#if 0 -struct keysym -{ - char *unshifted_name; /* the name in unshifted state */ - char *shifted_name; /* the name in shifted state */ - unsigned char unshifted_ascii; /* the ascii code in unshifted state */ - unsigned char shifted_ascii; /* the ascii code in shifted state */ - unsigned char keycode; /* keyboard scancode */ -}; - -/* The table for key symbols. If the "shifted" member of an entry is - NULL, the entry does not have shifted state. */ -static struct keysym keysym_table[] = -{ - {"escape", 0, 0x1b, 0, 0x01}, - {"1", "exclam", '1', '!', 0x02}, - {"2", "at", '2', '@', 0x03}, - {"3", "numbersign", '3', '#', 0x04}, - {"4", "dollar", '4', '$', 0x05}, - {"5", "percent", '5', '%', 0x06}, - {"6", "caret", '6', '^', 0x07}, - {"7", "ampersand", '7', '&', 0x08}, - {"8", "asterisk", '8', '*', 0x09}, - {"9", "parenleft", '9', '(', 0x0a}, - {"0", "parenright", '0', ')', 0x0b}, - {"minus", "underscore", '-', '_', 0x0c}, - {"equal", "plus", '=', '+', 0x0d}, - {"backspace", 0, '\b', 0, 0x0e}, - {"tab", 0, '\t', 0, 0x0f}, - {"q", "Q", 'q', 'Q', 0x10}, - {"w", "W", 'w', 'W', 0x11}, - {"e", "E", 'e', 'E', 0x12}, - {"r", "R", 'r', 'R', 0x13}, - {"t", "T", 't', 'T', 0x14}, - {"y", "Y", 'y', 'Y', 0x15}, - {"u", "U", 'u', 'U', 0x16}, - {"i", "I", 'i', 'I', 0x17}, - {"o", "O", 'o', 'O', 0x18}, - {"p", "P", 'p', 'P', 0x19}, - {"bracketleft", "braceleft", '[', '{', 0x1a}, - {"bracketright", "braceright", ']', '}', 0x1b}, - {"enter", 0, '\n', 0, 0x1c}, - {"control", 0, 0, 0, 0x1d}, - {"a", "A", 'a', 'A', 0x1e}, - {"s", "S", 's', 'S', 0x1f}, - {"d", "D", 'd', 'D', 0x20}, - {"f", "F", 'f', 'F', 0x21}, - {"g", "G", 'g', 'G', 0x22}, - {"h", "H", 'h', 'H', 0x23}, - {"j", "J", 'j', 'J', 0x24}, - {"k", "K", 'k', 'K', 0x25}, - {"l", "L", 'l', 'L', 0x26}, - {"semicolon", "colon", ';', ':', 0x27}, - {"quote", "doublequote", '\'', '"', 0x28}, - {"backquote", "tilde", '`', '~', 0x29}, - {"shift", 0, 0, 0, 0x2a}, - {"backslash", "bar", '\\', '|', 0x2b}, - {"z", "Z", 'z', 'Z', 0x2c}, - {"x", "X", 'x', 'X', 0x2d}, - {"c", "C", 'c', 'C', 0x2e}, - {"v", "V", 'v', 'V', 0x2f}, - {"b", "B", 'b', 'B', 0x30}, - {"n", "N", 'n', 'N', 0x31}, - {"m", "M", 'm', 'M', 0x32}, - {"comma", "less", ',', '<', 0x33}, - {"period", "greater", '.', '>', 0x34}, - {"slash", "question", '/', '?', 0x35}, - {"alt", 0, 0, 0, 0x38}, - {"space", 0, ' ', 0, 0x39}, - {"capslock", 0, 0, 0, 0x3a}, - {"F1", 0, 0, 0, 0x3b}, - {"F2", 0, 0, 0, 0x3c}, - {"F3", 0, 0, 0, 0x3d}, - {"F4", 0, 0, 0, 0x3e}, - {"F5", 0, 0, 0, 0x3f}, - {"F6", 0, 0, 0, 0x40}, - {"F7", 0, 0, 0, 0x41}, - {"F8", 0, 0, 0, 0x42}, - {"F9", 0, 0, 0, 0x43}, - {"F10", 0, 0, 0, 0x44}, - /* Caution: do not add NumLock here! we cannot deal with it properly. */ - {"delete", 0, 0x7f, 0, 0x53} + savedefault_func, + BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, + "savedefault [--wait=T] [[+/-]NUM | `fallback']", + "Save the current entry as the default boot entry if no argument is" + " specified. If a number is specified, this number is saved. If" + " `fallback' is used, next fallback entry is saved." + " If T is not 0, prompt the user to confirm the write operation by" + " pressing the Y key, and if no key-press detected within T seconds," + " the write will be discarded." }; -#endif struct keysym { char *name; /* the name in unshifted state */ - unsigned short code; /* lo=ascii code, hi=scan code */ +// unsigned short code; /* lo=ascii code, hi=scan code */ + unsigned int code; /* lo=ascii code, hi=scan code */ }; /* The table for key symbols. If the "shifted" member of an entry is NULL, the entry does not have shifted state. */ static struct keysym keysym_table[] = { - {"escape", 0x011B}, // ESC - {"1", 0x0231}, // 1 - {"exclam", 0x0221}, // '!' - {"2", 0x0332}, // 2 - {"at", 0x0340}, // '@' - {"3", 0x0433}, // 3 - {"numbersign", 0x0423}, // '#' - {"4", 0x0534}, // 4 - {"dollar", 0x0524}, // '$' - {"5", 0x0635}, // 5 - {"percent", 0x0625}, // '%' - {"6", 0x0736}, // 6 - {"caret", 0x075E}, // '^' - {"7", 0x0837}, // 7 - {"ampersand", 0x0826}, // '&' - {"8", 0x0938}, // 8 - {"asterisk", 0x092A}, // '*' - {"9", 0x0A39}, // 9 - {"parenleft", 0x0A28}, // '(' - {"0", 0x0B30}, // 0 - {"parenright", 0x0B29}, // ')' - {"minus", 0x0C2D}, // - - {"underscore", 0x0C5F}, // '_' - {"equal", 0x0D3D}, // = - {"plus", 0x0D2B}, // '+' - {"backspace", 0x0E08}, // BS - {"ctrlbackspace", 0x0E7F}, // (DEL) - {"tab", 0x0F09}, // Tab - {"q", 0x1071}, // q - {"Q", 0x1051}, // Q - {"w", 0x1177}, // w - {"W", 0x1157}, // W - {"e", 0x1265}, // e - {"E", 0x1245}, // E - {"r", 0x1372}, // r - {"R", 0x1352}, // R - {"t", 0x1474}, // t - {"T", 0x1454}, // T - {"y", 0x1579}, // y - {"Y", 0x1559}, // Y - {"u", 0x1675}, // u - {"U", 0x1655}, // U - {"i", 0x1769}, // i - {"I", 0x1749}, // I - {"o", 0x186F}, // o - {"O", 0x184F}, // O - {"p", 0x1970}, // p - {"P", 0x1950}, // P - {"bracketleft", 0x1A5B}, // '[' - {"braceleft", 0x1A7B}, // '{' - {"bracketright", 0x1B5D}, // ']' - {"braceright", 0x1B7D}, // '}' - {"enter", 0x1C0D}, // Enter -//{"control", 0x1DXX}, // no more supported - {"a", 0x1E61}, // a - {"A", 0x1E41}, // A - {"s", 0x1F73}, // s - {"S", 0x1F53}, // S - {"d", 0x2064}, // d - {"D", 0x2044}, // D - {"f", 0x2166}, // f - {"F", 0x2146}, // F - {"g", 0x2267}, // g - {"G", 0x2247}, // G - {"h", 0x2368}, // h - {"H", 0x2348}, // H - {"j", 0x246A}, // j - {"J", 0x244A}, // J - {"k", 0x256B}, // k - {"K", 0x254B}, // K - {"l", 0x266C}, // l - {"L", 0x264C}, // L - {"semicolon", 0x273B}, // ';' - {"colon", 0x273A}, // ':' - {"quote", 0x2827}, // '\'' - {"doublequote", 0x2822}, // '"' - {"backquote", 0x2960}, // '`' - {"tilde", 0x297E}, // '~' -//{"shift", 0x2AXX}, // no more supported - {"backslash", 0x2B5C}, // '\\' - {"bar", 0x2B7C}, // '|' - {"z", 0x2C7A}, // z - {"Z", 0x2C5A}, // Z - {"x", 0x2D78}, // x - {"X", 0x2D58}, // X - {"c", 0x2E63}, // c - {"C", 0x2E43}, // C - {"v", 0x2F76}, // v - {"V", 0x2F56}, // V - {"b", 0x3062}, // b - {"B", 0x3042}, // B - {"n", 0x316E}, // n - {"N", 0x314E}, // N - {"m", 0x326D}, // m - {"M", 0x324D}, // M - {"comma", 0x332C}, // ',' - {"less", 0x333C}, // '<' - {"period", 0x342E}, // '.' - {"greater", 0x343E}, // '>' - {"slash", 0x352F}, // '/' - {"question", 0x353F}, // '?' -//{"alt", 0x38XX}, // no more supported - {"space", 0x3920}, // Space -//{"capslock", 0x3AXX}, // no more supported - {"F1", 0x3B00}, - {"F2", 0x3C00}, - {"F3", 0x3D00}, - {"F4", 0x3E00}, - {"F5", 0x3F00}, - {"F6", 0x4000}, - {"F7", 0x4100}, - {"F8", 0x4200}, - {"F9", 0x4300}, - {"F10", 0x4400}, + {"escape", 0x17011B}, // ESC 17011b + {"1", 0x0031}, // 1 + {"exclam", 0x0021}, // ! + {"2", 0x0032}, // 2 + {"at", 0x0040}, // @ + {"3", 0x0033}, // 3 + {"numbersign",0x0023}, // # + {"4", 0x0034}, // 4 + {"dollar", 0x0024}, // $ + {"5", 0x0035}, // 5 + {"percent", 0x0025}, // % + {"6", 0x0036}, // 6 + {"caret", 0x005E}, // ^ + {"7", 0x0037}, // 7 + {"ampersand", 0x0026}, // & + {"8", 0x0038}, // 8 + {"asterisk", 0x002A}, // * + {"9", 0x0039}, // 9 + {"parenleft", 0x0028}, // ( + {"0", 0x0030}, // 0 + {"parenright",0x0029}, // ) + {"minus", 0x002D}, // - + {"underscore",0x005F}, // _ + {"equal", 0x003D}, // = + {"plus", 0x002B}, // + + {"backspace", 0x0008}, // BS + {"ctrlbackspace", 0x2000008}, // (DEL) 2000008 + {"tab", 0x0009}, // Tab + {"q", 0x0071}, // q + {"Q", 0x0051}, // Q + {"w", 0x0077}, // w + {"W", 0x0057}, // W + {"e", 0x0065}, // e + {"E", 0x0045}, // E + {"r", 0x0072}, // r + {"R", 0x0052}, // R + {"t", 0x0074}, // t + {"T", 0x0054}, // T + {"y", 0x0079}, // y + {"Y", 0x0059}, // y + {"u", 0x0075}, // u + {"U", 0x0055}, // U + {"i", 0x0069}, // i + {"I", 0x0049}, // I + {"o", 0x006F}, // o + {"O", 0x004F}, // Q + {"p", 0x0070}, // p + {"P", 0x0050}, // P + {"bracketleft", 0x005B}, // [ + {"braceleft", 0x007B}, // { + {"bracketright",0x005D}, // ] + {"braceright", 0x007D}, // } + {"enter", 0x000D}, // Enter + {"a", 0x0061}, // a + {"A", 0x0041}, // A + {"s", 0x0073}, // s + {"S", 0x0053}, // S + {"d", 0x0064}, // d + {"D", 0x0044}, // D + {"f", 0x0066}, // f + {"F", 0x0046}, // F + {"g", 0x0067}, // g + {"G", 0x0047}, // G + {"h", 0x0068}, // h + {"H", 0x0048}, // H + {"j", 0x006A}, // j + {"J", 0x004A}, // J + {"k", 0x006B}, // k + {"K", 0x004B}, // K + {"l", 0x006C}, // l + {"L", 0x004C}, // L + {"semicolon", 0x003B}, // ; + {"colon", 0x003A}, // : + {"quote", 0x0027}, // ' + {"doublequote", 0x0022}, // " + {"backquote", 0x0060}, // ` + {"tilde", 0x007E}, // ~ + {"backslash", 0x005C}, // "\" + {"bar", 0x007C}, // | + {"z", 0x007A}, // z + {"Z", 0x005A}, // Z + {"x", 0x0078}, // x + {"X", 0x0058}, // X + {"c", 0x0063}, // c + {"C", 0x0043}, // C + {"v", 0x0076}, // v + {"V", 0x0056}, // V + {"b", 0x0062}, // b + {"B", 0x0042}, // B + {"n", 0x006E}, // n + {"N", 0x004E}, // N + {"m", 0x006D}, // m + {"M", 0x004D}, // M + {"comma", 0x002C}, // , + {"less", 0x003C}, // < + {"period", 0x002E}, // . + {"greater", 0x003E}, // > + {"slash", 0x002F}, // / + {"question", 0x003F}, // ? + {"space", 0x0020}, // Space + {"F1", 0xB3B00}, //b3b00 + {"F2", 0xC3C00}, //c3c00 + {"F3", 0xD3D00}, //d3d00 + {"F4", 0xE3E00}, //e3e00 + {"F5", 0xF3F00}, //f3f00 + {"F6", 0x104000}, //104000 + {"F7", 0x114100}, //114100 + {"F8", 0x124200}, //124200 + {"F9", 0x134300}, //134300 + {"F10", 0x144400}, //144400 /* Caution: do not add NumLock here! we cannot deal with it properly. */ - {"home", 0x4700}, - {"uparrow", 0x4800}, - {"pageup", 0x4900}, // PgUp - {"leftarrow", 0x4B00}, - {"center", 0x4C00}, // keypad center key - {"rightarrow", 0x4D00}, - {"end", 0x4F00}, - {"downarrow", 0x5000}, - {"pagedown", 0x5100}, // PgDn - {"insert", 0x5200}, // Insert - {"delete", 0x5300}, // Delete - {"shiftF1", 0x5400}, - {"shiftF2", 0x5500}, - {"shiftF3", 0x5600}, - {"shiftF4", 0x5700}, - {"shiftF5", 0x5800}, - {"shiftF6", 0x5900}, - {"shiftF7", 0x5A00}, - {"shiftF8", 0x5B00}, - {"shiftF9", 0x5C00}, - {"shiftF10", 0x5D00}, - {"ctrlF1", 0x5E00}, - {"ctrlF2", 0x5F00}, - {"ctrlF3", 0x6000}, - {"ctrlF4", 0x6100}, - {"ctrlF5", 0x6200}, - {"ctrlF6", 0x6300}, - {"ctrlF7", 0x6400}, - {"ctrlF8", 0x6500}, - {"ctrlF9", 0x6600}, - {"ctrlF10", 0x6700}, - - {"Aq", 0x1000}, // A=Alt or AltGr. Provided by steve. - {"Aw", 0x1100}, - {"Ae", 0x1200}, - {"Ar", 0x1300}, - {"At", 0x1400}, - {"Ay", 0x1500}, - {"Au", 0x1600}, - {"Ai", 0x1700}, - {"Ao", 0x1800}, - {"Ap", 0x1900}, - {"Aa", 0x1e00}, - {"As", 0x1f00}, - {"Ad", 0x2000}, - {"Af", 0x2100}, - {"Ag", 0x2200}, - {"Ah", 0x2300}, - {"Aj", 0x2400}, - {"Ak", 0x2500}, - {"Al", 0x2600}, - {"Az", 0x2c00}, - {"Ax", 0x2d00}, - {"Ac", 0x2e00}, - {"Av", 0x2f00}, - {"Ab", 0x3000}, - {"An", 0x3100}, - {"Am", 0x3200}, - {"A1", 0x7800}, - {"A2", 0x7900}, - {"A3", 0x7A00}, - {"A4", 0x7B00}, - {"A5", 0x7C00}, - {"A6", 0x7D00}, - {"A7", 0x7E00}, - {"A8", 0x7F00}, - {"A9", 0x8000}, - {"A0", 0x8100}, - {"oem102", 0x565c}, - {"shiftoem102", 0x567c}, - {"Aminus", 0x8200}, - {"Aequal", 0x8300}, - {"Abracketleft", 0x1A00}, - {"Abracketright", 0x1B00}, - {"Asemicolon", 0x2700}, - {"Aquote", 0x2800}, - {"Abackquote", 0x2900}, // 2a00 is alt+shift - {"Abackslash", 0x2b00}, - {"Asemicolon", 0x2700}, - {"Acomma", 0x3300}, - {"Aperiod", 0x3400}, - {"Aslash", 0x3500}, + {"home", 0x54700}, //54700 + {"uparrow", 0x14800}, //上箭头 14800 + {"pageup", 0x94900}, // PgUp 94900 + {"leftarrow", 0x44B00}, //左箭头 44b00 + {"rightarrow",0x34D00}, //右箭头 34d00 + {"end", 0x46F00}, //64f00 + {"downarrow", 0x25000}, //下箭头 25000 + {"pagedown", 0xA5100}, // PgDn a5100 + {"insert", 0x75200}, // Insert 75200 + {"delete", 0x85300}, // Delete 85300 + {"shiftF1", 0x10B3B00}, + {"shiftF2", 0x10C3C00}, + {"shiftF3", 0x10D3D00}, + {"shiftF4", 0x10E3E00}, + {"shiftF5", 0x10F3F00}, + {"shiftF6", 0x1104000}, + {"shiftF7", 0x1114100}, + {"shiftF8", 0x1124200}, + {"shiftF9", 0x1134300}, + {"shiftF10", 0x1144400}, + {"ctrlF1", 0x20B3B00}, + {"ctrlF2", 0x20C3C00}, + {"ctrlF3", 0x20D3D00}, + {"ctrlF4", 0x20E3E00}, + {"ctrlF5", 0x20F3F00}, + {"ctrlF6", 0x2104000}, + {"ctrlF7", 0x2114100}, + {"ctrlF8", 0x2124200}, + {"ctrlF9", 0x2134300}, + {"ctrlF10", 0x2144400}, + {"Aq", 0x4000071}, // A=Alt or AltGr. Provided by steve. + {"Aw", 0x4000077}, + {"Ae", 0x4000065}, + {"Ar", 0x4000072}, + {"At", 0x4000074}, + {"Ay", 0x4000079}, + {"Au", 0x4000075}, + {"Ai", 0x4000069}, + {"Ao", 0x400006f}, + {"Ap", 0x4000070}, + {"Aa", 0x4000061}, + {"As", 0x4000073}, + {"Ad", 0x4000064}, + {"Af", 0x4000066}, + {"Ag", 0x4000067}, + {"Ah", 0x4000068}, + {"Aj", 0x400006A}, + {"Ak", 0x400006B}, + {"Al", 0x400006C}, + {"Az", 0x400007A}, + {"Ax", 0x4000078}, + {"Ac", 0x4000063}, + {"Av", 0x4000066}, + {"Ab", 0x4000062}, + {"An", 0x400006E}, + {"Am", 0x400006D}, + {"A1", 0x4000031}, + {"A2", 0x4000032}, + {"A3", 0x4000033}, + {"A4", 0x4000034}, + {"A5", 0x4000035}, + {"A6", 0x4000036}, + {"A7", 0x4000037}, + {"A8", 0x4000038}, + {"A9", 0x4000039}, + {"A0", 0x4000030}, +// {"oem102", 0x565c}, +// {"shiftoem102", 0x567c}, + {"Aminus", 0x400002D}, //- + {"Aequal", 0x400003D}, //= + {"Abracketleft", 0x400005B}, //[ + {"Abracketright", 0x400005D}, //] + {"Asemicolon", 0x400003B}, //; + {"Aquote", 0x4000027}, //' + {"Abackquote", 0x4000060}, //` + {"Abackslash", 0x400005C}, //'\' + {"Acomma", 0x400002C}, //, + {"Aperiod", 0x400002E}, //. + {"Aslash", 0x400002F}, //'/' }; //static int find_key_code (char *key); -static unsigned long find_ascii_code (char *key); +struct key_map ascii_key_map[(KEY_MAP_SIZE + 1) * 4]; -#if 0 -static int -find_key_code (char *key) +int remap_ascii_char (int key); +int +remap_ascii_char (int key) { - int i; - - for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++) + int i; + + //一些有bug的UEFI固件返回了每个SHIFT+键组合,如大写字母Q返回0x1000051而不是0x0051。为了适应这个bug。2023-08-09 + if ((key & 0x1000000) && (key & 0xffffff) < 0x7f) + key = key & 0xff; + for (i=0; ascii_key_map[i].from_code; i++) { - if (keysym_table[i].unshifted_name && - grub_strcmp (key, keysym_table[i].unshifted_name) == 0) - return keysym_table[i].keycode; - else if (keysym_table[i].shifted_name && - grub_strcmp (key, keysym_table[i].shifted_name) == 0) - return keysym_table[i].keycode; + if (ascii_key_map[i].from_code == key) + return (ascii_key_map[i].to_code); } - - return 0; + return key; } -#endif - -static unsigned long + +static unsigned int find_ascii_code (char *key); +static unsigned int find_ascii_code (char *key) { int i; - - for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++) + for (i = 0; i < (int)(sizeof (keysym_table) / sizeof (keysym_table[0])); i++) { if (grub_strcmp (key, keysym_table[i].name) == 0) return keysym_table[i].code; @@ -14139,12 +11064,12 @@ find_ascii_code (char *key) return 0; } +static int setkey_func (char *arg, int flags); static int setkey_func (char *arg, int flags) { char *to_key, *from_key; - unsigned long to_code, from_code; -// int map_in_interrupt = 0; + unsigned int to_code, from_code; errnum = 0; to_key = arg; @@ -14153,8 +11078,7 @@ setkey_func (char *arg, int flags) if (! *to_key) { /* If the user specifies no argument, reset the key mappings. */ -// grub_memset (bios_key_map, 0, KEY_MAP_SIZE * sizeof (unsigned short)); - grub_memset (ascii_key_map, 0, KEY_MAP_SIZE * sizeof (unsigned long)); + grub_memset (ascii_key_map, 0, KEY_MAP_SIZE * sizeof (unsigned int)); return 1; } @@ -14172,14 +11096,8 @@ setkey_func (char *arg, int flags) from_code = find_ascii_code (from_key); if (! to_code || ! from_code) { - //map_in_interrupt = 1; - //to_code = find_key_code (to_key); - //from_code = find_key_code (from_key); - //if (! to_code || ! from_code) - //{ errnum = ERR_BAD_ARGUMENT; return 0; - //} } { @@ -14188,11 +11106,11 @@ setkey_func (char *arg, int flags) /* Find an empty slot. */ for (i = 0; i < KEY_MAP_SIZE; i++) { - if ((unsigned short)(ascii_key_map[i]) == from_code) + if (ascii_key_map[i].from_code == from_code) /* Perhaps the user wants to overwrite the map. */ break; - - if (! ascii_key_map[i]) + + if (! ascii_key_map[i].from_code) break; } @@ -14206,9 +11124,12 @@ setkey_func (char *arg, int flags) /* If TO is equal to FROM, delete the entry. */ grub_memmove ((char *) &ascii_key_map[i], (char *) &ascii_key_map[i + 1], - sizeof (unsigned long) * (KEY_MAP_SIZE - i)); + sizeof (unsigned int) * (KEY_MAP_SIZE - i)); else - ascii_key_map[i] = (to_code << 16) | from_code; + { + ascii_key_map[i].from_code = from_code; + ascii_key_map[i].to_code = to_code; + } } return 1; @@ -14226,14 +11147,16 @@ static struct builtin builtin_setkey = " underscore, equal, plus, backspace, tab, bracketleft, braceleft," " bracketright, braceright, enter, semicolon, colon, quote, doublequote," " backquote, tilde, backslash, bar, comma, less, period, greater," - " slash, question, alt, space, delete, oem102, shiftoem102," + " slash, question, space, delete" " [ctrl|shift]F1-10. For Alt+ prefix with A, e.g. 'setkey at Aequal'." " Use 'setkey at at' to reset one key, 'setkey' to reset all keys." }; - -#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS) + +//#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS) +#if defined(SUPPORT_GRAPHICS) /* terminal */ +static int terminal_func (char *arg, int flags); static int terminal_func (char *arg, int flags) { @@ -14243,9 +11166,9 @@ terminal_func (char *arg, int flags) unsigned long long to = -1; unsigned long long lines = 0; int no_message = 0; - unsigned long term_flags = 0; + unsigned int term_flags = 0; /* XXX: Assume less than 32 terminals. */ - unsigned long term_bitmap = 0; + unsigned int term_bitmap = 0; errnum = 0; /* Get GNU-style long options. */ @@ -14298,6 +11221,7 @@ terminal_func (char *arg, int flags) } if (graphics_inited && graphics_mode > 0xFF) { + console_setcursor(0); current_term->shutdown(); current_term = term_table + 1; current_term->startup(); @@ -14381,7 +11305,6 @@ terminal_func (char *arg, int flags) { if (term_table[i].checkkey () >= 0) { - (void) term_table[i].getkey (); default_term = i; goto end; @@ -14409,505 +11332,78 @@ terminal_func (char *arg, int flags) time2 = time1; if (to > 0) - to--; - } - } - } - - end: - current_term = term_table + default_term; - current_term->flags = term_flags; - - /* If the interface is currently the command-line, - restart it to repaint the screen. */ - if (current_term != prev_term /*&& (flags & BUILTIN_CMDLINE)*/) - { - if (prev_term->shutdown) - prev_term->shutdown(); - if (current_term->startup) - current_term->startup(); -// grub_longjmp (restart_cmdline_env, 0); - } - - return 1; -} - -static struct builtin builtin_terminal = -{ - "terminal", - terminal_func, - BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, - "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS]\n [--lines=LINES] [--silent] [console] [serial] [hercules] [graphics]", - "Select a terminal. When multiple terminals are specified, wait until" - " you push any key to continue. If both console and serial are specified," - " the terminal to which you input a key first will be selected. If no" - " argument is specified, print current setting. The option --dumb" - " specifies that your terminal is dumb, otherwise, vt100-compatibility" - " is assumed. If you specify --no-echo, input characters won't be echoed." - " If you specify --no-edit, the BASH-like editing feature will be disabled." - " If --timeout is present, this command will wait at most for SECS" - " seconds. The option --lines specifies the maximum number of lines." - " The option --silent is used to suppress messages." -}; -#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */ - - -#ifdef SUPPORT_SERIAL - -static struct terminfo *term = (struct terminfo *)0x8000; //use 200 bytes - -static struct - { - const char *name; - char *var; - } - options[] = - { - {"--name=", ((struct terminfo *)0x8000)->name}, - {"--cursor-address=", ((struct terminfo *)0x8000)->cursor_address}, - {"--clear-screen=", ((struct terminfo *)0x8000)->clear_screen}, - {"--enter-standout-mode=", ((struct terminfo *)0x8000)->enter_standout_mode}, - {"--exit-standout-mode=", ((struct terminfo *)0x8000)->exit_standout_mode} - }; - -static int -terminfo_func (char *arg, int flags) -{ - errnum = 0; - if (*arg) - { - grub_memset (term, 0, sizeof (struct terminfo)); - - while (*arg) - { - int i; - char *next = skip_to (0, arg); - - nul_terminate (arg); - - for (i = 0; i < sizeof (options) / sizeof (options[0]); i++) - { - const char *name = options[i].name; - int len = grub_strlen (name); - - if (! grub_memcmp (arg, name, len)) - { - grub_strcpy (options[i].var, ti_unescape_string (arg + len)); - break; - } - } - - if (i == sizeof (options) / sizeof (options[0])) - { - errnum = ERR_BAD_ARGUMENT; - return ! errnum; - } - - arg = next; - } - - if (term->name[0] == 0 || term->cursor_address[0] == 0) - { - errnum = ERR_BAD_ARGUMENT; - return ! errnum; - } - - ti_set_term (term); - } - else - { - /* No option specifies printing out current settings. */ - ti_get_term (term); - - grub_printf ("name=%s\n", - (ti_escape_string (term->name))); - grub_printf ("cursor_address=%s\n", - (ti_escape_string (term->cursor_address))); - grub_printf ("clear_screen=%s\n", - (ti_escape_string (term->clear_screen))); - grub_printf ("enter_standout_mode=%s\n", - (ti_escape_string (term->enter_standout_mode))); - grub_printf ("exit_standout_mode=%s\n", - (ti_escape_string (term->exit_standout_mode))); - } - - return 1; -} - -static struct builtin builtin_terminfo = -{ - "terminfo", - terminfo_func, - BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, - "terminfo [--name=NAME --cursor-address=SEQ [--clear-screen=SEQ]" - "\n [--enter-standout-mode=SEQ] [--exit-standout-mode=SEQ]]", - - "Define the capabilities of your terminal. Use this command to" - " define escape sequences, if it is not vt100-compatible." - " You may use \\e for ESC and ^X for a control character." - " If no option is specified, the current settings are printed." -}; -#endif /* SUPPORT_SERIAL */ - - -#if 0 -/* testload */ -static int -testload_func (char *arg, int flags) -{ - //int i; - - kernel_type = KERNEL_TYPE_NONE; - - if (! grub_open (arg)) - return 0; - - disk_read_hook = disk_read_print_func; - - /* Perform filesystem test on the specified file. */ - /* Read whole file first. */ - grub_printf ("Whole file: "); - - grub_read ((char *) RAW_ADDR (0x300000), -1); - - /* Now compare two sections of the file read differently. */ - - for (i = 0; i < 0x10ac0; i++) - { - *((unsigned char *) RAW_ADDR (0x400000 + i)) = 0; - *((unsigned char *) RAW_ADDR (0x500000 + i)) = 1; - } - - /* First partial read. */ - grub_printf ("\nPartial read 1: "); - - filepos = 0; - grub_read ((char *) RAW_ADDR (0x400000), 0x7); - grub_read ((char *) RAW_ADDR (0x400007), 0x100); - grub_read ((char *) RAW_ADDR (0x400107), 0x10); - grub_read ((char *) RAW_ADDR (0x400117), 0x999); - grub_read ((char *) RAW_ADDR (0x400ab0), 0x10); - grub_read ((char *) RAW_ADDR (0x400ac0), 0x10000); - - /* Second partial read. */ - grub_printf ("\nPartial read 2: "); - - filepos = 0; - grub_read ((char *) RAW_ADDR (0x500000), 0x10000); - grub_read ((char *) RAW_ADDR (0x510000), 0x10); - grub_read ((char *) RAW_ADDR (0x510010), 0x7); - grub_read ((char *) RAW_ADDR (0x510017), 0x10); - grub_read ((char *) RAW_ADDR (0x510027), 0x999); - grub_read ((char *) RAW_ADDR (0x5109c0), 0x100); - - grub_printf ("\nHeader1 = 0x%x, next = 0x%x, next = 0x%x, next = 0x%x\n", - *((int *) RAW_ADDR (0x400000)), - *((int *) RAW_ADDR (0x400004)), - *((int *) RAW_ADDR (0x400008)), - *((int *) RAW_ADDR (0x40000c))); - - grub_printf ("Header2 = 0x%x, next = 0x%x, next = 0x%x, next = 0x%x\n", - *((int *) RAW_ADDR (0x500000)), - *((int *) RAW_ADDR (0x500004)), - *((int *) RAW_ADDR (0x500008)), - *((int *) RAW_ADDR (0x50000c))); - - for (i = 0; i < 0x10ac0; i++) - if (*((unsigned char *) RAW_ADDR (0x400000 + i)) - != *((unsigned char *) RAW_ADDR (0x500000 + i))) - break; - - grub_printf ("Max is 0x10ac0: i=0x%x, filepos=0x%x\n", i, filepos); - disk_read_hook = 0; - grub_close (); - return 1; -} - -static struct builtin builtin_testload = -{ - "testload", - testload_func, - BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT, - "testload FILE", - "Read the entire contents of FILE in several different ways and" - " compares them, to test the filesystem code. The output is somewhat" - " cryptic, but if no errors are reported and the final `i=X," - " filepos=Y' reading has X and Y equal, then it is definitely" - " consistent, and very likely works correctly subject to a" - " consistent offset error. If this test succeeds, then a good next" - " step is to try loading a kernel." -}; -#endif - - -//static struct vbe_controller *controller = (struct vbe_controller *)0x8000;//use 512 bytes -//static struct vbe_mode *mode = (struct vbe_mode *)0x700;//use 255 bytes -/* testvbe MODE */ -static int -testvbe_func (char *arg, int flags) -{ - unsigned long long mode_number; -// struct vbe_controller controller; //struct size 512 -// struct vbe_mode mode; //struct size 255 - - errnum = 0; - if (! *arg) - { - errnum = ERR_BAD_ARGUMENT; - return 0; - } - - if (! safe_parse_maxint (&arg, &mode_number)) - return 0; - - /* Preset `VBE2'. */ - grub_memmove (controller->signature, "VBE2", 4); - - /* Detect VBE BIOS. */ - if (get_vbe_controller_info (controller) != 0x004F) - { - printf_debug0 (" VBE BIOS is not present.\n"); - return 0; - } - - if (controller->version < 0x0200) - { - printf_debug0 (" VBE version %d.%d is not supported.\n", - (unsigned long)(controller->version >> 8), - (unsigned long)(unsigned char)(controller->version)); - return 0; - } - - if (get_vbe_mode_info (mode_number, mode) != 0x004F - || (mode->mode_attributes & 0x0091) != 0x0091) - { - printf_debug0 (" Mode 0x%x is not supported.\n", mode_number); - return 0; - } - - /* Now trip to the graphics mode. */ - if (set_vbe_mode (mode_number | (1 << 14)) != 0x004F) - { - printf_debug0 (" Switching to Mode 0x%x failed.\n", mode_number); - return 0; - } - - /* Draw something on the screen... */ - { - unsigned char *base_buf = (unsigned char *) mode->phys_base; - int scanline = controller->version >= 0x0300 - ? mode->linear_bytes_per_scanline : mode->bytes_per_scanline; - /* FIXME: this assumes that any depth is a modulo of 8. */ - int bpp = (mode->bits_per_pixel + 7) / 8; - int width = mode->x_resolution; - int height = mode->y_resolution; - int x, y; - unsigned color = 0; - - /* Iterate drawing on the screen, until the user hits any key. */ - while (checkkey () == -1) - { - for (y = 0; y < height; y++) - { - unsigned char *line_buf = base_buf + scanline * y; - - for (x = 0; x < width; x++) - { - unsigned char *buf = line_buf + bpp * x; - int i; - - for (i = 0; i < bpp; i++, buf++) - *buf = (color >> (i * 8)) & 0xff; - } - - color++; - } - } - - /* Discard the input. */ - getkey (); - } - - /* Back to the default text mode. */ - if (set_vbe_mode (0x03) != 0x004F) - { -#if 1 - printf_debug0 ("\nSwitching to text mode failed!!\n"); - return 0; -#else - /* Why?! */ - grub_reboot (); -#endif - } - - return 1; -} - -static struct builtin builtin_testvbe = -{ - "testvbe", - testvbe_func, - BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, - "testvbe MODE", - "Test the VBE mode MODE. Hit any key to return." -}; - -static inline unsigned short * vbe_far_ptr_to_linear (unsigned long ptr) -{ - unsigned long seg = (ptr >> 16); - unsigned short off = (unsigned short)(ptr /* & 0xFFFF */); - - return (unsigned short *)((seg << 4) + off); -} - - -static struct vbe_mode * -find_video_mode(/*struct vbe_controller *controller,*/ int width, int height, int depth, int *mode_number) -{ - // if height == depth == 0, then width is not a width but a mode number -// static struct vbe_mode mode; - int i; - - if (!height && !depth) { - if (get_vbe_mode_info (width, mode) == 0x004F) - if ((mode->mode_attributes & 0x0091) == 0x0091) { - *mode_number = width; - return mode; - } - } - - for (i = 0; i<0x200; i++) - { - if (get_vbe_mode_info (i, mode) != 0x004F) - continue; - - /* Skip this, if this is not supported or linear frame buffer - mode is not support. */ - if ((mode->mode_attributes & 0x0091) != 0x0091) - continue; - - if (debug > 0) - printf("Mode (0x%x) %dx%dx%d %x %x\n", - (unsigned long)i, - (unsigned long)mode->x_resolution, - (unsigned long)mode->y_resolution, - (unsigned long)mode->bits_per_pixel, - (unsigned long)mode->mode_attributes, - (unsigned long)mode->phys_base); - - if ((mode->x_resolution == width) && - (mode->y_resolution == height) && - (mode->bits_per_pixel == depth)) { - *mode_number = i; - return mode; - } - } - return NULL; -} - -/* setvbe (Contributed by Gerardo Richarte. Thanks!) */ -/* set the `video=' option for the next `kernel' command. */ -static int -setvbe_func (char *arg, int flags) -{ - int mode_number; - unsigned long long width = 10000; - unsigned long long height = 10000; - unsigned long long depth = 128; - -// struct vbe_controller controller; //struct size 512 -// struct vbe_mode mode; //struct size 255 - struct vbe_mode *mode2; - - errnum = 0; - if (!*arg) - { - *kernel_option_video = 0; /* initialize the string to be empty. */ - printf_debug0 ("\nVideo option cleared. Nothing will be added to subsequent kernel command-line.\n"); - errnum = 0; - return 1; - } - - errnum = ERR_BAD_ARGUMENT; - if (! safe_parse_maxint (&arg, &width)) - return 0; - if (*arg == 'x') { - arg++; - if (! safe_parse_maxint (&arg, &height)) - return 0; - arg++; - if (! safe_parse_maxint (&arg, &depth)) - return 0; - } else { - height = depth = 0; - } - - printf_debug0 ("Trying setvbe for resolution %dx%dx%d\n", (unsigned long)width, (unsigned long)height, (unsigned long)depth); - - /* Preset `VBE2'. */ - grub_memmove (controller->signature, "VBE2", 4); - - /* Detect VBE BIOS. */ - if (get_vbe_controller_info (controller) != 0x004F) - { - printf_debug0 (" VBE BIOS is not present.\n"); - return 0; - } - - if (controller->version < 0x0200) - { - printf_debug0 (" VBE version %d.%d is not supported.\n", - (unsigned long) (controller->version >> 8), - (unsigned long)(unsigned char) (controller->version)); - return 0; - } - - mode2 = find_video_mode(/*controller,*/ width, height, depth, &mode_number); - - if (!mode2) - { - printf_debug0 (" Resolution %dx%dx%d not found. Try vbeprobe command to see available modes\n", (unsigned long)width, (unsigned long)height, (unsigned long)depth); - return 0; + to--; + } + } } - /* Now trip to the graphics mode. */ - if (set_vbe_mode (mode_number | (1 << 14)) != 0x004F) + end: + current_term = term_table + default_term; + current_term->flags = term_flags; + + /* If the interface is currently the command-line, + restart it to repaint the screen. */ + if (current_term != prev_term /*&& (flags & BUILTIN_CMDLINE)*/) + { + if (prev_term->shutdown) + prev_term->shutdown(); + if (grub_memcmp (current_term->name, "console", 7) == 0) { - printf_debug0 (" Switching to Mode 0x%x failed.\n", (unsigned long)mode_number); - return 0; + current_term->chars_per_line = 80; + current_term->max_lines = 25; + setcursor (1); } - grub_sprintf (kernel_option_video, " video=%dx%dx%d@0x%x,%d", mode2->x_resolution, mode2->y_resolution, mode2->bits_per_pixel, mode2->phys_base, ((controller->version >= 0x0300) ? (mode2->linear_bytes_per_scanline) : (mode2->bytes_per_scanline))); - - printf_debug0 ("\nThe option \"%s\" will be automatically\nappended to each subsequent kernel command-line.\n", kernel_option_video); + if (current_term->startup) + current_term->startup(); + cls(); + } - errnum = 0; return 1; } -static struct builtin builtin_setvbe = +static struct builtin builtin_terminal = { - "setvbe", - setvbe_func, - BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_MENU | BUILTIN_HELP_LIST, - "setvbe [MODE_3D]", - "Set the VBE mode MODE_3D(which is of the form 1024x768x32) for each subsequent kernel command-line." - " If no argument is specified, clear(nullify, invalidate) the video option" - " string setup by the previous setvbe command." + "terminal", + terminal_func, + BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, + "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS]\n [--lines=LINES] [--silent] [console] [graphics]", + "Select a terminal. When multiple terminals are specified, wait until" + " you push any key to continue. If both console and serial are specified," + " the terminal to which you input a key first will be selected. If no" + " argument is specified, print current setting. The option --dumb" + " specifies that your terminal is dumb, otherwise, vt100-compatibility" + " is assumed. If you specify --no-echo, input characters won't be echoed." + " If you specify --no-edit, the BASH-like editing feature will be disabled." + " If --timeout is present, this command will wait at most for SECS" + " seconds. The option --lines specifies the maximum number of lines." + " The option --silent is used to suppress messages." }; +#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */ - +static inline unsigned short * vbe_far_ptr_to_linear (unsigned int ptr); +static inline unsigned short * vbe_far_ptr_to_linear (unsigned int ptr) +{ + unsigned int seg = (ptr >> 16); + unsigned short off = (unsigned short)(ptr /* & 0xFFFF */); + + return (unsigned short *)(grub_size_t)((seg << 4) + off); +} + /* timeout */ +static int timeout_func (char *arg, int flags); static int timeout_func (char *arg, int flags) { unsigned long long ull; errnum = 0; + if (! safe_parse_maxint (&arg, &ull)) return 0; if ((int)ull > 99) ull = 99; grub_timeout = ull; + return 1; } @@ -14916,21 +11412,9 @@ static struct builtin builtin_timeout = "timeout", timeout_func, BUILTIN_MENU, -#if 0 - "timeout SEC", - "Set a timeout, in SEC seconds, before automatically booting the" - " default entry (normally the first entry defined)." -#endif }; - -/* title */ -//static int -//title_func (char *arg, int flags) -//{ -// /* This function is not actually used at least currently. */ -// return 1; -//} +static int iftitle_func (char *arg, int flags); static int iftitle_func (char *arg, int flags) { @@ -14961,16 +11445,15 @@ struct builtin builtin_title = "title", NULL/*title_func*/, 0/*BUILTIN_TITLE*/, -#if 0 - "title [NAME ...]", - "Start a new boot entry, and set its name to the contents of the" - " rest of the line, starting with the first non-space character." -#endif + "title [[$[0xRRGGBB]]TITLE] [\\n[$[0xRRGGBB]]NOTE]", + "$[0xRRGGBB] Sets the color for TITLE and NOTE.\n" + "$[] Restore COLOR STATE STANDARD." }; - -extern int tpm_init(void); + +//extern int tpm_init(void); /* tpm */ +static int tpm_func (char *arg, int flags); static int tpm_func (char *arg, int flags) { @@ -14979,7 +11462,7 @@ tpm_func (char *arg, int flags) { if (grub_memcmp (arg, "--init", 6) == 0) { - return tpm_init(); + //return tpm_init(); } else return ! (errnum = ERR_BAD_ARGUMENT); @@ -14998,251 +11481,7 @@ static struct builtin builtin_tpm = "Initialise TPM." }; - -/* unhide */ -static int -unhide_func (char *arg, int flags) -{ - errnum = 0; - /* If no arguments, unhide current partition in the current drive. */ - if (! *arg || *arg == ' ' || *arg == '\t') - { - current_drive = saved_drive; - current_partition = saved_partition; - } - else if (! set_device (arg)) - return 0; - - return set_partition_hidden_flag (0); -} - -static struct builtin builtin_unhide = -{ - "unhide", - unhide_func, - BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_MENU | BUILTIN_HELP_LIST | BUILTIN_IFTITLE, - "unhide [PARTITION]", - "Unhide PARTITION by clearing the \"hidden\" bit in its" - " partition type code. The default partition is the current" - " root device." -}; - -/* usb */ -static int -usb_func (char *arg, int flags) -{ - errnum = 0; - int i; - - if (grub_memcmp (arg, "--delay=", 8) == 0) - { - unsigned long long tmp; - arg += 8; - if (! safe_parse_maxint (&arg, &tmp)) - return 0; - if (tmp & 0xf0) - One_transfer = 0x200; - usb_delay = tmp & 0xf; - arg = skip_to (0, arg); - } - if (grub_memcmp (arg, "--init", 6) == 0) - { - printf("\r... Scanning USB devices ... "); - init_usb(); - if (!(usb_count_error & 0x80)) - { - floppies_orig = (*(char*)0x410); - harddrives_orig = (*(char*)0x475); - printf_debug0("\rFound %d USB devices. Device Num:", usb_count_error); - for (i = 0; i < usb_count_error ; i++) - { - if (usb_drive_num[i] == 0) - { - fd_geom[0].flags |= BIOSDISK_FLAG_LBA_EXTENSION; - fd_geom[0].heads = 0xff; - fd_geom[0].sectors = 0x3f; - fd_geom[0].cylinders = (unsigned long)fd_geom[0].total_sectors / 0xff / 0x3f; - } - else if (usb_drive_num[i] >= 0x9f) - cdrom_drive = usb_drive_num[i]; - - printf_debug0(" 0x%x;", usb_drive_num[i]); - } - } - else - { - printf_debug0("\rError %x. No USB device found. ", (usb_count_error)); - switch (usb_count_error) - { - case 0x80: - printf("BIOS does not support the use of INT1A PCI installation check. \n"); - break; - case 0x81: - printf("USB device enumeration failed. Try to restart. \n"); - break; - case 0x82: - printf("USB device is not ready. \n"); - break; - } - } - return 1; - } - else - return ! (errnum = ERR_BAD_ARGUMENT); -} - -static struct builtin builtin_usb = -{ - "usb", - usb_func, - BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, - "usb [--delay=0xMN] --init", - "Initialise usb2.0 device.\n" - "M: single transmission sectors. 0: 32 sectors (default); 1: 1 sectors.\n" - "N: specifies delay,reduce speed. default 0, other 1,2,3,4 etc." -}; - - - -#if 0 -/* uppermem */ -static int -uppermem_func (char *arg, int flags) -{ - if (! safe_parse_maxint (&arg, (int *)(void *) &mbi.mem_upper)) - return 0; - - mbi.flags &= ~MB_INFO_MEM_MAP; - return 1; -} - -static struct builtin builtin_uppermem = -{ - "uppermem", - uppermem_func, - BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, - "uppermem KBYTES", - "Force GRUB to assume that only KBYTES kilobytes of upper memory are" - " installed. Any system address range maps are discarded." -}; -#endif - - -/* vbeprobe */ -static int -vbeprobe_func (char *arg, int flags) -{ -// struct vbe_controller controller; //struct size 512 - unsigned short *mode_list; - unsigned long long mode_number = -1; - - errnum = 0; - if (*arg) - { - if (! safe_parse_maxint (&arg, &mode_number)) - return 0; - } - - /* Set the signature to `VBE2', to obtain VBE 3.0 information. */ - grub_memmove (controller->signature, "VBE2", 4); - - if (get_vbe_controller_info (controller) != 0x004F) - { - printf_debug0 (" VBE BIOS is not present.\n"); - return 0; - } - - /* Check the version. */ - if (controller->version < 0x0200) - { - printf_debug0 (" VBE version %d.%d is not supported.\n", - (unsigned long) (controller->version >> 8), - (unsigned long)(unsigned char) (controller->version)); - return 0; - } - - /* Print some information. */ - printf_debug0 (" VBE version %d.%d\n", - (unsigned long) (controller->version >> 8), - (unsigned long)(unsigned char) (controller->version)); - printf_debug0 (" ModeNum Attr Resolution BitPerPixel MemoryModel RGBASize RGBAPosition\n"); - - /* Iterate probing modes. */ - for (mode_list = vbe_far_ptr_to_linear (controller->video_mode); - *mode_list != 0xFFFF; - mode_list++) - { -// struct vbe_mode mode; //struct size 255 - - if (get_vbe_mode_info (*mode_list, mode) != 0x004F) - continue; - -#if 0 - /* Skip this, if this is not supported or linear frame buffer - mode is not support. */ - if ((mode->mode_attributes & 0x0081) != 0x0081) - continue; -#endif - - if (mode_number == -1 || mode_number == *mode_list) - { - char *model; - switch (mode->memory_model) - { - case 0x00: model = "Text"; break; - case 0x01: model = "CGA graphics"; break; - case 0x02: model = "Hercules graphics"; break; - case 0x03: model = "Planar"; break; - case 0x04: model = "Packed pixel"; break; - case 0x05: model = "Non-chain 4, 256 color"; break; - case 0x06: model = "Direct Color"; break; - case 0x07: model = "YUV"; break; - default: model = "Unknown"; break; - } - - printf_debug0 (" 0x%-3X %2X %4u x %-4u %2u %-12s", - (unsigned long) *mode_list, - (unsigned long) mode->mode_attributes, - (unsigned long) mode->x_resolution, - (unsigned long) mode->y_resolution, - (unsigned long) mode->bits_per_pixel, - model); - - if (mode->memory_model == 0x06) - printf_debug0 (" %u:%u:%u:%u %u:%u:%u:%u\n", - mode->red_mask_size, - mode->green_mask_size, - mode->blue_mask_size, - mode->reserved_mask_size, - mode->red_field_position, - mode->green_field_position, - mode->blue_field_position, - mode->reserved_field_position); - else - printf_debug0 ("\n"); - - if (mode_number != -1) - break; - } - } - - if (mode_number != -1 && mode_number != *mode_list) - printf_debug0 (" Mode 0x%x is not found or supported.\n", (unsigned long)mode_number); - - return 1; -} - -static struct builtin builtin_vbeprobe = -{ - "vbeprobe", - vbeprobe_func, - BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, - "vbeprobe [MODE]", - "Probe VBE information. If the mode number MODE is specified, show only" - " the information about only the mode." -}; - - +int builtin_cmd (char *cmd, char *arg, int flags); int builtin_cmd (char *cmd, char *arg, int flags) { @@ -15258,7 +11497,7 @@ builtin_cmd (char *cmd, char *arg, int flags) builtin1 = find_command (cmd); - if ((int)builtin1 != -1) + if ((grub_size_t)builtin1 != (grub_size_t)-1) { if (! builtin1 || ! (builtin1->flags & flags)) { @@ -15273,23 +11512,26 @@ builtin_cmd (char *cmd, char *arg, int flags) else return command_func (cmd, flags); } - -static int read_val(char **str_ptr,long long *val) + +//call_func,s_calc,set_func,calc_func使用 +static int read_val(char **str_ptr,long long *val) //读值 { char *p; char *arg = *str_ptr; while (*arg == ' ' || *arg == '\t') arg++; p = arg; - if (*arg == '*') arg++; - - if (! safe_parse_maxint_with_suffix (&arg,(unsigned long long *)(int)val, 0)) + if (*arg == '*') arg++; //后面紧随内存地址 + if (! safe_parse_maxint_with_suffix (&arg,(unsigned long long *)(grub_size_t)val, 0)) { return 0; } - if (*p == '*') + if (*p == '*') //取内存的值 { - *val = *((unsigned long long *)(int)*val); + if ((unsigned long long)*val >= 0x8200 && (unsigned long long)*val < 0x8400) + *val = *((unsigned long long *)(grub_size_t)IMG((grub_size_t)*val)); + else + *val = *((unsigned long long *)(grub_size_t)*val); } while (*arg == ' ' || *arg == '\t') arg++; @@ -15297,6 +11539,8 @@ static int read_val(char **str_ptr,long long *val) return 1; } +long long return_value64; +static long long s_calc (char *arg, int flags); static long long s_calc (char *arg, int flags) { @@ -15304,18 +11548,33 @@ s_calc (char *arg, int flags) long long val2 = 0; long long *p_result = &val1; char O; + int mem=0; +#if defined(__i386__) + unsigned long long r; +#endif + return_value64 = 0; errnum = 0; - if (*arg == '*') + if (grub_memcmp (arg, "--mem", 5) == 0) + { + arg += 5; + mem=1; + } + if (*arg == '*') //后面紧随内存地址 { arg++; - if (! safe_parse_maxint_with_suffix (&arg, (unsigned long long*)(int)&val1, 0)) + if (! safe_parse_maxint_with_suffix (&arg, (unsigned long long*)(grub_size_t)&val1, 0)) { return 0; } - p_result = (long long *)(int)val1; - val1 = *p_result; - while (*arg == ' ') arg++; + + if (!mem && (unsigned long long)val1 >= 0x8200 && (unsigned long long)val1 < 0x8400) + p_result = (long long *)(grub_size_t)IMG((int)val1); //取内存的值 + else + p_result = (long long *)(grub_size_t)val1; + + val1 = *p_result; + while (*arg == ' ') arg++; } else { @@ -15374,14 +11633,23 @@ s_calc (char *arg, int flags) val1 *= val2; break; case '/': - if ((long)val2 == 0) - return !(errnum = ERR_DIVISION_BY_ZERO); - val1 = (long)val1 / (long)val2; - break; + if (val2 == 0) + return !(errnum = ERR_DIVISION_BY_ZERO); +#if defined(__i386__) + val1 = (long long)grub_divmod64 (val1, val2, 0); +#else + val1 = val1 / val2; +#endif + break; case '%': - if ((long)val2 == 0) - return !(errnum = ERR_DIVISION_BY_ZERO); - val1 = (long)val1 % (long)val2; + if (val2 == 0) + return !(errnum = ERR_DIVISION_BY_ZERO); +#if defined(__i386__) + grub_divmod64 (val1, val2, &r); + val1 = (long long)r; +#else + val1 = val1 % val2; +#endif break; case '&': val1 &= val2; @@ -15403,12 +11671,16 @@ s_calc (char *arg, int flags) } } - printf_debug0(" %ld (HEX:0x%lX)\n",val1,val1); +// printf_debug0(" %ld (HEX:0x%lX)\n",val1,val1); +// printf_debug0(" %d (HEX:0x%X)\n",(int)val1,(int)val1); + printf_debug0(" %d (HEX:0x%X)\n",val1,val1); if (p_result != &val1) *p_result = val1; + return_value64 = val1; return val1; } +static int calc_func (char *arg, int flags); static int calc_func (char *arg, int flags) { @@ -15428,219 +11700,416 @@ static struct builtin builtin_calc = "\n 3.operators '| % >>' are command operator,can not have space on both sides" }; + +int FindHighestSetBit (grub_uint32_t mask); +int +FindHighestSetBit (grub_uint32_t mask) +{ + int bit = 0; + while (mask) + { + mask >>= 8; + bit += 8; + } + return bit; +} + +int max (grub_uint32_t bit1, grub_uint32_t bit2); +int +max (grub_uint32_t bit1, grub_uint32_t bit2) +{ + if (bit1 > bit2) + return bit1; + else + return bit2; +} + +int GetBitsPerPixel (struct grub_efi_gop_pixel_bitmask *PixelBits); +int +GetBitsPerPixel (struct grub_efi_gop_pixel_bitmask *PixelBits) //获得像素元素尺寸(像素位掩模) +{ + int HighestPixel = -1; //最高像素 + int BluePixel; //兰像素 + int RedPixel; //红像素 + int GreenPixel; //绿像素 + int RsvdPixel; //保留像素 + + RedPixel = FindHighestSetBit (PixelBits->r); //ff0000 查找最高点设置位(像素位掩模->兰掩模) + GreenPixel = FindHighestSetBit (PixelBits->g); //ff00 + BluePixel = FindHighestSetBit (PixelBits->b); //ff + RsvdPixel = FindHighestSetBit (PixelBits->a); //0 + HighestPixel = max (RedPixel, GreenPixel); //ff0000 + HighestPixel = max (HighestPixel, BluePixel); //ff0000 + HighestPixel = max (HighestPixel, RsvdPixel); //ff0000 + return HighestPixel; +} + +static void grub_video_gop_get_bitmask (grub_uint32_t mask, unsigned int *mask_size, unsigned int *field_pos); +static void +grub_video_gop_get_bitmask (grub_uint32_t mask, unsigned int *mask_size, + unsigned int *field_pos) //gop视频获得位掩码 +{ + int i; + int last_p; + for (i = 31; i >= 0; i--) + if (mask & (1 << i)) + break; + if (i == -1) + { + *mask_size = *field_pos = 0; + return; + } + last_p = i; + for (; i >= 0; i--) + if (!(mask & (1 << i))) + break; + *field_pos = i + 1; + *mask_size = last_p - *field_pos + 1; +} + +//0x20-0x7f及0x2191、0x2193(上下箭头)的16*16点阵字符。hex格式,lzma压缩。 +static char mini_font_lzma[] = { +0x5D,0x00,0x00,0x80,0x00,0xAC,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x0C, +0x43,0x90,0x39,0x67,0xD5,0x47,0x76,0xE2,0x4A,0xFC,0x16,0xF6,0xCE,0x1E,0x52,0x1A, +0x03,0x6A,0x5B,0x7B,0xE2,0x81,0x9A,0x24,0xEB,0x83,0x3C,0xB7,0xB8,0x17,0xFB,0x21, +0x07,0xC9,0x9E,0x94,0x4F,0x3D,0x72,0x38,0x16,0x78,0xFA,0x10,0xA1,0xD2,0xD6,0x90, +0x17,0x41,0xAE,0xBD,0x64,0x8B,0x23,0xD6,0xD0,0x09,0x00,0xEB,0x23,0x18,0x03,0x34, +0x37,0x29,0x24,0xF7,0x38,0x0D,0x5F,0xE7,0x42,0x03,0xCA,0x49,0xE8,0x5D,0xB7,0x8D, +0x76,0xAC,0x54,0x6D,0x3F,0x63,0x7E,0xE6,0x21,0xEA,0x9C,0x69,0x77,0xB2,0x8C,0x52, +0xE7,0xB6,0x68,0xFD,0x2B,0xBC,0x06,0x00,0xB6,0xB1,0xE9,0x72,0xF6,0xB3,0x88,0x40, +0xC2,0x22,0xAC,0xFF,0x50,0xFB,0x39,0xCC,0x0A,0x08,0x13,0xE0,0xE0,0x78,0xD1,0x7F, +0xAB,0xFB,0xFF,0x9B,0x2C,0x49,0xA4,0xEF,0x71,0xE8,0xBE,0x43,0x41,0x8E,0x2B,0x6A, +0xCA,0x7C,0x9F,0xF1,0xE0,0x11,0x91,0xE0,0xC6,0x38,0x0B,0xA4,0x9A,0xAE,0x5C,0x93, +0x86,0xB2,0x35,0x77,0x20,0xED,0xD7,0x53,0x2B,0xE3,0xD0,0xFA,0x20,0x2E,0xE4,0x4E, +0xF0,0x32,0xBE,0x05,0x40,0x96,0x94,0x24,0xF3,0x65,0x5F,0x73,0x07,0xF6,0x1A,0xEF, +0xF9,0x47,0xBF,0x45,0x7B,0x21,0x6C,0x59,0xD6,0x77,0xD6,0xF5,0x8F,0x4F,0x66,0xE0, +0x7E,0xF5,0x28,0x7F,0x73,0x88,0xD4,0xE1,0x76,0x7C,0xA3,0x54,0x09,0xF3,0x20,0xF5, +0x63,0xFB,0x90,0x18,0xF8,0xDB,0x09,0x1A,0xE7,0x8E,0x46,0x88,0xF6,0x6C,0x75,0x47, +0x5E,0x4A,0x79,0x02,0xFE,0x25,0x0A,0x6A,0x10,0x2B,0xB8,0x99,0x97,0x69,0x13,0x7D, +0x1D,0x59,0x02,0x06,0x8C,0x21,0x2A,0x62,0x4C,0x34,0x8E,0x13,0xCC,0x4A,0x37,0xD3, +0x95,0x02,0x90,0x45,0xE6,0xE6,0x35,0xA1,0x9D,0x1C,0x2C,0xAD,0xDD,0xCA,0xAA,0x5A, +0xC5,0xC9,0xBE,0xA6,0x83,0xC6,0xB7,0xB1,0x18,0x0C,0x7F,0x3F,0x7C,0x70,0xEF,0x07, +0x2F,0x24,0xE4,0x90,0x33,0xDF,0x29,0xDC,0x72,0x5B,0xCC,0x48,0xF6,0x7B,0x62,0x61, +0xA9,0xB3,0x90,0x9E,0x17,0xBA,0x44,0x93,0x5F,0x29,0x5D,0x42,0xBC,0x18,0x82,0x55, +0x9E,0xDA,0xF0,0xAC,0xA0,0xAC,0x1A,0xC0,0x82,0x16,0x3D,0x62,0x72,0xFE,0x90,0x0E, +0x21,0x7E,0x89,0x6A,0x23,0x1D,0x89,0xE6,0x83,0x00,0x43,0x86,0xF7,0x0C,0x50,0x2D, +0xBF,0xDC,0x70,0xB7,0xFC,0x9E,0x7C,0x8E,0x1E,0xA2,0x38,0xDF,0xCD,0x09,0x2B,0xAE, +0x16,0x7A,0xB7,0xAC,0x9B,0xF4,0xDE,0xA1,0xE7,0xB2,0x13,0x3A,0x88,0x21,0x9E,0xBE, +0x28,0x97,0x5B,0xAC,0x83,0xB0,0x00,0x48,0xC9,0x62,0x7F,0x07,0x21,0x2E,0x39,0xF3, +0x67,0x8A,0x8E,0x70,0xB2,0x57,0x7B,0x34,0x1B,0xC9,0xF3,0x05,0x13,0xAB,0x43,0x4B, +0x03,0xCB,0xC0,0x98,0xFD,0x5A,0x17,0xD4,0x7B,0xAA,0xEE,0x69,0xFC,0x94,0x52,0x4C, +0x3A,0x5A,0x75,0x3A,0xC6,0x6B,0xB6,0x57,0x62,0xE8,0xCC,0xF1,0xC9,0xA6,0xE9,0x0A, +0x92,0x09,0x39,0x8F,0x55,0x15,0x2C,0x87,0x41,0x4F,0xFE,0xE8,0xDF,0xDD,0x62,0x30, +0x30,0xBA,0x0F,0x8F,0xAA,0xF9,0x44,0x0E,0xAC,0x5A,0x52,0x0D,0x3A,0x2E,0x5F,0x44, +0x47,0xC5,0x0D,0x01,0x16,0x7D,0xA5,0x55,0xCE,0x29,0x4A,0xF2,0x27,0xE3,0x54,0x91, +0xE8,0x1C,0x30,0x8C,0x48,0x7C,0x1D,0x78,0xB3,0x3A,0xF7,0xEB,0xB2,0xC9,0x8B,0xA1, +0xE5,0x18,0x68,0xA3,0xCD,0x51,0x3B,0x52,0x60,0xF0,0xC6,0xD1,0x49,0xE8,0x1E,0xC7, +0xE4,0x6C,0x36,0x71,0x14,0x07,0x9C,0xE9,0xE4,0x33,0xE4,0x44,0x1D,0xB6,0x78,0x95, +0x6E,0x68,0x79,0xAF,0x88,0x2C,0xCC,0x56,0xC0,0x00,0x93,0xFF,0x8B,0x5B,0xB7,0x29, +0xE4,0xEA,0x79,0x18,0xAE,0xA8,0xD1,0x9D,0x1F,0xBC,0x35,0x51,0x3F,0x05,0xB7,0x9E, +0x05,0xE3,0x21,0xC5,0xB9,0x69,0xC3,0x24,0x9D,0x33,0x9C,0xEB,0x28,0xCF,0x0E,0x63, +0x02,0x32,0xFE,0x80,0x53,0xB7,0x22,0x0C,0xCD,0x07,0x57,0x0F,0x5B,0x0C,0xD2,0x31, +0xEA,0x53,0x70,0xF5,0xD5,0x2F,0x99,0x4E,0xA3,0xA6,0x36,0x6D,0x25,0x36,0x28,0x1E, +0x49,0x74,0xC8,0x51,0xB9,0x0F,0x9B,0x22,0xF9,0xD8,0x27,0x9E,0xC6,0xC3,0x68,0x95, +0x84,0x67,0x87,0xF2,0x95,0x0D,0x48,0xF4,0x96,0x31,0x61,0x68,0xDD,0x4A,0xEC,0x40, +0x30,0x03,0x21,0x6D,0x58,0xC8,0x94,0x57,0x91,0x30,0x79,0x9C,0x28,0xB8,0x1E,0x04, +0xBB,0x86,0xA8,0x3C,0x50,0xD0,0x5A,0xD7,0x38,0x15,0xC5,0x92,0xD6,0xE5,0xB6,0xE6, +0x4D,0x8B,0xE4,0xC9,0xFB,0xA3,0xF5,0x27,0x21,0x9C,0x9B,0xBF,0x6D,0x11,0xD3,0x04, +0x50,0x98,0xA5,0xD3,0x3F,0x95,0x5C,0x32,0x05,0xC9,0xD9,0xEA,0xED,0xF7,0x0A,0x31, +0xD9,0x51,0xC5,0x46,0xD0,0xB8,0x67,0x58,0x80,0x06,0x8E,0x75,0x39,0x33,0x21,0x24, +0x68,0x25,0x46,0xBE,0x09,0xCC,0x4F,0x0B,0x30,0x3C,0x04,0xD5,0x6A,0x54,0xD3,0xB8, +0x0E,0x52,0x7D,0xD6,0x80,0x08,0xC8,0x71,0x06,0x3E,0xAF,0xC7,0xAA,0xF7,0x2D,0x76, +0x9E,0x42,0x0F,0x43,0x63,0xBC,0x5B,0x20,0x27,0xE6,0xB7,0xBA,0xA3,0xD8,0xD4,0xF1, +0x5A,0xE2,0x84,0xE7 +}; + /* graphicsmode */ +int graphicsmode_func (char *arg, int flags); int graphicsmode_func (char *arg, int flags) { #ifdef SUPPORT_GRAPHICS -// extern unsigned long current_x_resolution; -// extern unsigned long current_y_resolution; -// extern unsigned long current_bits_per_pixel; -// extern unsigned long current_bytes_per_scanline; -// extern unsigned long current_phys_base; - unsigned long long tmp_graphicsmode; - int old_graphics_mode = graphics_mode; + unsigned long long tmp_graphicsmode = -1; char *x_restrict = "0:-1"; char *y_restrict = "0:-1"; char *z_restrict = "0:-1"; + unsigned int x = 0, x0 = 0; /* x_resolution */ + unsigned int y = 0, y0 = 0; /* y_resolution */ + unsigned int z = 0, z0 = 0; /* bits_per_pixel */ + grub_efi_handle_t *handles; + grub_efi_uintn_t num_handles; + unsigned int bytes_per_scanline=0, bits_per_pixel, bytes_per_scanline0=0; + static struct grub_efi_gop *gop; + unsigned int red_mask_size, green_mask_size, blue_mask_size, reserved_mask_size; + unsigned int red_field_pos, green_field_pos, blue_field_pos, reserved_field_pos; + int mode, test = 0; + static grub_efi_guid_t graphics_output_guid = GRUB_EFI_GOP_GUID; + grub_efi_status_t status; errnum = 0; if (! *arg) { - tmp_graphicsmode = graphics_mode; - goto enter_graphics_mode; + printf ("The current graphic mode is %d.\n",graphics_mode); + return graphics_mode; + } + + if (grub_memcmp (arg, "--info", 6) == 0) + { + tmp_graphicsmode = 0x2ff; + } + else if (grub_memcmp (arg, "--test", 6) == 0) + { + test = 1; + arg += 6; + goto transfer; } else if (safe_parse_maxint (&arg, &tmp_graphicsmode)) { - if (tmp_graphicsmode > 0xFF) /* VBE */ - { - unsigned short *mode_list; - unsigned long mode_found = 0; - unsigned long x = 0; /* x_resolution */ - unsigned long y = 0; /* y_resolution */ - unsigned long z = 0; /* bits_per_pixel */ -#define _X_ ((unsigned long)mode->x_resolution) -#define _Y_ ((unsigned long)mode->y_resolution) -#define _Z_ ((unsigned long)mode->bits_per_pixel) - - if ((unsigned long)tmp_graphicsmode == -1) /* mode auto detect */ - { - unsigned long long tmp_ll; - char *tmp_arg; - - tmp_arg = arg = wee_skip_to (arg, 0); - if (! *arg) - goto xyz_done; - if (! safe_parse_maxint (&arg, &tmp_ll)) - goto bad_arg; - if (tmp_ll != -1ULL || (unsigned char)*arg > ' ') - x_restrict = tmp_arg; - - tmp_arg = arg = wee_skip_to (arg, 0); - if (! *arg) - goto xyz_done; - if (! safe_parse_maxint (&arg, &tmp_ll)) - goto bad_arg; - if (tmp_ll != -1ULL || (unsigned char)*arg > ' ') - y_restrict = tmp_arg; - - tmp_arg = arg = wee_skip_to (arg, 0); - if (! *arg) - goto xyz_done; - if (! safe_parse_maxint (&arg, &tmp_ll)) - goto bad_arg; - if (tmp_ll != -1ULL || (unsigned char)*arg > ' ') - z_restrict = tmp_arg; - } + if ((unsigned int)tmp_graphicsmode == (unsigned int)-1) /* mode auto detect */ + { + unsigned long long tmp_ll; + char *tmp_arg; +transfer: + tmp_arg = arg = wee_skip_to (arg, 0); + if (! *arg) //只有 -1 + goto xyz_done; + if (! safe_parse_maxint (&arg, &tmp_ll)) + goto bad_arg; + if (tmp_ll != -1ULL || (unsigned char)*arg > ' ') + x_restrict = tmp_arg; + + tmp_arg = arg = wee_skip_to (arg, 0); + if (! *arg) + goto xyz_done; //只有 -1 x + if (! safe_parse_maxint (&arg, &tmp_ll)) + goto bad_arg; + if (tmp_ll != -1ULL || (unsigned char)*arg > ' ') + y_restrict = tmp_arg; + + tmp_arg = arg = wee_skip_to (arg, 0); + if (! *arg) + goto xyz_done; //只有 -1 x y + if (! safe_parse_maxint (&arg, &tmp_ll)) + goto bad_arg; + if (tmp_ll != -1ULL || (unsigned char)*arg > ' ') + z_restrict = tmp_arg; //全部 -1 x y z + }//if ((unsigned long)tmp_graphicsmode == -1) + }//lse if (!safe_parse_maxint (&arg, &tmp_graphicsmode)) + else + goto bad_arg; xyz_done: - /* Preset `VBE2'. */ - grub_memmove (controller->signature, "VBE2", 4); - - /* Detect VBE BIOS. */ - if (get_vbe_controller_info (controller) != 0x004F) - return !(errnum = ERR_NO_VBE_BIOS); - - if (memcmp ((char*)controller->signature, "VESA", 4) != 0) - return !(errnum = ERR_BAD_VBE_SIGNATURE); + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, + &graphics_output_guid, NULL, &num_handles); //定位手柄(通过协议, + if (!handles || num_handles == 0) //如果句柄为零, 或者句柄数为零 + return 0; //错误 +// for (i = 0; i < num_handles; i++) +// { +// gop_handle = handles[0]; //句柄 + gop = grub_efi_open_protocol (handles[0], &graphics_output_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); //打开协议 + if (tmp_graphicsmode == 0x2ff) + { + printf_debug0 ("GOP Video current_mode=%d, physical_address=0x%lx, size=0x%x\n",graphics_mode,gop->mode->fb_base,gop->mode->fb_size);//80000000,1d4c00; + printf_debug0 ("Mode Format Resolution BitPixel RGBASize RGBAPos PixelsScanline\n"); + } + for (mode = gop->mode->max_mode - 1; mode >= 0; mode--) + { + grub_efi_uintn_t size1; + struct grub_efi_gop_mode_info *info = NULL; + status = efi_call_4 (gop->query_mode, gop, mode, &size1, &info); //gop查询模式 通过mode查询, 返回模式尺寸及信息 - if (controller->version < 0x0200) - return !(errnum = ERR_LOW_VBE_VERSION); + if (status) //失败 + goto bad_arg; + switch (info->pixel_format) + { + case GRUB_EFI_GOT_RGBA8: + red_mask_size = 8; + red_field_pos = 0; + green_mask_size = 8; + green_field_pos = 8; + blue_mask_size = 8; + blue_field_pos = 16; + reserved_mask_size = 8; + reserved_field_pos = 24; + bits_per_pixel = sizeof (struct grub_efi_gop_blt_pixel) << 3; + break; - //if ((unsigned long)tmp_graphicsmode == -1) /* mode auto detect */ - - /* Iterate probing modes. */ - mode_list = vbe_far_ptr_to_linear (controller->video_mode); - for (; *mode_list != 0xFFFF; mode_list++) - { - if (get_vbe_mode_info (*mode_list, mode) != 0x004F) - continue; + case GRUB_EFI_GOT_BGRA8: + red_mask_size = 8; + red_field_pos = 16; + green_mask_size = 8; + green_field_pos = 8; + blue_mask_size = 8; + blue_field_pos = 0; + reserved_mask_size = 8; + reserved_field_pos = 24; + bits_per_pixel = sizeof (struct grub_efi_gop_blt_pixel) << 3; + break; - if (*mode_list <= 0xFF) - continue; + case GRUB_EFI_GOT_BITMASK: + grub_video_gop_get_bitmask (info->pixel_bitmask.r, &red_mask_size, &red_field_pos); + grub_video_gop_get_bitmask (info->pixel_bitmask.g, &green_mask_size, &green_field_pos); + grub_video_gop_get_bitmask (info->pixel_bitmask.b, &blue_mask_size, &blue_field_pos); + grub_video_gop_get_bitmask (info->pixel_bitmask.a, &reserved_mask_size, &reserved_field_pos); + bits_per_pixel = GetBitsPerPixel (&info->pixel_bitmask); //输出信息->像素位掩模 + break; - if (*mode_list != 0x102) - { - /* Skip this, if this is not supported or linear frame buffer - mode is not support. or not a graphics mode */ - if ((mode->mode_attributes & 0x0091) != 0x0091) - continue; + default: + return printf_warning ("unsupported video mode"); + } + + if (tmp_graphicsmode == 0x2ff) + { + printf_debug0 ("%d %d %4u x %-4u %u %u:%u:%u:%u %02u:%02u:%02u:%02u %u\n", + mode | 0x100,info->pixel_format,info->width,info->height, bits_per_pixel, red_mask_size, green_mask_size, blue_mask_size, + reserved_mask_size, red_field_pos, green_field_pos, blue_field_pos, reserved_field_pos, info->pixels_per_scanline); + } - if (mode->phys_base == 0) - continue; - - if ((mode->phys_base & 0x0F)) /* Unaligned !! */ - continue; - - if (mode->memory_model != 6) /* Direct Color */ - continue; - -// if (mode->bits_per_pixel != 24 && mode->bits_per_pixel != 32 && mode->bits_per_pixel != 16 && _Z_ < 0x10) -// continue; - } - /* ok, find out one valid mode. */ - if (tmp_graphicsmode == *mode_list) /* the specified mode */ - { - x = _X_; - y = _Y_; - z = _Z_; - current_bytes_per_scanline = ((controller->version >= 0x0300) - ? mode->linear_bytes_per_scanline - : mode->bytes_per_scanline); - current_phys_base = mode->phys_base; - mode_found = *mode_list; - break; /* done. */ +#define _X_ ((unsigned int)info->width) +#define _Y_ ((unsigned int)info->height) +#define _Z_ ((unsigned int)bits_per_pixel) + /* ok, find out one valid mode. */ + if ((tmp_graphicsmode & 0xff) == (unsigned long long)mode) /* the specified mode */ + { + x = _X_; + y = _Y_; + z = _Z_; + bytes_per_scanline = info->pixels_per_scanline * (bits_per_pixel >> 3); +// status = efi_call_2 (gop->set_mode, gop, mode); //gop设置模式 +// if (status) //失败 +// goto bad_arg; + break; } - if ((unsigned long)tmp_graphicsmode == -1 /* mode auto detect */ - && x * y * z < _X_ * _Y_ * _Z_ - && in_range (x_restrict, _X_) - && in_range (y_restrict, _Y_) - && in_range (z_restrict, _Z_) - ) + else if ((unsigned int)tmp_graphicsmode == (unsigned int)-1 /* mode auto detect */ + && x * y * z < _X_ * _Y_ * _Z_ + && in_range (x_restrict, _X_) + && in_range (y_restrict, _Y_) + && in_range (z_restrict, _Z_)) { - x = _X_; - y = _Y_; - z = _Z_; - current_bytes_per_scanline = ((controller->version >= 0x0300) - ? mode->linear_bytes_per_scanline - : mode->bytes_per_scanline); - current_phys_base = mode->phys_base; - mode_found = *mode_list; + x = _X_; + y = _Y_; + z = _Z_; + bytes_per_scanline = info->pixels_per_scanline * (bits_per_pixel >> 3); +// status = efi_call_2 (gop->set_mode, gop, mode); //gop设置模式 +// if (status) //失败 +// goto bad_arg; + tmp_graphicsmode = 0x100 | mode; + break; } - } /* for */ - if (mode_found <= 0xFF) - return !(errnum = ERR_NO_VBE_MODES); - - tmp_graphicsmode = mode_found; - current_x_resolution = x; - current_y_resolution = y; - current_bits_per_pixel = z; - current_bytes_per_pixel = (z+7)/8; + else if (mode == 0) + { + x0 = _X_; + y0 = _Y_; + z0 = _Z_; + bytes_per_scanline0 = info->pixels_per_scanline * (bits_per_pixel >> 3); + } + } //for (mode = 0; mode < gop->mode->max_mode; mode++) +// }//for (i = 0; i < num_handles; i + #undef _X_ #undef _Y_ #undef _Z_ + + if ((unsigned int)tmp_graphicsmode == (unsigned int)-1) + { + if (test) + return 0; + tmp_graphicsmode = 0x100; + x = x0; + y = y0; + z = z0; + bytes_per_scanline = bytes_per_scanline0; + } + + if (tmp_graphicsmode == 0x2ff) + { +// return graphics_mode; + goto ok; + } + else if (tmp_graphicsmode == 3 && graphics_mode != 3) //在控制台设置模式3会死机。 + { + cls(); + graphics_end (); + current_term->chars_per_line = 80; + current_term->max_lines = 25; + graphics_mode = tmp_graphicsmode; + goto ok; + } + else if (tmp_graphicsmode > 0xff) + { + if (test) + return tmp_graphicsmode; + status = efi_call_2 (gop->set_mode, gop, tmp_graphicsmode & 0xff); //gop设置模式 + if (status) //失败 + goto bad_arg; + current_x_resolution = x; + current_y_resolution = y; + current_bits_per_pixel = z; + current_bytes_per_pixel = (z+7)/8; + current_phys_base = gop->mode->fb_base; + current_bytes_per_scanline = bytes_per_scanline; + + if (IMAGE_BUFFER) + grub_free (IMAGE_BUFFER); +// IMAGE_BUFFER = grub_malloc (current_x_resolution * current_y_resolution * current_bytes_per_pixel);//应当在加载图像前设置 + //可能info->pixels_per_scanline >= info->width 2023-03-26 +// IMAGE_BUFFER = grub_zalloc (current_bytes_per_scanline * current_y_resolution);//应当在加载图像前设置 使用grub_malloc,切换分辨率可能花屏。2023-08-24 + IMAGE_BUFFER = grub_malloc (current_bytes_per_scanline * current_y_resolution); //如果设置了返回主菜单不重新加载背景图,背景图会被清除。2023-09-25 + if (graphics_mode != (unsigned int)tmp_graphicsmode) //如果当前图形模式与设置的不同 + { + menu_tab_ext &= 0xfd; //清除背景图已加载标记 + grub_memset (IMAGE_BUFFER, 0, current_bytes_per_scanline * current_y_resolution); //清除背景图,避免切换分辨率可能花屏 2023-09-25 } - else if (tmp_graphicsmode == 3) + if (!JPG_FILE) + { + JPG_FILE = grub_zalloc (0x8000); //使用grub_malloc,切换分辨率可能花屏。2023-08-24 + } + if (!UNIFONT_START) { - if (graphics_inited) + if (embed_font_path[0]) { - if (current_term->shutdown) - current_term->shutdown(); + font_func (embed_font_path, 1); + grub_free (embed_font); + menu_tab_ext &= 0xfb; //清除字库已加载标记 } else { - if (current_term != term_table) /* terminal console */ - current_term = term_table; /* terminal console */ + //进入图形模式,加载袖珍字库,防止黑屏。这样也可以使防止加载精简中文字库(不包含英文字符)的问题。 + grub_memmove ((char *)0x10000, mini_font_lzma, 820); + font_func ("(md)0x80+2", 1); //如果是gz压缩格式,要明确压缩文件尺寸,如:font_func ("(md)0x80+2,820", 1); + menu_tab_ext &= 0xfb; //清除字库已加载标记 } - return old_graphics_mode; } -enter_graphics_mode: - if (graphics_mode != (unsigned long)tmp_graphicsmode - || current_term != term_table + 1 /* terminal graphics */ - ) + + if (graphics_mode != (unsigned int)tmp_graphicsmode //如果当前视频模式不是探测图形模式 + || current_term != term_table + 1) /* terminal graphics */ //或者当前终端不是图像终端 { graphics_mode = tmp_graphicsmode; - if (graphics_inited) - { - struct term_entry *prev_term = current_term; - if (current_term->shutdown) - current_term->shutdown(); - current_term = prev_term; - if (current_term->startup) - current_term->startup(); - } - else if (graphics_mode > 0xFF) - { - current_term = term_table + 1; /* terminal graphics */ - if (current_term->startup) - current_term->startup(); - } - if (! errnum) + if (graphics_inited) //如果在图形模式 { - printf_debug0 (" Graphics mode number set to 0x%X\n", graphics_mode); - } + current_term->chars_per_line = current_x_resolution / (font_w + font_spacing); + current_term->max_lines = current_y_resolution / (font_h + line_spacing); + } else { - graphics_mode = old_graphics_mode; + console_setcursor(0); //避免转到后图形模式后,在某一固定位置遗留一个文本模式的光标。 + console_shutdown (); //视乎不起作用。 + graphics_init(); } } - else /* already in graphics mode. */ - { - printf_debug0 (" Graphics mode number was already 0x%X\n", graphics_mode); - } - } - else - { -bad_arg: - if (errnum == 0) - errnum = ERR_BAD_ARGUMENT; - return 0; - } - - return old_graphics_mode; -#else - return 0x12; + cls(); + } //else if (safe_parse_maxint (&arg, &tmp_graphicsmode)) #endif +ok: + if (graphics_mode > 0xFF) + menu_tab_ext |= 1; //已在图形模式 +// else +// menu_tab_ext &= 0xfe; //清除图形模式标记 + return graphics_mode; +bad_arg: + errnum = ERR_BAD_ARGUMENT; + return 0; } struct builtin builtin_graphicsmode = @@ -15648,20 +12117,21 @@ struct builtin builtin_graphicsmode = "graphicsmode", graphicsmode_func, BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, - "graphicsmode [MODE] [RANGE_X_RESOLUTION [RANGE_Y_RESOLUTION [RANGE_COLOR_DEPTH]]]", - "value = -1 - no restriction. Only 24-bit and 32-bit 'Direct Color' modes\n" - " are supported. Examples:\n" - "graphicsmode 3 (set text mode - 80x25 characters)\n" + "graphicsmode [--info] [--test] [MODE] [-1 | RANGE_X_RESOLUTION]", + "Examples:\n" + "graphicsmode (display graphic information)\n" "graphicsmode ;; set /A GMODE=%@retval% (get current mode)\n" - "graphicsmode -1 (switch to highest 24 or 32-bit color mode available)\n" - "graphicsmode -1 800 -1 24:32 (switch to highest mode for 800 pixel width)\n" - "graphicsmode -1 100:1000 100:1000 24:32 (highest mode available below x/y = 1001/1001)\n" - "graphicsmode -1 800 600 24:32 (switch to highest 800x600 graphics mode)" + "graphicsmode --info (Returns the currently supported graphics mode)\n" + "graphicsmode --test (Test whether the specified graphics mode exists)\n" + "graphicsmode -1 (auto select mode)\n" + "graphicsmode -1 800 (switch to highest mode for 800 pixel width)\n" + "graphicsmode -1 100:1000 (The highest mode available in the range of x = 100-1000)" }; char menu_init_script_file[32]; +static int initscript_func (char *arg, int flags); static int initscript_func (char *arg, int flags) { @@ -15682,7 +12152,7 @@ static struct builtin builtin_initscript = BUILTIN_MENU, }; - +static int echo_func (char *arg,int flags); static int echo_func (char *arg,int flags) { @@ -15694,6 +12164,7 @@ echo_func (char *arg,int flags) unsigned int echo_ec = 0; unsigned long long saved_color_64; unsigned char saved_color; + unsigned char img = 0; //y = getxy(); //x = (unsigned int)(unsigned char)y; //y = (unsigned int)(unsigned char)(y >> 8); @@ -15706,9 +12177,24 @@ echo_func (char *arg,int flags) { arg += 3; char c = 0; - if (*arg == '-') c=*arg++; - y = ((*arg++ - '0') & 15)*10; - y += ((*arg++ - '0') & 15); + char s[5] = {0}; + char* p = s; + unsigned long long length; + int i=2, j=0; + if (*arg == '-') c=*arg++; + if (*arg == '0' && (arg[1]|32) == 'x') + { + if (arg[3] == '-' || (arg[4]|32) == 'x') + i = 3; + else + i = 4; + } + while(i--) + s[j++] = *arg++; + safe_parse_maxint (&p, &length); + y = length; +// y = ((*arg++ - '0') & 15)*10; +// y += ((*arg++ - '0') & 15); if ( c != '\0' ) { y = current_term->max_lines - y; @@ -15716,9 +12202,10 @@ echo_func (char *arg,int flags) } if (*arg == '-') c = *arg++; - - x = ((*arg++ - '0') & 15)*10; - x += ((*arg++ - '0') & 15); + safe_parse_maxint (&arg, &length); + x = length; +// x = ((*arg++ - '0') & 15)*10; +// x += ((*arg++ - '0') & 15); if (c != 0) x = current_term->chars_per_line - x; //saved_xy = getxy(); saved_x = fontx; @@ -15732,7 +12219,7 @@ echo_func (char *arg,int flags) printf(" 0 1 2 3 4 5 6 7-L-0 1 2 3 4 5 6 7"); for (i=0;i<16;i++) { - if (y < current_term->max_lines-1) + if (y < (unsigned int)current_term->max_lines-1) y++; else { @@ -15784,7 +12271,7 @@ echo_func (char *arg,int flags) return 1; } - if (y < current_term->max_lines-1) + if (y < (unsigned int)current_term->max_lines-1) y++; else putchar('\n', 255); @@ -15816,23 +12303,41 @@ echo_func (char *arg,int flags) gotoxy(saved_x, saved_y); return 1; } - else if (grub_memcmp(arg,"-mem=",3) == 0) //-mem=offset=length + else if (grub_memcmp(arg,"--uefi-img",10) == 0) + { + printf("%x",(grub_size_t)g4e_data); + return 1; + } + else if (grub_memcmp(arg,"--img=",6) == 0) //--img=offset=length + { + img = 1; + goto mem; + } + else if (grub_memcmp(arg,"-mem=",5) == 0) //-mem=offset=length 怪怪的, 为了所谓'兼容' + { + arg--; + goto mem; + } + else if (grub_memcmp(arg,"--mem=",6) == 0) //--mem=offset=length { +mem: + arg += 6; + unsigned long long offset; unsigned long long length; unsigned char s[16]; - unsigned long long j = 16; - - arg += 5; + unsigned int j = 16; + safe_parse_maxint (&arg, &offset); arg++; safe_parse_maxint (&arg, &length); - + if (j > length) j = length; + while (1) { - grub_memmove64((unsigned long long)(int)s, offset, j); + grub_memmove((void *)(grub_size_t)s, (const void *)(grub_size_t)(img ? (offset - 0x8200 + (grub_size_t)g4e_data) : offset), j); hexdump(offset,(char*)&s,j); if (quit_print) break; @@ -15844,6 +12349,11 @@ echo_func (char *arg,int flags) } return 1; } + else if (grub_memcmp(arg,"--uefi-v",8) == 0) + { + printf("UEFI revision: %x\n",grub_efi_system_table->hdr.revision); + return 1; + } else break; arg = skip_to (0,arg); } @@ -15879,6 +12389,7 @@ echo_func (char *arg,int flags) else { current_color_64bit = ull; + current_color = color_64_to_8 (current_color_64bit); } arg = p + 1; } @@ -15887,15 +12398,15 @@ echo_func (char *arg,int flags) else if (arg[6] == ']') { int char_attr = 0; - if (arg[2] & 7) + if (arg[2] & 7) //A 只要位:0-6有值(位7无效), 高亮字符背景色 char_attr |= 0x80; - if (arg[3] & 7) + if (arg[3] & 7) //B 只要位:0-6有值(位7无效), 高亮字符前景色 char_attr |= 8; - char_attr |= (arg[4] & 7) << 4; - char_attr |= (arg[5] & 7); + char_attr |= (arg[4] & 7) << 4; //C 位:0-6 字符背景色, 位7无效 + char_attr |= (arg[5] & 7); //D 位:0-6 字符前景色, 位7无效 current_color = char_attr; current_color_64bit = color_8_to_64 (current_color); - if (!(current_color & 0x70)) + if (!(current_color & 0x70)) //如果字符背景色位3有值, 使用原始背景色 { current_color |= saved_color; current_color_64bit |= saved_color_64; @@ -15903,10 +12414,12 @@ echo_func (char *arg,int flags) arg += 7; } } - - grub_putchar((unsigned char)*arg, 255); + if (current_term->setcolorstate) + current_term->setcolorstate (current_color | 0x100); //控制台直接输入颜色 +// grub_putchar((unsigned char)*arg, 255); //移动到判断之后,避免打印‘\0’ 2022-11-05 if (!(*arg)) break; + grub_putchar((unsigned char)*arg, 255); } if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_STANDARD); @@ -15924,8 +12437,9 @@ static struct builtin builtin_echo = "echo", echo_func, BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, - "echo [-P:XXYY] [-h] [-e] [-n] [-v] [-rrggbb] [-mem=offset=length] [[$[ABCD]]MESSAGE ...] ", + "echo [-P:XXYY] [-h] [-e] [-n] [-v] [-rrggbb] [--uefi-img] [--uefi-v]\n [[--mem | --img]=offset=length] [[$[ABCD]]MESSAGE ...]", "-P:XXYY position control line(XX) and column(YY).\n" + " XX(YY) are both 2 digit decimal or both 3/4 character hex. Can precede with - sign for position from end.\n" "-h show a color panel.\n" "-n do not output the trailing newline.\n" "-e enable interpretation of backslash escapes.\n" @@ -15933,19 +12447,34 @@ static struct builtin builtin_echo = " \\Xnnnn show unicode characters(big endian).\n" "-v show version and memory information.\n" "-rrggbb show 24 bit colors.\n" - "-mem=offset=length hexdump.\n" + "--uefi-img show the main program (pre_stage2) entrance of UEFI.\n" + "--uefi-v show UEFI version.\n" + "--mem=memory_offset=length hexdump.\n" + "--img=pre_stage2_offset=length hexdump.\n" "$[ABCD] the color for MESSAGE.(console only, 8 bit number)\n" "A=bright background, B=bright characters, C=background color, D=Character color.\n" - "$[0xCD] 8 or 64 bit number value for MESSAGE. C=background, D=Character.\n" - "$[] using COLOR STATE STANDARD." + "$[0xCD] Sets the 8 or 64 bit numeric color for MESSAGE.\n" + " C=background(high 32 bits), D=Character(low 32 bits).\n" + "$[] Restore COLOR STATE STANDARD." }; +int else_disabled = 0; //else禁止 +int brace_nesting = 0; //大括弧嵌套数 +int is_else_if; //是else_if调用 +static int if_func(char *arg,int flags); static int if_func(char *arg,int flags) { char *str1,*str2; int cmp_flag = 0; long long ret = 0; errnum = 0; + + + if (is_else_if) //如果是else_if调用, 则自身复位 + is_else_if = 0; + else if (!brace_nesting) //如果不是else_if调用, 并且大括弧嵌套数为零, 则清除else禁止 + else_disabled = 0; + while(*arg) { if (substring("/i ", arg, 1) == -1) @@ -15989,7 +12518,7 @@ static int if_func(char *arg,int flags) errnum = ERR_BAD_ARGUMENT; return 0; } - cmpn = (unsigned long)(*arg - '='); + cmpn = (unsigned int)(*arg - '='); *arg = 0; arg = skip_to (SKIP_WITH_TERMINATE,str2); if (safe_parse_maxint(&s1,&v1) && safe_parse_maxint(&str2,&v2)) @@ -16021,12 +12550,14 @@ static struct builtin builtin_if = }; -static unsigned long var_ex_size; +static unsigned int var_ex_size; static VAR_NAME *var_ex; static VAR_VALUE *var_ex_value; #define FIND_VAR_FLAG_EXISTS 0x10000 #define FIND_VAR_FLAG_VAR_EX 0x20000 -static long find_var(const char *ch,const int flag) + +static int find_var(const char *ch,const int flag); +static int find_var(const char *ch,const int flag) { int i,j = -1; //ch[0] == '?' && ch[1] == '\0'; @@ -16039,18 +12570,18 @@ static long find_var(const char *ch,const int flag) if (*ch != '?' && var_ex_size > 0) { int k; - for(k=0; k < var_ex_size && var_ex[k][0]; ++k) + for(k=0; k < (int)var_ex_size && var_ex[k][0]; ++k) { if (memcmp(var_ex[k], ch, MAX_VAR_LEN) == 0) return k | FIND_VAR_FLAG_EXISTS | FIND_VAR_FLAG_VAR_EX; if (j == -1 && var_ex[k][0] == '@') j = k | FIND_VAR_FLAG_VAR_EX; } - if (i == MAX_VARS && k < var_ex_size) + if (i == MAX_VARS && k < (int)var_ex_size) i = k | FIND_VAR_FLAG_VAR_EX; } if (flag == 1 || (j == -1 && i == MAX_VARS )) return -1; - return ((unsigned int)j < i)? j : i; + return ((unsigned int)j < (unsigned int)i)? j : i; } /* flags: @@ -16068,7 +12599,7 @@ int envi_cmd(const char *var,char * const env,int flags) memset( (char *)BASE_ADDR, 0, 512 ); sprintf(VAR[_WENV_], "?_WENV"); sprintf(VAR[_WENV_+1], "?_BOOT"); - QUOTE_CHAR = '\"'; +// QUOTE_CHAR = '\"'; return 1; } @@ -16087,9 +12618,10 @@ int envi_cmd(const char *var,char * const env,int flags) printf("%.8s=%.512s\n",VAR[i],ENVI[i]); } } + if (var_ex_size > 0) { - for(i=0; i < var_ex_size && var_ex[i][0]; ++i) + for(i=0; i < (int)var_ex_size && var_ex[i][0]; ++i) { if (var_ex[i][0] < 'A') continue; @@ -16150,25 +12682,28 @@ int envi_cmd(const char *var,char * const env,int flags) */ if (ch[0]=='@') { - unsigned long date, time; + struct grub_datetime datetime; if (flags != 1) return 0; p = WENV_TMP; - get_datetime(&date, &time); + memset(p, 0, 512 - 0x80); + + get_datetime(&datetime); if (substring(ch,"@date",1) == 0) { - sprintf(p,"%04X-%02X-%02X",(date >> 16),(char)(date >> 8),(char)date); + sprintf(p,"%04d-%02d-%02d",datetime.year,datetime.month,datetime.day); } else if (substring(ch,"@time",1) == 0) { - sprintf(p,"%02X:%02X:%02X",(char)(time >> 24),(char)(time >> 16),(char)(time>>8)); + sprintf(p,"%02d:%02d:%02d",datetime.hour,datetime.minute,datetime.second); } else if (substring(ch,"@random",1) == 0) { - WENV_RANDOM = (WENV_RANDOM * date + (*(int *)0x46c)) & 0x7fff; +// WENV_RANDOM = (WENV_RANDOM * (*(unsigned int *)&datetime) + (*(int *)0x46c)) & 0x7fff; + WENV_RANDOM = (((datetime.minute << 8) + WENV_RANDOM + 1) * (datetime.second + 1)) & 0x7fff; sprintf(p,"%d",WENV_RANDOM); } else if (substring(ch,"@boot",1) == 0) @@ -16191,16 +12726,19 @@ int envi_cmd(const char *var,char * const env,int flags) p = command_path; } else if (substring(ch,"@retval",1) == 0) - sprintf(p,"%d",*(int*)0x4CB00); + sprintf(p,"%d",return_value); + else if (substring(ch,"@retval64",1) == 0) + sprintf(p,"%ld",return_value64); #ifdef PATHEXT else if (substring(ch,"@pathext",1) == 0) sprintf(p,"%s",PATHEXT); #endif + else if (substring(ch,"@uefi",1) == 0) + sprintf(p,"%d",*(char *)IMG(0x8272)); else return 0; - j = FIND_VAR_FLAG_EXISTS; } - else if (*(short *)ch == 0x3f || *(grub_u64_t*)ch == 0x564e45575f3fLL || *(grub_u64_t*)ch == 0x444955555f3fLL)//?_UUID ?_WENV + else if (*(short *)ch == 0x3f || *(grub_u64_t*)ch == 0x564e45575f3fLL || *(grub_u64_t*)ch == 0x444955555f3fLL) //"?" "?_UUID" "?_WENV" { p = WENV_ENVI; p_name = VAR[_WENV_]; @@ -16270,6 +12808,7 @@ int envi_cmd(const char *var,char * const env,int flags) return sprintf(p,"%.512s",env); } +static void case_convert(char *ch,int flag); static void case_convert(char *ch,int flag) { if (flag != 'a' && flag != 'A') @@ -16284,13 +12823,40 @@ static void case_convert(char *ch,int flag) } } +static char value[512]; +static int set_func(char *arg, int flags); static int set_func(char *arg, int flags) { errnum = 0; if( *arg == '*' ) - return reset_env_all(); + return reset_env_all(); //envi_cmd(NULL, NULL, 3) + else if (grub_memcmp (arg, "tftp", 4) == 0) + { + if (cur_pxe_type) + cur_pxe_type = 0; + return 1; + } + else if (grub_memcmp (arg, "http", 4) == 0) + { + if (!cur_pxe_type && !only_tftp) + cur_pxe_type = 1; + return 1; + } + else if (grub_memcmp (arg, "gbk2uni=", 8) == 0) + { + gbk = 1; + arg += 8; + if (!grub_open (arg)) + return 0; + _gbk2utf16_2 = grub_zalloc (filemax); + if (! _gbk2utf16_2) + return 0; + grub_read ((unsigned long long)(grub_size_t)_gbk2utf16_2, filemax, GRUB_READ); + grub_close (); + return 1; + } else if (strcmp(VAR[_WENV_], "?_WENV") != 0) - reset_env_all(); + reset_env_all(); //envi_cmd(NULL, NULL, 3) if (*arg == '@') { if (substring("@extend",arg,1) > 1) @@ -16302,19 +12868,19 @@ static int set_func(char *arg, int flags) long long l2; if (!read_val(&arg,&l1) || !read_val(&arg,&l2)) return 0; - if ((unsigned long)l2 > 0xFFFF) + if ((unsigned int)l2 > 0xFFFF) return 0; l2 &= 0xffff; - var_ex_size = (unsigned long)l2; - var_ex = (VAR_NAME *)(int)l1; - var_ex_value = (VAR_VALUE*)(int)(l1 + ((l2 + 63) >> 6 << 9)); + var_ex_size = (unsigned int)l2; + var_ex = (VAR_NAME *)(grub_size_t)l1; + var_ex_value = (VAR_VALUE*)(grub_size_t)(l1 + ((l2 + 63) >> 6 << 9)); memset((char *)var_ex, 0, var_ex_size << 3); return 1; } else - return printf("BASE:%X,%X,VARS:%d",(int)var_ex,(int)var_ex_value,var_ex_size); + return printf("BASE:%X,%X,VARS:%d",(grub_size_t)var_ex,(grub_size_t)var_ex_value,var_ex_size); } - char value[512]; +// char value[512]; int convert_flag=0; unsigned long long wait_t = 0xffffff00; while (*arg) @@ -16416,18 +12982,23 @@ static struct builtin builtin_set = BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST | BUILTIN_IFTITLE, "set [/p] [/a|/A] [/l|/u] [VARIABLE=[STRING]]", "/p,Get a line of input;l|/u,lower/upper case;/a|/A,numerical expression that is evaluated(use calc)." - "/a,set value to a Decimal;/A to a HEX." + "/a,set value to a Decimal;/A to a HEX.\n" + "set [tftp|http]" }; typedef struct _SETLOCAL { char var_name[480];//user var_names. struct _SETLOCAL *prev; - unsigned long saved_drive; - unsigned long saved_partition; - unsigned long boot_drive; - unsigned long install_partition; + unsigned int saved_drive; + unsigned int saved_partition; + unsigned int boot_drive; + unsigned int install_partition; int debug; +#if defined(__i386__) char reserved[8];//预留位置,同时也是为了凑足12字节 +#else + char reserved[4];//预留位置,同时也是为了凑足12字节 +#endif char var_str[MAX_USER_VARS<<9];//user vars only char saved_dir[256]; char command_path[128]; @@ -16436,6 +13007,7 @@ static SETLOCAL *bc = NULL; static SETLOCAL *cc = NULL; static SETLOCAL *sc = NULL; +static int setlocal_func(char *arg, int flags); static int setlocal_func(char *arg, int flags) { errnum = 0; @@ -16469,7 +13041,7 @@ static struct builtin builtin_setlocal = }; -unsigned char menu_tab = 0; +//unsigned char menu_tab = 0; unsigned char num_string = 0; unsigned char menu_font_spacing = 0; unsigned char menu_line_spacing = 0; @@ -16486,13 +13058,16 @@ unsigned short graphic_high; unsigned short row_space; char graphic_file[128]; struct box DrawBox[16]; -struct string* strings = (struct string*) MENU_TITLE; +struct string* strings; extern int new_menu; int num_text_char(char *p); unsigned char DateTime_enable; +unsigned long long hotkey_color_64bit = 0; +unsigned int hotkey_color = 0; #define MENU_BOX_X ((menu_border.menu_box_x > 2) ? menu_border.menu_box_x : 2) -#define MENU_BOX_W ((menu_border.menu_box_w && menu_border.menu_box_w < (current_term->chars_per_line - MENU_BOX_X - 1)) ? menu_border.menu_box_w : (current_term->chars_per_line - MENU_BOX_X - 1)) +#define MENU_BOX_W ((menu_border.menu_box_w && menu_border.menu_box_w < (current_term->chars_per_line - MENU_BOX_X - 1)) ? menu_border.menu_box_w : (current_term->chars_per_line - MENU_BOX_X * 2)) //UEFI固件的右上角(0x2510)是宽字符 +static int setmenu_func(char *arg, int flags); static int setmenu_func(char *arg, int flags) { @@ -16503,6 +13078,7 @@ setmenu_func(char *arg, int flags) if (new_menu == 0) { + strings = (struct string*) MENU_TITLE; num_string = 0; DateTime_enable = 0; for (i=0; i<16; i++) @@ -16674,6 +13250,7 @@ setmenu_func(char *arg, int flags) else if (grub_memcmp (arg, "--u", 3) == 0) { menu_tab = 0; + menu_tab_ext = 0; //初始化 num_string = 0; DateTime_enable = 0; menu_font_spacing = 0; @@ -16685,8 +13262,9 @@ setmenu_func(char *arg, int flags) current_term->max_lines = current_y_resolution / font_h; current_term->chars_per_line = current_x_resolution / font_w; } - *(unsigned char *)0x8274 = 0; - *(unsigned short *)0x8308 = 0x1110; + *(unsigned char *)IMG(0x8274) = 0; +// *(unsigned short *)IMG(0x8308) = 0x1110; + *(unsigned short *)IMG(0x82c8) = 0x1110; memmove ((char *)&menu_border,(char *)&tmp_broder,sizeof(tmp_broder)); graphic_type = 0; for (i=0; i<16; i++) @@ -16735,12 +13313,14 @@ setmenu_func(char *arg, int flags) } else if (grub_memcmp (arg, "--triangle-on", 13) == 0) { - *(unsigned short *)0x8308 = 0x1110; +// *(unsigned short *)IMG(0x8308) = 0x1110; + *(unsigned short *)IMG(0x82c8) = 0x1110; arg += 13; } else if (grub_memcmp (arg, "--triangle-off", 14) == 0) { - *(unsigned short *)0x8308 = 0; +// *(unsigned short *)IMG(0x8308) = 0; + *(unsigned short *)IMG(0x82c8) = 0; arg += 14; } else if (grub_memcmp (arg, "--highlight-short", 17) == 0) @@ -16777,10 +13357,10 @@ setmenu_func(char *arg, int flags) menu_border.menu_box_x = val; break; case 'w': - if (val != 0) +// if (val != 0) menu_border.menu_box_w = val; - else - menu_border.menu_box_w = current_term->chars_per_line - menu_border.menu_box_x * 2 + 1; +// else +// menu_border.menu_box_w = current_term->chars_per_line - menu_border.menu_box_x * 2 + 1; //多余,影响w判断 2023-02-22 break; case 'y': menu_border.menu_box_y = val; @@ -16805,17 +13385,17 @@ setmenu_func(char *arg, int flags) } else if (grub_memcmp (arg, "--auto-num-all-on", 17) == 0) { - *(unsigned char *)0x8274 = 2; + *(unsigned char *)IMG(0x8274) = 2; arg += 17; } else if (grub_memcmp (arg, "--auto-num-on", 13) == 0) { - *(unsigned char *)0x8274 = 1; + *(unsigned char *)IMG(0x8274) = 1; arg += 13; } else if (grub_memcmp (arg, "--auto-num-off", 14) == 0) { - *(unsigned char *)0x8274 = 0; + *(unsigned char *)IMG(0x8274) = 0; arg += 14; } else if (grub_memcmp (arg, "--font-spacing=", 15) == 0) @@ -16888,6 +13468,13 @@ setmenu_func(char *arg, int flags) menu_border.menu_box_h = graphic_row * graphic_list; menu_border.border_w = 0; } + else if (grub_memcmp (arg, "--hotkey-color=", 15) == 0) //--hotkey-color=COLOR 64位色 + { + arg += 15; + if (safe_parse_maxint (&arg, &val)) + hotkey_color_64bit = val; + hotkey_color = color_64_to_8 (hotkey_color_64bit); + } else return 0; cont: @@ -16910,7 +13497,7 @@ static struct builtin builtin_setmenu = "--auto-num-off* --auto-num-all-on --auto-num-on --triangle-on* --triangle-off\n" "--highlight-short* --highlight-full --keyhelp-on* --keyhelp-off\n" "--font-spacing=FONT:LINE. default 0\n" - "--string[=iINDEX]=[X|s|m]=[-]Y=COLOR=\"STRING\"\n" + "--string[=iINDEX]=[X|s|m]=[-]Y=COLOR=\"[$[0xRRGGBB]]STRING\"\n" " iINDEX range is i0-i15. Auto-increments if =iINDEX is omitted.\n" " If the horizontal position is 's', \"STRING\" centers across the whole screen.\n" " If the horizontal position is 'm', \"STRING\" centers within menu area.\n" @@ -16921,6 +13508,8 @@ static struct builtin builtin_setmenu = " \"STRING\"=\"date&time\" ISO8601 format. equivalent to: \"date&time=yyyy-MM-dd HH:mm:ss\"\n" " --string= to disable all strings.\n" " --string=iINDEX to disable the specified index.\n" + " $[0xRRGGBB] Sets the color for STRING.\n" + " $[] Restore COLOR STATE STANDARD.\n" "--box x=X y=Y w=W h=H l=L\n" " If W=0, menu box in middle. L=menu border thickness 0-4, 0=none.\n" "--help=X=W=Y\n" @@ -16940,6 +13529,7 @@ static struct builtin builtin_setmenu = "--draw-box=INDEX=START_X=START_y=HORIZ=VERT=LINEWIDTH=COLOR.\n" " LINEWIDTH:1-255; all dimensions in pixels. INDEX range is 0-15.\n" " --draw-box=INDEX to disable the specified index. --draw-box= to clear all indexes.\n" + "--hotkey-color=COLOR set hotkey color.\n" "Note: * = default. Use only 0xRRGGBB for COLOR." }; @@ -16960,6 +13550,7 @@ static char *month_list[12] = }; unsigned short refresh = 0; +void DateTime_refresh(void); void DateTime_refresh(void) { int i = DateTime_enable-1; @@ -16977,34 +13568,38 @@ void DateTime_refresh(void) putchar_hooked = 0; if (!refresh) { - unsigned long date, time; + struct grub_datetime datetime; char y; int backup_x = fontx; int backup_y = fonty; refresh = 250; - get_datetime(&date, &time); - unsigned long long col = current_color_64bit; + get_datetime(&datetime); current_term->setcolorstate (COLOR_STATE_NORMAL); if (strings[i].start_y < 0) y = strings[i].start_y + current_term->max_lines; else y = strings[i].start_y; gotoxy (strings[i].start_x, y); - if ((strings[i].color & 0xffffffff00000000) == 0) - current_color_64bit = strings[i].color | (current_color_64bit & 0xffffffff00000000); + if (!(strings[i].color & 0xffffffff00000000)) + { + if (!(splashimage_loaded & 2)) + current_color_64bit = strings[i].color | (console_color_64bit[COLOR_STATE_NORMAL] & 0xffffffff00000000); + else + current_color_64bit = strings[i].color | (current_color_64bit & 0xffffffff00000000); + } else current_color_64bit = strings[i].color | 0x1000000000000000; - - year = date >> 16; - month = ((date >> 12) & 0xf) * 10 + ((date >> 8) & 0xf); - day = date; - hour = ((time >> 28) & 0xf) * 10 + ((time >> 24) & 0xf); - min = time >> 16; - sec = time >> 8; + current_term->setcolorstate (color_64_to_8 (current_color_64bit & 0x00ffffffffffffff) | 0x100); + year = datetime.year; + month = datetime.month; + day = datetime.day; + hour = datetime.hour; + min = datetime.minute; + sec = datetime.second; p = (char *)strings[i].string; - if (!*(p+1)) - grub_printf("%04X-%02d-%02X %02d:%02X:%02X", year, month, day, hour, min, sec); + if (*p != '=') + grub_printf("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, min, sec); else { gotoxy (strings[i].start_x + num_text_char(p), y); @@ -17049,7 +13644,7 @@ void DateTime_refresh(void) p += 2; } } - current_color_64bit = col; + current_term->setcolorstate (COLOR_STATE_NORMAL); gotoxy (backup_x,backup_y); } else @@ -17057,6 +13652,7 @@ void DateTime_refresh(void) return; } +static int endlocal_func(char *arg, int flags); static int endlocal_func(char *arg, int flags) { errnum = 0; @@ -17081,7 +13677,7 @@ static int endlocal_func(char *arg, int flags) install_partition = saved->install_partition; debug = saved->debug; cc = cc->prev; - grub_free(saved); +// grub_free(saved); return 1; } static struct builtin builtin_endlocal = @@ -17090,7 +13686,15 @@ static struct builtin builtin_endlocal = endlocal_func, BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT, }; - + +struct _debug_break +{ + int pid; + int line; +}; + +struct _debug_break debug_break[10] = {{0},{0}}; + struct bat_label { char *label; @@ -17122,6 +13726,7 @@ find a label in current batch script.(p_bat_prog) return line of the batch script. if not find ,return -1; */ +static int bat_find_label(char *label); static int bat_find_label(char *label) { struct bat_label *label_entry; @@ -17139,17 +13744,19 @@ static int bat_find_label(char *label) return 0; } +static int bat_get_args(char *arg,char *buff,int flags); static int bat_get_args(char *arg,char *buff,int flags) { -#define ARGS_TMP RAW_ADDR(0x100000) +//#define ARGS_TMP RAW_ADDR(0x100000) + char *ARGS_TMP = grub_zalloc (0x400); char *p = ((char *)ARGS_TMP); char *s1 = buff; int isParam0 = (flags & 0xff); if (*arg == '(') { - unsigned long tmp_partition = current_partition; - unsigned long tmp_drive = current_drive; + unsigned int tmp_partition = current_partition; + unsigned int tmp_drive = current_drive; char *cd = set_device (arg); if (cd) { @@ -17247,18 +13854,21 @@ static int bat_get_args(char *arg,char *buff,int flags) } quit: + grub_free (ARGS_TMP); return buff-s1; } + +grub_u32_t ptrace = 0; /* bat_run_script run batch script. if filename is NULL then is a call func.the first word of arg is a label. */ - +static int bat_run_script(char *filename,char *arg,int flags); static int bat_run_script(char *filename,char *arg,int flags) { - int debug_bat = debug_prog; - if (prog_pid != p_bat_prog->pid) +// int debug_bat = debug_prog; + if (prog_pid != (unsigned int)p_bat_prog->pid) { errnum = ERR_FUNC_CALL; return 0; @@ -17278,8 +13888,15 @@ static int bat_run_script(char *filename,char *arg,int flags) } } - if (debug_prog) - printf("S^:%s [%d]\n",filename,prog_pid); + if (debug_prog) + { + if (debug_bat) + printf("S^:%s [%d]\n",filename,prog_pid); + ptrace++; + if (ptrace > 1 && debug_ptrace) + debug_bat = 0; + } + char **p_entry = bat_entry + i; @@ -17289,17 +13906,14 @@ static int bat_run_script(char *filename,char *arg,int flags) char *p_buff;//buff for command_line char *cmd_buff; grub_u32_t ret = grub_strlen(arg) + 1; - //if (arg_len > 0x8000) - //{ - // errnum = ERR_WONT_FIT; - // return 0; - //} if ((cmd_buff = grub_malloc(ret + 0x800)) == NULL) { return 0; } + else_disabled = 0; //else禁止 + brace_nesting = 0; //大括弧嵌套数 /*copy filename to buff*/ i = grub_strlen(filename); grub_memmove(cmd_buff,filename,i+1); @@ -17336,6 +13950,26 @@ static int bat_run_script(char *filename,char *arg,int flags) p_entry++; continue; } + + if (*p_bat == '{') //左大括弧 + { + if (!ret) + goto ddd; + else + { + brace_nesting++; //大括弧嵌套数+1 + p_entry++; //批处理下一行 + continue; + } + } + + if (*p_bat == '}') //如果是右大括弧 + { + brace_nesting--; //大括弧嵌套数-1 + else_disabled |= 1 << brace_nesting; //设置else禁止位 + p_entry++; //批处理下一行 + continue; + } while(*p_bat) { @@ -17405,7 +14039,16 @@ static int bat_run_script(char *filename,char *arg,int flags) for (i = 1;i< 10;++i) { if (s[i][0]) +#if 1 p_cmd += sprintf(p_cmd,"%s ",s[i]); +#else + { //消除末尾的空格 2022-11-05 会使得外部命令SISO、RUN列表文件时,扩展名只显示前2个! 2022-12-15 + if (i == 1) + p_cmd += sprintf(p_cmd,"%s",s[i]); + else + p_cmd += sprintf(p_cmd," %s",s[i]); + } +#endif else break; } @@ -17419,9 +14062,17 @@ static int bat_run_script(char *filename,char *arg,int flags) } *p_cmd = '\0'; - - if (p_bat_prog->debug_break && (p_bat_prog->debug_break == (grub_u32_t)(p_entry-bat_entry))) debug_bat = debug_prog = 1; - if (debug_prog) printf("S[%d#%d]:[%s]\n",prog_pid,((grub_u32_t)(p_entry-bat_entry)),p_buff); + //批处理调试: debug 批处理文件名 参数. 例如: debug /run --automenu +// if (p_bat_prog->debug_break && ((grub_u32_t)p_bat_prog->debug_break == (grub_u32_t)(p_entry-bat_entry))) debug_bat = debug_prog = 1; + for (i=0; i<10; i++) + { + if (debug_break[i].pid == prog_pid && debug_break[i].line == (grub_u32_t)(p_entry-bat_entry)) + { + debug_bat = debug_prog = 1; + break; + } + } + if (debug_prog && debug_bat) printf("S[%d#%d]:[%s]\n",prog_pid,((grub_u32_t)(p_entry-bat_entry)),p_buff); if (debug_bat) { Next_key: @@ -17430,29 +14081,35 @@ static int bat_run_script(char *filename,char *arg,int flags) i=getkey() & 0xdf; if (current_term->setcolorstate) current_term->setcolorstate(COLOR_STATE_STANDARD); grub_printf("\r%75s","\r"); + char *SYSTEM_RESERVED_MEMORY; switch(i) { - case 'Q': + case 'Q': //结束批处理 errnum = 2000; break; - case 'C': - commandline_func((char *)SYSTEM_RESERVED_MEMORY,0); + case 'C': //进入命令行 按'ESC'键返回批处理调试 + SYSTEM_RESERVED_MEMORY = grub_zalloc (512); + if (!SYSTEM_RESERVED_MEMORY) + return 0; + commandline_func(SYSTEM_RESERVED_MEMORY,0); + grub_free (SYSTEM_RESERVED_MEMORY); break; - case 'S': + case 'S': //跳过本行 ++p_entry; continue; - case 'N': + case 'N': //运行至断点 debug_bat = 0; + debug_ptrace = 0; break; - case 'E': + case 'E': //退出调试模式 debug_bat = debug_prog = 0; break; - case 'B': + case 'B': //设置断点(共10个) 批处理号(共10个),批处理行号 { char buff[12]; grub_u64_t t; buff[0] = 0; - printf("Current:\nDebug Check Memory [0x%x]=>0x%x\nDebug Break Line: %d\n",debug_check_memory,debug_break,p_bat_prog->debug_break); +// printf("Current:\nDebug Check Memory [0x%x]=>0x%x\nDebug Break Line: %d\n",debug_check_memory,debug_break,p_bat_prog->debug_break); get_cmdline_str.prompt = &msg_password[8]; get_cmdline_str.maxlen = sizeof (buff) - 1; get_cmdline_str.echo_char = 0; @@ -17460,15 +14117,16 @@ static int bat_run_script(char *filename,char *arg,int flags) get_cmdline_str.cmdline = (grub_u8_t*)buff; get_cmdline (); - if (buff[0] == '+' || buff[0] == '-' || buff[0] == '*') p_bat = &buff[1]; +// if (buff[0] == '+' || buff[0] == '-' || buff[0] == '*') p_bat = &buff[1]; + if (buff[0] == 'p' || buff[0] == 'c' || buff[0] == 'l') p_bat = &buff[1]; else p_bat = buff; - - if (safe_parse_maxint (&p_bat, &t)) +#if 0 + if (safe_parse_maxint ((char **)(grub_size_t)&p_bat, (unsigned long long *)(grub_size_t)&t)) { if (buff[0] == '*') { debug_check_memory = t; - debug_break = *(int*)debug_check_memory; + debug_break = *(int*)(grub_size_t)debug_check_memory; printf("\rDebug Check Memory [0x%x]=>0x%x\n",debug_check_memory,debug_break); } else @@ -17480,26 +14138,103 @@ static int bat_run_script(char *filename,char *arg,int flags) printf("\rDebug Break Line: %d\n",p_bat_prog->debug_break); } } +#else + if (buff[0] == 'c') //清除断点 例如: c2 (清除2号断点); c (清除全部断点) + { + t = 0; + safe_parse_maxint ((char **)(grub_size_t)&p_bat, (unsigned long long *)(grub_size_t)&t); + if (t) + debug_break[t-1].pid = 0; + else + { + for (i=0; i<10; i++) + { + debug_break[i].pid = 0; + } + } + } + else if (buff[0] == 'l') //显示断点 (断点号,批处理号,批处理行号) + { + for (i=0; i<10; i++) + { + if (debug_break[i].pid) + printf("\ri=%d, pid=%d, line=%d\n",i+1,debug_break[i].pid,debug_break[i].line); + } + } + else //设置断点(隐含当前批处理标号) 例如: 45 (当前批处理,45行) + { + i = 0; + while (debug_break[i].pid && i < 10) i++; + safe_parse_maxint ((char **)(grub_size_t)&p_bat, (unsigned long long *)(grub_size_t)&t); + debug_break[i].pid = prog_pid; + if (buff[0] == 'p') //设置断点 例如: p2,134 (2号批处理,134行) + { + debug_break[i].pid = t; + p_bat++; + safe_parse_maxint ((char **)(grub_size_t)&p_bat, (unsigned long long *)(grub_size_t)&t); + } + debug_break[i].line = t; + printf("\rDebug Break pid=%d, line=%d\n",debug_break[i].pid,debug_break[i].line); + } +#endif goto Next_key; } + case 'P': //单步执行(跨过子程序) + debug_ptrace = 1; + break; + default: //单步执行 + debug_ptrace = 0; + break; } if (errnum == 2000) break; } - ret = run_line (p_buff,flags); - + + if (errnum == ERR_BAT_BRACE_END) //如果是批处理大括弧结束 + { +ddd: + errnum = ERR_NONE; //消除错误号 + int brace_count = 0; //大括弧计数=0 + while (1) + { + p_bat = *(p_entry); //批处理入口 +aaa: + while (*p_bat && *p_bat != '{' && *p_bat != '}') p_bat++; //搜索左右大括弧,直至找到,或者结束. + if (*p_bat == '{') //如果是左大括弧 + { + brace_count++; //大括弧计数+1 + p_bat++; //下一行批处理 + goto aaa; //继续搜索 + } + if (*p_bat == '}') //如果是右大括弧 + { + brace_count--; //大括弧计数-1 + if (!brace_count) //如果大括弧计数=0 + { + p_entry++; //批处理下一入口 + break; //搜索结束 + } + else //否则 + p_bat++; //下一行批处理 + goto aaa; //继续搜索 + } + else //如果没有搜索左右大括弧 + p_entry++; //批处理下一入口 + } + continue; + } +#if 0 if (debug_check_memory) { - if (debug_break != *(int*)debug_check_memory) + if (debug_break != *(int*)(grub_size_t)debug_check_memory) { - printf("\nB: %s\n[0x%x]=>0x%x (0x%x)\n",p_buff,debug_check_memory,*(int*)debug_check_memory,debug_break); + printf("\nB: %s\n[0x%x]=>0x%x (0x%x)\n",p_buff,debug_check_memory,*(int*)(grub_size_t)debug_check_memory,debug_break); debug_bat = debug_prog = 1; } } - - if ((*(short *)0x417 & 0x104) && checkkey() == 0x2E03) +#endif + if (ctrl_c_trap && checkkey() == 0x2000063) { - getkey(); unsigned char k; loop_yn: grub_printf("\nTerminate batch job (Y/N)? "); @@ -17544,25 +14279,25 @@ static int bat_run_script(char *filename,char *arg,int flags) grub_free(cmd_buff); if (debug_prog) - printf("S$:%s [%d]\n",filename,prog_pid); + { + ptrace--; + if (ptrace == 1 && debug_ptrace) + { + debug_bat = 1; + debug_ptrace = 0; + } + if (debug_bat) + printf("S$:%s [%d]\n",filename,prog_pid); + } errnum = (i == 1000) ? 0 : i; return errnum?0:(int)ret; } - +static int goto_func(char *arg, int flags); static int goto_func(char *arg, int flags) { errorcheck_func ("on",0); -#if 0 - errnum = ERR_BAT_GOTO; - if (flags & BUILTIN_BAT_SCRIPT)//batch script return arg addr. - { - return bat_find_label(arg); - } - else - return fallback_func(arg,flags);//in menu script call fallback_func to jump next menu. -#endif unsigned long long val; char *p = arg; if (*arg == '+' || *arg == '-' || safe_parse_maxint (&p, &val)) @@ -17585,6 +14320,7 @@ static struct builtin builtin_goto = "When the LABEL there is no prefix ':', the LABEL can't be a number." }; +static int call_func(char *arg,int flags); static int call_func(char *arg,int flags) { errnum = 0; @@ -17592,21 +14328,31 @@ static int call_func(char *arg,int flags) { return bat_run_script(NULL, arg, flags); } - if (*(short *)arg == 0x6E46) + if (*(short *)arg == 0x6E46) //Fn Fn.[func] 参数 call Fn.26 { - unsigned int func; +// unsigned int func; + grub_size_t func; long long ull; int i; char *ch[10]={0}; arg += 3; if (! read_val(&arg,&ull)) return 0; - func=(unsigned int)ull; +// func=(unsigned int)ull; + func = (grub_size_t)ull; arg[parse_string(arg)] = 0; for (i=0;i<10;++i) { - if (read_val(&arg,&ull)) - ch[i] = (char *)(int)ull; + if (*arg == 'g' && *(arg+1) == '4' && *(arg+2) == 'e') + { + arg += 3; + safe_parse_maxint (&arg, (unsigned long long *)&ull); + ch[i] = (char *)(grub_size_t)IMG(ull); + } + else if (read_val(&arg,&ull)) + { + ch[i] = (char *)(grub_size_t)ull; + } else { ch[i] = arg; @@ -17619,13 +14365,34 @@ static int call_func(char *arg,int flags) } } errnum = 0; +// if (func<0xFF) +// func = (*(int **)0x8300)[func]; + if (func<0xFF) - func = (*(int **)0x8300)[func]; - return ((int (*)())func)(ch[0],ch[1],ch[2],ch[3],ch[4],ch[5],ch[6],ch[7],ch[8],ch[9]); +// func = (grub_size_t)(*(int *)(grub_size_t)(*(int *)IMG(0x8300) + func * sizeof(long))); + func = (*(grub_size_t **)IMG(0x8300))[func]; + + return ((int (*)())func)(ch[0],ch[1],ch[2],ch[3],ch[4],ch[5],ch[6],ch[7],ch[8],ch[9]); +/* +#define ABS(x) ((x) - EXT_C(main) + 0x8200) +#define IMG(x) ((x) - 0x8200 + g4e_data) +grub_image = 112c6000 +EXT_C(main) = IMG(0x8200) = 112c6400 +ABS(x) = x - (EXT_C(main) - 0x8200) = x - (112c6400 - 0x8200) +IMG(x) = x + (112c6400 - 0x8200) +grub_printf("\ncall_func-1,%x,%x,%x,%x,%x,",IMG(0x8300),*(int *)IMG(0x8300),*(int **)IMG(0x8300),*(int *)IMG(*(int *)IMG(0x8300)),*(long *)IMG(*(int *)IMG(0x8300))); +112c6500,9c08,9e8800009c08,1f444,1f444; +*/ } else + { return run_line(arg,flags); + } } +/* +int (*)() 这是一个函数的指针,指向一个 int () 这样的函数。它要指向一个函数才能有用。指向一个函数之后可以用它来代替该函数。之后使用这个指针相当于使用该函数。 +*/ + static struct builtin builtin_call = { @@ -17634,6 +14401,28 @@ static struct builtin builtin_call = BUILTIN_BAT_SCRIPT | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_IFTITLE | BUILTIN_MENU, }; + +static int exit_g4d_func(char *arg, int flags); +static int exit_g4d_func(char *arg, int flags) +{ + grub_machine_fini (); + efi_call_4 (grub_efi_system_table->boot_services->exit, + grub_efi_image_handle, GRUB_EFI_SUCCESS, 0, 0); + for (;;) ; + return 1; +} + +static struct builtin builtin_exit_g4d = +{ + "exit_g4d", + exit_g4d_func, + BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_SCRIPT | BUILTIN_HELP_LIST | BUILTIN_BOOTING, + "exit", + "exit GRUB4DOS_for_UEFI" +}; + + +static int exit_func(char *arg, int flags); static int exit_func(char *arg, int flags) { #if 0 @@ -17659,6 +14448,7 @@ static struct builtin builtin_exit = "Exit batch script with a status of N or Exit menu script" }; +static int shift_func(char *arg, int flags); static int shift_func(char *arg, int flags) { char **s = batch_args; @@ -17690,6 +14480,7 @@ static struct builtin builtin_shift = " not given, it is assumed to be 0." }; +static int grub_exec_run(char *program, char *psp, int flags); static int grub_exec_run(char *program, char *psp, int flags) { int pid; @@ -17699,17 +14490,17 @@ static int grub_exec_run(char *program, char *psp, int flags) if (kernel_type < KERNEL_TYPE_CHAINLOADER) kernel_type = KERNEL_TYPE_NONE; /*Is a batch file? */ - if (*(unsigned long *)program == BAT_SIGN || *(unsigned long *)program == 0x21BFBBEF)//!BAT + if (*(unsigned int *)program == BAT_SIGN || *(unsigned int *)program == 0x21BFBBEF)//BAT_SIGN=!BAT { int crlf = 0; if (prog_pid >= 10) { return 0; } - struct bat_array *p_bat_array = (struct bat_array *)grub_malloc(0x2600); +// struct bat_array *p_bat_array = (struct bat_array *)grub_malloc(0x2600); + struct bat_array *p_bat_array = (struct bat_array *)grub_malloc(0x200 + sizeof(struct bat_label) * 0x80 + sizeof(char *) * 0x800); if (p_bat_array == NULL) return 0; -// p_bat_array->path = program - (*(unsigned long *)(program - 24)); p_bat_array->path = psp + PI->path; struct bat_array *p_bat_array_orig = p_bat_prog; @@ -17717,26 +14508,41 @@ static int grub_exec_run(char *program, char *psp, int flags) char *p_bat = program; struct bat_label *label_entry =(struct bat_label *)((char *)p_bat_array + 0x200); char **bat_entry = (char **)(label_entry + 0x80);//0x400/sizeof(label_entry) - unsigned long i_bat = 1,i_lab = 1;//i_bat:lines of script;i_lab=numbers of label. - grub_u32_t size = grub_strlen(program); + unsigned int i_bat = 1,i_lab = 1;//i_bat:lines of script;i_lab=numbers of label. + unsigned int type = 0; //type=0/1/2=Windows:(每行结尾是“\r\n”)/Unix:(每行结尾是“\n”)/Mac OS:(每行结尾是“\r”) + grub_u32_t size = grub_strlen(program); //取批处理尺寸(注意:PI->proglen是包含尾随文件的尺寸,如果有的话) p_bat_array->size = size++; sprintf(p_bat_array->md,"(md,0x%x,0x%x)",program + size,PI->proglen - size); + if (PI->proglen > size) //如果批处理有尾随文件,移动尾随文件,对齐0x200 + { + bat_md_start = (grub_size_t)(program + size + 511) & (-512); + bat_md_count = PI->proglen - size; + grub_memmove((void *)bat_md_start,(void *)(program + size),PI->proglen - size); + sprintf(p_bat_array->md,"(md,0x%x,0x%x)",bat_md_start,bat_md_count); + bat_md_start >>= 9; + bat_md_count = ((bat_md_count + 511) & (-512)) >> 9; + } + //判断回车换行模式 if (debug_prog) { while(*p_bat++) { - if (*p_bat == '\r') - crlf = 1; - else if (*p_bat != '\n') + if (*p_bat == '\r' && *(p_bat+1) == '\n') + crlf = 1; + else if (*p_bat == '\r') + type = 2; + else if (*p_bat == '\n') + type = 1; + else continue; + break; } } - - program = skip_to(SKIP_LINE,program);//skip head - +// program = skip_to(SKIP_LINE,program);//skip head + if (debug_prog) bat_entry[i_bat++] = (char*)-1; while ((p_bat = program))//scan batch file and make label and bat entry. { program = skip_to(SKIP_LINE,program); @@ -17748,7 +14554,7 @@ static int grub_exec_run(char *program, char *psp, int flags) if (debug_prog) bat_entry[i_bat++] = (char*)-1; i_lab++; } - else + else if (*(unsigned int *)p_bat != BAT_SIGN && *(unsigned int *)p_bat != 0x21BFBBEF) bat_entry[i_bat++] = p_bat; if (debug_prog) @@ -17757,15 +14563,25 @@ static int grub_exec_run(char *program, char *psp, int flags) p += grub_strlen(p_bat) + crlf; while(++p < program) { - if (!*p || *p == '\n') bat_entry[i_bat++] = (char*)-1; +// if (!*p || *p == '\n') bat_entry[i_bat++] = (char*)-1; + if (type == 0 && *p == '\n') + bat_entry[i_bat++] = (char*)-1; + else if (type == 1 && (!*p || *p == '\n')) + bat_entry[i_bat++] = (char*)-1; + if (type == 2 && (!*p || *p == '\r')) + bat_entry[i_bat++] = (char*)-1; } } - +#if 0 if ((i_lab & 0x80) || (i_bat & 0x800))//max label 128,max script line 2048. { grub_free(p_bat_array); return 0; } +#else + if ((i_lab & 0x80) || (i_bat & 0x800)) + break; +#endif } label_entry[i_lab].label = NULL; @@ -17776,86 +14592,109 @@ static int grub_exec_run(char *program, char *psp, int flags) p_bat_array->debug_break = 0; p_bat_array->entry = label_entry; p_bat_prog = p_bat_array; - pid = bat_run_script(filename, arg,flags | BUILTIN_BAT_SCRIPT | BUILTIN_USER_PROG);//run batch script from line 0; + pid = bat_run_script(filename, arg,flags | BUILTIN_BAT_SCRIPT | BUILTIN_USER_PROG);//run batch script from line 0; p_bat_prog = p_bat_array_orig; grub_free(p_bat_array); return pid; } - + /* call the new program. */ - pid = ((int (*)(char *,int))program)(arg, flags | BUILTIN_USER_PROG);/* pid holds return value. */ +// pid = ((int (*)(char *,int))program)(arg, flags | BUILTIN_USER_PROG);/* pid holds return value. */ + pid = ((int (*)(char *,int,int,int))program)(arg, flags | BUILTIN_USER_PROG, 0, 0);/* pid holds return value. */ return pid; } -unsigned short beep_duration; -unsigned short *beep_buf_count; -unsigned char i_count, beep_play, beep_mode, beep_enable = 0; -extern unsigned short beep_buf[256]; -int beep_func(char *arg, int flags) + +static int else_func(char *arg, int flags); +static int else_func(char *arg, int flags) { - unsigned long long val; - unsigned short *p; - unsigned char beep_state; - - if (beep_enable == 1) + if (else_disabled & (1 << brace_nesting)) //如果else禁止 { - if (i_count == 0) - goto play; - if (--beep_duration) - return 1; - else + return !(errnum = ERR_BAT_BRACE_END); + } + else //如果else允许 + { + if (*arg == 'i') //如果是 else if { - beep_frequency = 0; - console_beep(); - goto play; + is_else_if = 1; //告知 if 函数, 这是 else_if + return builtin_cmd (0,arg,flags); } + else //如果是 else + return 1; } +} + +static struct builtin builtin_else = +{ + "else", + else_func, + BUILTIN_BAT_SCRIPT | BUILTIN_SCRIPT, //使用于批处理脚本及脚本 +}; + +static inline unsigned char inb (unsigned short p) +{ + unsigned char r; + asm ("inb %1, %0" : "=a" (r) : "dN" (p)); + return r; +} - beep_state = 0; - beep_mode = 0; - beep_duration = 0; - beep_play = 1; - p = beep_buf; +static inline void outb (unsigned short p, unsigned char d) +{ + asm ("outb %1, %0" : : "dN" (p), "a" (d)); +} +static void +speaker_play (unsigned int hz, unsigned long time) +{ + unsigned int div = 0; + unsigned long ms = 1000 * time; + if (hz == 0) + { + outb (0x61, inb (0x61) & 0xfc); + efi_call_1 (grub_efi_system_table->boot_services->stall, ms); + return; + } + if (hz < 20) + hz = 20; + if (hz > 20000) + hz = 20000; + div = 1193180 / hz; + /* speaker freq */ + outb (0x43, 0xb6); + outb (0x42, (unsigned char) div); + outb (0x42, (unsigned char) (div >> 8)); + /* speaker on */ + outb (0x61, inb (0x61) | 0x3); + /* sleep */ + efi_call_1 (grub_efi_system_table->boot_services->stall, ms); + /* speaker off */ + outb (0x61, inb (0x61) & 0xfc); +} + +static int beep_func (char *arg, int flags); +static int beep_func (char *arg, int flags) +{ + unsigned int hz; + unsigned long time; + unsigned long long val; while (1) { if (grub_memcmp(arg,"--play=",7) == 0) { - arg += 7; - if (safe_parse_maxint (&arg, &val)) - beep_play = val; - if (!beep_play) - { - beep_enable = 0; - beep_frequency = 0; - console_beep(); - return 1; - } } else if (grub_memcmp(arg,"--start",7) == 0) { - arg += 7; - beep_state = 1; - p = beep_buf; } else if (grub_memcmp(arg,"--mid",5) == 0) { - arg += 5; - beep_state = 2; - p = beep_buf_count; } else if (grub_memcmp(arg,"--end",5) == 0) { - arg += 5; - beep_state = 0; - p = beep_buf_count; } else if (grub_memcmp(arg,"--nowait",8) == 0) { - arg += 8; - beep_mode = 1; } else break; @@ -17865,71 +14704,18 @@ int beep_func(char *arg, int flags) while (*arg) { if (safe_parse_maxint (&arg, &val)) - { - if (val < 20) - *p++ = 0; - else - *p++ = 1193180 / (unsigned long)val; - } + hz = val; + else + break; arg = skip_to (0, arg); if (safe_parse_maxint (&arg, &val)) - *p++ = (unsigned long)val; + time = val; + else + break; + speaker_play (hz, time); arg = skip_to (0, arg); } - beep_buf_count = p; - - if (beep_state) - return 1; - *p++ = 0; - *p++ = 0; - i_count = 0; - - if (beep_enable == 0 && beep_mode) - { - beep_enable = 1; - return 1; - } - -play: - if (i_count > 252) - return 0; - beep_frequency = beep_buf[i_count]; - beep_duration = beep_buf[i_count+1]; - - if (beep_frequency == 0 && beep_duration == 0) - { - if (beep_play < 0xff) - beep_play--; - if (beep_play == 0) - { - beep_enable = 0; - return 1; - } - i_count = 0; - goto play; - } - else if (beep_frequency) - console_beep(); - - if (!beep_mode) - { - if (console_checkkey () != -1) - { - console_getkey (); - beep_frequency = 0; - console_beep(); - beep_enable = 0; - beep_play = 0; - return 0; - } - defer(beep_duration); - beep_frequency = 0; - console_beep(); - i_count += 2; - goto play; - } - - i_count += 2; + speaker_play (0, 0); return 1; } @@ -17938,29 +14724,19 @@ static struct builtin builtin_beep = "beep", beep_func, BUILTIN_BAT_SCRIPT | BUILTIN_SCRIPT | BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, - "beep [--start|--mid|--end] [--play=N] [--nowait] FREQUENCY DURATION FREQUENCY DURATION ...", - "FREQUENCY: Hz. DURATION: ms. Max: 126 notes.\n" - "N: 0-255. 0 is stop play, 255 is continuous play (any key stops play).\n" - "When the syllable is a lot, can be written in different lines.\n" - "The use of [--start|--mid|--end] specifies." + "beep FREQUENCY DURATION FREQUENCY DURATION ...", + "FREQUENCY: Hz. DURATION: ms." }; - /* The table of builtin commands. Sorted in dictionary order. */ struct builtin *builtin_table[] = { -#ifdef SUPPORT_GRAPHICS - &builtin_background, -#endif &builtin_beep, &builtin_blocklist, &builtin_boot, &builtin_calc, &builtin_call, &builtin_cat, -#ifdef CDROM_INIT - &builtin_cdrom, -#endif &builtin_chainloader, &builtin_checkrange, &builtin_checktime, @@ -17977,21 +14753,19 @@ struct builtin *builtin_table[] = &builtin_delmod, &builtin_displaymem, &builtin_echo, + &builtin_else, &builtin_endlocal, &builtin_errnum, &builtin_errorcheck, &builtin_exit, + &builtin_exit_g4d, &builtin_fallback, &builtin_find, #ifdef SUPPORT_GRAPHICS &builtin_font, - &builtin_foreground, #endif &builtin_fstest, &builtin_geometry, -#ifdef SUPPORT_GFX - &builtin_gfxmenu, -#endif &builtin_goto, &builtin_graphicsmode, &builtin_halt, @@ -18005,10 +14779,11 @@ struct builtin *builtin_table[] = &builtin_initscript, &builtin_insmod, #ifdef FSYS_IPXE - &builtin_ipxe, +// &builtin_ipxe, #endif &builtin_is64bit, &builtin_kernel, + &builtin_load, &builtin_lock, &builtin_ls, &builtin_makeactive, @@ -18019,7 +14794,7 @@ struct builtin *builtin_table[] = &builtin_module, &builtin_modulenounzip, #ifdef SUPPORT_GRAPHICS - &builtin_outline, +// &builtin_outline, #endif /* SUPPORT_GRAPHICS */ &builtin_pager, &builtin_partnew, @@ -18029,7 +14804,6 @@ struct builtin *builtin_table[] = #ifdef FSYS_PXE &builtin_pxe, #endif - &builtin_quit, #ifndef NO_DECOMPRESSION &builtin_raw, #endif @@ -18038,32 +14812,21 @@ struct builtin *builtin_table[] = &builtin_root, &builtin_rootnoverify, &builtin_savedefault, -#ifdef SUPPORT_SERIAL - &builtin_serial, -#endif /* SUPPORT_SERIAL */ &builtin_set, &builtin_setkey, &builtin_setlocal, &builtin_setmenu, - &builtin_setvbe, &builtin_shift, #ifdef SUPPORT_GRAPHICS &builtin_splashimage, #endif /* SUPPORT_GRAPHICS */ -#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS) +#if defined(SUPPORT_GRAPHICS) &builtin_terminal, #endif /* SUPPORT_SERIAL || SUPPORT_HERCULES SUPPORT_GRAPHICS */ -#ifdef SUPPORT_SERIAL - &builtin_terminfo, -#endif /* SUPPORT_SERIAL */ - &builtin_testvbe, &builtin_timeout, &builtin_title, &builtin_tpm, - &builtin_unhide, - &builtin_usb, &builtin_uuid, - &builtin_vbeprobe, &builtin_vol, &builtin_write, 0 diff --git a/stage2/char_io.c b/stage2/char_io.c index c10aa652..3949b37b 100644 --- a/stage2/char_io.c +++ b/stage2/char_io.c @@ -21,13 +21,38 @@ #include #include -#ifdef SUPPORT_HERCULES -# include -#endif +int grub_sprintf (char *buffer, const char *format, ...); +int get_cmdline (void); +int safe_parse_maxint_with_suffix (char **str_ptr, unsigned long long *myint_ptr, int unitshift); +int grub_tolower (int c); +int grub_isspace (int c); +unsigned short grub_crc16(unsigned char *data, int size); +int grub_crc32(char *data,grub_u32_t size); +int grub_memcmp (const char *s1, const char *s2, grub_size_t n); +int grub_strncat (char *s1, const char *s2, int n); +int grub_strcmp (const char *s1, const char *s2); +int getkey (void); +int checkkey (void); +//inline void debug_sleep(int debug_boot, int line, char *file); +void gotoxy (int x, int y); +int getxy (void); +int strncmpx(const char *s1,const char *s2, unsigned int n, int case_insensitive); +int substring (const char *s1, const char *s2, int case_insensitive); +int nul_terminate (char *str); +int grub_strlen (const char *str); +int memcheck (unsigned long long addr, unsigned long long len); +void *grub_memmove (void *to, const void *from, int len); +void *grub_memset (void *start, int c, grub_size_t len); +char *grub_strstr (const char *s1, const char *s2); +char *grub_strtok (char *s, const char *delim); +unsigned long long grub_memmove64(unsigned long long dst_addr, unsigned long long src_addr, unsigned long long len); +unsigned long long grub_memset64(unsigned long long dst_addr, unsigned int data, unsigned long long len); +int grub_memcmp64(unsigned long long str1addr, unsigned long long str2addr, unsigned long long len); +unsigned short *_gbk2utf16_2; +#define _gbk2utf16_2_size 0x7930 +grub_u32_t gbk = 0; + -#ifdef SUPPORT_SERIAL -# include -#endif struct term_entry term_table[] = { @@ -36,7 +61,7 @@ struct term_entry term_table[] = 0, 80, 25, - console_putchar, + graphics_putchar, console_checkkey, console_getkey, console_getxy, @@ -45,8 +70,8 @@ struct term_entry term_table[] = console_setcolorstate, console_setcolor, console_setcursor, - 0, - 0 + console_startup, + console_shutdown }, #ifdef SUPPORT_GRAPHICS { "graphics", @@ -61,12 +86,13 @@ struct term_entry term_table[] = graphics_cls, /* cls */ console_setcolorstate, // graphics_setcolorstate, /* setcolorstate */ console_setcolor, // graphics_setcolor, /* setcolor */ - 0/*graphics_setcursor*/, /* nocursor */ + 0,/*graphics_setcursor*/ /* nocursor */ graphics_init, /* initialize */ graphics_end /* shutdown */ }, #endif /* SUPPORT_GRAPHICS */ -#ifdef SUPPORT_SERIAL +#if 0 +//#ifdef SUPPORT_SERIAL { "serial", /* A serial device must be initialized. */ @@ -85,8 +111,8 @@ struct term_entry term_table[] = 0, 0 }, -#endif /* SUPPORT_SERIAL */ -#ifdef SUPPORT_HERCULES +//#endif /* SUPPORT_SERIAL */ +//#ifdef SUPPORT_HERCULES { "hercules", 0, @@ -104,13 +130,15 @@ struct term_entry term_table[] = 0, 0 }, -#endif /* SUPPORT_HERCULES */ +//#endif /* SUPPORT_HERCULES */ +#endif /* This must be the last entry. */ - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; int count_lines = -1; int use_pager = 1; +void print_error (void); void print_error (void) { @@ -118,14 +146,151 @@ print_error (void) grub_printf ("\nError %u:(http://grub4dos.chenall.net/e/%u)\n\t %s\n", errnum, errnum, err_list[errnum]); } +void grub_putstr (char *str); +void +grub_putstr (char *str) +{ + while (*str) + grub_putchar ((unsigned char)*str++, 255); +} + +/* Convert unicode filename to UTF-8 filename. N is the max UTF-16 characters + * to be converted. The caller should asure there is enough room in the UTF8 + * buffer. Return the length of the converted UTF8 string. + * 将unicode文件名转换为UTF-8文件名。N是要转换的最大UTF-16字符数。 + * 调用方应该测量UTF8缓冲区中是否有足够的空间。返回转换后的UTF8字符串的长度。 + */ +unsigned int unicode_to_utf8 (unsigned short *filename, unsigned char *utf8, unsigned int n); +unsigned int +unicode_to_utf8 (unsigned short *filename, unsigned char *utf8, unsigned int n) +{ + unsigned short uni; + unsigned int j, k; + + for (j = 0, k = 0; j < n && (uni = filename[j]); j++) + { + if (uni <= 0x007F) + { + utf8[k++] = uni; + } + else if (uni <= 0x07FF) + { + utf8[k++] = 0xC0 | (uni >> 6); + utf8[k++] = 0x80 | (uni & 0x003F); + } + else + { + utf8[k++] = 0xE0 | (uni >> 12); + utf8[k++] = 0x80 | ((uni >> 6) & 0x003F); + utf8[k++] = 0x80 | (uni & 0x003F); + } + } + utf8[k] = 0; + return k; +} + +#if 0 +//unicode_to_utf8是这个函数的子集,比较简单一些。 +/* Convert UCS2 to UTF-8. */ +grub_uint8_t *grub_ucs2_to_utf8 (const grub_uint16_t *src, grub_uint8_t *dest, grub_size_t size); +grub_uint8_t * +grub_ucs2_to_utf8 (const grub_uint16_t *src, grub_uint8_t *dest, grub_size_t size) +{ + grub_uint32_t code_high = 0; + grub_uint32_t code; + grub_uint8_t *dest_0 = dest; + + while (size--) + { + code = *src++; + if (!code) + { + *dest == 0; + return (dest - dest_0); + } + + if (code_high) + { + if (code >= 0xDC00 && code <= 0xDFFF) + { + /* Surrogate pair. */ + code = ((code_high - 0xD800) << 10) + (code - 0xDC00) + 0x10000; + + *dest++ = (code >> 18) | 0xF0; + *dest++ = ((code >> 12) & 0x3F) | 0x80; + *dest++ = ((code >> 6) & 0x3F) | 0x80; + *dest++ = (code & 0x3F) | 0x80; + } + else + { + /* Error... */ + *dest++ = '?'; + /* *src may be valid. Don't eat it. */ + src--; + } + + code_high = 0; + } + else + { + if (code <= 0x007F) + *dest++ = code; + else if (code <= 0x07FF) + { + *dest++ = (code >> 6) | 0xC0; + *dest++ = (code & 0x3F) | 0x80; + } + else if (code >= 0xD800 && code <= 0xDBFF) + { + code_high = code; + continue; + } + else if (code >= 0xDC00 && code <= 0xDFFF) + { + /* Error... */ + *dest++ = '?'; + } + else if (code < 0x10000) + { + *dest++ = (code >> 12) | 0xE0; + *dest++ = ((code >> 6) & 0x3F) | 0x80; + *dest++ = (code & 0x3F) | 0x80; + } + else + { + *dest++ = (code >> 18) | 0xF0; + *dest++ = ((code >> 12) & 0x3F) | 0x80; + *dest++ = ((code >> 6) & 0x3F) | 0x80; + *dest++ = (code & 0x3F) | 0x80; + } + } + } + +// return dest; + *dest == 0; + return (dest - dest_0); +} +#endif + + +void grub_putstr_utf16(unsigned short *str); +void +grub_putstr_utf16(unsigned short *str) //打印unicode16字符串 +{ + while (*str) + grub_putchar ((unsigned char)*str++, 255); +} + +#if defined(__i386__) +char * convert_to_ascii (char *buf, int c, int lo, int hi); char * -convert_to_ascii (char *buf, int c,...) +convert_to_ascii (char *buf, int c, int lo, int hi) //适应gcc高版本 2023-05-24 { union { unsigned long long ll; struct { - unsigned long lo; - unsigned long hi; + unsigned int lo; + unsigned int hi; }; struct { unsigned char l1; @@ -140,8 +305,10 @@ convert_to_ascii (char *buf, int c,...) } num; char *ptr = buf; - num.hi = *(unsigned long *)((&c) + 2); - num.lo = *(unsigned long *)((&c) + 1); +// num.hi = *(unsigned int *)((&c) + 2); +// num.lo = *(unsigned int *)((&c) + 1); + num.hi = hi; //适应gcc高版本 2023-05-24 + num.lo = lo; //适应gcc高版本 2023-05-24 if (c == 'x' || c == 'X') /* hex */ { @@ -161,14 +328,14 @@ convert_to_ascii (char *buf, int c,...) } do { - unsigned long H0, H1, L0, L1; + unsigned int H0, H1, L0, L1; /* 0x100000000 == 4294967296 */ /* num.ll == (H1 * 10 + H0) * 0x100000000 + L1 * 10 + L0 */ - H0 = num.hi % 10; + H0 = num.hi % 10; //num.hi/10 = H1......H0 H1 = num.hi / 10; L0 = num.lo % 10; - L1 = num.lo / 10; + L1 = num.lo / 10; //num.lo/10 = L1......L0 /* num.ll == H1 * 10 * 0x100000000 + H0 * 0x100000000 + L1 * 10 + L0 */ /* num.ll == H1 * 10 * 0x100000000 + H0 * 4294967290 + H0 * 6 + L1 * 10 + L0 */ L0 += H0 * 6; @@ -185,7 +352,7 @@ convert_to_ascii (char *buf, int c,...) *(ptr++) = '0' + L0; } while (num.ll); } - /* reorder to correct direction!! */ + /* reorder to correct direction!! 重新排序到正确的方向*/ { char *ptr1 = ptr - 1; char *ptr2 = buf; @@ -201,68 +368,92 @@ convert_to_ascii (char *buf, int c,...) return ptr; } - -void -grub_putstr (const char *str) +#else +char *convert_to_ascii (char *buf, int c, unsigned long long lo); +char * +convert_to_ascii (char *buf, int c, unsigned long long lo) { - while (*str) - grub_putchar ((unsigned char)*str++, 255); -} + union + { + unsigned long long ll; + unsigned long long lo; + struct + { + unsigned char l1; + unsigned char l2; + unsigned char l3; + unsigned char l4; + unsigned char l5; + unsigned char l6; + unsigned char l7; + unsigned char l8; + }; + } num; + char *ptr = buf; -#if 0 -/* (Patch from Jamey Sharp, 26 Jan 2009) - * Replace grub_printf calls with grub_sprintf by #define, not asm magic. - * define in shared.h: - * #define grub_printf(...) grub_sprintf(NULL, __VA_ARGS__) - */ -//static int grub_printf_return_address; -//void -//grub_printf (const char *format, ...) -//{ -// /* sorry! this does not work :-( */ -// //return grub_sprintf (NULL, format,...); -//#if 1 -// asm volatile ("popl %ebp"); /* restore EBP */ -// //asm volatile ("ret"); -// asm volatile ("popl %0" : "=m"(grub_printf_return_address)); -// asm volatile ("pushl $0"); /* buffer = 0 for grub_sprintf */ -//#ifdef HAVE_ASM_USCORE -// asm volatile ("call _grub_sprintf"); -//#else -// asm volatile ("call grub_sprintf"); -//#endif -// asm volatile ("popl %eax"); -// asm volatile ("pushl %0" : : "m"(grub_printf_return_address)); -// asm volatile ("ret"); -//#else -// int *dataptr = (int *)(void *) &format; -// -// dataptr--; /* (*dataptr) is return address */ -// grub_printf_return_address = (*dataptr); /* save return address */ -// -// asm volatile ("leave"); /* restore ESP and EBP */ -// //asm volatile ("ret"); -// asm volatile ("popl %eax"); /* discard return address */ -// asm volatile ("pushl $0"); /* buffer = 0 for grub_sprintf */ -// asm volatile ("call grub_sprintf"); -// asm volatile ("popl %eax"); -// asm volatile ("pushl %0" : : "m"(grub_printf_return_address)); -// asm volatile ("ret"); -//#endif -//} +// num.lo = *(unsigned long long *)((&c) + 1); + num.lo = lo; + + if (c == 'x' || c == 'X') /* hex */ + { + do { + int dig = num.l1 & 0xF; + *(ptr++) = ((dig > 9) ? dig + c - 33 : '0' + dig); + } while (num.ll >>= 4); + } + else /* decimal */ + { + if ((num.l8 & 0x80) && c == 'd') + { + num.ll = - num.ll; + *(ptr++) = '-'; + buf++; + } + + do + { + unsigned long long L0, L1; + + /* 0x100000000 == 4294967296 */ + L0 = num.lo % 10; + L1 = num.lo / 10; //num.lo/10 = L1......L0 19999999......6 + + num.ll = L1; + *(ptr++) = '0' + L0; + } while (num.ll); + } + + /* reorder to correct direction!! 重新排序到正确的方向*/ + { + char *ptr1 = ptr - 1; + char *ptr2 = buf; + while (ptr1 > ptr2) + { + long long tmp = *ptr1; + *ptr1 = *ptr2; + *ptr2 = tmp; + ptr1--; + ptr2++; + } + } + + return ptr; +} #endif +int grub_sprintf (char *buffer, const char *format, ...); int grub_sprintf (char *buffer, const char *format, ...) { - /* Call with buffer==NULL, and it will just printf(). */ - /* XXX hohmuth ugly hack -- should unify with printf() */ - unsigned long *dataptr = (unsigned long *)(((int *)(void *) &format) + 1); - //unsigned long *dataptr = (unsigned long *)(((unsigned int *)(void *) &buffer)); -// char c, *ptr, str[32]; + +// unsigned int *dataptr = (unsigned int *)(((int *)(void *) &format) + 1); + + va_list ap ; //定义一个va_list变量ap + va_start(ap,format); //ap指向参数format之后的那个参数的地址,即指向第一个可变参数在堆栈的地址 + unsigned char str[32]; unsigned char pad; const unsigned char *ptr; @@ -273,320 +464,196 @@ grub_sprintf (char *buffer, const char *format, ...) unsigned int accuracy; unsigned char *putchar_hook_back=NULL; int stdout = 1; - if (buffer && (grub_u32_t)buffer <= 3) + unsigned char c; + + if (buffer && (grub_size_t)buffer <= (grub_size_t)3) { - if (!debug_msg) return 1; - if ((grub_u32_t)buffer != 3 && debug < (int)buffer) - return 1; + if (!debug_msg) goto err; + if ((grub_size_t)buffer != (grub_size_t)3 && (grub_size_t)debug < (grub_size_t)buffer) + goto err; - bp=NULL,buffer=NULL;//reset buffer and bp to NULL + bp=NULL,buffer=NULL;//reset buffer and bp to NULL - if (debug_msg < (grub_u32_t)buffer) - { - stdout = 0; - putchar_hook_back = set_putchar_hook((grub_u8_t*)0); - } + if (debug_msg < (grub_size_t)buffer) + { + stdout = 0; + putchar_hook_back = set_putchar_hook((grub_u8_t*)0); + } } - //dataptr++; - //dataptr++; -#if 1 - while (*format) + + while (*format) //grub_printf("%02x%c",q,' '); 首次:%02x%c 第二次:%c { - if (*format == '%') + if (*format == '%') //%02x%c; %c { - pad = ' '; - width = 0; - length = 0; - accuracy = -1; - align = 0; - ptr = (const unsigned char *)format++; - if (*format == '-') - { - ++align,++format; - } - if (*format == '0') - { - pad = *format++; - } - if (*format == '*') - { - ++format; - width=*(dataptr++); - } - else - { - while (*format >= '0' && *format <= '9') - width = width * 10 + *(format++) - '0'; - } - if (*format == '.') - { - ++format; - if (*format == '*') - { - ++format; - accuracy = *(dataptr++); - } - else - { - accuracy = 0; - while (*format >= '0' && *format <= '9') - accuracy = accuracy * 10 + *(format++) - '0'; - } - } + pad = ' '; + width = 0; + length = 0; + accuracy = -1; + align = 0; + ptr = (const unsigned char *)format++; //&(%02x%c) 改变为 02x%c; &(%c) 改变为c + if (*format == '-') + ++align,++format; + if (*format == '0') + pad = *format++; //0 改变为 2%c; + + if (*format == '*') + { + ++format; +// width=*(dataptr++); + width = va_arg(ap, int); + } + else + { + while (*format >= '0' && *format <= '9') + width = width * 10 + *(format++) - '0'; //2 改变为 x%c; 0 + } + + if (*format == '.') + { + ++format; + if (*format == '*') + { + ++format; +// accuracy = *(dataptr++); + accuracy = va_arg(ap, unsigned int); + } + else + { + accuracy = 0; + while (*format >= '0' && *format <= '9') + accuracy = accuracy * 10 + *(format++) - '0'; + } + } - if (*format == 'l') - { - ++length,++format; - } + if (*format == 'l') + { +#if defined(__i386__) + ++length,++format; +#else + ++format; +#endif + } - switch(*format) - { - case '%': - ptr = (const unsigned char *)format; - accuracy = 1; - --width; - break; - case 'c': - accuracy = 1; - --width; - ptr = (unsigned char *)dataptr++; - break; - case 's': - ptr = (unsigned char *)(unsigned int) (*(dataptr++)); - if (ptr) - { - length = grub_strlen((char *)ptr); - width -= (length > accuracy)?accuracy:length; - } - else - accuracy = 0; - break; - case 'd': case 'x': case 'X': case 'u': - { - int lo, hi; + switch(*format) //x%c; c + { + case '%': + ptr = (const unsigned char *)format; + accuracy = 1; + --width; + break; + case 'c': + accuracy = 1; + --width; //-1 +// ptr = (unsigned char *)dataptr++; + c = va_arg(ap, long); // ; ' ' + ptr = &c; +// *ptr = va_arg(ap, long); //va_arg不能给指针(以及数组)赋值,只能给变量赋值。比如此例,如果强迫赋值给*ptr(=' '),则会使grub_printf("%02x%c",q,' ') + //变为grub_printf("%02x c",q,' ')。如果循环调用的话,第二次会出错误。 + break; + case 's': +// ptr = (unsigned char *)(grub_size_t) (*(dataptr++)); + ptr = va_arg(ap, unsigned char *); + if (ptr) + { + length = grub_strlen((char *)ptr); + width -= (length > accuracy)?accuracy:length; + } + else + accuracy = 0; + break; + case 'd': case 'x': case 'X': case 'u': + { +#if defined(__i386__) + int lo, hi; +// lo = *(dataptr++); +// hi = (length ? (*(dataptr++)) : ((*format == 'd' && lo<(int)0)?(int)-1:(int)0)); + lo = va_arg(ap, unsigned int); + hi = (length ? (va_arg(ap, unsigned int)) : ((*format == 'd' && lo<(int)0)?(int)-1:(int)0)); + *convert_to_ascii ((char *)str, *format, lo, hi) = 0; +#else + unsigned long long lo; + lo = va_arg(ap, unsigned long long); + *convert_to_ascii ((char *)str, *format, lo) = 0; +#endif + } + accuracy = grub_strlen ((char *)str); //1 + width -= accuracy; //1 + ptr = str; + break; + default: + format = (char *)ptr; + goto next_c; + } + + if (align == 0) //0 + { + for(;width>(int)0;--width) //第二次是 -1 + { + if (buffer) + *bp = pad; /* putchar(pad); */ + else + grub_putchar (pad, 255); //0 补空 + ++bp; + } + } - lo = *(dataptr++); - hi = (length ? (*(dataptr++)) : ((*format == 'd' && lo<0)?-1:0)); - *convert_to_ascii ((char *)str, *format, lo, hi) = 0; - } - accuracy = grub_strlen ((char *)str); - width -= accuracy; - ptr = str; - break; - default: - format = (char *)ptr; - goto next_c; - } - if (align == 0) - { - for(;width>0;--width) - { - if (buffer) - *bp = pad; /* putchar(pad); */ - else - grub_putchar (pad, 255); - ++bp; - } - } - while (*ptr && accuracy) - { - if (buffer) - *bp = *ptr; - else - grub_putchar (*ptr, accuracy); - ++bp,++ptr; - --accuracy; - } - if (align) - { - for(;width>0;--width) - { - if (buffer) - *bp = pad; /* putchar(pad); */ - else - grub_putchar (pad, 255); - ++bp; - } - } + while (*ptr && accuracy) //2 && 1; ' ' && 1 + { + if (buffer) + *bp = *ptr; + else + grub_putchar (*ptr, accuracy); //2 实际数据; ' '; 1 + ++bp,++ptr; + --accuracy; //0 + } + + if (align) + { + for(;width>(int)0;--width) + { + if (buffer) + *bp = pad; /* putchar(pad); */ + else + grub_putchar (pad, 255); + ++bp; + } + } } else { - next_c: - if (buffer) - *bp = *format; - else - grub_putchar((unsigned char)*format, 255); - ++bp; + next_c: + if (buffer) + *bp = *format; + else + grub_putchar((unsigned char)*format, 255); + ++bp; } /* if */ - ++format; + ++format; //%c } /* while */ -#else - while ((c = *(format++)) != 0) - { - if (c != '%') - { - if (buffer) - *bp++ = c; /* putchar(c); */ - else - { - grub_putchar (c, 255); - bp++; - } - } - else - { - pad = ' '; - width = 0; - length = 0; - accuracy = -1; - -get_next_c: - c = *(format++); - -find_specifier: - switch (c) - { - case '%': - if (buffer) - *bp = c; - else - grub_putchar(c, 255); - bp++; - break; - case '.': - accuracy = 0; - while ((c = *(format++)) >= '0' && c <= '9') - accuracy = accuracy * 10 + c - '0'; - goto find_specifier; - case 'd': case 'x': case 'X': case 'u': - { - unsigned int lo, hi; - - lo = *(dataptr++); - hi = (length ? (*(dataptr++)) : 0); - *convert_to_ascii (str, c, lo, hi) = 0; - } - //dataptr++; - width -= grub_strlen (str); - if (width > 0) - { - while(width--) - if (buffer) - *bp++ = pad; /* putchar(pad); */ - else - { - grub_putchar (pad, 255); - bp++; - } - } - ptr = str; - if (buffer) - { - while (*ptr) - *bp++ = *(ptr++); /* putchar(*(ptr++)); */ - } else { - while (*ptr) - { - grub_putchar (*(ptr++), 255); - bp++; - } - } - break; - - case 'c': - if (length) - break; /* invalid */ - if (width > 0) - { - while(--width) - if (buffer) - *bp++ = pad; /* putchar(pad); */ - else - { - grub_putchar (pad, 255); - bp++; - } - } - if (buffer) - { - *bp++ = (*(char *)(dataptr++)) /*& 0xff*/; - } else { - grub_putchar ((*(char *)(dataptr++)) /*& 0xff*/, 255); - bp++; - } - //dataptr++; - break; - case 's': - if (length) - break; /* invalid */ - width -= grub_strlen ((char *) (unsigned int) *(dataptr)); - if (width > 0) - { - while(width--) - if (buffer) - *bp++ = pad; /* putchar(pad); */ - else - { - grub_putchar (pad, 255); - bp++; - } - } - ptr = (char *)(unsigned int) (*(dataptr++)); - //dataptr++; - while ((c = *(ptr++)) && accuracy--) - { - if (buffer) - *bp = c; - else - grub_putchar (c, 255); - bp++; - } - break; - case 'l': - if (length) - break; /* invalid */ - length++; - //c = *(format++); /* should be one of d, x, X, u */ - goto get_next_c; - case '0': - if (length) - break; /* invalid */ - pad = '0'; - case '1' ... '9': - if (length) - break; /* invalid */ - width = c - '0'; - while ((c = *(format++)) >= '0' && c <= '9') - width = width * 10 + c - '0'; - goto find_specifier; - } /* switch */ - } /* if */ - } /* while */ -#endif if (buffer) - *bp = 0; + *bp = 0; if (stdout == 0) - set_putchar_hook(putchar_hook_back); + set_putchar_hook(putchar_hook_back); + va_end(ap); //清空va_list,即结束变参的获取 return bp - (unsigned char *)buffer; +err: + va_end(ap); //清空va_list,即结束变参的获取 + return 1; } #include "grub4dos_version.h" - +void init_page (void); #ifdef GRUB4DOS_VERSION void init_page (void) { - //int i; unsigned char tmp_buf[128]; - //unsigned char ch = ' '; -// cls (); - - if(cursor_state==2) + if(cursor_state & 2) { if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_HEADING); @@ -597,11 +664,11 @@ init_page (void) } grub_sprintf ((char *)tmp_buf, - " GRUB4DOS " GRUB4DOS_VERSION ", Mem: %dK/%dM/%ldM, End: %X", - (unsigned long)saved_mem_lower, - (unsigned long)(saved_mem_upper >> 10), - (unsigned long long)(saved_mem_higher >> 10), - (unsigned int)(((char *) init_free_mem_start) + 1024 + 256 * sizeof (char *) + config_len)); + " GRUB4DOS " GRUB4DOS_VERSION ", Mem: %dK/%dM/%ldM, Free_mem_start: 0x%x", + (unsigned int)saved_mem_lower << 2, + (unsigned int)saved_mem_upper >> 8, + (unsigned long long)saved_mem_higher >> 8, + (unsigned int)free_mem_lower_start); grub_printf("%-*.*s",current_term->chars_per_line,current_term->chars_per_line,tmp_buf); if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_STANDARD); @@ -612,10 +679,8 @@ init_page (void) void init_page (void) { -// cls (); - grub_printf ("GNU GRUB version %s (%dK lower / %dK upper memory)\n", - version_string, saved_mem_lower, saved_mem_upper); + version_string, saved_mem_lower << 2, saved_mem_upper << 10); } #endif @@ -625,46 +690,48 @@ static int num_history = 0; /* Get the NOth history. If NO is less than zero or greater than or equal to NUM_HISTORY, return NULL. Otherwise return a valid string. */ +static char *get_history (int no); static char * get_history (int no) { int j; - char *p = (char *) HISTORY_BUF; + unsigned char *p = (unsigned char *) HISTORY_BUF; if (no < 0 || no >= num_history) return 0; /* get history NO */ for (j = 0; j < no; j++) { p += *(unsigned short *)p; - if (p > (char *) HISTORY_BUF + MAX_CMDLINE * HISTORY_SIZE) + if (p > (unsigned char *) HISTORY_BUF + MAX_CMDLINE * HISTORY_SIZE) { num_history = j; return 0; } } - return p + 2; + return (char *)p + 2; } /* Add CMDLINE to the history buffer. */ +static void add_history (const char *cmdline, int no); static void add_history (const char *cmdline, int no) { int j, len; - char *p = (char *) HISTORY_BUF; + unsigned char *p = (unsigned char *) HISTORY_BUF; /* get history NO */ for (j = 0; j < no; j++) { p += *(unsigned short *)p; - if (p > (char *) HISTORY_BUF + MAX_CMDLINE * HISTORY_SIZE) + if (p > (unsigned char *) HISTORY_BUF + MAX_CMDLINE * HISTORY_SIZE) return; } /* get cmdline length */ len = grub_strlen (cmdline) + 3; - if (((char *) HISTORY_BUF + MAX_CMDLINE * HISTORY_SIZE) > (p + len)) - grub_memmove (p + len, p, ((char *) HISTORY_BUF + MAX_CMDLINE * HISTORY_SIZE) - (p + len)); + if (((unsigned char *) HISTORY_BUF + MAX_CMDLINE * HISTORY_SIZE) > (p + len)) + grub_memmove (p + len, p, ((unsigned char *) HISTORY_BUF + MAX_CMDLINE * HISTORY_SIZE) - (p + len)); *(unsigned short *)p = len; - grub_strcpy (p + 2, cmdline); + grub_strcpy ((char *)p + 2, cmdline); if (num_history < 0x7FFFFFFF) num_history++; } @@ -693,10 +760,9 @@ static void cl_delete (int count); /* Move the cursor backward. */ static void cl_backward (int count) { - unsigned long unicode = 0; + unsigned int unicode = 0; unsigned char b = *(buf + lpos - 1); unsigned char a = *(buf + lpos - 2); - //unsigned long count = 1; /* get the length of the current sequence */ #ifdef SUPPORT_GRAPHICS @@ -758,7 +824,8 @@ static void cl_backward (int count) { /* get char width */ count = 2; /* initalize as wide char */ - if (*(unsigned long *)(UNIFONT_START + (unicode << 5)) == narrow_char_indicator) +// if (*(unsigned int *)(UNIFONT_START + (unicode << 5)) == narrow_char_indicator) + if (((*(unsigned char *)(narrow_mem + unicode/8)) & (1 << (unicode&7))) == 0) count--; // count = 1; } xpos -= count; @@ -770,9 +837,8 @@ static void cl_backward (int count) /* Move the cursor forward. */ static void cl_forward (int count) { - unsigned long unicode = 0; + unsigned int unicode = 0; unsigned char b = *(buf + lpos); - //unsigned long count = 1; /* get the length of the current sequence */ #ifdef SUPPORT_GRAPHICS @@ -838,7 +904,8 @@ static void cl_forward (int count) { /* get char width */ count = 2; /* initalize as wide char */ - if (*(unsigned long *)(UNIFONT_START + (unicode << 5)) == narrow_char_indicator) +// if (*(unsigned int *)(UNIFONT_START + (unicode << 5)) == narrow_char_indicator) + if (((*(unsigned char *)(narrow_mem + unicode/8)) & (1 << (unicode&7))) == 0) count--; // count = 1; } xpos += count; @@ -851,18 +918,18 @@ static void cl_forward (int count) only LEN characters from LPOS. */ static void cl_refresh (int full, int len) { - unsigned long i; - unsigned long start; - unsigned long pos = xpos; - unsigned long offset = 0; - unsigned long lpos_fontx; + unsigned int i; + unsigned int start; + unsigned int pos = xpos; + unsigned int offset = 0; + unsigned int lpos_fontx; if (full) { /* From the start to the end. */ len = CMDLINE_WIDTH; pos = 0; - if(cursor_state==2) + if(cursor_state & 2) gotoxy (password_x, fonty); else gotoxy (0, fonty); @@ -925,9 +992,9 @@ static void cl_refresh (int full, int len) lpos_fontx = 0; /* Print BUF. If ECHO_CHAR is not zero, put it instead. */ - for (i = start; i < start + len && i < llen; i++) + for (i = start; i < start + (unsigned int)len && i < (unsigned int)llen; i++) { - if (i == lpos) + if (i == (unsigned int)lpos) lpos_fontx = fontx; if (! get_cmdline_str.echo_char) { @@ -945,14 +1012,14 @@ static void cl_refresh (int full, int len) grub_putchar (' ', 0); /* width = 0 means no actual print */ #endif - if (i == lpos) + if (i == (unsigned int)lpos) lpos_fontx = fontx; if (len && lpos_fontx == 0) printf_warning ("\nReport bug! lpos=%d, start=%d, len=%d, llen=%d, plen=%d, section=%d\n", lpos, start, len, llen, plen, section); /* Fill up the rest of the line with spaces. */ - for (; i < start + len; i++) + for (; i < start + (unsigned int)len; i++) { grub_putchar (' ', 255); pos++; @@ -960,9 +1027,9 @@ static void cl_refresh (int full, int len) /* If the cursor is at the last position, put `>' or a space, depending on if there are more characters in BUF. */ - if (pos == CMDLINE_WIDTH) + if (pos == (unsigned int)CMDLINE_WIDTH) { - if (start + len < llen) + if (start + (unsigned int)len < (unsigned int)llen) grub_putchar ('>', 255); else grub_putchar (' ', 255); @@ -985,7 +1052,7 @@ static void cl_insert (const char *str) { int l = grub_strlen (str); - if (llen + l < get_cmdline_str.maxlen) + if (llen + l < (int)get_cmdline_str.maxlen) { if (lpos == llen) grub_memmove (buf + lpos, str, l + 1); @@ -1013,7 +1080,6 @@ static void cl_insert (const char *str) static void cl_delete (int count) { unsigned char b = *(buf + lpos); - //unsigned long count = 1; /* get the length of the current sequence */ #ifdef SUPPORT_GRAPHICS @@ -1047,6 +1113,7 @@ static void cl_delete (int count) #endif } +static int real_get_cmdline (void); static int real_get_cmdline (void) { @@ -1081,7 +1148,8 @@ real_get_cmdline (void) section is switched to another section, only if the cursor is put outside that section. */ - int c; +// int c; + unsigned short c = 0; int history = -1; /* The index for the history. */ buf = (unsigned char *) CMDLINE_BUF; @@ -1112,7 +1180,8 @@ real_get_cmdline (void) while ((t2 = getrtsecs ()) == 0xFF); while (wait_t) { - if (checkkey () != -1) +// if (checkkey () != -1) + if ((c = checkkey ()) != (unsigned short)-1) break; if ((t1 = getrtsecs ()) != t2 && t1 != 0xFF) { @@ -1125,7 +1194,8 @@ real_get_cmdline (void) } get_cmdline_str.readline &= 1; - while ((char)(c = /*ASCII_CHAR*/ (getkey ())) != '\n' && (char)c != '\r') +// while ((char)(c = /*ASCII_CHAR*/ (getkey ())) != '\n' && (char)c != '\r') + while ((char)c != '\n' && (char)c != '\r') { /* If READLINE is non-zero, handle readline-like key bindings. */ if (get_cmdline_str.readline) @@ -1257,7 +1327,7 @@ real_get_cmdline (void) if (history < 0) /* Save the working buffer. */ grub_strcpy ((char *)get_cmdline_str.cmdline, (const char *)buf); - else if (grub_strcmp (get_history (history), (const char *)buf) != 0) + else if (grub_strcmp ((const char *)get_history (history), (const char *)buf) != 0) /* If BUF is modified, add it into the history list. */ add_history ((const char *)buf, history); @@ -1338,6 +1408,7 @@ real_get_cmdline (void) cl_insert (str); } } + c = getkey (); } // if (fontx) @@ -1362,6 +1433,7 @@ real_get_cmdline (void) int get_cmdline_obsolete (struct get_cmdline_arg cmdline); +int get_cmdline_obsolete (struct get_cmdline_arg cmdline); int get_cmdline_obsolete (struct get_cmdline_arg cmdline) { @@ -1380,7 +1452,7 @@ get_cmdline_obsolete (struct get_cmdline_arg cmdline) int get_cmdline (void) { - unsigned long old_cursor = cursor_state; + unsigned int old_cursor = cursor_state; int ret; /* Because it is hard to deal with different conditions simultaneously, @@ -1437,18 +1509,19 @@ get_cmdline (void) return ret; } -// Parse decimal or hexadecimal ASCII input string to 64-bit integer -// input number may have K,M,G,T or k,m,g,t suffix -// if unitshift is 0, the number is plain number. +// Parse decimal or hexadecimal ASCII input string to 64-bit integer 将十进制或十六进制ASCII输入字符串解析为64位整数 +// input number may have K,M,G,T or k,m,g,t suffix 输入数字可以有K、M、G、T或k、m、g、t后缀 +// if unitshift is 0, the number is plain number. 如果unitshift为0,则该数字为纯数字。 // 1K=1024, 1M=1048576, 1G=1<<30, 1T=1<<40 -// if unitshift is 9, the input number is number of 512-bytes sectors and suffixes means KBytes, MBytes,... +// if unitshift is 9, the input number is number of 512-bytes sectors and suffixes means KBytes, MBytes,... 如果unitshift为9,则输入数字是512字节扇区的数量,后缀表示KB,MB // 1K=2 sectors, 1M=2048 sectors, ... -// unitshift must be in the range 0-63 +// unitshift must be in the range 0-63 unitshift必须在0-63的范围内 +//*str_ptr返回源结束地址 +//会改变*str_ptr值,增大8字节!!! int safe_parse_maxint_with_suffix (char **str_ptr, unsigned long long *myint_ptr, int unitshift) { unsigned long long myint = 0; - //unsigned long long mult = 10; char *ptr = *str_ptr; char found = 0; char negative = 0; @@ -1458,13 +1531,6 @@ safe_parse_maxint_with_suffix (char **str_ptr, unsigned long long *myint_ptr, in * 0x8000000000000000(the minimal long long) to 0x7fffffffffffffff(the maximal long long). * The hex numbers are not checked. */ -#if 0 - if (*ptr == '-') /* check whether or not the negative sign exists */ - { - ptr++; - negative = 1; - } -#else switch(*ptr) { case '-': @@ -1474,7 +1540,7 @@ safe_parse_maxint_with_suffix (char **str_ptr, unsigned long long *myint_ptr, in default: break; } -#endif + /* * Is this a hex number? */ @@ -1487,7 +1553,7 @@ safe_parse_maxint_with_suffix (char **str_ptr, unsigned long long *myint_ptr, in /* A bit tricky. This below makes use of the equivalence: (A <= B && A <= C) <=> ((A - B) <= (C - B)) when C > B and A is unsigned. */ -#if 1 + unsigned char digit; digit = (unsigned char)(*ptr-'0'); // '0'...'9' become 0...9, 'A'...'F' become 17...22, 'a'...'f' become 49...54 @@ -1499,18 +1565,7 @@ safe_parse_maxint_with_suffix (char **str_ptr, unsigned long long *myint_ptr, in break; // end of hexadecimal number digit +=10; } // don't have to call tolower function -#else - unsigned int digit; - digit = tolower (*ptr) - '0'; - if (digit > 9) - { - digit -= 'a' - '0'; - if (mult == 10 || digit > 5) - break; - digit += 10; - } -#endif found = 16; if ( myint>>(64-4) ) { // highest digit has already been filled with non-zero, another left shift will overflow @@ -1530,7 +1585,7 @@ safe_parse_maxint_with_suffix (char **str_ptr, unsigned long long *myint_ptr, in if (digit>9) break; found = 10; -#if 1 + if ( myint > ((-1ULL>>1)/10) // multiply with 10 will overflow (result > max signed long long) || (myint = myint*10 + digit, // numbers less than (1ULL<<63) are valid (positive or negative). @@ -1545,20 +1600,7 @@ safe_parse_maxint_with_suffix (char **str_ptr, unsigned long long *myint_ptr, in errnum = ERR_NUMBER_OVERFLOW; return 0; } -#else - /* we do not check for hex or negative */ - if (mult == 10 && ! negative) - /* 0xFFFFFFFFFFFFFFFF == 18446744073709551615ULL */ - // if ((unsigned)myint > (((unsigned)(MAXINT - digit)) / (unsigned)mult)) - if (myint > 1844674407370955161ULL || - (myint == 1844674407370955161ULL && digit > 5)) - { - errnum = ERR_NUMBER_OVERFLOW; - return 0; - } - myint *= mult; - myint += digit; -#endif + ptr++; } } @@ -1610,92 +1652,12 @@ safe_parse_maxint_with_suffix (char **str_ptr, unsigned long long *myint_ptr, in return 1; } } -#if 0 + int -safe_parse_maxint (char **str_ptr, unsigned long long *myint_ptr) +grub_tolower (int c) { - char *ptr = *str_ptr; - unsigned long long myint = 0; - unsigned long long mult = 10; - int found = 0; - int negative = 0; - - /* - * The decimal numbers can be positive or negative, ranging from - * 0x80000000(the minimal int) to 0x7fffffff(the maximal int). - * The hex numbers are not checked. - */ - - if (*ptr == '-') /* check whether or not the negative sign exists */ - { - ptr++; - negative = 1; - } - - /* - * Is this a hex number? - */ - if (*ptr == '0' && tolower (*(ptr + 1)) == 'x') - { - ptr += 2; - mult = 16; - } - - while (1) - { - /* A bit tricky. This below makes use of the equivalence: - (A >= B && A <= C) <=> ((A - B) <= (C - B)) - when C > B and A is unsigned. */ - unsigned int digit; - - digit = tolower (*ptr) - '0'; - if (digit > 9) - { - digit -= 'a' - '0'; - if (mult == 10 || digit > 5) - break; - digit += 10; - } - - found = 1; - /* we do not check for hex or negative */ - if (mult == 10 && ! negative) - /* 0xFFFFFFFFFFFFFFFF == 18446744073709551615ULL */ -// if ((unsigned)myint > (((unsigned)(MAXINT - digit)) / (unsigned)mult)) - if (myint > 1844674407370955161ULL || - (myint == 1844674407370955161ULL && digit > 5)) - { - errnum = ERR_NUMBER_OVERFLOW; - return 0; - } - myint *= mult; - myint += digit; - ptr++; - } - - if (!found) - { - errnum = ERR_NUMBER_PARSING; - return 0; - } - - *str_ptr = ptr; - *myint_ptr = negative ? -myint : myint; - - return 1; -} -#endif - -int -grub_tolower (int c) -{ -#if 0 - if (c >= 'A' && c <= 'Z') - return (c + ('a' - 'A')); -#else if ((unsigned int)(c - 'A') < 26) return c|0x20; -#endif return c; } @@ -1804,6 +1766,7 @@ static grub_u32_t crc32_tab[256] = { 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; +static grub_u32_t calc_crc32(grub_u32_t crc, const void *data, grub_u32_t size); static grub_u32_t calc_crc32(grub_u32_t crc, const void *data, grub_u32_t size) { const grub_u8_t *p; @@ -1816,6 +1779,7 @@ static grub_u32_t calc_crc32(grub_u32_t crc, const void *data, grub_u32_t size) return crc^~0U; } +int grub_crc32(char *data,grub_u32_t size); int grub_crc32(char *data,grub_u32_t size) { int crc = 0; @@ -1823,21 +1787,21 @@ int grub_crc32(char *data,grub_u32_t size) if ((*data == '(' || * data== '/') && grub_open(data)) { - while((len = grub_read ((unsigned long long)(unsigned long)mbr, SECTOR_SIZE, GRUB_READ))) + while((len = grub_read ((unsigned long long)(grub_size_t)mbr, SECTOR_SIZE, GRUB_READ))) crc = calc_crc32(crc,mbr,len); grub_close(); } else { errnum = 0; - crc = calc_crc32(crc,data,size?size:strlen(data)); + crc = calc_crc32(crc,data,size?size:(grub_u32_t)strlen(data)); } return crc; } int -grub_memcmp (const char *s1, const char *s2, int n) +grub_memcmp (const char *s1, const char *s2, grub_size_t n) { while (n) { @@ -1893,6 +1857,19 @@ grub_strcmp (const char *s1, const char *s2) return 0; } +#if 0 +unsigned int +grub_putchar (unsigned int c, unsigned int max_width) +{ + return current_term->putchar (c, max_width); +} +#endif +/* Check if a key code is available. */ +int +checkkey (void) +{ + return current_term->checkkey (); +} /* Wait for a keypress and return its code. */ int @@ -1903,31 +1880,68 @@ getkey (void) /* Check if a key code is available. */ int -checkkey (void) +getxy (void) { - return current_term->checkkey (); + return current_term->getxy (); } -unsigned char *set_putchar_hook(unsigned char *hooked) +void +gotoxy (int x, int y) { - unsigned char *re = putchar_hooked; - putchar_hooked = hooked; - return re; + current_term->gotoxy (x, y); +} + +void cls (void); +void +cls (void) +{ + /* If the terminal is dumb, there is no way to clean the terminal. */ + if (current_term->flags & TERM_DUMB) + grub_putchar ('\n', 255); + else + current_term->cls (); +} + +void setcolorstate (color_state state); +void +setcolorstate (color_state state) +{ + current_term->setcolorstate (state); +} + +void setcolor (unsigned int state,unsigned long long *color); +void +setcolor (unsigned int state,unsigned long long *color) +{ + current_term->setcolor (state, color); +} + +unsigned char *set_putchar_hook(unsigned char *hooked); +unsigned char *set_putchar_hook(unsigned char *hooked) //设置打印字符钩子 +{ + unsigned char *re = putchar_hooked; //保存旧钩子 + putchar_hooked = hooked; //设置新钩子 + return re; //返回旧钩子 } /* FIXME: this is problematic! it could cause memory conflicts! */ /* Display an ASCII character. */ +unsigned int grub_putchar (unsigned int c, unsigned int max_width); unsigned int -_putchar (unsigned int c, unsigned int max_width) +//_putchar (unsigned int c, unsigned int max_width) +grub_putchar (unsigned int c, unsigned int max_width) { + /* if it is a Line Feed, we insert a Carriage Return. */ if (putchar_hooked) { - if ((unsigned int)putchar_hooked > 0x800) - *(unsigned long*)putchar_hooked++ = (unsigned char)c; + if ((grub_size_t)putchar_hooked > 0x800) + *(unsigned char*)putchar_hooked++ = (unsigned char)c; return 1; } + //return current_term->putchar (c, max_width); + if (c == '\t'/* && current_term->getxy*/) { c = 8 - (fontx/*(current_term->getxy ())*/ & 7); @@ -1978,9 +1992,12 @@ _putchar (unsigned int c, unsigned int max_width) count_lines = 0; } } + return i; } +#if 0 +inline void debug_sleep(int l_debug_boot, int line, char *file); inline void debug_sleep(int l_debug_boot, int line, char *file) { @@ -1991,44 +2008,31 @@ debug_sleep(int l_debug_boot, int line, char *file) //grub_printf("\r%*s\r", CMDLINE_WIDTH, " "); } } +#endif #ifdef DEBUG_TIME +inline void debug_time(const int line,const char*file); inline void debug_time(const int line,const char*file) { - unsigned long date, time; - get_datetime(&date, &time); + unsigned int date, time; + //get_datetime(&date, &time); printf("%s[%d]:%02X:%02X:%02X\n",file,line,(char)(time >> 24),(char)(time >> 16),(char)(time>>8)); } #endif -void -gotoxy (int x, int y) -{ - current_term->gotoxy (x, y); -} -int -getxy (void) -{ - return current_term->getxy (); -} -void -cls (void) -{ - /* If the terminal is dumb, there is no way to clean the terminal. */ - if (current_term->flags & TERM_DUMB) - grub_putchar ('\n', 255); - else - current_term->cls (); -} -unsigned long -setcursor (unsigned long on) + + +//unsigned int cursor_state_put; +unsigned int setcursor (unsigned int on); +unsigned int +setcursor (unsigned int on) //设置控制台光标开关, 设置光标状态变量 { - unsigned long old_state = cursor_state; - cursor_state = on; - - if (current_term->setcursor) + unsigned int old_state = cursor_state; + cursor_state = on; //光标状态变量 位0: 0/1=光标关/光标开 位1: 0/1=在命令行/在菜单界面 +// cursor_state_put = on; + if (current_term->setcursor) //设置控制台光标开关=0/1=关闭/打开 图形模式不起作用 current_term->setcursor (on & 1); return old_state; @@ -2047,7 +2051,7 @@ setcursor (unsigned long on) return 1 s1 isn't a substring of S2 return -1 s1 is a substring of S2. */ -int strncmpx(const char *s1,const char *s2, unsigned long n, int case_insensitive) +int strncmpx(const char *s1,const char *s2, unsigned int n, int case_insensitive) { int x = (n?0:--n); while (n) @@ -2079,32 +2083,29 @@ substring (const char *s1, const char *s2, int case_insensitive) ch1 = *(s1++); ch2 = *(s2++); - if (case_insensitive) + if (case_insensitive) //为1,不区分大小写 { ch1 = tolower(ch1); ch2 = tolower(ch2); } - if (! ch1) /* S1 is a substring of S2, or they match exactly */ + if (! ch1) /* S1 is a substring of S2, or they match exactly S1是S2的子字符串,或者它们完全匹配*/ return ch2 ? -1 : 0; if (ch1 != ch2) - return 1; /* S1 isn't a substring of S2 */ + return 1; /* S1 isn't a substring of S2 S1不是S2的子字符串*/ } } -/* Terminate the string STR with NUL. */ +/* Terminate the string STR with NUL. 用NUL终止字符串STR*/ int nul_terminate (char *str) { int ch; - -// while (*str && ! grub_isspace (*str)) -// str++; while ((ch = *str) && ! grub_isspace (ch)) { - if (ch == '"') + if (ch == '"') //跳过"...." { str++; while (*str != '"') @@ -2113,14 +2114,14 @@ nul_terminate (char *str) if (ch == '\\') { str++; - if (! (ch = *str)) + if (! (ch = *str)) //遇到\0退出 break; } - str++; + str++; //跳过"\"或者""" } // ch = *str; - *str = 0; + *str = 0; return ch; } @@ -2167,49 +2168,6 @@ memcheck (unsigned long long addr, unsigned long long len) return ! errnum; } -#if 0 -void -grub_memcpy(void *dest, const void *src, int len) -{ - int i; - register char *d = (char*)dest, *s = (char*)src; - - for (i = 0; i < len; i++) - d[i] = s[i]; -} -#endif - -#if 0 -static inline void * _memcpy_forward(void *dst, const void *src, unsigned int len) -{ - int r0, r1, r2, r3; - __asm__ __volatile__( - "movl %%ecx, %0; shrl $2, %%ecx; " // ECX=(len / 4) - "rep; movsl; " - "movl %0, %%ecx; andl $3, %%ecx; " // ECX=(len % 4) - "rep; movsb; " - : "=&r"(r0), "=&c"(r1), "=&D"(r2), "=&S"(r3) - : "1"(len), "2"((long)dst), "3"((long)src) - : "memory"); - return dst; -} -static inline void * _memcpy_backward(void *dst, const void *src, unsigned int len) -{ - int r0, r1, r2, r3; - __asm__ __volatile__( - "std; \n\t" - "movl %%ecx, %0; andl $3, %%ecx; " // now ESI,EDI point to end-1, ECX=(len % 4) - "rep; movsb; " - "subl $3, %%edi; subl $3, %%esi; " - "movl %0, %%ecx; shrl $2, %%ecx; " // now ESI,EDI point to end-4, ECX=(len / 4) - "rep; movsl; \n\t" - "cld; \n\t" - : "=&r"(r0),"=&c"(r1), "=&D"(r2), "=&S"(r3) - : "1"(len), "2"((long)dst+len-1), "3"((long)src+len-1) - : "memory"); - return dst; -} -#endif static inline int _memcmp(const void *str1, const void *str2, unsigned int len) { int a, r1, r2, r3; @@ -2245,114 +2203,32 @@ static inline void _memset(void *dst, unsigned char data, unsigned int len) :"memory"); } - -/* struct copy needs the memcpy function */ -/* #undef memcpy */ -#if 1 -void * grub_memcpy(void * to, const void * from, unsigned int n) -{ - /* This assembly code is stolen from - * linux-2.4.22/include/asm-i386/string.h - * It assumes ds=es=data space, this should be normal. - */ - int d0, d1, d2; - __asm__ __volatile__( - "rep ; movsl\n\t" - "testb $2,%b4\n\t" - "je 1f\n\t" - "movsw\n" - "1:\ttestb $1,%b4\n\t" - "je 2f\n\t" - "movsb\n" - "2:" - : "=&c" (d0), "=&D" (d1), "=&S" (d2) - :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from) - : "memory"); - return to; -} -#else -/* just in case the assembly version of grub_memcpy does not work. */ -void * grub_memcpy(void * to, const void * from, unsigned int n) -{ - char *d = (char *)to, *s = (char *)from; - - while (n--) - *d++ = *s++; - - return to; -} -#endif - void * grub_memmove (void *to, const void *from, int len) { -#if 0 - if (memcheck ((int) to, len)) - { - /* This assembly code is stolen from - linux-2.2.2/include/asm-i386/string.h. This is not very fast - but compact. */ - int d0, d1, d2; - - if (to < from) - { - asm volatile ("cld\n\t" - "rep\n\t" - "movsb" - : "=&c" (d0), "=&S" (d1), "=&D" (d2) - : "0" (len),"1" (from),"2" (to) - : "memory"); - } - else - { - asm volatile ("std\n\t" - "rep\n\t" - "movsb\n\t" - "cld" - : "=&c" (d0), "=&S" (d1), "=&D" (d2) - : "0" (len), - "1" (len - 1 + (const char *) from), - "2" (len - 1 + (char *) to) - : "memory"); - } - } -#else - int r0, r1, r2, r3; + char *t = (char*)to, *f = (char*)from; + if (to < from) { - __asm__ __volatile__( - "movl %%ecx, %0; shrl $2, %%ecx; " - "rep; movsl; " - "movl %0, %%ecx; andl $3, %%ecx; " - "rep; movsb; " - : "=&r"(r0), "=&c"(r1), "=&D"(r2), "=&S"(r3) - : "1"(len), "2"((long)to), "3"((long)from) - : "memory"); + while (len--) + *t++ = *f++; } - else + else if (to > from) { - __asm__ __volatile__( - "std; \n\t" - "movl %%ecx, %0; andl $3, %%ecx; " - "rep; movsb; " - "subl $3, %%edi; subl $3, %%esi; " - "movl %0, %%ecx; shrl $2, %%ecx; " - "rep; movsl; \n\t" - "cld; \n\t" - : "=&r"(r0),"=&c"(r1), "=&D"(r2), "=&S"(r3) - : "1"(len), "2"((long)to+len-1), "3"((long)from+len-1) - : "memory"); + t += len - 1; + f += len - 1; + while (len--) + *t-- = *f--; } -#endif - return errnum ? NULL : to; + return errnum ? NULL : to; } void * -grub_memset (void *start, int c, int len) +grub_memset (void *start, int c, grub_size_t len) { char *p = start; - if (memcheck ((unsigned int)start, len)) + if (memcheck ((grub_size_t)start, len)) { while (len -- > 0) *p ++ = c; @@ -2361,6 +2237,7 @@ grub_memset (void *start, int c, int len) return errnum ? NULL : start; } +char *grub_strcpy (char *dest, const char *src); char * grub_strcpy (char *dest, const char *src) { @@ -2368,9 +2245,22 @@ grub_strcpy (char *dest, const char *src) return dest; } +char *grub_strncpy (char *dest, const char *src, int c); +char * +grub_strncpy (char *dest, const char *src, int c) +{ + char *p = dest; + + while ((*p++ = *src++) != '\0' && --c) + ; + + return dest; +} + /* The strtok.c comes from reactos. It follows GPLv2. */ /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +char* grub_strtok(char *s, const char *delim); char* grub_strtok(char *s, const char *delim) { @@ -2423,58 +2313,25 @@ grub_strtok(char *s, const char *delim) /* GCC emits references to memcpy() for struct copies etc. */ void *memcpy (void *dest, const void *src, int n) __attribute__ ((alias ("grub_memmove"))); -#if 0 -int -grub_memcmp64_lm (const unsigned long long s1, const unsigned long long s2, unsigned long long n) -{ - if (((unsigned long *)&s1)[1] || ((unsigned long *)&s2)[1] || ((unsigned long *)&n)[1] || (s1 + n) > 0x100000000ULL || (s2 + n) > 0x100000000ULL) - { - return mem64 (2, s1, s2, n); /* 2 for CMP */ - } - - return grub_memcmp ((char *)(unsigned int)s1, (char *)(unsigned int)s2, n); -} - -void -grub_memmove64 (unsigned long long to, const unsigned long long from, unsigned long long len) -{ - if (((unsigned long *)&to)[1] || ((unsigned long *)&from)[1] || ((unsigned long *)&len)[1] || (to + len) > 0x100000000ULL || (from + len) > 0x100000000ULL) - { - } - - grub_memmove ((void *)(unsigned int)to, (void *)(unsigned int)from, len); -} - -void -grub_memset64 (unsigned long long start, unsigned long long c, unsigned long long len) -{ - if (((unsigned long *)&start)[1] || ((unsigned long *)&len)[1] || (start + len) > 0x100000000ULL) - { - mem64 (3, start, c, len); /* 3 for SET */ - return; - } - - grub_memset ((void *)(unsigned int)start, c, len); -} - -#endif +#define PAGINGTXSTEP 0x800000 -#define PAGING_PML4_ADDR (PAGING_TABLES_BUF+0x0000) -#define PAGING_PDPT_ADDR (PAGING_TABLES_BUF+0x1000) -#define PAGING_PD_ADDR (PAGING_TABLES_BUF+0x2000) +#if defined(__i386__) +//#define PAGING_PML4_ADDR (PAGING_TABLES_BUF+0x0000) +//#define PAGING_PDPT_ADDR (PAGING_TABLES_BUF+0x1000) +//#define PAGING_PD_ADDR (PAGING_TABLES_BUF+0x2000) // If this value is changed, memory_paging_map_for_transfer must also be modified. -#define PAGINGTXSTEP 0x800000 +//#define PAGINGTXSTEP 0x800000 #define DST_VIRTUAL_BASE 0x1000000UL #define SRC_VIRTUAL_BASE 0x2000000UL -#define DST_VIRTUAL_ADDR(addr) (((unsigned long)(addr) & 0x1FFFFFUL)+DST_VIRTUAL_BASE) -#define SRC_VIRTUAL_ADDR(addr) (((unsigned long)(addr) & 0x1FFFFFUL)+SRC_VIRTUAL_BASE) +#define DST_VIRTUAL_ADDR(addr) (((unsigned int)(addr) & 0x1FFFFFUL)+DST_VIRTUAL_BASE) +#define SRC_VIRTUAL_ADDR(addr) (((unsigned int)(addr) & 0x1FFFFFUL)+SRC_VIRTUAL_BASE) #define DST_VIRTUAL_PTR(addr) ((void*)DST_VIRTUAL_ADDR(addr)) #define SRC_VIRTUAL_PTR(addr) ((void*)SRC_VIRTUAL_ADDR(addr)) // Set to 0 to test mem64 function -#define DISABLE_AMD64 0 +//#define DISABLE_AMD64 0 extern void memory_paging_init(void); extern void memory_paging_enable(void); @@ -2486,15 +2343,17 @@ unsigned char memory_paging_initialized = 0; void memory_paging_init() { // prepare PDP, PDT - unsigned long long *paging_PML4 = (unsigned long long *)PAGING_PML4_ADDR; - unsigned long long *paging_PDPT = (unsigned long long *)PAGING_PDPT_ADDR; - unsigned long long *paging_PD = (unsigned long long *)PAGING_PD_ADDR; + unsigned long long *paging_PML4 = (unsigned long long *)(PAGING_TABLES_BUF); + unsigned long long *paging_PDPT = (unsigned long long *)(PAGING_TABLES_BUF+0x1000); + unsigned long long *paging_PD = (unsigned long long *)(PAGING_TABLES_BUF+0x2000); unsigned long long a; - - paging_PML4[0] = PAGING_PDPT_ADDR | PML4E_P; + +// paging_PML4[0] = PAGING_PDPT_ADDR | PML4E_P; + paging_PML4[0] = (unsigned long long)(grub_size_t)paging_PDPT | PML4E_P; _memset(paging_PML4+1,0,4096-8*1); - paging_PDPT[0] = PAGING_PD_ADDR | PDPTE_P; +// paging_PDPT[0] = PAGING_PD_ADDR | PDPTE_P; + paging_PDPT[0] = (unsigned long long)(grub_size_t)paging_PD | PDPTE_P; _memset(paging_PDPT+1,0,4096-8*1); // virtual address 0-16MB = physical address 0-16MB @@ -2510,9 +2369,10 @@ void memory_paging_init() memory_paging_initialized = 1; } + void memory_paging_map_for_transfer(unsigned long long dst_addr, unsigned long long src_addr) { - unsigned long long *paging_PD = (unsigned long long *)PAGING_PD_ADDR; + unsigned long long *paging_PD = (unsigned long long *)(PAGING_TABLES_BUF+0x2000); unsigned long long a; if (!memory_paging_initialized) memory_paging_init(); @@ -2534,6 +2394,7 @@ void memory_paging_map_for_transfer(unsigned long long dst_addr, unsigned long l asm volatile ("movl %%cr3,%0; movl %0,%%cr3" : "=&q"(r0) : : "memory"); } } + void memory_paging_enable() { if (!memory_paging_initialized) @@ -2553,12 +2414,14 @@ void memory_paging_enable() "btsl $7, %1; \n\t" // CR4.PGE(bit7) "movl %1, %%cr4; \n\t" // set PGE :"=&r"(r0),"=&r"(r1) - :"r"(PAGING_PDPT_ADDR), +// :"r"(PAGING_PDPT_ADDR), + :"r"(PAGING_TABLES_BUF+0x1000), "i"(PROT_MODE_CSEG), "i"(PROT_MODE_DSEG) :"memory"); } } + void memory_paging_disable() { int r0; @@ -2573,6 +2436,7 @@ void memory_paging_disable() "i"(PROT_MODE_CSEG) :"memory"); } +#endif /* Transfer data in memory. @@ -2582,37 +2446,45 @@ code must be below 16MB as mapped by memory_paging_init function unsigned long long grub_memmove64(unsigned long long dst_addr, unsigned long long src_addr, unsigned long long len) { +#if !defined(__i386__) + + return (unsigned long long)(grub_size_t)grub_memmove ((void *)(grub_size_t)dst_addr, (void *)(grub_size_t)src_addr, len); +#if 0 + if (dst_addr < src_addr) + { + char *d = (char *)dst_addr, *s = (char *)src_addr; + while (len--) + *d++ = *s++; + } + else + { + char *d = (char *)dst_addr + len; + char *s = (char *)src_addr + len; + while (len--) + *d-- = *s--; + } + return ; +#endif + +#else if (!len) { errnum = 0; return dst_addr; } if (!dst_addr) { errnum = ERR_WONT_FIT; return 0; } // forward copy should be faster than backward copy // If src_addr < dst_addr < src_addr+len, forward copy is not safe, so we do backward copy in that case. -#if 0 - unsigned char backward = ((src_addr < dst_addr) && (dst_addr < src_addr+len)); -#endif - unsigned long highaddr = (unsigned long)( dst_addr >>32) - | (unsigned long)((dst_addr+len-1)>>32) - | (unsigned long)( src_addr >>32) - | (unsigned long)((src_addr+len-1)>>32); + + unsigned int highaddr = (unsigned int)( dst_addr >>32) + | (unsigned int)((dst_addr+len-1)>>32) + | (unsigned int)( src_addr >>32) + | (unsigned int)((src_addr+len-1)>>32); if ( highaddr==0 ) { // below 4GB just copy it normally - void *pdst = (void*)(unsigned long)dst_addr; - void *psrc = (void*)(unsigned long)src_addr; -#if 0 - if (backward) - _memcpy_backward(pdst, psrc, len); - else - _memcpy_forward(pdst, psrc, len); -#else + void *pdst = (void*)(unsigned int)dst_addr; + void *psrc = (void*)(unsigned int)src_addr; + grub_memmove(pdst, psrc, len); -#endif errnum = 0; return dst_addr; } - else if ( (highaddr>>(52-32))==0 && (is64bit & IS64BIT_AMD64) && !DISABLE_AMD64) - { // AMD64/IA32-e paging - mem64 (1, dst_addr, src_addr, len); /* 1 for MOVE */ - return dst_addr; - } else if ( (highaddr>>(52-32))==0 && (is64bit & IS64BIT_PAE)) { // PAE paging void *pdst = DST_VIRTUAL_PTR(dst_addr); @@ -2624,16 +2496,9 @@ grub_memmove64(unsigned long long dst_addr, unsigned long long src_addr, unsigne unsigned long long nr = len; // number of bytes remaining while (1) { - unsigned long n1 = (nr>=PAGINGTXSTEP)? PAGINGTXSTEP: (unsigned long)nr; // number of bytes per round (8MB) + unsigned long long n1 = (nr>=PAGINGTXSTEP)? PAGINGTXSTEP: (unsigned int)nr; // number of bytes per round (8MB) // Copy -#if 0 - if (backward) - _memcpy_backward(pdst, psrc, n1); - else - _memcpy_forward(pdst, psrc, n1); -#else grub_memmove(pdst, psrc, n1); -#endif // update loop variables if ((nr -= n1)==0) break; memory_paging_map_for_transfer((dsta+=n1), (srca+=n1)); @@ -2645,24 +2510,33 @@ grub_memmove64(unsigned long long dst_addr, unsigned long long src_addr, unsigne { errnum = ERR_WONT_FIT; return 0; } +#endif } + unsigned long long grub_memset64(unsigned long long dst_addr, unsigned int data, unsigned long long len) { +#if !defined(__i386__) + + char *p = (char *)dst_addr; + if (!len) { return dst_addr; } + if (!dst_addr) { return dst_addr; } + while (len-- > 0) + *p++ = data; + + return dst_addr; + + +#else if (!len) { errnum=0; return dst_addr; } if (!dst_addr) { errnum = ERR_WONT_FIT; return 0; } - unsigned long highaddr = (unsigned long)( dst_addr >>32) - | (unsigned long)((dst_addr+len-1)>>32); + unsigned int highaddr = (unsigned int)( dst_addr >>32) + | (unsigned int)((dst_addr+len-1)>>32); if ( highaddr==0 ) { // below 4GB - _memset((void*)(unsigned long)dst_addr, data, len); + _memset((void*)(unsigned int)dst_addr, data, len); errnum = 0; return dst_addr; } - else if ( (highaddr>>(52-32))==0 && (is64bit & IS64BIT_AMD64) && !DISABLE_AMD64) - { // AMD64/IA32-e paging - mem64 (3, dst_addr, data, len); /* 3 for SET */ - return dst_addr; - } else if ( (highaddr>>(52-32))==0 && (is64bit & IS64BIT_PAE)) { // PAE paging void *pdst = DST_VIRTUAL_PTR(dst_addr); @@ -2673,7 +2547,7 @@ grub_memset64(unsigned long long dst_addr, unsigned int data, unsigned long long unsigned long long nr = len; // number of bytes remaining while (1) { - unsigned long n1 = (nr>=PAGINGTXSTEP)? PAGINGTXSTEP: (unsigned long)nr; // number of bytes per round (8MB) + unsigned int n1 = (nr>=PAGINGTXSTEP)? PAGINGTXSTEP: (unsigned int)nr; // number of bytes per round (8MB) // Copy _memset(pdst, data, n1); // update loop variables @@ -2688,23 +2562,42 @@ grub_memset64(unsigned long long dst_addr, unsigned int data, unsigned long long { errnum = ERR_WONT_FIT; return 0; } +#endif } + int grub_memcmp64(unsigned long long str1addr, unsigned long long str2addr, unsigned long long len) { +#if !defined(__i386__) + + return grub_memcmp((const char *)str1addr, (const char *)str2addr, len); + +#if 0 + char *s1 = (char *)str1addr; + char *s2 = (char *)str2addr; + while (len) + { + if (*s1 < *s2) + return -1; + else if (*s1 > *s2) + return 1; + s1++; + s2++; + len--; + } + + return 0; +#endif +#else if (!len) { errnum=0; return 0; } - unsigned long highaddr = (unsigned long)( str1addr >>32) - | (unsigned long)((str1addr+len-1)>>32) - | (unsigned long)( str2addr >>32) - | (unsigned long)((str2addr+len-1)>>32); + unsigned int highaddr = (unsigned int)( str1addr >>32) + | (unsigned int)((str1addr+len-1)>>32) + | (unsigned int)( str2addr >>32) + | (unsigned int)((str2addr+len-1)>>32); if ( highaddr==0 ) { // below 4GB - return _memcmp((const char*)(unsigned long)str1addr, - (const char*)(unsigned long)str2addr, (unsigned long)len); - } - else if ( (highaddr>>(52-32))==0 && (is64bit & IS64BIT_AMD64) && !DISABLE_AMD64) - { // AMD64/IA32-e paging - return mem64 (2, str1addr, str2addr, len); /* 2 for CMP */ + return _memcmp((const char*)(unsigned int)str1addr, + (const char*)(unsigned int)str2addr, (unsigned int)len); } else if ( (highaddr>>(52-32))==0 && (is64bit & IS64BIT_PAE)) { // PAE paging @@ -2718,7 +2611,7 @@ grub_memcmp64(unsigned long long str1addr, unsigned long long str2addr, unsigned { while (1) { - unsigned long n1 = (nr>=PAGINGTXSTEP)? PAGINGTXSTEP: (unsigned long)nr; // number of bytes per round (8MB) + unsigned int n1 = (nr>=PAGINGTXSTEP)? PAGINGTXSTEP: (unsigned int)nr; // number of bytes per round (8MB) // Compare r = _memcmp(p1, p2, n1); if (r) break; @@ -2734,4 +2627,307 @@ grub_memcmp64(unsigned long long str1addr, unsigned long long str2addr, unsigned { errnum = ERR_WONT_FIT; return 0; } +#endif } + +char * grub_strchr (const char *s, int c); //在字符串中查找字符 查到,返回第一个匹配的字符串位置;否则返回0 +char * +grub_strchr (const char *s, int c) +{ + do + { + if (*s == c) //查到,返回字符串位置 + return (char *) s; + } + while (*s++); + + return 0; +} + +char * grub_strrchr (const char *s, int c); +char * +grub_strrchr (const char *s, int c) //在字符串中查找字符 查到,返回最后一个匹配的字符串位置;否则返回0 +{ + char *p = NULL; + + do + { + if (*s == c) //查到,记录字符在字符串中的位置 + p = (char *) s; + } + while (*s++); + + return p; +} + +/* +mode=0,utf8_to_gbk +mode=1,utf8_to_utf16 +mode=2,utf8_to_url +url可以理解为双字节表示的单字节流 +比如:字符串:ab%20中 ascii码:63 64 25 32 30 d6 d0 00 url码:63 00 64 00 25 00 32 00 30 00 d6 00 d0 00 00 00 +返回:to尺寸 +*/ +int utf8_to_multimode (void *to, unsigned char *from, unsigned int from_len, int mode); +int +utf8_to_multimode (void *to, unsigned char *from, unsigned int from_len, int mode) +{ + unsigned char *to_gbk = 0; + unsigned short *to_utf16 = 0; + unsigned i_from = 0; + unsigned i_to = 0; + int i; + unsigned short tmp_utf16,tmp_gbk = 0; +#if 0 + if (!mode && !gbk) + { + printf_errinfo ("Please load GBK.\n"); + return 0; + } +#endif + if (!mode) + to_gbk = (unsigned char *)to; + else + to_utf16 = (unsigned short *)to; + + if (from_len == 0 || from == NULL || (to == NULL)) + return 0; + + for (i_from = 0; i_from < from_len; ) + { + if (from[i_from] < 0x80) //0-7f 单字节ASCII码 0-7f + { + if (from[i_from] == '\\') + { + if (mode == 0 || mode == 1) + i_from++; + else if (mode == 2) + { + i_from += 2; + to_utf16[i_to ++] = '%'; + to_utf16[i_to ++] = '2'; + to_utf16[i_to ++] = '0'; +// goto aaa; + continue; + } + } + if (!mode) + to_gbk[i_to ++] = from[i_from ++]; + else + to_utf16[i_to ++] = from[i_from ++]; +//aaa: + } + else if (from[i_from] < 0xC2) //80-c1 错误 舍弃 + { + i_from ++; + } + else if (from[i_from] < 0xE0) //c2-df 双字节 80-7ff + { + if (i_from >= from_len - 1) break; //超过from尺寸 + + tmp_utf16 = ((from[i_from] & 0x1F) << 6) | (from[i_from + 1] & 0x3F); + + if (mode == 1) + to_utf16[i_to ++] = tmp_utf16; + + i_from += 2; + } + else if (from[i_from] < 0xF0) //e0-ef 三字节 800-ffff + { + if (i_from >= from_len - 2) break; + + tmp_utf16 = ((from[i_from] & 0x0F) << 12) | ((from[i_from + 1] & 0x3F) << 6) | (from[i_from + 2] & 0x3F); //utf8 -> utf16 + if (gbk) + { +// for (i = 0; i < sizeof(_gbk2utf16_2) / sizeof(short); i += 2) //utf16 -> gbk + for (i = 0; i < (_gbk2utf16_2_size / sizeof(short)); i += 2) //utf16 -> gbk + { + if (_gbk2utf16_2[i+1] == tmp_utf16) + { + tmp_gbk = _gbk2utf16_2[i]; + break; + } + } + } + + if (!mode) + { + to_gbk[i_to ++] = tmp_gbk >> 8; + to_gbk[i_to ++] = tmp_gbk & 0xFF; + } + else if (mode == 1) + to_utf16[i_to ++] = tmp_utf16; + else if (mode == 2 && gbk) + { + to_utf16[i_to ++] = tmp_gbk >> 8; + to_utf16[i_to ++] = tmp_gbk & 0xFF; + } + else + { + to_utf16[i_to ++] = '?'; + to_utf16[i_to ++] = '?'; + } + + i_from += 3; + } + else if (from[i_from] < 0xF5) //f0-f4 四字节 10000-10FFFF 第二平面,舍弃 + { + i_from += 4; + } + else //f5-ff 错误 舍弃 + { + i_from ++; + } + } + + if (!mode) + to_gbk[i_to] = 0; + else + to_utf16[i_to] = 0; + + return i_to; +} +#if 0 +/* +mode=0,utf16_to_gbk +mode=1,utf16_to_utf8 +mode=2,utf16_to_url +url可以理解为双字节表示的单字节流 +比如:字符串:ab%20中 ascii码:63 64 25 32 30 d6 d0 00 url码:63 00 64 00 25 00 32 00 30 00 d6 00 d0 00 00 00 +返回:to尺寸 +*/ +int utf16_to_multimode (void *to, unsigned short *from, unsigned int from_len, int mode); +int +utf16_to_multimode (void *to, unsigned short *from, unsigned int from_len, int mode) +{ + unsigned char *to_utf8; + unsigned short *to_url; + unsigned i_from = 0; + unsigned i_to = 0; + grub_uint32_t i, code_high = 0; + unsigned short tmp_gbk; +#if 0 + if (!mode && !gbk) + { + printf_errinfo ("Please load GBK.\n"); + return 0; + } +#endif + if (mode == 0 || mode == 1) + to_utf8 = (unsigned char *)to; + else + to_url = (unsigned short *)to; + + if (from_len == 0 || from == NULL || (to == NULL)) + return 0; + + for (i_from = 0; i_from < from_len; ) + { + grub_uint32_t code = *from++; + if (!code) + return i_to; + + if (code_high) + { + if (code >= 0xDC00 && code <= 0xDFFF) //D800-DBFF + { + /* Surrogate pair. */ + code = ((code_high - 0xD800) << 10) + (code - 0xDC00) + 0x10000; + if (!mode) + { + to_utf8[i_to ++] = (code >> 18) | 0xF0; + to_utf8[i_to ++] = ((code >> 12) & 0x3F) | 0x80; + to_utf8[i_to ++] = ((code >> 6) & 0x3F) | 0x80; + to_utf8[i_to ++] = (code & 0x3F) | 0x80; + } + } + else + { + /* Error... */ + if (!mode) + to_utf8[i_to ++] = '?'; + /* *src may be valid. Don't eat it. */ + from--; + } + + code_high = 0; + } + else + { + if (code <= 0x007F) //0-7f 单字节ASCII码 + { + if (mode == 2) + to_url[i_to ++] = code; + else + to_utf8[i_to ++] = code; + } + else if (code <= 0x07FF) //80-7ff + { + if (mode == 1) + { + to_utf8[i_to ++] = (code >> 6) | 0xC0; + to_utf8[i_to ++] = (code & 0x3F) | 0x80; + } + } + else if (code >= 0xD800 && code <= 0xDBFF) //D800-DBFF + { + code_high = code; + continue; + } + else if (code >= 0xDC00 && code <= 0xDFFF) //DC00-DFFF + { + /* Error... */ + if (mode == 1) + to_utf8[i_to ++] = '?'; + } + else if (code < 0x10000 && gbk) //800-d7ff e000-ffff 双字节 + { + if (mode != 1) + { + for (i = 0; i < sizeof(_gbk2utf16_2) / sizeof(short); i += 2) //utf16 -> gbk + { + if (_gbk2utf16_2[i+1] == code) + { + tmp_gbk = _gbk2utf16_2[i]; + break; + } + } + if (mode == 0) + { + to_utf8[i_to ++] = tmp_gbk >> 8; + to_utf8[i_to ++] = tmp_gbk & 0xFF; + } + else + { + to_url[i_to ++] = tmp_gbk >> 8; + to_url[i_to ++] = tmp_gbk & 0xFF; + } + } + else + { + to_utf8[i_to ++] = (code >> 12) | 0xE0; + to_utf8[i_to ++] = ((code >> 6) & 0x3F) | 0x80; + to_utf8[i_to ++] = (code & 0x3F) | 0x80; + } + } + else //10000以上 三字节 + { + if (!mode) + { + to_utf8[i_to ++] = (code >> 18) | 0xF0; + to_utf8[i_to ++] = ((code >> 12) & 0x3F) | 0x80; + to_utf8[i_to ++] = ((code >> 6) & 0x3F) | 0x80; + to_utf8[i_to ++] = (code & 0x3F) | 0x80; + } + } + } + } + + if (mode == 0 || mode == 1) + to_utf8[i_to] = 0; + else + to_url[i_to] = 0; + + return i_to; +} +#endif diff --git a/stage2/cmdline.c b/stage2/cmdline.c index c085e254..b016a5d2 100644 --- a/stage2/cmdline.c +++ b/stage2/cmdline.c @@ -21,6 +21,15 @@ #include //grub_jmp_buf restart_cmdline_env; +char *wee_skip_to (char *cmdline, int flags); +char *skip_to (int flags, char *cmdline); +void print_cmdline_message (int forever); +int expand_var(const char *str,char *out,const unsigned int len_max); +int run_line (char *heap,int flags); +void enter_cmdline (char *heap, int forever); +//int count_lines; +//int use_pager; +int errorcheck; char * wee_skip_to (char *cmdline, int flags) @@ -46,7 +55,8 @@ skip_to (int flags, char *cmdline) *cmdline++ = 0; while (*cmdline == '\r' || *cmdline == '\n' || *cmdline == ' ' || *cmdline == '\t') cmdline++; - if (*cmdline != eol && *(unsigned short *)cmdline != 0x3A3A) +// if (*cmdline != eol && *(unsigned short *)cmdline != 0x3A3A) + if (*cmdline != eol && *(unsigned short *)cmdline != 0x3A3A && *(unsigned short *)cmdline != 0x2023) break; } cmdline++; @@ -58,9 +68,11 @@ skip_to (int flags, char *cmdline) while (*cmdline && !grub_isspace(*cmdline) && ! ((flags & 1) && *cmdline == '=')) { - if (*cmdline == QUOTE_CHAR) +// if (*cmdline == QUOTE_CHAR) + if (*cmdline == '\"') { - while (*++cmdline && *cmdline != QUOTE_CHAR) +// while (*++cmdline && *cmdline != QUOTE_CHAR) + while (*++cmdline && *cmdline != '\"') ; } else if (*cmdline == '\\') @@ -97,21 +109,22 @@ extern int command_func (char *arg, int flags); extern int commandline_func (char *arg, int flags); extern int errnum_func (char *arg, int flags); extern int checkrange_func (char *arg, int flags); +extern int else_disabled; //else禁止 +extern int brace_nesting; //大括弧嵌套数 /* Find the builtin whose command name is COMMAND and return the pointer. If not found, return 0. */ +struct builtin *find_command (char *command); struct builtin * find_command (char *command) { char *ptr; char c; struct builtin **builtin; - if (! command) return 0; while (*command == ' ' || *command == '\t')command++; - if (! *command) return 0; @@ -122,7 +135,6 @@ find_command (char *command) c = *ptr; *ptr = 0; - /* Seek out the builtin whose command name is COMMAND. */ for (builtin = builtin_table; *builtin != 0; builtin++) { @@ -139,13 +151,11 @@ find_command (char *command) } *ptr = c; - /* Cannot find builtin COMMAND. Check if it is an executable file. */ if (command_func (command, 0)) { return (struct builtin *)(char *)(-1); } - /* Cannot find COMMAND. */ errnum = ERR_UNRECOGNIZED; return 0; @@ -156,11 +166,14 @@ find_command (char *command) #define OPT_MULTI_CMD_AND (1<<5) #define OPT_MULTI_CMD_OR_FLAG 0x3B7C #define OPT_MULTI_CMD_OR (1<<6) -static char *get_next_arg(char *arg) + +char *get_next_arg(char *arg); +char *get_next_arg(char *arg) //获得下一参数 { while(*arg && !isspace(*arg)) { - if (*arg == QUOTE_CHAR) while (*++arg && *arg != QUOTE_CHAR); +// if (*arg == QUOTE_CHAR) while (*++arg && *arg != QUOTE_CHAR); + if (*arg == '\"') while (*++arg && *arg != '\"'); if (*arg == '\\') ++arg; if (*arg) ++arg; } @@ -168,6 +181,7 @@ static char *get_next_arg(char *arg) return arg; } +static char *skip_to_next_cmd (char *cmd,int *status,int flags); static char *skip_to_next_cmd (char *cmd,int *status,int flags) { // *status = 0; @@ -206,29 +220,34 @@ static char *skip_to_next_cmd (char *cmd,int *status,int flags) case OPT_MULTI_CMD_OR_FLAG:// |; *status = OPT_MULTI_CMD_OR; break; + case 0x207b: // '{' + case 0x007b: + case 0x207d: // '}' + case 0x007d: + *(cmd - 1) = '\0'; + *(cmd + 1) = '\0'; + return cmd; default: continue; } char *p = cmd + 1; - if ((flags == 0 || (*status & flags)) && (!*p || *p == ' ' || p[1] == ' ')) { *(cmd - 1) = '\0'; cmd = get_next_arg(cmd); break; } -// *status = 0; } - if (*cmd == '\0') *status = 0; + return cmd; } -#define PRINTF_BUFFER ((unsigned char *)SYSTEM_RESERVED_MEMORY + 0x20000) +//#define PRINTF_BUFFER ((unsigned char *)SYSTEM_RESERVED_MEMORY + 0x20000) //char *pre_cmdline = (char *)0x4CB08; -static char *cmd_buffer = ((char *)0x3A9000); +//static char *cmd_buffer = ((char *)0x3A9000); int expand_var(const char *str,char *out,const unsigned int len_max) { @@ -281,48 +300,62 @@ int expand_var(const char *str,char *out,const unsigned int len_max) } return out - out_start; } + static int run_cmd_line (char *heap,int flags); -int run_line (char *heap,int flags) +int run_line (char *heap,int flags) //原始 cmd_buffer: 101df7b0 { - - char *cmdline_buf = cmd_buffer; - char *arg; - int status = 0; - int ret = 0; - int arg_len = strlen(heap) + 1; - cmd_buffer += (arg_len + 0xf) & -0x10; - memmove(cmdline_buf,heap,arg_len); - heap = cmdline_buf; - __asm__ __volatile__ ("movl %%esp,%0" ::"m"(arg_len):"memory"); - if (arg_len < 0x3000) + char *cmdline_buf = cmd_buffer; //cmd_buffer: /grldr\0 + char *arg; + int status = 0; + int ret = 0; + int arg_len = strlen(heap) + 1; +#if 0 + //吸收命令行尾部空格 会使得外部命令SISO、RUN列表文件时,扩展名只显示前2个! + char *p = heap; + while (*p++); + while (*(p - 2) == ' ' || *(p - 2) == '\t') { - errnum = ERR_BAD_ARGUMENT; - printf("\nFAULT: <<<<<<<<<>>>>>>>>\n"); - return 0; + *(p - 2) = 0; + p--; } +#endif + cmd_buffer += (arg_len + 0xf) & -0x10; //cmd_buffer: 0 + memmove(cmdline_buf,heap,arg_len); //将堆移动到命令缓存头部 + heap = cmdline_buf; +#if 0 + __asm__ __volatile__ ("movl %%esp,%0" ::"m"(arg_len):"memory"); + if (arg_len < 0x3000) + { + errnum = ERR_BAD_ARGUMENT; + printf("\nFAULT: <<<<<<<<<>>>>>>>>\n"); + return 0; + } - if (debug > 10) printf("SP:0x%X\n[%s]\n",arg_len,heap); + if (debug > 10) printf("SP:0x%X\n[%s]\n",arg_len,heap); +#endif + while(*heap && (arg = heap)) + { + heap = skip_to_next_cmd(heap,&status,OPT_MULTI_CMD_AND | OPT_MULTI_CMD_OR | OPT_MULTI_CMD);//next cmd + ret = run_cmd_line(arg,flags); + if (errnum > 1000) break; + if (errnum == ERR_BAT_BRACE_END) break; //如果是批处理大括弧结束, 则退出 + if (((status & OPT_MULTI_CMD_AND) && !ret) || ((status & OPT_MULTI_CMD_OR) && ret)) + { + errnum = ERR_NONE; + heap = skip_to_next_cmd(heap,&status,OPT_MULTI_CMD);//next cmd + } + } - while(*heap && (arg = heap)) - { - heap = skip_to_next_cmd(heap,&status,OPT_MULTI_CMD_AND | OPT_MULTI_CMD_OR | OPT_MULTI_CMD);//next cmd - ret = run_cmd_line(arg,flags); - if (errnum > 1000) break; - if (((status & OPT_MULTI_CMD_AND) && !ret) || ((status & OPT_MULTI_CMD_OR) && ret)) - { - errnum = ERR_NONE; - heap = skip_to_next_cmd(heap,&status,OPT_MULTI_CMD);//next cmd - } - } - cmd_buffer = cmdline_buf; - return ret; +// if (cmdBuff) +// grub_free(cmdBuff); + cmd_buffer = cmdline_buf; + return ret; } static int run_cmd_line (char *heap,int flags) { char *arg = heap; -#define ret *(int*)0x4CB00 -// int ret = 0; +#define ret return_value int status = 0; struct builtin *builtin; int status_t = 0; @@ -338,10 +371,12 @@ static int run_cmd_line (char *heap,int flags) ++heap; if (*heap == 0 || *(unsigned short *)heap == 0x2023 || *(unsigned short *)heap == 0x3A3A) return 1; + /* Invalidate the cache, because the user may exchange removable disks. */ buf_drive = -1; + while (*heap && (arg = heap)) - { + { heap = skip_to_next_cmd(heap,&status,0);//next cmd switch(status_t) { @@ -354,7 +389,8 @@ static int run_cmd_line (char *heap,int flags) } i = grub_strlen(arg); grub_memmove(cmdBuff,arg,i); - if (skip_to (0, arg) - arg == i) +// if (skip_to (0, arg) - arg == i) + if (skip_to (0, arg) - arg == i || cmdBuff[skip_to (0, arg) - arg] == ':') //修正找不到标签 cmdBuff[i++] = ' '; cmdBuff[i] = 0; grub_strncat(cmdBuff,(const char *)PRINTF_BUFFER,0x20000); @@ -376,7 +412,7 @@ static int run_cmd_line (char *heap,int flags) { char *f_buf = cmd_buffer; int t_read,t_len; - while ((t_read = grub_read ((unsigned long long)(int)f_buf,0x400,GRUB_READ))) + while ((t_read = grub_read ((unsigned long long)(grub_size_t)f_buf,0x400,GRUB_READ))) { f_buf[t_read] = 0; t_len = grub_strlen(f_buf); @@ -392,8 +428,7 @@ static int run_cmd_line (char *heap,int flags) grub_memset(hook_buff,0,filemax); hook_buff = PRINTF_BUFFER + filemax; } - - grub_read ((unsigned long long)(int)PRINTF_BUFFER,hook_buff - PRINTF_BUFFER,GRUB_WRITE); + grub_read ((unsigned long long)(grub_size_t)PRINTF_BUFFER,hook_buff - PRINTF_BUFFER,GRUB_WRITE); grub_close(); restart_st: @@ -403,7 +438,7 @@ static int run_cmd_line (char *heap,int flags) break; } - if (debug > 10) + if (debug > 10 || debug_bat) printf("r0:[0x%X]:[%s]\n",arg,arg); if (status & 8) @@ -411,12 +446,32 @@ static int run_cmd_line (char *heap,int flags) if (substring(heap,"nul",1) == 0) hook_buff = set_putchar_hook((unsigned char*)0x800); else + { + grub_memset(PRINTF_BUFFER,0,0x40000); hook_buff = set_putchar_hook(PRINTF_BUFFER); + } } - + builtin = find_command (arg); + + if (*arg == '{') //左大括弧 + { + if (!ret) + return !(errnum = ERR_BAT_BRACE_END); + + errnum = ERR_NONE; //消除错误号 + brace_nesting++; //大括弧嵌套数+1 + return 1; + } - if ((int)builtin != -1) + if (*arg == '}') //右大括弧 + { + errnum = ERR_NONE; //消除错误号 + brace_nesting--; //大括弧嵌套数-1 + else_disabled |= 1 << brace_nesting; //设置else禁止位 + return 1; + } + if ((grub_size_t)builtin != (grub_size_t)-1) { if (! builtin || ! (builtin->flags & flags)) { @@ -440,7 +495,9 @@ static int run_cmd_line (char *heap,int flags) } } else + { ret = command_func (arg,flags); + } errnum_old = errnum; if (arg == cmdBuff) @@ -484,9 +541,9 @@ static int run_cmd_line (char *heap,int flags) return (errnum > 0 && errnumType == MB_ARD_MEMORY - && desc->BaseAddr <= top - && desc->BaseAddr + desc->Length > top) - { - top = desc->BaseAddr + desc->Length; - cont++; - } - } - } - while (cont); - - /* For now, GRUB assumes 32bits addresses, so... */ - if (top > 0x100000000ULL && bottom < 0x100000000ULL) - top = 0x100000000ULL; - - return top - bottom; -} +unsigned int grub_sleep (unsigned int seconds); unsigned int -grub_sleep (unsigned int seconds) +grub_sleep (unsigned int seconds) //暂停(秒) { unsigned long long j; int time1; @@ -210,8 +172,7 @@ grub_sleep (unsigned int seconds) return seconds; } -// check 64bit and PAE -// return value bit0=PAE supported bit1=AMD64/Intel64 supported +#if defined(__i386__) int check_64bit_and_PAE () { unsigned int has_cpuid_instruction; @@ -224,9 +185,9 @@ int check_64bit_and_PAE () "pushl %%edx; popfl;" // restore original EFLAGS "xorl %%edx, %0; shrl $21, %%eax; and $1, %%eax;" // check for bit 21 difference : "=a"(has_cpuid_instruction) : : "%edx" ); - if (!has_cpuid_instruction) - return 0; - unsigned int *sig = (unsigned int *)0x308000; //&vm_cpu_signature; + if (!has_cpuid_instruction) + return 0; + unsigned int *sig = grub_malloc (0x20); unsigned int maxfn,feature; int x=0; asm ("cpuid;" @@ -260,692 +221,2299 @@ int check_64bit_and_PAE () "xchgl %%ebx,%1" // restore EBX, and put result into %1. : "=a" (leaf), "+r" (sig[0]), "=c" (sig[1]), "=d" (sig[2]) : "0" (leaf)); - + grub_free(sig); return x; } +#endif + +///////////////////////////////////////////////////////////////////////////////////////// +//kern/efi/efi.c +/* The handle of GRUB itself. Filled in by the startup code. GRUB本身的处理。由启动代码填写。*/ +grub_efi_handle_t grub_efi_image_handle; //这是个句柄. + +/* The pointer to a system table. Filled in by the startup code. 指向系统表的指针。由启动代码填写 */ +grub_efi_system_table_t *grub_efi_system_table; -unsigned int prog_pid = 0; -void *grub_malloc(unsigned long size) +static grub_efi_guid_t console_control_guid = GRUB_EFI_CONSOLE_CONTROL_GUID; +static grub_efi_guid_t loaded_image_guid = GRUB_EFI_LOADED_IMAGE_GUID; +static grub_efi_guid_t device_path_guid = GRUB_EFI_DEVICE_PATH_GUID; + +void *grub_efi_locate_protocol (grub_efi_guid_t *protocol, void *registration); +void * +grub_efi_locate_protocol (grub_efi_guid_t *protocol, void *registration) //EFI定位协议 { - struct malloc_array *p_memalloc_array = malloc_array_start; - unsigned long alloc_mem = 0; - size = (size + 0x1F) & ~0xf; //分配内存,16字节对齐,额外分配16字节.也就是说最少的内存分配是32字节. + void *interface; + grub_efi_status_t status; + + status = efi_call_3 (grub_efi_system_table->boot_services->locate_protocol, + protocol, registration, &interface); + if (status != GRUB_EFI_SUCCESS) + return 0; + + return interface; +} - for ( ; p_memalloc_array->addr != free_mem_end; p_memalloc_array = p_memalloc_array->next)//find free mem array; +/* Return the array of handles which meet the requirement. If successful, 返回满足要求的句柄数组。 + the number of handles is stored in NUM_HANDLES. The array is allocated 如果成功,句柄的数量存储在NUM_HANDLES。数组是从堆中分配的。 + from the heap. */ +grub_efi_handle_t *grub_efi_locate_handle (grub_efi_locate_search_type_t search_type, grub_efi_guid_t *protocol, + void *search_key, grub_efi_uintn_t *num_handles); +grub_efi_handle_t * +grub_efi_locate_handle (grub_efi_locate_search_type_t search_type, + grub_efi_guid_t *protocol, + void *search_key, + grub_efi_uintn_t *num_handles) //EFI定位句柄 +{ + grub_efi_boot_services_t *b; //引导协议 + grub_efi_status_t status; //状态 + grub_efi_handle_t *buffer; //缓存 + grub_efi_uintn_t buffer_size = 8 * sizeof (grub_efi_handle_t); //缓存尺寸 + + buffer = grub_malloc (buffer_size); //分配内存 + if (! buffer) //分配失败 + return 0; + + b = grub_efi_system_table->boot_services; //引导协议 + status = efi_call_5 (b->locate_handle, search_type, protocol, search_key, + &buffer_size, buffer); + if (status == GRUB_EFI_BUFFER_TOO_SMALL) //如果缓存太小 { - if (p_memalloc_array->addr & 1)//used mem - continue; - alloc_mem = p_memalloc_array->next->addr - p_memalloc_array->addr; - if (alloc_mem < size) - { - continue; - } + grub_free (buffer); //释放内存 + buffer = grub_malloc (buffer_size); //又分配同样大小的内存? 或许是调用函数返回了需要的尺寸!! + if (! buffer) + return 0; - if (alloc_mem > size) //add new array - { - struct malloc_array *P = malloc_array_start; - for ( ; P->addr; P++) - { - if (P == (struct malloc_array *)mem_alloc_array_end) - { - errnum = ERR_WONT_FIT; - return NULL; - } - } + status = efi_call_5 (b->locate_handle, search_type, protocol, search_key, + &buffer_size, buffer); + } - P->addr = p_memalloc_array->addr + size; - P->next = p_memalloc_array->next; - p_memalloc_array->next = P; - } + if (status != GRUB_EFI_SUCCESS) //如果不成功 + { + grub_free (buffer); //释放内存 + return 0; + } + + *num_handles = buffer_size / sizeof (grub_efi_handle_t); //句柄数 + return buffer; //返回句柄地址 +} + +void *grub_efi_open_protocol (grub_efi_handle_t handle, grub_efi_guid_t *protocol, grub_efi_uint32_t attributes); +void * +grub_efi_open_protocol (grub_efi_handle_t handle, + grub_efi_guid_t *protocol, + grub_efi_uint32_t attributes) //efi打开协议 +{ + grub_efi_boot_services_t *b; + grub_efi_status_t status; + void *interface; + + b = grub_efi_system_table->boot_services; + status = efi_call_6 (b->open_protocol, handle, + protocol, + &interface, + grub_efi_image_handle, + 0, + attributes); //调用efi系统表->引导服务->打开协议 + + if (status != GRUB_EFI_SUCCESS) //如果状态 != 成功 + return 0; //返回错误 + + return interface; //成功返回接口 +} + +int grub_efi_set_text_mode (int on); +int +grub_efi_set_text_mode (int on) //efi设置文本模式 ok +{ + grub_efi_console_control_protocol_t *c; + grub_efi_screen_mode_t mode, new_mode; + + c = grub_efi_locate_protocol (&console_control_guid, 0); + if (! c) + /* No console control protocol instance available, assume it is 没有控制台控制协议实例可用,假设它已经在文本模式中。 + already in text mode. */ + return 1; + + if (efi_call_4 (c->get_mode, c, &mode, 0, 0) != GRUB_EFI_SUCCESS) + return 0; - alloc_mem = p_memalloc_array->addr; - p_memalloc_array->addr |= 1;//set mem used + new_mode = on ? GRUB_EFI_SCREEN_TEXT : GRUB_EFI_SCREEN_GRAPHICS; + if (mode != new_mode) + if (efi_call_2 (c->set_mode, c, new_mode) != GRUB_EFI_SUCCESS) + return 0; - return (void *)alloc_mem; + return 1; +} + +void grub_efi_stall (grub_efi_uintn_t microseconds); +void +grub_efi_stall (grub_efi_uintn_t microseconds) //efi失速 +{ + efi_call_1 (grub_efi_system_table->boot_services->stall, microseconds); +} + +grub_efi_loaded_image_t * +grub_efi_get_loaded_image (grub_efi_handle_t image_handle) //获得加载映像 +{ + return grub_efi_open_protocol (image_handle, + &loaded_image_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); //打开协议(映像句柄,guid,获得协议) +} + +//有的主板热复位功能有问题,键盘“ctrl+alt+del”重启也会出现掉me固件,内存识别为零。 +void grub_reboot (void); +void +grub_reboot (void) //重新启动 +{ +// grub_machine_fini (); + efi_call_4 (grub_efi_system_table->runtime_services->reset_system, //系统表->运行时服务->重置系统 +// GRUB_EFI_RESET_WARM, GRUB_EFI_SUCCESS, 0, NULL); //热复位,成功 ,0,NULL + GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL); //冷复位,成功 ,0,NULL + for (;;) ; +} + +void grub_halt (void); +void +grub_halt (void) //关机 +{ +// grub_machine_fini (); + efi_call_4 (grub_efi_system_table->runtime_services->reset_system, //系统表->运行时服务->重置系统 + GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL); //关机,成功 ,0,NULL + for (;;) ; +} + +grub_efi_device_path_t *grub_efi_get_device_path (grub_efi_handle_t handle); +grub_efi_device_path_t * +grub_efi_get_device_path (grub_efi_handle_t handle) //efi获得设备路径 +{ + return grub_efi_open_protocol (handle, &device_path_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); //打开协议 获得协议 +} + +/* Return the device path node right before the end node. 在结束节点之前返回设备路径节点 */ +grub_efi_device_path_t *grub_efi_find_last_device_path (const grub_efi_device_path_t *dp); +grub_efi_device_path_t * +grub_efi_find_last_device_path (const grub_efi_device_path_t *dp) //efi查找最后设备路径 +{ + grub_efi_device_path_t *next, *p; + + if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) //结束整个设备路径 类型=7f,子类型=ff + return 0; + + for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p); + ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next); + p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next))//; //下一个类型!=7f,子类型!=ff + ; + + return p; +} + +/* Duplicate a device path. 复制设备路径 */ +grub_efi_device_path_t *grub_efi_duplicate_device_path (const grub_efi_device_path_t *dp); +grub_efi_device_path_t * +grub_efi_duplicate_device_path (const grub_efi_device_path_t *dp) //efi复制设备路径 +{ + grub_efi_device_path_t *p; //设备路径 + grub_size_t total_size = 0; //总尺寸 + //计算总尺寸 + for (p = (grub_efi_device_path_t *) dp; + ; + p = GRUB_EFI_NEXT_DEVICE_PATH (p)) //设备路径存在 + { + total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p); //总尺寸+设备路径尺寸 + if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p)) //如果是结束 + break; //退出循环 } - errnum = ERR_WONT_FIT; - return NULL; + + p = grub_malloc (total_size); //分配内存 + if (! p) //如果失败 + return 0; + + grub_memcpy (p, dp, total_size); //复制dp到p + return p; //返回内存地址 } -void grub_free(void *ptr) +/* Compare device paths. */ +int grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1, const grub_efi_device_path_t *dp2); +int +grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1, + const grub_efi_device_path_t *dp2) //efi比较设备路径 返回: 0/1/-1=相等/不相等/包含 { - if (ptr == NULL) - return; - struct malloc_array *P = malloc_array_start; - struct malloc_array *P1 = malloc_array_start; + if (! dp1 || ! dp2) //如果dp1或者dp2为零, 错误 + /* Return non-zero. */ + return 1; - for (;P->addr != free_mem_end;P1 = P,P = P->next) + while (1) { - if ((P->addr & ~0xfUL) == (unsigned long)ptr) - { - P->addr &= ~0xfUL;//unused memory + grub_efi_uint8_t type1, type2; + grub_efi_uint8_t subtype1, subtype2; + grub_efi_uint16_t len1, len2; + int ret; - if (P1 != P && (P1->addr & 1) == 0) - {//向前合并可用内存块. - P1->next = P->next; - P->addr = 0; - P = P1; - } + type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1); + type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2); - P1 = P->next; - if (P1->addr != free_mem_end && (P1->addr & 1) == 0) - {//向后合并可用内存块. - P1->addr = 0; - P->next = P1->next; - } - return; + if (type1 != type2) //如果设备路径类型不同 + return 1; + + subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1); + subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2); + + if (subtype1 != subtype2) //如果设备路径子类型不同 + return 1; + + len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1); + len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2); + + if (len1 != len2) //如果设备路径尺寸不同 + return 1; + + ret = grub_memcmp ((const char *)dp1, (const char *)dp2, len1); //比较数据 + if (ret != 0) //如果数据不同 + return 1; + + dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1); //下一设备路径 + dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2); + + //假设路径首位不会是结束 + if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1)) //如果dp1是结束 + { + if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp2)) //如果dp1也是结束, 返回相等 + return 0; + else //否则, 返回包含 + return -1; } + else if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp2)) //如果dp1不是结束, 但是dp2是结束, 返回包含 + return -1; } - return; } -/* This queries for BIOS information. */ -void -init_bios_info (void) +int grub_efi_is_child_dp (const grub_efi_device_path_t *child, + const grub_efi_device_path_t *parent); +int +grub_efi_is_child_dp (const grub_efi_device_path_t *child, + const grub_efi_device_path_t *parent) //是子路径(子路径, 父路径) { - unsigned long cont, memtmp, addr; - unsigned long drive; - unsigned long force_pxe_as_boot_device; - unsigned long use_fixed_boot_device = boot_drive; - unsigned long use_lba1sector; + grub_efi_device_path_t *dp, *ldp; + int ret = 0; - if (use_fixed_boot_device != -1) - { - /* save boot device info in it */ - use_fixed_boot_device = ((unsigned short)boot_drive | (install_partition & 0x00FF0000)); - } - is64bit = check_64bit_and_PAE (); - - /* initialize mem alloc array */ - grub_memset(mem_alloc_array_start,0,(int)(mem_alloc_array_end - mem_alloc_array_start)); - mem_alloc_array_start[0].addr = free_mem_start; - mem_alloc_array_start[1].addr = 0; /* end the array */ - malloc_array_start = (struct malloc_array *)mem_alloc_array_start + 10; - malloc_array_start->addr = free_mem_start + 0x400000; - malloc_array_start->next = (struct malloc_array *)&free_mem_end; - use_lba1sector = debug_boot & 2; - debug_boot &= 1; - /* - * Get information from BIOS on installed RAM. - */ - if (debug_boot) + dp = grub_efi_duplicate_device_path (child); //复制子路径 + if (! dp) + return 0; + + while (!ret) //循环条件: 没有最后路径, 或者比较结果是相等 { - debug_msg = 1; - printf("DEBUG BOOT selected...\n"); + ldp = grub_efi_find_last_device_path (dp); //查找子路径的最后路径 + if (!ldp) //没有最后路径, 退出 + break; + //屏蔽最后路径 + ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; //0x7f + ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; //0xff + ldp->length = sizeof (*ldp); + + ret = (grub_efi_compare_device_paths (dp, parent) == 0); //比较子路径与父路径(返回: 0/1/-1=相等/不相等/包含) 不相等或包含则继续 } - //saved_mem_lower = get_memsize (0); /* int12 --------safe enough */ - saved_mem_lower = (*(unsigned short *)0x413); - if (debug_boot) grub_printf("0x%x", saved_mem_lower); - DEBUG_SLEEP - if (debug_boot) - printf("Get upper memory... "); - saved_mem_upper = get_memsize (1); /* int15/88 -----safe enough */ - if (debug_boot) grub_printf("0x%x", saved_mem_upper); - DEBUG_SLEEP + grub_free (dp); + return ret; //返回: 0/1=没有最后路径/相等 +} - /* - * We need to call this somewhere before trying to put data - * above 1 MB, since without calling it, address line 20 will be wired - * to 0. Not too desirable. - */ +static void dump_vendor_path (grub_efi_vendor_device_path_t *vendor); +static void +dump_vendor_path (grub_efi_vendor_device_path_t *vendor) +{ + grub_printf ("VenHw(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)", //供应商 + (unsigned) vendor->vendor_guid.data1, + (unsigned) vendor->vendor_guid.data2, + (unsigned) vendor->vendor_guid.data3, + (unsigned) vendor->vendor_guid.data4[0], + (unsigned) vendor->vendor_guid.data4[1], + (unsigned) vendor->vendor_guid.data4[2], + (unsigned) vendor->vendor_guid.data4[3], + (unsigned) vendor->vendor_guid.data4[4], + (unsigned) vendor->vendor_guid.data4[5], + (unsigned) vendor->vendor_guid.data4[6], + (unsigned) vendor->vendor_guid.data4[7]); + + return; +} - debug = debug_boot + 1; - if (debug_boot) - printf("Turning on gate A20... "); +void grub_efi_device_path_to_str (grub_efi_device_path_t *dp); +void +grub_efi_device_path_to_str (grub_efi_device_path_t *dp) +{ + while (GRUB_EFI_DEVICE_PATH_VALID (dp)) + { + grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); + grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); + grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp); + switch (type) { - if (gateA20 (1)) /* int15/24 -----safe enough */ - { - /* wipe out the messages on success */ - if (debug_boot) - printf("Ok.\n"); - } else { - printf("gateA20 Failure! Report bug, please!\n"); - grub_sleep (5); /* sleep 5 second on failure */ - } - } - DEBUG_SLEEP + case GRUB_EFI_END_DEVICE_PATH_TYPE: //0xff0x7f + grub_printf ("\n"); + break; + case GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE: + switch (subtype) + { + case GRUB_EFI_PCI_DEVICE_PATH_SUBTYPE: + { + grub_efi_pci_device_path_t *pci = (grub_efi_pci_device_path_t *) dp; + grub_printf ("/PCI(%x,%x)", (unsigned) pci->function, (unsigned) pci->device); + } + break; + case GRUB_EFI_PCCARD_DEVICE_PATH_SUBTYPE: + { + grub_efi_pccard_device_path_t *pccard = (grub_efi_pccard_device_path_t *) dp; + grub_printf ("/PCCARD(%x)", (unsigned) pccard->function); + } + break; + case GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE: + { + grub_efi_memory_mapped_device_path_t *mmapped = (grub_efi_memory_mapped_device_path_t *) dp; + grub_printf ("/MMap(%x,%lx,%lx)", + (unsigned) mmapped->memory_type, + (unsigned long long) mmapped->start_address, + (unsigned long long) mmapped->end_address); + } + break; + case GRUB_EFI_VENDOR_DEVICE_PATH_SUBTYPE: + dump_vendor_path ((grub_efi_vendor_device_path_t *) dp); + break; + case GRUB_EFI_CONTROLLER_DEVICE_PATH_SUBTYPE: + { + grub_efi_controller_device_path_t *controller = (grub_efi_controller_device_path_t *) dp; + grub_printf ("/Ctrl(%x)", (unsigned) controller->controller_number); + } + break; + default: + grub_printf ("/UnknownHW(%x)", (unsigned) subtype); //未知硬件 + break; + } + break; + case GRUB_EFI_ACPI_DEVICE_PATH_TYPE: + switch (subtype) + { + case GRUB_EFI_ACPI_DEVICE_PATH_SUBTYPE: + { + grub_efi_acpi_device_path_t *acpi = (grub_efi_acpi_device_path_t *) dp; + if (acpi->hid == 0x60441d0 || acpi->hid == 0x70041d0 || acpi->hid == 0x70141d1) + grub_printf ("/Floopy(%x)", (unsigned) acpi->uid); + else + grub_printf ("/ACPI(%x,%x)", (unsigned) acpi->hid, (unsigned) acpi->uid); + } + break; + case GRUB_EFI_EXPANDED_ACPI_DEVICE_PATH_SUBTYPE: + { + grub_efi_expanded_acpi_device_path_t *eacpi = (grub_efi_expanded_acpi_device_path_t *) dp; + grub_printf ("/ACPI("); + + if (GRUB_EFI_EXPANDED_ACPI_HIDSTR (dp)[0] == '\0') + grub_printf ("%x,", (unsigned) eacpi->hid); + else + grub_printf ("%s,", GRUB_EFI_EXPANDED_ACPI_HIDSTR (dp)); + + if (GRUB_EFI_EXPANDED_ACPI_UIDSTR (dp)[0] == '\0') + grub_printf ("%x,", (unsigned) eacpi->uid); + else + grub_printf ("%s,", GRUB_EFI_EXPANDED_ACPI_UIDSTR (dp)); + + if (GRUB_EFI_EXPANDED_ACPI_CIDSTR (dp)[0] == '\0') + grub_printf ("%x)", (unsigned) eacpi->cid); + else + grub_printf ("%s)", GRUB_EFI_EXPANDED_ACPI_CIDSTR (dp)); + } + break; + default: + grub_printf ("/UnknownACPI(%x)", (unsigned) subtype); + break; + } + break; + case GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE: + switch (subtype) + { + case GRUB_EFI_ATAPI_DEVICE_PATH_SUBTYPE: + { + grub_efi_atapi_device_path_t *atapi = (grub_efi_atapi_device_path_t *) dp; + grub_printf ("/ATAPI(%x,%x,%x)", + (unsigned) atapi->primary_secondary, + (unsigned) atapi->slave_master, + (unsigned) atapi->lun); + } + break; + case GRUB_EFI_SCSI_DEVICE_PATH_SUBTYPE: + { + grub_efi_scsi_device_path_t *scsi = (grub_efi_scsi_device_path_t *) dp; + grub_printf ("/SCSI(%x,%x)", + (unsigned) scsi->pun, + (unsigned) scsi->lun); + } + break; + case GRUB_EFI_FIBRE_CHANNEL_DEVICE_PATH_SUBTYPE: + { + grub_efi_fibre_channel_device_path_t *fc = (grub_efi_fibre_channel_device_path_t *) dp; + grub_printf ("/FibreChannel(%lx,%lx)", //光纤通道 + (unsigned long long) fc->wwn, + (unsigned long long) fc->lun); + } + break; + case GRUB_EFI_1394_DEVICE_PATH_SUBTYPE: + { + grub_efi_1394_device_path_t *firewire = (grub_efi_1394_device_path_t *) dp; + grub_printf ("/1394(%lx)", (unsigned long long)firewire->guid); + } + break; + case GRUB_EFI_USB_DEVICE_PATH_SUBTYPE: + { + grub_efi_usb_device_path_t *usb = (grub_efi_usb_device_path_t *) dp; + grub_printf ("/USB(%x,%x)", + (unsigned) usb->parent_port_number, + (unsigned) usb->usb_interface); + } + break; + case GRUB_EFI_USB_LOGICAL_UNIT_DEVICE_PATH_SUBTYPE: + { + grub_efi_usb_logical_unit_device_path_t *usb = (grub_efi_usb_logical_unit_device_path_t *) dp; + grub_printf ("/UNIT(%x)", + (unsigned) usb->LUN); + } + break; + case GRUB_EFI_USB_CLASS_DEVICE_PATH_SUBTYPE: + { + grub_efi_usb_class_device_path_t *usb_class = (grub_efi_usb_class_device_path_t *) dp; + grub_printf ("/USBClass(%x,%x,%x,%x,%x)", + (unsigned) usb_class->vendor_id, + (unsigned) usb_class->product_id, + (unsigned) usb_class->device_class, + (unsigned) usb_class->device_subclass, + (unsigned) usb_class->device_protocol); + } + break; + case GRUB_EFI_I2O_DEVICE_PATH_SUBTYPE: + { + grub_efi_i2o_device_path_t *i2o = (grub_efi_i2o_device_path_t *) dp; + grub_printf ("/I2O(%x)", (unsigned) i2o->tid); + } + break; + case GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE: + { + grub_efi_mac_address_device_path_t *mac = (grub_efi_mac_address_device_path_t *) dp; + (grub_size_t)grub_printf ("/MacAddr(%02x:%02x:%02x:%02x:%02x:%02x,%x)", + (unsigned) mac->mac_address[0], + (unsigned) mac->mac_address[1], + (unsigned) mac->mac_address[2], + (unsigned) mac->mac_address[3], + (unsigned) mac->mac_address[4], + (unsigned) mac->mac_address[5], + (unsigned) mac->if_type); + } + break; + case GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE: + { + grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) dp; + grub_printf ("/IPv4"); + grub_printf ("(%u.%u.%u.%u,%u.%u.%u.%u,%u,%u,%4x,%2x", + (unsigned) ipv4->local_ip_address[0], + (unsigned) ipv4->local_ip_address[1], + (unsigned) ipv4->local_ip_address[2], + (unsigned) ipv4->local_ip_address[3], + (unsigned) ipv4->remote_ip_address[0], + (unsigned) ipv4->remote_ip_address[1], + (unsigned) ipv4->remote_ip_address[2], + (unsigned) ipv4->remote_ip_address[3], + (unsigned) ipv4->local_port, + (unsigned) ipv4->remote_port, + (unsigned) ipv4->protocol, + (unsigned) ipv4->static_ip_address); + if (len == sizeof (*ipv4)) + { + grub_printf (",%u.%u.%u.%u,%u.%u.%u.%u", + (unsigned) ipv4->gateway_ip_address[0], + (unsigned) ipv4->gateway_ip_address[1], + (unsigned) ipv4->gateway_ip_address[2], + (unsigned) ipv4->gateway_ip_address[3], + (unsigned) ipv4->subnet_mask[0], + (unsigned) ipv4->subnet_mask[1], + (unsigned) ipv4->subnet_mask[2], + (unsigned) ipv4->subnet_mask[3]); + } + grub_printf (")"); + } + break; + case GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE: + { + grub_efi_ipv6_device_path_t *ipv6 = (grub_efi_ipv6_device_path_t *) dp; + grub_printf ("(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x,%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x,%u,%u,%x,%x", + (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[0]), + (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[1]), + (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[2]), + (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[3]), + (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[4]), + (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[5]), + (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[6]), + (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[7]), + (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[0]), + (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[1]), + (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[2]), + (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[3]), + (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[4]), + (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[5]), + (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[6]), + (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[7]), + (unsigned) ipv6->local_port, + (unsigned) ipv6->remote_port, + (unsigned) ipv6->protocol, + (unsigned) ipv6->static_ip_address); + if (len == sizeof (*ipv6)) + { + grub_printf (",%u,%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + (unsigned) ipv6->prefix_length, + (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[0]), + (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[1]), + (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[2]), + (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[3]), + (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[4]), + (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[5]), + (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[6]), + (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[7])); + } + grub_printf (")"); + } + break; + case GRUB_EFI_INFINIBAND_DEVICE_PATH_SUBTYPE: + { + grub_efi_infiniband_device_path_t *ib = (grub_efi_infiniband_device_path_t *) dp; + grub_printf ("/InfiniBand(%x,%lx,%lx,%lx)", //无限带宽 + (unsigned) ib->port_gid[0], /* XXX */ + (unsigned long long) ib->remote_id, + (unsigned long long) ib->target_port_id, + (unsigned long long) ib->device_id); + } + break; + case GRUB_EFI_UART_DEVICE_PATH_SUBTYPE: + { + grub_efi_uart_device_path_t *uart = (grub_efi_uart_device_path_t *) dp; + grub_printf ("/UART(%llu,%u,%x,%x)", + (unsigned long long) uart->baud_rate, + uart->data_bits, + uart->parity, + uart->stop_bits); + } + break; + case GRUB_EFI_SATA_DEVICE_PATH_SUBTYPE: + { + grub_efi_sata_device_path_t *sata; + sata = (grub_efi_sata_device_path_t *) dp; + grub_printf ("/Sata(%x,%x,%x)", + sata->hba_port, + sata->multiplier_port, + sata->lun); + } + break; + + case GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE: + dump_vendor_path ((grub_efi_vendor_device_path_t *) dp); + break; + case GRUB_EFI_URI_DEVICE_PATH_SUBTYPE: + { + grub_efi_uri_device_path_t *uri = (grub_efi_uri_device_path_t *) dp; + grub_printf ("/URI(%s)", uri->uri); + } + break; + case GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE: + { + grub_efi_dns_device_path_t *dns = (grub_efi_dns_device_path_t *) dp; + grub_printf ("/DNS("); + if (dns->is_ipv6) + { + grub_printf ("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[0]) >> 16), + (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[0])), + (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[1]) >> 16), + (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[1])), + (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[2]) >> 16), + (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[2])), + (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[3]) >> 16), + (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[3]))); + } + else + { + grub_printf ("%d.%d.%d.%d", + dns->dns_server_ip[0].v4.addr[0], + dns->dns_server_ip[0].v4.addr[1], + dns->dns_server_ip[0].v4.addr[2], + dns->dns_server_ip[0].v4.addr[3]); + } + grub_printf (")"); + } + break; + default: + grub_printf ("/UnknownMessaging(%x)", (unsigned) subtype); //未知消息 + break; + } + break; + case GRUB_EFI_MEDIA_DEVICE_PATH_TYPE: + switch (subtype) + { + case GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE: + { + grub_efi_hard_drive_device_path_t *hd = (grub_efi_hard_drive_device_path_t *) dp; + grub_printf + ("/HD(%u,%lx,%lx,%02x%02x%02x%02x%02x%02x%02x%02x,%s)", + hd->partition_number, + (unsigned long long) hd->partition_start, + (unsigned long long) hd->partition_size, + (unsigned) hd->partition_signature[0], + (unsigned) hd->partition_signature[1], + (unsigned) hd->partition_signature[2], + (unsigned) hd->partition_signature[3], + (unsigned) hd->partition_signature[4], + (unsigned) hd->partition_signature[5], + (unsigned) hd->partition_signature[6], + (unsigned) hd->partition_signature[7], + ((unsigned) hd->partmap_type == 1 ? "MBR" : "GPT")); + } + break; + case GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE: + { + grub_efi_cdrom_device_path_t *cd = (grub_efi_cdrom_device_path_t *) dp; + grub_printf ("/CD(%u,%lx,%lx)", + cd->boot_entry, + (unsigned long long) cd->boot_start, + (unsigned long long) cd->boot_size); + } + break; + case GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE: + dump_vendor_path ((grub_efi_vendor_device_path_t *) dp); + break; + case GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE: + { + grub_efi_file_path_device_path_t *fp; + grub_uint8_t *buf; + fp = (grub_efi_file_path_device_path_t *) dp; + buf = grub_zalloc ((len - 4) * 2 + 1); + if (buf) + { + grub_efi_char16_t *dup_name = grub_zalloc (len - 4); + if (!dup_name) + { + errnum = GRUB_ERR_NONE; + grub_printf ("/File((null))"); + grub_free (buf); + break; + } +// *grub_utf16_to_utf8 (buf, grub_memcpy (dup_name, fp->path_name, len - 4), +// (len - 4) / sizeof (grub_efi_char16_t)) = '\0'; + unicode_to_utf8 (grub_memcpy (dup_name, fp->path_name, len - 4), buf, (len - 4) / sizeof (grub_efi_char16_t)); + grub_free (dup_name); + } + else + errnum = GRUB_ERR_NONE; + grub_printf ("/File(%s)", buf); + if (buf) + grub_free (buf); + } + break; + case GRUB_EFI_PROTOCOL_DEVICE_PATH_SUBTYPE: + { + grub_efi_protocol_device_path_t *proto = (grub_efi_protocol_device_path_t *) dp; + grub_printf ("/Protocol(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)", + (unsigned) proto->guid.data1, + (unsigned) proto->guid.data2, + (unsigned) proto->guid.data3, + (unsigned) proto->guid.data4[0], + (unsigned) proto->guid.data4[1], + (unsigned) proto->guid.data4[2], + (unsigned) proto->guid.data4[3], + (unsigned) proto->guid.data4[4], + (unsigned) proto->guid.data4[5], + (unsigned) proto->guid.data4[6], + (unsigned) proto->guid.data4[7]); + } + break; + default: + grub_printf ("/UnknownMedia(%x)", (unsigned) subtype); + break; + } + break; + case GRUB_EFI_BIOS_DEVICE_PATH_TYPE: + switch (subtype) + { + case GRUB_EFI_BIOS_DEVICE_PATH_SUBTYPE: + { + grub_efi_bios_device_path_t *bios = (grub_efi_bios_device_path_t *) dp; + grub_printf ("/BIOS(%x,%x,%s)", + (unsigned) bios->device_type, + (unsigned) bios->status_flags, + (char *) (dp + 1)); + } + break; + default: + grub_printf ("/UnknownBIOS(%x)", (unsigned) subtype); + break; + } + break; + default: + { + grub_printf ("/UnknownType(%x,%x)", (unsigned) type, (unsigned) subtype); + return; + } + break; + }//switch (type) + + if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) + break; + + dp = (grub_efi_device_path_t *) ((char *) dp + len); + } + return; +} - /* Store the size of extended memory in EXTENDED_MEMORY, in order to - tell it to non-Multiboot OSes. */ - extended_memory = saved_mem_upper; +/* Print the chain of Device Path nodes. This is mainly for debugging. 打印设备路径节点的链。这主要是为了调试*/ +void grub_efi_print_device_path (grub_efi_device_path_t *dp); +void +grub_efi_print_device_path (grub_efi_device_path_t *dp) //efi打印设备路径 +{ + unsigned short *str; + grub_efi_device_to_text_protocol_t *DPTTP; //设备路径到文本协议 + static grub_efi_guid_t dpttp_guid = GRUB_EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID; + grub_efi_handle_t *handles; + grub_efi_uintn_t num_handles; - /* - * The MBI.MEM_UPPER variable only recognizes upper memory in the - * first memory region. If there are multiple memory regions, - * the rest are reported to a Multiboot-compliant OS, but otherwise - * unused by GRUB. - */ + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, + &dpttp_guid, NULL, &num_handles); //定位手柄(通过协议) + if (!handles || num_handles == 0) //如果不支持路径到文本,退出。否则在UEFI版本1.0a会死机 + { + if (!dp) + return; + grub_efi_device_path_to_str (dp); + return; + } - addr = saved_mmap_addr; - cont = 0; + DPTTP = grub_efi_locate_protocol (&dpttp_guid, 0); //EFI定位协议 + str = (unsigned short *)efi_call_3 (DPTTP->ConvertDevicePathToText, + dp, FALSE, FALSE); - if (debug_boot) - printf("Get E820 memory... "); - do - { - cont = get_mmap_entry ((void *) addr, cont); /* int15/e820 ------ will write memory! */ + grub_putstr_utf16 (str); + grub_putchar ('\n', 255); - /* If the returned buffer's length is zero, quit. */ - if (! *((unsigned long *) addr)) - break; + return; +} +//-------------------------------------------------------------------------------------; +//kern/mm.c - saved_mmap_length += *((unsigned long *) addr) + 4; - addr += *((unsigned long *) addr) + 4; - } - while (cont); - if (debug_boot) grub_printf("0x%x", saved_mmap_length); - DEBUG_SLEEP +/* Magic words. 魔术词 */ +#define GRUB_MM_FREE_MAGIC 0x2d3c2808 +#define GRUB_MM_ALLOC_MAGIC 0x6db08fa4 - if (! (saved_mmap_length)) - if (debug_boot) - printf("Get E801 memory...\n"); +typedef struct grub_mm_header //内存头 +{ + struct grub_mm_header *next; //下一个内存头 + grub_size_t size; //尺寸 + grub_size_t magic; //魔术 + grub_size_t padding; //衬垫 +} +*grub_mm_header_t; //32位: 0x10 64位: 0x20 - if (saved_mmap_length) - { - unsigned long long max_addr; - - if (debug_boot) printf("Get MBI.MEM_{LOWER,UPPER} elements...\n"); - - /* - * This is to get the lower memory, and upper memory (up to the - * first memory hole), into the MBI.MEM_{LOWER,UPPER} - * elements. This is for OS's that don't care about the memory - * map, but might care about total RAM available. - */ - //saved_mem_lower = mmap_avail_at (0) >> 10; - saved_mem_upper = mmap_avail_at (0x100000) >> 10; - saved_mem_higher = mmap_avail_at (0x100000000ULL) >> 10; - - /* Find the maximum available address. Ignore any memory holes. */ - for (max_addr = 0, addr = saved_mmap_addr; - addr < saved_mmap_addr + saved_mmap_length; - addr += *((unsigned long *) addr) + 4) - { - struct AddrRangeDesc *desc = (struct AddrRangeDesc *) addr; - - if (desc->Type == MB_ARD_MEMORY && desc->Length > 0 - && desc->BaseAddr + desc->Length > max_addr) - max_addr = desc->BaseAddr + desc->Length; - } +#if defined(__i386__) +# define GRUB_MM_ALIGN_LOG2 4 +#else +# define GRUB_MM_ALIGN_LOG2 5 +#endif - extended_memory = (max_addr - 0x100000) >> 10; - } - else if ((memtmp = get_eisamemsize ()) != -1) /* int15/e801 ------safe enough */ - { - cont = memtmp & ~0xFFFF; - memtmp = memtmp & 0xFFFF; +#define GRUB_MM_ALIGN (1 << GRUB_MM_ALIGN_LOG2) //0x10 - if (cont != 0) - extended_memory = (cont >> 10) + 0x3c00; - else - extended_memory = memtmp; - - saved_mem_upper = memtmp; +typedef struct grub_mm_region //内存区域 +{ + struct grub_mm_header *first; //第一内存头 + struct grub_mm_region *next; //下一个内存区域 + grub_size_t pre_size; //预先调整尺寸 + grub_size_t size; //尺寸 +} +*grub_mm_region_t; //0x10 - if (cont != 0) - { - saved_mem_upper += (cont >> 10); - -// /* XXX should I do this at all ??? */ -// -// saved_mmap_addr = (unsigned long) fakemap; -// saved_mmap_length = sizeof (struct AddrRangeDesc) * 2; -// fakemap[0].Length = (saved_mem_lower << 10); -// fakemap[1].Length = (saved_mem_upper << 10); -// fakemap[2].Length = 0; - } - //else - { - /* XXX should I do this at all ??? */ +#ifndef GRUB_MACHINE_EMU +extern grub_mm_region_t EXPORT_VAR (grub_mm_base); +#endif +grub_mm_region_t grub_mm_base; //内存基址 + +/* Get a header from the pointer PTR, and set *P and *R to a pointer 从指针PTR获取头,并分别将*P和*R设置为指向头的指针和指向其区域的指针, + to the header and a pointer to its region, respectively. PTR must 必须分配PTR。 + be allocated. */ +static int get_header_from_pointer (void *ptr, grub_mm_header_t *p, grub_mm_region_t *r); +static int +get_header_from_pointer (void *ptr, grub_mm_header_t *p, grub_mm_region_t *r) +{ + if ((grub_addr_t) ptr & (GRUB_MM_ALIGN - 1)) + { + printf_debug ("unaligned pointer %x", ptr); + return 0; + } + for (*r = grub_mm_base; *r; *r = (*r)->next) + if ((grub_addr_t) ptr > (grub_addr_t) ((*r) + 1) + && (grub_addr_t) ptr <= (grub_addr_t) ((*r) + 1) + (*r)->size) + break; - saved_mmap_addr = (unsigned long) fakemap; - saved_mmap_length = sizeof (fakemap); - fakemap[0].Length = (saved_mem_lower << 10); - fakemap[1].Length = (memtmp << 10); - fakemap[2].Length = cont; - } - } - DEBUG_SLEEP - //printf("\r \r"); /* wipe out the messages */ - minimum_mem_hi_in_map = (saved_mem_upper<<10)+0x100000; - mbi.mem_upper = saved_mem_upper; - mbi.mem_lower = saved_mem_lower; - mbi.mmap_addr = saved_mmap_addr; - mbi.mmap_length = saved_mmap_length; + if (! *r) + { + printf_errinfo ("out of range pointer %x\n", ptr); //指针超出范围 + return 0; + } - init_free_mem_start = get_code_end (); + *p = (grub_mm_header_t) ptr - 1; + if ((*p)->magic == GRUB_MM_FREE_MAGIC) //魔术 0x2d3c2808 + { + printf_errinfo ("double free at %x", *p); + return 0; + } + if ((*p)->magic != GRUB_MM_ALLOC_MAGIC) //魔术 0x6db08fa4 + { + printf_errinfo ("alloc magic is broken at %x: %x", *p,(*p)->magic); //eb985d0:0 + return 0; + } + return 1; +} - /* - * Initialize other Multiboot Info flags. - */ +/* Deallocate the pointer PTR. 释放指针PTR。 */ +void grub_free (void *ptr); +void +grub_free (void *ptr) +{ + grub_mm_header_t p; + grub_mm_region_t r; + + if (! ptr) + return; - mbi.flags = (MB_INFO_MEMORY | MB_INFO_CMDLINE | MB_INFO_BOOTDEV | MB_INFO_DRIVE_INFO | MB_INFO_CONFIG_TABLE | MB_INFO_BOOT_LOADER_NAME); - if (saved_mmap_length) - mbi.flags |= MB_INFO_MEM_MAP; + if (!get_header_from_pointer (ptr, &p, &r)) + return; - force_pxe_as_boot_device = 0; - /* if booted by fbinst, we can skip tons of checks ... */ - if (fb_status) + if (r->first->magic == GRUB_MM_ALLOC_MAGIC) { - boot_drive = FB_DRIVE; - install_partition = 0xFFFFFF; - goto set_root; + p->magic = GRUB_MM_FREE_MAGIC; + r->first = p->next = p; } - -#ifdef FSYS_PXE - if (! ((*(char *)0x8205) & 0x01)) /* if it is not disable pxe */ - { - //pxe_detect(); - if (! pxe_entry) + else { - PXENV_GET_CACHED_INFO_t get_cached_info; - if (debug_boot) - printf_debug0("begin pxe scan... "); - pxe_scan (); - DEBUG_SLEEP + grub_mm_header_t q, s; + for (s = r->first, q = s->next; q <= p || q->next >= p; s = q, q = s->next) + { + if (q->magic != GRUB_MM_FREE_MAGIC) + { + printf_errinfo ("free magic is broken at %x: 0x%x", q, q->magic); + return; + } + if (q <= q->next && (q > p || q->next < p)) + break; + } - if (pxe_entry) - { - //pxe_basemem = *((unsigned short*)0x413); + p->magic = GRUB_MM_FREE_MAGIC; + p->next = q->next; + q->next = p; + if (p->next + p->next->size == p) + { + p->magic = 0; - get_cached_info.PacketType = PXENV_PACKET_TYPE_DHCP_ACK; - get_cached_info.Buffer = get_cached_info.BufferSize = 0; - if (debug_boot) - printf_debug0("\rbegin pxe call(type=DHCP_ACK)... "); - pxe_call (PXENV_GET_CACHED_INFO, &get_cached_info); - DEBUG_SLEEP + p->next->size += p->size; + q->next = p->next; + p = p->next; + } - if (get_cached_info.Status) + r->first = q; + if (q == p + p->size) { - printf_debug0 ("\nFatal: DHCP_ACK failure!\n"); - goto pxe_init_fail; + q->magic = 0; + p->size += q->size; + if (q == s) + s = p; + s->next = p; + q = s; } - discover_reply = LINEAR(get_cached_info.Buffer); + r->first = q; + } +} + +/* +typedef struct grub_mm_header //内存头 first q p +{ // 1000000 cc00010 cc00010 + struct grub_mm_header *next; //下一个内存头 -1 cc00010 cc00010 + grub_size_t size; //尺寸 -1 1ffbfe-401 1ffbfe + grub_size_t magic; //魔术 -1 2d3c2808 2d3c2808 + char padding[4]; //衬垫 +} +*/ +/* Allocate the number of units N with the alignment ALIGN from the ring 从*FIRST开始,从缓冲区中分配对齐方式为ALIGN的N个单元。对齐必须是2的幂。 + buffer starting from *FIRST. ALIGN must be a power of two. Both N and N和ALIGN都以GRUB_MM_ALIGN为单位(32位系统是0x10)。 + ALIGN are in units of GRUB_MM_ALIGN. Return a non-NULL if successful, 如果成功,则返回非空值,否则返回空值。 + otherwise return NULL. */ +static void *grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align); +static void * +grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) //真实分配内存(插槽起始内存头, 分配N个单元, 对齐方式) +{ + grub_mm_header_t p, q; //内存头 + /* When everything is allocated side effect is that *first will have alloc 当所有东西都被分配时,副作用是*first会标记alloc magic, + magic marked, meaning that there is no room in this region. */ //这意味着这个区域没有空间。 + if ((*first)->magic == GRUB_MM_ALLOC_MAGIC) //如果没有空间,错误 0x6db08fa4 + return 0; + + /* Try to search free slot for allocation in this memory region. 尝试在此内存区域中搜索空闲插槽以进行分配。*/ + for (q = *first, p = q->next; ; q = p, p = p->next) //搜索空闲插槽 起始: q=插槽起始内存头, p=下一个; 循环: q=下一个, p=下下一个 + { + grub_off_t extra; //额外的 64位 - pxe_yip = discover_reply->yip; - pxe_sip = discover_reply->sip; - pxe_gip = discover_reply->gip; + extra = ((grub_addr_t) (p + 1) >> GRUB_MM_ALIGN_LOG2) & (align - 1); //额外的=(下下一个/0x10)&(对齐方式-1) - pxe_mac_type = discover_reply->Hardware; - pxe_mac_len = discover_reply->Hardlen; - grub_memmove (&pxe_mac, &discover_reply->CAddr, pxe_mac_len); + if (extra) //如果额外的存在 + extra = align - extra; //额外的=对齐方式-额外的 - get_cached_info.PacketType = PXENV_PACKET_TYPE_CACHED_REPLY; - get_cached_info.Buffer = get_cached_info.BufferSize = 0; - if (debug_boot) - printf_debug0("\rbegin pxe call(type=CACHED_REPLY)... "); - pxe_call (PXENV_GET_CACHED_INFO, &get_cached_info); - DEBUG_SLEEP + if (! p) //如果下一个结束 + { + printf_errinfo ("null in the ring"); //环中的NULL + return 0; + } - if (get_cached_info.Status) + if (p->magic != GRUB_MM_FREE_MAGIC) //如果魔术错误 2d3c2808 { - printf_debug0 ("\nFatal: CACHED_REPLY failure!\n"); -pxe_init_fail: - pxe_keep = 0; - pxe_unload (); - DEBUG_SLEEP - pxe_entry = 0; - discover_reply = 0; - goto pxe_init_done; + printf_errinfo ("free magic is broken at %x: 0x%x", (grub_size_t)p, p->magic); //自由魔法在%p被打破 + return 0; } - discover_reply = LINEAR(get_cached_info.Buffer); -#ifdef FSYS_IPXE - ipxe_init(); -#endif - /* on pxe boot, we only use preset_menu */ - //if (preset_menu != (char*)0x800) - // preset_menu = (char*)0x800; - if (*config_file) - *config_file = 0; - force_pxe_as_boot_device = 1; - if (bios_id != 1) /* if it is not Bochs ... */ - goto set_root;; /* ... skip cdrom check. */ + if (p->size >= n + extra) //如果下一个->尺寸 >= N+额外的 + { + extra += (p->size - extra - n) & (~(align - 1)); + if (extra == 0 && p->size == n) + { + /* There is no special alignment requirement and memory block 没有特殊的对齐要求,内存块完全匹配。 + is complete match. + + 1. Just mark memory block as allocated and remove it from 只需将内存块标记为已分配,并将其从空闲列表中删除。 + free list. + + Result: 结果: + +---------------+ previous block's next 下一个块的下一个 + | alloc, size=n | | 分配,尺寸=n + +---------------+ v + */ + q->next = p->next; + } + else if (align == 1 || p->size == n + extra) + { + /* There might be alignment requirement, when taking it into 当考虑到内存块适合时,可能需要对齐。 + account memory block fits in. + + 1. Allocate new area at end of memory block. 1. 在内存块末尾分配新区域。 + 2. Reduce size of available blocks from original node. 2. 从原始节点减小可用块的尺寸。 + 3. Mark new area as allocated and "remove" it from free 3. 将新区域标记为已分配,并将其从释放列表中“删除”。 + list. + + Result: 结果: + +---------------+ + | free, size-=n | next --+ 释放,尺寸-n 下一个 + +---------------+ | + | alloc, size=n | | 分配,尺寸=n + +---------------+ v + */ + + p->size -= n; //dbffff-401=dbfbfe + p += p->size; //1000010+dbfbfe*10=ebfbff0 + } + else if (extra == 0) + { + grub_mm_header_t r; + + r = p + extra + n; + r->magic = GRUB_MM_FREE_MAGIC; + r->size = p->size - extra - n; + r->next = p->next; + q->next = r; + if (q == p) + { + q = r; + r->next = r; + } + } + else + { + /* There is alignment requirement and there is room in memory 内存块中有对齐要求和空间。 + block. Split memory block to three pieces. 把内存块分成三块。 + + 1. Create new memory block right after section being 1. 在分配分区后立即创建新的内存块。 + allocated. Mark it as free. 标记为释放。 + 2. Add new memory block to free chain. 2. 将新的内存块添加到空闲链。 + 3. Mark current memory block having only extra blocks. 3. 标记只有额外块的当前内存块。 + 4. Advance to aligned block and mark that as allocated and 4. 向对齐的块发送,并将其标记为已分配,然后将其从空闲列表中“删除”。 + "remove" it from free list. + + Result: 结果: + +------------------------------+ + | free, size=extra | next --+ 释放,尺寸=extra + +------------------------------+ | + | alloc, size=n | | 分配,尺寸=n + +------------------------------+ | + | free, size=orig.size-extra-n | <------+, next --+ 释放,尺寸=orig.size-extra-n + +------------------------------+ v + */ +#if 0 + grub_mm_header_t r; + + r = p + extra + n; + r->magic = GRUB_MM_FREE_MAGIC; + r->size = p->size - extra - n; + r->next = p; + p->size = extra; + q->next = r; + p += extra; +#else + n = p->size - extra; + p->size = extra; + p += extra; +#endif } + + p->magic = GRUB_MM_ALLOC_MAGIC; + p->size = n; + /* Mark find as a start marker for next allocation to fasten it. 标记“查找”作为下次分配的开始标记,以固定它。 + This will have side effect of fragmenting memory as small 这将产生副作用的碎片内存作为小块之前,这将是不使用。 + pieces before this will be un-used. */ + /* So do it only for chunks under 64K. 所以只能对64K以下的块执行此操作。*/ + if (n < (0x8000 >> GRUB_MM_ALIGN_LOG2) //如果20<800, 或者a8dd010=ebffdf0 + || *first == p) + *first = q; //*first=a8dd010 下一循环的内存头 + return p + 1; //ebffe00 + }//if (p->size >= n + extra) + + /* Search was completed without result. 搜索已完成,但没有结果。*/ + if (p == *first) + break; + }//for (q = *first, p = q->next; ; q = p, p = p->next) + + return 0; +} + + +/* Allocate SIZE bytes with the alignment ALIGN and return the pointer. 使用对齐方式分配内存字节并返回指针。*/ +void * grub_memalign (grub_size_t align, grub_size_t size); +void * +grub_memalign (grub_size_t align, grub_size_t size) //内存对齐(对齐,尺寸) +{ + grub_mm_region_t r; //内存区域 + grub_size_t n = ((size + GRUB_MM_ALIGN - 1) >> GRUB_MM_ALIGN_LOG2) + 1; //(size+0x10-1)/0x10 节对齐 + int count = 0; + + if (!grub_mm_base) //如果内存基址=0 + goto fail; //失败 + +// if (size > ~(grub_size_t) align) //如果尺寸大于对齐 size > ~align +// goto fail; //失败 + + /* We currently assume at least a 32-bit grub_size_t, 我们目前假设至少有32位grub_size_t, + so limiting allocations to - 1MiB 因此,以健全的名义将分配限制在"地址空间尺寸"-1MiB是有益的。 + in name of sanity is beneficial. */ +// if ((size + align) > ~(grub_size_t) 0x100000) //如果(尺寸+对齐) > 0x100000 +// goto fail; //失败 + + align = (align >> GRUB_MM_ALIGN_LOG2); //对齐/0x10 + if (align == 0) + align = 1; + +again: + for (r = grub_mm_base; r; r = r->next) //从内存基址开始,直到遇到0结束 + { + void *p; + p = grub_real_malloc (&(r->first), n, align); + if (p) + return p; } + + /* If failed, increase free memory somehow. 如果失败,以某种方式增加可用内存。*/ + switch (count) + { + case 0: + /* Invalidate disk caches. 使磁盘缓存无效 */ + count++; + goto again; + default: + break; + } + +fail: + printf_errinfo ("out of malloc memory\n"); //内存不足 + return 0; +} + +/* Allocate SIZE bytes and return the pointer. */ +void *grub_malloc (grub_size_t size); +void * +grub_malloc (grub_size_t size) //分配内存尺寸字节,并返回指针。 +{ + return grub_memalign (0, size); //内存对齐(对齐,尺寸) +} + +/* Allocate SIZE bytes, clear them and return the pointer. 分配SIZE字节,清除它们并返回指针*/ +void *grub_zalloc (grub_size_t size); +void * +grub_zalloc (grub_size_t size) +{ + void *ret; + + ret = grub_memalign (0, size); + if (ret) + grub_memset (ret, 0, size); + + return ret; +} +#if 0 +/* Reallocate SIZE bytes and return the pointer. The contents will be 重新分配SIZE字节并返回指针。内容与PTR相同。 + the same as that of PTR. */ +void * grub_realloc (void *ptr, grub_size_t size); +void * +grub_realloc (void *ptr, grub_size_t size) +{ + grub_mm_header_t p; + grub_mm_region_t r; + void *q; + grub_size_t n; + + if (! ptr) + return grub_malloc (size); + + if (! size) + { + grub_free (ptr); + return 0; } -pxe_init_done: -#endif /* FSYS_PXE */ - /* setup boot_drive and install_partition for dos boot drive */ -redo_dos_geometry: - if (dos_drive_geometry) + /* FIXME: Not optimal. */ + n = ((size + GRUB_MM_ALIGN - 1) >> GRUB_MM_ALIGN_LOG2) + 1; + get_header_from_pointer (ptr, &p, &r); + + if (p->size >= n) + return ptr; + + q = grub_malloc (size); + if (! q) + return q; + + /* We've already checked that p->size < n. */ + grub_memcpy (q, ptr, p->size << GRUB_MM_ALIGN_LOG2); + grub_free (ptr); + return q; +} +#endif + +///////////////////////////////////////////////////////////////////////////////////////// +#if 0 +#define GRUB_UCS2_LIMIT 0x10000 +#define GRUB_UTF16_UPPER_SURROGATE(code) \ + (0xD800 | ((((code) - GRUB_UCS2_LIMIT) >> 10) & 0x3ff)) +#define GRUB_UTF16_LOWER_SURROGATE(code) \ + (0xDC00 | (((code) - GRUB_UCS2_LIMIT) & 0x3ff)) + +/* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE + bytes (if SRCSIZE is -1, it is ignored) in length to a UTF-16 string. + Return the number of characters converted. DEST must be able to hold + at least DESTSIZE characters. If an invalid sequence is found, return -1. + If SRCEND is not NULL, then *SRCEND is set to the next byte after the + last byte used in SRC. */ +grub_size_t grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize, + const grub_uint8_t *src, grub_size_t srcsize, + const grub_uint8_t **srcend); +grub_size_t +grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize, + const grub_uint8_t *src, grub_size_t srcsize, + const grub_uint8_t **srcend) +{ + grub_uint16_t *p = dest; + int count = 0; + grub_uint32_t code = 0; + + if (srcend) + *srcend = src; + + while (srcsize && destsize) { - unsigned long j = -1; - if (dos_part_start) + int was_count = count; + if (srcsize != (grub_size_t)-1) + srcsize--; + if (!grub_utf8_process (*src++, &code, &count)) { - /* find the partition starting at dos_part_start. */ - /* only primary partitions can be a DOS boot drive. */ - /* So we read the MBR and check the partition table. */ - /* At this moment we cannot use geometry. */ - /* So we safely call BIOS, read at 2000:0000 */ - if (biosdisk_standard (0x02, (unsigned char)dos_drive_geometry, 0, 0, 1, 1, 0x2000)) - goto failed_dos_boot_drive; - for (j = 0; j < 4; j++) - { - if (*(unsigned long *)(j*16+0x201C6) == dos_part_start) - goto succeeded_dos_boot_drive; - } - goto failed_dos_boot_drive; + code = '?'; + count = 0; + /* Character c may be valid, don't eat it. */ + if (was_count) + src--; } -succeeded_dos_boot_drive: - ((unsigned short *)&install_partition)[1] = (unsigned char)j; - boot_drive = (unsigned char)dos_drive_geometry; - - /* set geometry_ok flag for dos boot drive */ - if (boot_drive == 0) + if (count != 0) + continue; + if (code == 0) + break; + if (destsize < 2 && code >= GRUB_UCS2_LIMIT) + break; + if (code >= GRUB_UCS2_LIMIT) { - fd_geom[0].flags |= BIOSDISK_FLAG_GEOMETRY_OK; - fd_geom[0].heads = ((unsigned char *)&dos_drive_geometry)[1]+1; - fd_geom[0].sectors = ((unsigned char *)&dos_drive_geometry)[2]; + *p++ = GRUB_UTF16_UPPER_SURROGATE (code); + *p++ = GRUB_UTF16_LOWER_SURROGATE (code); + destsize -= 2; } - else if (boot_drive == 0x80) + else { - hd_geom[0].flags |= BIOSDISK_FLAG_GEOMETRY_OK; - hd_geom[0].heads = ((unsigned char *)&dos_drive_geometry)[1]+1; - hd_geom[0].sectors = ((unsigned char *)&dos_drive_geometry)[2]; + *p++ = code; + destsize--; } } - else if (use_fixed_boot_device == -1) -// if (! ((*(char *)0x8211) & 2)) // if not booting as a Linux kernel + + if (srcend) + *srcend = src; + return p - dest; +} +#endif +/* Convert UTF-16 to UTF-8. */ +grub_uint8_t *grub_utf16_to_utf8 (grub_uint8_t *dest, const grub_uint16_t *src, grub_size_t size); +grub_uint8_t * +grub_utf16_to_utf8 (grub_uint8_t *dest, const grub_uint16_t *src, + grub_size_t size) +{ + grub_uint32_t code_high = 0; + + while (size--) { - unsigned long j, k; - - boot_drive = *(unsigned char *)0x8206; - ((unsigned short *)&install_partition)[1] = *(unsigned char *)0x8207; - /* check if there is a valid volume-boot-sector at 0x7C00. */ - if (probe_bpb((struct master_and_dos_boot_sector *)0x7C00)) - goto failed_dos_boot_drive; -// j = (dos_part_start ? 0x80 : 0); - j = boot_drive; - if (*((unsigned long long *) (0x7C00 + 3)) == 0x2020205441465845) //exfat + grub_uint32_t code = *src++; + + if (code_high) { - dos_part_start = *((unsigned long *) (0x7C00 + 0x40)); - k = ( j | 0xfe << 8 | 0x3f << 16); + if (code >= 0xDC00 && code <= 0xDFFF) + { + /* Surrogate pair. */ + code = ((code_high - 0xD800) << 10) + (code - 0xDC00) + 0x10000; + + *dest++ = (code >> 18) | 0xF0; + *dest++ = ((code >> 12) & 0x3F) | 0x80; + *dest++ = ((code >> 6) & 0x3F) | 0x80; + *dest++ = (code & 0x3F) | 0x80; + } + else + { + /* Error... */ + *dest++ = '?'; + /* *src may be valid. Don't eat it. */ + src--; + } + + code_high = 0; } - else + else { - dos_part_start = *((unsigned long *) (0x7C00 + 0x1C)); - k = ( j | ((*(unsigned short *)(0x7C00 + 0x1A) - 1) << 8) - | ((*(unsigned short *)(0x7C00 + 0x18)) << 16) ); + if (code <= 0x007F) + *dest++ = code; + else if (code <= 0x07FF) + { + *dest++ = (code >> 6) | 0xC0; + *dest++ = (code & 0x3F) | 0x80; + } + else if (code >= 0xD800 && code <= 0xDBFF) + { + code_high = code; + continue; + } + else if (code >= 0xDC00 && code <= 0xDFFF) + { + /* Error... */ + *dest++ = '?'; + } + else if (code < 0x10000) + { + *dest++ = (code >> 12) | 0xE0; + *dest++ = ((code >> 6) & 0x3F) | 0x80; + *dest++ = (code & 0x3F) | 0x80; + } + else + { + *dest++ = (code >> 18) | 0xF0; + *dest++ = ((code >> 12) & 0x3F) | 0x80; + *dest++ = ((code >> 6) & 0x3F) | 0x80; + *dest++ = (code & 0x3F) | 0x80; + } } - if (! k) - goto failed_dos_boot_drive; -// boot_drive = j; - dos_drive_geometry = k; - goto redo_dos_geometry; - } - else - { } -failed_dos_boot_drive: - /* Set cdrom drive. */ - -#define FIND_DRIVES (*((char *)0x475)) - /* Get the geometry. */ + return dest; +} - if ((((unsigned char)boot_drive) >= 0x80 + FIND_DRIVES) - && ! ((*(char *)0x8205) & 0x10)) /* if it is not disable startup cdrom drive look-up. */ - { - cdrom_drive = get_cdinfo (boot_drive, &tmp_geom); - if (! cdrom_drive || cdrom_drive != boot_drive) - cdrom_drive = GRUB_INVALID_DRIVE; +//------------------------------------------------------------------------------------- +//kern/efi/mm.c + +#define ALIGN_UP(addr, align) \ + ((addr + (typeof (addr)) align - 1) & ~((typeof (addr)) align - 1)) +#define ALIGN_UP_OVERHEAD(addr, align) ((-(addr)) & ((typeof (addr)) (align) - 1)) +#define ALIGN_DOWN(addr, align) \ + ((addr) & ~((typeof (addr)) align - 1)) +#define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0])) +#define COMPILE_TIME_ASSERT(cond) switch (0) { case 1: case !(cond): ; } + +#define GRUB_EFI_PAGE_SHIFT 12 +#define GRUB_EFI_PAGE_SIZE (1 << GRUB_EFI_PAGE_SHIFT) +#define GRUB_EFI_BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> GRUB_EFI_PAGE_SHIFT) + +#define GRUB_MMAP_REGISTER_BY_FIRMWARE 1 + +#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff //64位不同 + +#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) //字节转页 向上舍入 +#define BYTES_TO_PAGES_DOWN(bytes) ((bytes) >> 12) //字节转页 向下舍入 +#define PAGES_TO_BYTES(pages) ((pages) << 12) //页转字节 + +/* The size of a memory map obtained from the firmware. This must be 从固件获得的内存映射的大小。这必须是4kb的倍数. + a multiplier of 4KB. */ +#define MEMORY_MAP_SIZE 0x3000 //内存映射尺寸 + +/* The minimum and maximum heap size for GRUB itself. GRUB自身的最小和最大堆尺寸 */ +#define MIN_HEAP_SIZE 0x100000 //最小堆尺寸 1MB 100页 +#define MAX_HEAP_SIZE (1600 * 0x100000) //最大堆尺寸 1600MB 160000页 + +static void *finish_mmap_buf = 0; +static grub_efi_uintn_t finish_mmap_size = 0; +static grub_efi_uintn_t finish_key = 0; +static grub_efi_uintn_t finish_desc_size; +static grub_efi_uint32_t finish_desc_version; +int grub_efi_is_finished = 0; //EFI完成 + +/* + * We need to roll back EFI allocations on exit. Remember allocations that 我们需要在退出时备份EFI分配。记住我们将在退出时释放的分配。 + * we'll free on exit. + */ +struct efi_allocation; //分配 +struct efi_allocation { + grub_efi_physical_address_t address; //地址 8位 + grub_efi_uint64_t pages; //页 8位 + struct efi_allocation *next; //下一个 4位 0=结束符 +}; + +#if 0 +static struct efi_allocation *efi_allocated_memory; //0x14位 静态,地址不变 +static void grub_efi_store_alloc (grub_efi_physical_address_t address, grub_efi_uintn_t pages); +static void +grub_efi_store_alloc (grub_efi_physical_address_t address, + grub_efi_uintn_t pages) //分配池(地址,页) 向"启动服务数据=12bafd24"写数据 +{ + grub_efi_boot_services_t *b; //引导服务 + struct efi_allocation *alloc; //分配 动态地址,变化 + grub_efi_status_t status; //状态 + b = grub_efi_system_table->boot_services; //系统表->引导服务 + status = efi_call_3 (b->allocate_pool, GRUB_EFI_LOADER_DATA, //装载数据 2 + sizeof(*alloc), (void**)&alloc); //(分配池,存储器类型->装载数据,分配字节,返回分配地址} + + if (status == GRUB_EFI_SUCCESS) //如果分配成功 + { //插槽位置 + alloc->next = efi_allocated_memory; //下一个 + alloc->address = address; //地址 + alloc->pages = pages; //页 + efi_allocated_memory = alloc; //当前 + } + else //失败 + printf_errinfo ("Could not malloc memory to remember EFI allocation. " + "Exiting GRUB won't free all memory.\n"); +} + +static void grub_efi_drop_alloc (grub_efi_physical_address_t address, grub_efi_uintn_t pages); +static void +grub_efi_drop_alloc (grub_efi_physical_address_t address, + grub_efi_uintn_t pages) //释放池(地址,页) +{ + struct efi_allocation *ea, *eap; //分配表 + grub_efi_boot_services_t *b; //引导服务 + + b = grub_efi_system_table->boot_services; //系统表->引导服务 + for (eap = NULL, ea = efi_allocated_memory; ea; eap = ea, ea = ea->next) + { + if (ea->address != address || ea->pages != pages) //如果分配表地址不同, 或者分配表也不同 + continue; //继续 + + /* Remove the current entry from the list. 从列表中删除当前条目 */ + if (eap) + eap->next = ea->next; + else + efi_allocated_memory = ea->next; //第一次, 改变内存分配表 + /* Then free the memory backing it. 然后释放记忆支持它 */ + efi_call_1 (b->free_pool, ea); //释放池(分配) + + /* And leave, we're done. 离开,我们完成 */ + break; + } +} +#endif + +grub_efi_status_t grub_efi_allocate_pool (grub_efi_memory_type_t pool_type, + grub_efi_uintn_t buffer_size, void **buffer); +grub_efi_status_t +grub_efi_allocate_pool (grub_efi_memory_type_t pool_type, + grub_efi_uintn_t buffer_size, void **buffer) //分配池 +{ + grub_efi_boot_services_t *b; + grub_efi_status_t status; + + b = grub_efi_system_table->boot_services; + status = efi_call_3 (b->allocate_pool, pool_type, buffer_size, buffer); + return status; +} + +grub_efi_status_t grub_efi_free_pool (void *buffer); +grub_efi_status_t +grub_efi_free_pool (void *buffer) //释放池 +{ + grub_efi_boot_services_t *b; + grub_efi_status_t status; + + b = grub_efi_system_table->boot_services; + status = efi_call_1 (b->free_pool, buffer); + return status; +} + +//第一次分配页时,会多分配一页,用于记录分配结构. 似乎每一结构占用0x80字节(实际结构每一这么大).此页不会释放. +//分配页后,紧接分配池.并记录分配结构. +/* Allocate pages. Return the pointer to the first of allocated pages. 分配页面。返回指向第一个分配页面的指针 */ +void *grub_efi_allocate_pages_real (grub_efi_physical_address_t address, + grub_efi_uintn_t pages, + grub_efi_allocate_type_t alloctype, + grub_efi_memory_type_t memtype); +void * +grub_efi_allocate_pages_real (grub_efi_physical_address_t address, + grub_efi_uintn_t pages, + grub_efi_allocate_type_t alloctype, + grub_efi_memory_type_t memtype) //真实分配页面(地址,页,分配类型,存储类型) +{ + grub_efi_status_t status; //状态 + grub_efi_boot_services_t *b; //引导服务 + /* Limit the memory access to less than 4GB for 32-bit platforms. 限制访问32位内存平台限制小于4GB的。 */ + if (address > GRUB_EFI_MAX_USABLE_ADDRESS) //地址>最大可用地址4Gb + return 0; //退出 + + b = grub_efi_system_table->boot_services; //系统表->引导服务 + status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &address); //(分配页,分配类型,存储类型,页,返回分配地址) + if (status != GRUB_EFI_SUCCESS) //如果失败 + return 0; //退出 + + if (address == 0) //如果地址=0 对于分配最大地址页,似乎又重复了一次! + { + /* Uggh, the address 0 was allocated... This is too annoying, 地址0被分配…这太烦人了,所以重新分配另一个。 + so reallocate another one. */ + address = GRUB_EFI_MAX_USABLE_ADDRESS; //地址=最大可用地址4Gb + status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &address); //分配页,分配类型,存储类型,页,地址 + grub_efi_free_pages (0, pages); //释放页 + if (status != GRUB_EFI_SUCCESS) //如果失败 + return 0; + } + +// grub_efi_store_alloc (address, pages); //分配池(地址,页) - if (cdrom_drive == GRUB_INVALID_DRIVE) + return (void *) ((grub_addr_t) address);//返回地址 +} + +void *grub_efi_allocate_any_pages (grub_efi_uintn_t pages); +void * +grub_efi_allocate_any_pages (grub_efi_uintn_t pages) //分配最大地址页(请求页数) +{ + return grub_efi_allocate_pages_real (GRUB_EFI_MAX_USABLE_ADDRESS, //地址=最大可用地址4Gb + pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, //请求页数,分配类型->最大地址 1 + GRUB_EFI_LOADER_DATA); //存储器类型->装载数据 2 +} + +void *grub_efi_allocate_fixed (grub_efi_physical_address_t address, grub_efi_uintn_t pages); +void * +grub_efi_allocate_fixed (grub_efi_physical_address_t address, + grub_efi_uintn_t pages) //分配固定页 +{ + return grub_efi_allocate_pages_real (address, pages, //地址=给定地址,请求页数, + GRUB_EFI_ALLOCATE_ADDRESS, //分配类型->地址 2 + GRUB_EFI_LOADER_DATA); // //存储器类型->装载数据 2 +} + +//首先释放页,然后释放池. 再更改分配记录. +/* Free pages starting from ADDRESS. 从ADDRESS释放页 */ +void grub_efi_free_pages (grub_efi_physical_address_t address, grub_efi_uintn_t pages); +void +grub_efi_free_pages (grub_efi_physical_address_t address, + grub_efi_uintn_t pages) //释放页(地址,页) +{ + grub_efi_boot_services_t *b; + + b = grub_efi_system_table->boot_services;//系统表->引导服务 + efi_call_2 (b->free_pages, address, pages); //(释放页,地址,页) + +// grub_efi_drop_alloc (address, pages); //释放池 +} + +grub_err_t grub_efi_finish_boot_services (grub_efi_uintn_t *outbuf_size, void *outbuf, + grub_efi_uintn_t *map_key, + grub_efi_uintn_t *efi_desc_size, + grub_efi_uint32_t *efi_desc_version); +grub_err_t +grub_efi_finish_boot_services (grub_efi_uintn_t *outbuf_size, void *outbuf, + grub_efi_uintn_t *map_key, + grub_efi_uintn_t *efi_desc_size, + grub_efi_uint32_t *efi_desc_version) //完成引导服务(输出缓存尺寸,输出缓存,映射键,描述尺寸,描述版本) +{ + grub_efi_boot_services_t *b; + grub_efi_status_t status; + + while (1) { - /* read sector 16 - ISO9660 Primary Volume Descriptor - * sector 17 - EL Torito Volume Descriptor - */ - struct disk_address_packet + if (grub_efi_get_memory_map (&finish_mmap_size, finish_mmap_buf, &finish_key, + &finish_desc_size, &finish_desc_version) < 0) //获取EFI规范中定义的内存映射失败 + return printf_errinfo ("couldn't retrieve memory map\n"); //无法检索内存映射 + + if (outbuf && *outbuf_size < finish_mmap_size) + return printf_errinfo ("memory map buffer is too small\n"); //内存映射缓冲区太小 + + finish_mmap_buf = grub_malloc (finish_mmap_size); //分配内存 + + if (grub_efi_get_memory_map (&finish_mmap_size, finish_mmap_buf, &finish_key, + &finish_desc_size, &finish_desc_version) <= 0) //获取EFI规范中定义的内存映射失败 { - unsigned char length; - unsigned char reserved; - unsigned short blocks; - unsigned long buffer; - unsigned long long block; - - unsigned char dummy[16]; - } __attribute__ ((packed)) *dap; - - dap = (struct disk_address_packet *)0x580; - - dap->length = 0x10; - dap->reserved = 0; - dap->blocks = 2; - dap->buffer = 0x5F80/*SCRATCHSEG*/ << 16; - dap->block = 16; - - /* set a known value */ - grub_memset ((char *)0x5F800, 0xEC, 0x1000); - biosdisk_int13_extensions (0x4200, (unsigned char)boot_drive, dap, 0); - /* check ISO9660 Primary Volume Descriptor */ - if (! memcmp ((char *)0x5F800, "\1CD001\1\0", 8)) - /* check the EL Torito Volume Descriptor */ - if (! memcmp ((char *)0x60000, "\0CD001\1EL TORITO SPECIFICATION\0", 31)) - /* see if it is a big sector */ + grub_free (finish_mmap_buf); //释放 + return printf_errinfo ("couldn't retrieve memory map\n"); //无法检索内存映射 + } + + b = grub_efi_system_table->boot_services;//系统表->引导服务 + status = efi_call_2 (b->exit_boot_services, grub_efi_image_handle, + finish_key); //退出引导服务 + if (status == GRUB_EFI_SUCCESS) //如果成功, 退出 + break; + + if (status != GRUB_EFI_INVALID_PARAMETER) //如果错误不是无效参数 { - //char *p; - //for (p = (char *)0x5FA00; p < (char *)0x60000; p++) - //{ - // if ((*p) != (char)0xEC) - // { - cdrom_drive = boot_drive; - // break; - // } - //} + grub_free (finish_mmap_buf); //释放 + return printf_errinfo ("couldn't terminate EFI services\n"); //无法终止EFI服务 } + grub_free (finish_mmap_buf); //释放 + printf_debug ("Trying to terminate EFI services again\n"); //再次尝试终止EFI服务 } - } -#undef FIND_DRIVES + grub_efi_is_finished = 1; //EFI完成 + if (outbuf_size) //如果有输出缓存尺寸 + *outbuf_size = finish_mmap_size; + if (outbuf) //如果有输出缓存 + grub_memcpy (outbuf, finish_mmap_buf, finish_mmap_size); + if (map_key) //如果有映射键 + *map_key = finish_key; + if (efi_desc_size) //如果有描述尺寸 + *efi_desc_size = finish_desc_size; + if (efi_desc_version) //如果有描述版本 + *efi_desc_version = finish_desc_version; + + return GRUB_ERR_NONE; +} - printf_debug("boot drive=%X, %s\n", boot_drive,(cdrom_drive == GRUB_INVALID_DRIVE ? "Not CD":"Is CD")); - DEBUG_SLEEP - - if (cdrom_drive == GRUB_INVALID_DRIVE - && ! ((*(char *)0x8205) & 0x10)) /* if it is not disable startup cdrom drive look-up. */ - { - int err; - int version; - struct drive_parameters *drp = (struct drive_parameters *)0x600; - -#define FIND_DRIVES (*((char *)0x475)) - /* Drive 7F causes hang on motherboard "jetway 694AS/TAS", as reported - * by renfeide112@126.com, 2009-09-30. So no more play with 7F. */ - for (drive = 0xFF; drive > 0x7F; drive--) +#if 0 +/* + * To obtain the UEFI memory map, we must pass a buffer of sufficient size 要获得UEFI内存映射,我们必须通过足够大小的缓冲区来保存整个映射。 + * to hold the entire map. This function returns a sane start value for 这个函数返回理智的起始缓冲区尺寸值。 + * buffer size. + */ +grub_efi_uintn_t grub_efi_find_mmap_size (void); +grub_efi_uintn_t +grub_efi_find_mmap_size (void) //查找内存映射尺寸 +{ + grub_efi_uintn_t mmap_size = 0; + grub_efi_uintn_t desc_size; + + if (grub_efi_get_memory_map (&mmap_size, NULL, NULL, &desc_size, 0) < 0) //获得内存映射(内存映射尺寸,内存映射地址,映射键,描述符尺寸,描述符版本) { - if (drive >= 0x80 && drive < 0x80 + FIND_DRIVES) - continue; /* skip hard drives */ - - /* Get the geometry. */ - if (debug > 1) - { - printf_debug ("\rget_cdinfo(%X),", drive); - DEBUG_SLEEP - } - cdrom_drive = get_cdinfo (drive, &tmp_geom); - if (cdrom_drive) - { - if (drive != 0x7F) - break; - drive = cdrom_drive; - cdrom_drive = get_cdinfo (drive, &tmp_geom); - if (cdrom_drive == drive) - break; - drive = 0x7F; - } - - cdrom_drive = GRUB_INVALID_DRIVE; - - /* Some buggy BIOSes will hang at EBIOS `Get Drive Parameters' call - * (INT 13h function 48h). So we only do further checks for Bochs. - */ - - if (bios_id != 1) /* if it is not Bochs ... */ - continue; /* ... skip and try next drive. */ - - /* When qemu has a cdrom attached but not booted from cdrom, its - * `get bootable cdrom status call', the int13/ax=4B01, returns CF=0 - * but with a wrong `Bootable CD-ROM Specification Packet' as follows: - * - * The first byte(packet size) is 0x13, all the rest bytes are 0's. - * - * So we need to call get_diskinfo() here as a workaround. - * - * (The bug was reported by Jacopo Lazzari. Thanks!) - */ - - if (drive >= 0x80) - { - version = check_int13_extensions (drive, 0); + printf_errinfo ("cannot get EFI memory map size\n"); //无法获取EFI内存映射尺寸 + return 0; + } - if (! (version & 1)) /* not support functions 42h-44h, 47h-48h */ - continue; /* failure, try next drive. */ - - /* It is safe to clear out DRP. */ - grub_memset (drp, 0, sizeof (struct drive_parameters)); - - drp->size = sizeof (struct drive_parameters) - 16; - - err = biosdisk_int13_extensions (0x4800, drive, drp, 0); - if (! err && drp->bytes_per_sector == ISO_SECTOR_SIZE) + /* + * Add an extra page, since UEFI can alter the memory map itself on 添加一个额外的页面,因为UEFI可以通过回调或显式调用来改变内存映射本身,包括控制台输出. + * callbacks or explicit calls, including console output. + */ + return ALIGN_UP (mmap_size + GRUB_EFI_PAGE_SIZE, GRUB_EFI_PAGE_SIZE); //GRUB_EFI_PAGE_SIZE=1页=0x1000 向上舍入 +} +#endif + +/* Get the memory map as defined in the EFI spec. Return 1 if successful, 获取EFI规范中定义的内存映射。如果成功返回1,如果部分返回0, 如果错误返回-1. + return 0 if partial, or return -1 if an error occurs. */ +int grub_efi_get_memory_map (grub_efi_uintn_t *memory_map_size, grub_efi_memory_descriptor_t *memory_map, grub_efi_uintn_t *map_key, + grub_efi_uintn_t *descriptor_size, grub_efi_uint32_t *descriptor_version); +int +grub_efi_get_memory_map (grub_efi_uintn_t *memory_map_size, //指向缓冲区尺寸(以字节为单位)的指针。在输入时,这是调用方分配的缓冲区尺寸。在输出时,它是固件返回的缓冲区尺寸 + grub_efi_memory_descriptor_t *memory_map, //指向固件返回当前内存映射的缓冲区的指针。 + grub_efi_uintn_t *map_key, //指向固件返回当前内存映射键的位置的指针。 + grub_efi_uintn_t *descriptor_size, //指向固件返回单个EFI内存描述符尺寸(以字节为单位)的位置的指针。 + grub_efi_uint32_t *descriptor_version) //指向固件返回与EFI内存描述符关联的版本号的位置的指针。 + //获得内存映射(缓冲区尺寸指针,缓冲区指针,映射键指针,单个内存描述符尺寸指针,描述符版本指针) +{ //返回: 0/1/-1="请求尺寸<完成尺寸"/"请求尺寸>=完成尺寸"/错误 + grub_efi_status_t status; + grub_efi_boot_services_t *b; + grub_efi_uintn_t key; + grub_efi_uint32_t version; + grub_efi_uintn_t size; + + if (grub_efi_is_finished) //如果EFI完成 + { + int ret = 1; + if (*memory_map_size < finish_mmap_size) //如果请求尺寸<完成尺寸 + { + grub_memcpy (memory_map, finish_mmap_buf, *memory_map_size); //复制finish_mmap_buf到memory_map, memory_map_size字节 + ret = 0; + } + else + { + grub_memcpy (memory_map, finish_mmap_buf, finish_mmap_size); + ret = 1; + } + *memory_map_size = finish_mmap_size; + if (map_key) + *map_key = finish_key; + if (descriptor_size) + *descriptor_size = finish_desc_size; + if (descriptor_version) + *descriptor_version = finish_desc_version; + return ret; + } + //如果EFI未完成 + /* Allow some parameters to be missing. 允许缺少一些参数 */ + if (! map_key) + map_key = &key; + if (! descriptor_version) + descriptor_version = &version; + if (! descriptor_size) + descriptor_size = &size; + + b = grub_efi_system_table->boot_services;//系统表->引导服务 + status = efi_call_5 (b->get_memory_map, memory_map_size, memory_map, map_key, + descriptor_size, descriptor_version); //获得内存映射(给定请求尺寸,给定映射地址,映射键,描述尺寸,描述符版本) + //从给定映射抽取可用内存,然后给出可用内存集相对于给定映射地址的偏移memory_map_size. 回带描述符尺寸memory_map_size和描述符版本descriptor_version. + + if (*descriptor_size == 0) + *descriptor_size = sizeof (grub_efi_memory_descriptor_t); + if (status == GRUB_EFI_SUCCESS) //完成 + return 1; + else if (status == GRUB_EFI_BUFFER_TOO_SMALL) //缓冲器太小 + return 0; + else + return -1; +} + +/* Filter the descriptors. GRUB needs only available memory. 筛选内存映射。GRUB只需要可用内存 */ +static grub_efi_memory_descriptor_t *filter_memory_map (grub_efi_memory_descriptor_t *memory_map, grub_efi_memory_descriptor_t *filtered_memory_map, + grub_efi_uintn_t desc_size, grub_efi_memory_descriptor_t *memory_map_end); +static grub_efi_memory_descriptor_t * +filter_memory_map (grub_efi_memory_descriptor_t *memory_map, //映射起始 + grub_efi_memory_descriptor_t *filtered_memory_map, //筛选映射起始 + grub_efi_uintn_t desc_size, //描述符尺寸 + grub_efi_memory_descriptor_t *memory_map_end) //映射结束 +{ + grub_efi_memory_descriptor_t *desc; + grub_efi_memory_descriptor_t *filtered_desc; + + for (desc = memory_map, filtered_desc = filtered_memory_map; + desc < memory_map_end; + desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))//下一个内存描述符(描述符,尺寸) { - /* mount the drive, confirm the media exists. */ - current_drive = drive; - current_partition = 0x00FFFFFF; - if (open_device ()) + if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY //如果是常规内存 + && desc->physical_start < 0x100000) //并且物理起始 < 1Mb + { + min_con_mem_start = (int)desc->physical_start; //最低可用内存起始 +// min_con_mem_size = (int)(desc->num_pages * 0x1000); + min_con_mem_size = (int)(desc->num_pages << 12); + } + + if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY //如果是常规内存 +#if 1 + && desc->physical_start <= GRUB_EFI_MAX_USABLE_ADDRESS //并且物理起始<=最大可用地址4Gb +#endif + && desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000 //并且物理起始+使用内存 > 1Mb + && desc->num_pages != 0) //并且页数非0 + { + grub_memcpy (filtered_desc, desc, desc_size); //把常规内存映射, 复制到筛选映射起始 + + /* Avoid less than 1MB, because some loaders seem to be confused. 避免小于1MB,因为有些装载机看起来很混乱。*/ + if (desc->physical_start < 0x100000) //如果物理起始 < 1Mb { - /* Assume it is CDROM. */ - cdrom_drive = drive; - break; + desc->num_pages -= BYTES_TO_PAGES (0x100000 + - desc->physical_start); //减少使用内存 + desc->physical_start = 0x100000; //调整物理起始 = 1Mb } + +#if 1 + if (BYTES_TO_PAGES (filtered_desc->physical_start) + + filtered_desc->num_pages + > BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS)) //如果物理起始+使用内存 > 4Gb + filtered_desc->num_pages + = (BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS)//减少使用内存 + - BYTES_TO_PAGES (filtered_desc->physical_start)); +#endif + if (filtered_desc->num_pages == 0) //如果使用内存=0 + continue; + + filtered_desc = NEXT_MEMORY_DESCRIPTOR (filtered_desc, desc_size);//下一个内存描述符(描述符,尺寸) + } } - } /* if (drive >= 0x80) */ - - } /* for (drive = 0x7F; drive < 0xff; drive++) */ - } /* if (cdrom_drive == GRUB_INVALID_DRIVE) */ -#undef FIND_DRIVES - -// if (cdrom_drive != GRUB_INVALID_DRIVE) -// { -// /* skip pxe init if booting from cdrom */ -// *(char *)0x8205 |= 0x01; -// } - printf_debug("\rcdrom_drive == %X\n", cdrom_drive); - DEBUG_SLEEP + return filtered_desc; +} - /* check if the no-emulation-mode bootable cdrom exists. */ +//在使用内存堆头部,建立内存头,用于记录将来在堆内分配和释放内存. +/* Initialize a region starting from ADDR and whose size is SIZE, + to use it as free space. 从addr开始初始化一个大小为size的区域,将其用作可用空间。*/ +void grub_mm_init_region (void *addr, grub_size_t size); +void +grub_mm_init_region (void *addr, grub_size_t size) // +{ + grub_mm_header_t h; //内存头 + grub_mm_region_t r, *p, q; //内存区域 + /* Exclude last 4K to avoid overflows. 排除最后4K以避免溢出。*/ + /* If addr + 0x1000 overflows then whole region is in excluded zone. 如果addr+0x1000溢出,则整个区域都在排除区域中。*/ + if ((grub_addr_t) addr > ~((grub_addr_t) 0x1000)) + return; + /* If addr + 0x1000 + size overflows then decrease size. 如果addr+0x1000+size溢出,则减小size*/ + if (((grub_addr_t) addr + 0x1000) > ~(grub_addr_t) size) + size = ((grub_addr_t) -0x1000) - (grub_addr_t) addr; - /* if cdrom_drive is active, we assume it is the boot device */ - if (saved_entryno == 0 && force_cdrom_as_boot_device) - force_cdrom_as_boot_device = 0; - if (cdrom_drive != GRUB_INVALID_DRIVE && force_cdrom_as_boot_device) + for (p = &grub_mm_base, q = *p; q; p = &(q->next), q = *p) + { + if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q) //如果地址+尺寸+第一内存头->预先调整尺寸 = 第一内存头 + { + r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); + *r = *q; + r->pre_size += size; + if (r->pre_size >> GRUB_MM_ALIGN_LOG2) + { + h = (grub_mm_header_t) (r + 1); + h->size = (r->pre_size >> GRUB_MM_ALIGN_LOG2); + h->magic = GRUB_MM_ALLOC_MAGIC; + r->size += h->size << GRUB_MM_ALIGN_LOG2; + r->pre_size &= (GRUB_MM_ALIGN - 1); + *p = r; + grub_free (h + 1); + } + *p = r; + return; + } + } + + /* Allocate a region from the head. 从头部分配一个区域。*/ + r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); //节对齐 + /* If this region is too small, ignore it. 如果这个区域太小,忽略它。*/ + if (size < GRUB_MM_ALIGN + (char *) r - (char *) addr + sizeof (*r)) + return; + + size -= (char *) r - (char *) addr + sizeof (*r); + + h = (grub_mm_header_t) (r + 1); + h->next = h; //下一个内存头 + h->magic = GRUB_MM_FREE_MAGIC; //魔术 + h->size = (size >> GRUB_MM_ALIGN_LOG2); //尺寸 + + r->first = h; //第一内存头 + r->pre_size = (grub_addr_t) r - (grub_addr_t) addr; //预先调整尺寸 + r->size = (h->size << GRUB_MM_ALIGN_LOG2); //尺寸 + /* Find where to insert this region. Put a smaller one before bigger ones, 找到插入此区域的位置把小的放在大的之前,以防止碎片化。 + to prevent fragmentation. */ + for (p = &grub_mm_base, q = *p; q; p = &(q->next), q = *p) // + if (q->size > r->size) //如果第一内存区域尺寸>当前内存区域尺寸 + break; //结束 + + *p = r; //a8dd000 + r->next = q; +} + + +grub_efi_uint64_t memory_pages; +grub_efi_physical_address_t memory_address; +//分配一块将来由自己直接分配和释放的内存区域. +/* Add memory regions. 添加内存区域 */ +static void add_memory_regions (grub_efi_memory_descriptor_t *memory_map, grub_efi_uintn_t desc_size, + grub_efi_memory_descriptor_t *memory_map_end, grub_efi_uint64_t required_pages); +static void +add_memory_regions (grub_efi_memory_descriptor_t *memory_map, //排序后的内存映射起始 + grub_efi_uintn_t desc_size, //描述符尺寸 + grub_efi_memory_descriptor_t *memory_map_end, //排序后的内存映射结束 + grub_efi_uint64_t required_pages) //请求页数 +{ + grub_efi_memory_descriptor_t *desc; //内存描述符 + for (desc = memory_map; + desc < memory_map_end; + desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))//下一个内存描述符(描述符,尺寸) + { + grub_efi_uint64_t pages; + grub_efi_physical_address_t start; + void *addr; + + start = desc->physical_start; //物理起始 + pages = desc->num_pages; //页数 + if (pages < required_pages) //如果页数>请求页数 + continue; + + start += PAGES_TO_BYTES (pages - required_pages); //物理起始+页转字节(页数-请求页数) + pages = required_pages; //页数=请求页数 4323 + + addr = grub_efi_allocate_pages_real (start, required_pages, + GRUB_EFI_ALLOCATE_ADDRESS, //指定地址 + GRUB_EFI_LOADER_CODE); //真实分配页面(物理起始,请求页数,分配类型->地址,存储类型->装载程序代码) + if (! addr) + { + printf_errinfo ("cannot allocate conventional memory %p with %u pages", + (void *) ((grub_addr_t) start), + (unsigned) pages); + break; + } + memory_address = (grub_efi_physical_address_t)(grub_size_t)addr; + memory_pages = pages; + grub_mm_init_region (addr, PAGES_TO_BYTES (pages)); //初始化内存区域 + break; + } +} + +void grub_efi_memory_fini (void); +void +grub_efi_memory_fini (void) //内存结束 +{ + /* + * Free all stale allocations. grub_efi_free_pages() will remove 释放所有stale分配. + * the found entry from the list and it will always find the first grub_efi_free_pages() 将从列表中移除找到的条目,它总是会找到第一个列表条目. + * list entry (efi_allocated_memory is the list start). Hence we (efi_allocated_memory是列表开始) + * remove all entries from the list until none is left altogether. 因此,我们从列表中删除所有条目,直到没有剩下。 + */ +// while (efi_allocated_memory) +// grub_efi_free_pages (efi_allocated_memory->address, +// efi_allocated_memory->pages); //释放页 + grub_efi_free_pages (memory_address, memory_pages); //释放页 + + int drive; + struct grub_disk_data *d; + grub_efi_boot_services_t *b; + b = grub_efi_system_table->boot_services; //系统表->引导服务 + for (drive = 0xFF; drive >= 0; drive--) //从0xff到0 { - boot_drive = cdrom_drive; /* force it to be the boot drive */ - } + d = get_device_by_drive (drive,0); + if (!d) //避免驱动器不存在时死机 + continue; + + //卸载映射内存 + if (d->to_drive == 0xff && d->to_log2_sector != 0xb) //内存映射 + efi_call_2 (b->free_pages, d->start_sector << 9, d->sector_count >> 3); //释放页 2024-09-01 + } +} + +#if 0 //打印内存分布 +/* Print the memory map. 打印内存分布*/ +static void print_memory_map (grub_efi_memory_descriptor_t *memory_map, grub_efi_uintn_t desc_size, grub_efi_memory_descriptor_t *memory_map_end); +static void +print_memory_map (grub_efi_memory_descriptor_t *memory_map, //内存起始 + grub_efi_uintn_t desc_size, //描述符尺寸 + grub_efi_memory_descriptor_t *memory_map_end) //内存结束 +{ + grub_efi_memory_descriptor_t *desc; + int i; + + for (desc = memory_map, i = 0; + desc < memory_map_end; + desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size), i++)//下一个内存描述符(描述符,尺寸) + { + grub_printf ("MD: t=%x, p=%lx, v=%lx, n=%lx, a=%lx\n", + desc->type, desc->physical_start, desc->virtual_start, + desc->num_pages, desc->attribute); + console_getkey(); + } +} +#endif + +void grub_efi_mm_init (void); +void +grub_efi_mm_init (void) //内存管理初始化 +{ + grub_efi_memory_descriptor_t *memory_map; //内存映射地址 + grub_efi_memory_descriptor_t *memory_map_end; //内存映射结束地址 + grub_efi_memory_descriptor_t *filtered_memory_map; //过滤内存映射地址 + grub_efi_memory_descriptor_t *filtered_memory_map_end; //过滤内存映射结束地址 + grub_efi_uintn_t map_size; //映射尺寸 + grub_efi_uintn_t desc_size; //描述尺寸 + grub_efi_uint64_t required_pages; //请求页数 + int mm_status; //分配内存状态=1/0/-1=成功/部分/失败 + + /* Prepare a memory region to store two memory maps. 准备存储区域来存储两个内存映射 共6页*/ + memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); //分配最大地址页(请求页数) (字节转页 向上舍入) + if (! memory_map) //如果失败 + printf_errinfo ("cannot allocate memory"); //无法分配内存 + + /* Obtain descriptors for available memory. 获取可用内存的描述符 */ + map_size = MEMORY_MAP_SIZE; //内存映射尺寸 0x3000 + mm_status = grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0); //获得内存映射(映射尺寸,映射页,0,描述尺寸,0) 返回1/0/-1=成功/部分/失败 + //获得内存描述符尺寸desc_size, 获得可用内存描述符集地址偏移map_size + if (mm_status == 0) //如果是部分 + { + grub_efi_free_pages + ((grub_efi_physical_address_t) ((grub_addr_t) memory_map), + 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); //释放页 + + /* Freeing/allocating operations may increase memory map size. 释放/分配操作可以增加内存映射的大小 */ + map_size += desc_size * 32; //增大内存尺寸 + memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (map_size)); //再次分配最大地址页(请求页数)(6) + if (! memory_map) //如果失败 + printf_errinfo ("cannot allocate memory"); //无法分配内存 + + mm_status = grub_efi_get_memory_map (&map_size, memory_map, 0, + &desc_size, 0); //获得内存映射 + } + + if (mm_status < 0) //如果失败 + printf_errinfo ("cannot get memory map"); //无法分配内存 + + memory_map_end = NEXT_MEMORY_DESCRIPTOR (memory_map, map_size); //全部内存映射结尾 + + filtered_memory_map = memory_map_end; //筛选内存映射开始 + + filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map, + desc_size, memory_map_end); //筛选内存映射结尾 + + required_pages = 0x4000; //分配64Mb + /* Allocate memory regions for GRUB's memory management. 为GRUB's内存管理分配内存区域 */ + add_memory_regions (filtered_memory_map, desc_size, + filtered_memory_map_end, required_pages); + +#if 0 //打印内存分布 + /* For debug. */ + map_size = MEMORY_MAP_SIZE; + + if (grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0) < 0) + grub_printf ("cannot get memory map"); + + grub_printf ("printing memory map\n"); + print_memory_map (memory_map, desc_size, + NEXT_MEMORY_DESCRIPTOR (memory_map, map_size)); +#endif + + /* Release the memory maps. 释放内存映射 */ + grub_efi_free_pages ((grub_addr_t) memory_map, + 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); //释放页 +} +//----------------------------------------------------------------------------- +void get_datetime (struct grub_datetime *datetime); +void +get_datetime (struct grub_datetime *datetime) +{ + grub_efi_status_t status; + struct grub_efi_time efi_time; + + status = efi_call_2 (grub_efi_system_table->runtime_services->get_time, + &efi_time, 0); - if (boot_drive == cdrom_drive) - /* force it to be "whole drive" without partition table */ - install_partition = 0xFFFFFF; + if (status) + printf_debug ("can\'t get datetime using efi"); + else + { + datetime->year = efi_time.year; + datetime->month = efi_time.month; + datetime->day = efi_time.day; + datetime->hour = efi_time.hour; + datetime->minute = efi_time.minute; + datetime->second = efi_time.second; + } +} -set_root: +int getrtsecs (void); +int +getrtsecs (void) +{ + struct grub_datetime datetime; + get_datetime (&datetime); + return datetime.second; +} - if (force_pxe_as_boot_device) +void defer (unsigned short millisecond); //毫秒 +void +defer (unsigned short millisecond) +{ + efi_call_1 (grub_efi_system_table->boot_services->stall, millisecond * 1000); +} + +grub_efi_physical_address_t grub4dos_self_address = 0; +void copy_grub4dos_self_address (void); +void +copy_grub4dos_self_address (void) +{ + grub_efi_status_t status; //状态 + grub_efi_boot_services_t *b; //引导服务 + b = grub_efi_system_table->boot_services; //系统表->引导服务 + grub_size_t i, address; + + if (min_con_mem_start > 0x9F000) + return; + if (min_con_mem_start + min_con_mem_size <= 0x9F000) + grub4dos_self_address = min_con_mem_start + min_con_mem_size - 0x1000; + else + grub4dos_self_address = 0x9F000; + + address = grub4dos_self_address; + for (i = grub4dos_self_address - 0x1000; i > 0x40000 ; i -= 0x1000) { - boot_drive = PXE_DRIVE; - #ifdef FSYS_IPXE - char *ch = grub_strstr((char*)discover_reply->bootfile,":"); - if (ch && ((grub_u32_t)ch - (grub_u32_t)discover_reply->bootfile) < 10) - install_partition = IPXE_PART; - else - #endif - install_partition = 0xFFFFFF; + if (*(unsigned long long *)(grub_size_t)(i + 0x100) == 0x4946453442555247) //"GRUB4EFI" + address = i; } + //清除残留的钩子 避免测试中启动镜像后重启,热键失效。 注意不要碰触保留内存! 2023-06-21 + grub_memset ((void *)address, 0, grub4dos_self_address - address + 0x1000); + status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ADDRESS, + GRUB_EFI_RUNTIME_SERVICES_DATA, 1, &grub4dos_self_address); //(分配页,分配类型=指定地址,存储类型=运行时数据,页数=1,返回分配地址) + if (status) + return; + //清除残留 + grub_memset ((void *)(grub_size_t)grub4dos_self_address, 0, 0x1000); + //映射插槽结构起始于0(G4D起始于0x20), 尺寸8*0x18=0xc0 + //复制特定字符串, 为了SVBus(G4D位于0x103) + grub_memmove ((void *)(grub_size_t)(grub4dos_self_address + 0xe3), "$INT13SFGRUB4DOS", 16); + //复制特定字符串, 为了G4E外部命令 + grub_memmove ((void *)(grub_size_t)(grub4dos_self_address + 0x100), "GRUB4EFI", 8); + //复制bootx64.efi自身地址 + *(grub_size_t*)((char *)(grub_size_t)grub4dos_self_address + 0x110) = (grub_size_t)g4e_data; + //复制碎片字符串, 为了SVBus + grub_memmove ((void *)(grub_size_t)(grub4dos_self_address + 0x140), "FRAGMENT", 8); + //碎片结构起始于0x148, 尺寸0x280 +} - if (use_fixed_boot_device != -1) +/* Search the mods section from the PE32/PE32+ image. 从PE32/PE32+图像中搜索mods部分。此代码使用PE32头,但也应与PE32+一起使用。 + This code uses a PE32 header, but should work with PE32+ as well. */ +grub_addr_t grub_efi_modules_addr (void); +grub_addr_t +grub_efi_modules_addr (void) //模块地址 +{ + struct grub_pe32_header *header; + struct grub_pe32_coff_header *coff_header; + struct grub_pe32_section_table *sections; + struct grub_pe32_section_table *section; + struct grub_module_info *info; + grub_uint16_t i; + + header = image->image_base; + coff_header = &(header->coff_header); + sections = (struct grub_pe32_section_table *) ((char *) coff_header + + sizeof (*coff_header) + + coff_header->optional_header_size); + + for (i = 0, section = sections; + i < coff_header->num_sections; + i++, section++) { - /* force boot device to be the saved value. */ - boot_drive = (unsigned short)use_fixed_boot_device; - install_partition = use_fixed_boot_device | 0xFFFF; + if (grub_strcmp (section->name, "mods") == 0) + break; } - /* Set root drive and partition. */ - saved_drive = boot_drive; - saved_partition = install_partition; - force_cdrom_as_boot_device = 0; + if (i == coff_header->num_sections) + { + printf_debug("\nsection %d is last section; invalid.", i); //第%d节是最后一节;无效 + return 0; + } -// if (fb_status)//set boot_drive to fb_drive when boot from fbinst. -// boot_drive = FB_DRIVE; + info = (struct grub_module_info *) ((char *) image->image_base + + section->virtual_address); + if (section->name[0] != '.' && info->magic != GRUB_MODULE_MAGIC) + { + printf_debug("\nsection %d has bad magic %08x, should be %08x", + i, info->magic, GRUB_MODULE_MAGIC); //第%d节有错误的魔法%08x,应该是%08x + return 0; + } - debug = 1; - if (! atapi_dev_count) - min_cdrom_id = (cdrom_drive < 0xE0 && cdrom_drive >= 0xC0) ? 0xE0 : 0xC0; - -#if 0 /* comment out since this is done in dosstart.S - tinybit 2012-02-13 */ - /* if grub.exe is booted as a Linux kernel, check the initrd disk. */ + printf_debug("\nreturning section info for section %d: %s", + i, section->name); //返回第2节的节信息:模式 + return (grub_addr_t) info; +} - /* the real mode zero page(only the beginning 2 sectors, the boot params) is loaded at 0xA00 */ +grub_addr_t grub_modbase; //模块地址 +char embed_font_path[64] = {0}; +char preset_menu_path[64]; +char *embed_font = NULL; - /* check the header signature "HdrS" (0x53726448) */ +static int get_embed (void); +static int +get_embed (void) //获取嵌入数据 +{ + struct grub_module_header *header=0; + grub_size_t embed_menu_size; + char *embed_mod = NULL; + grub_size_t embed_mod_size = 0; + char embed_mod_cmd[64]; + grub_size_t embed_font_size = 0; - if (*(unsigned long*)(int*)(0xA00 + 0x202) == 0x53726448) - { - unsigned long initrd_addr; - unsigned long initrd_size; - - initrd_addr = *(unsigned long*)(int*)(0xA00 + 0x218); - initrd_size = *(unsigned long*)(int*)(0xA00 + 0x21c); - if (initrd_addr && initrd_size) - { - rd_base = initrd_addr; - rd_size = initrd_size; + grub_modbase = grub_efi_modules_addr (); - /* check if there is a partition table */ - if (*(unsigned short *)(initrd_addr + 0x40) == 0xAA55) - { - if (! probe_mbr ((struct master_and_dos_boot_sector *)initrd_addr, 0, initrd_size, 0)) - ram_drive = 0xfe; /* partition table is valid, so let it be a harddrive */ - else if (debug_boot) - { - printf_debug0 ("\nUnrecognized partition table for RAM DRIVE; assuming floppy. Please rebuild\nit using a Microsoft-compatible FDISK tool, if the INITRD is a hard-disk image.\n"); -DEBUG_SLEEP - } - } - } - } -#endif - if (debug_boot) grub_printf("\rInitialize variable space...\n"); - - VARIABLE_BASE_ADDR = 0x45000; - memset(ADDR_RET_STR,0,0x200); - run_line("set ?_BOOT=%@root%",1); - QUOTE_CHAR = '\"'; - if (use_lba1sector && run_line("geometry --lba1sector",1)) + FOR_MODULES (header) { - int chk; - if (debug_boot) - printf_debug0("\nYou pressed the `S` key, and \"geometry --lba1sector\" is successfully executed\n for drive 0x%X.This will Slow but Secure disk read for Buggy BIOS.\n",boot_drive); -DEBUG_SLEEP - while((chk = run_line("pause --wait=5",1))) + if (header->type == OBJ_TYPE_CONFIG) //嵌入式配置 + { + embed_menu_size = header->size - header->pad_size - sizeof (struct grub_module_header); +// preset_menu = grub_malloc (embed_menu_size + 0x1ff); + preset_menu = grub_memalign (512, embed_menu_size); //对齐分配 + if (!preset_menu) + continue; + +// preset_menu = (char *)(grub_size_t)(((unsigned long long)(grub_size_t)preset_menu + 0x1ff) & 0xfffffffffffffe00); + grub_memcpy (preset_menu, (char *) header + sizeof (struct grub_module_header), embed_menu_size); + grub_sprintf (preset_menu_path,"(md)0x%x+0x%x,0x%x", ((grub_size_t) preset_menu) >> 9, + (embed_menu_size + 0x1ff) >> 9, embed_menu_size); + preset_menu = preset_menu_path; + use_preset_menu = 1; + continue; + } + else if (header->type == OBJ_TYPE_MEMDISK) //嵌入式模块 + { + embed_mod_size = header->size - header->pad_size - sizeof (struct grub_module_header); +// embed_mod = grub_malloc (embed_mod_size + 0x1ff); + embed_mod = grub_memalign (512, embed_mod_size); //对齐分配 + if (!embed_mod) + continue; + +// embed_mod = (char *)(grub_size_t)(((unsigned long long)(grub_size_t)embed_mod + 0x1ff) & 0xfffffffffffffe00); + grub_memmove (embed_mod, (char *) header + sizeof (struct grub_module_header), embed_mod_size); + grub_sprintf (embed_mod_cmd, "insmod (md)0x%x+0x%x,0x%x", + ((grub_size_t) embed_mod) >> 9, (embed_mod_size + 0x1ff) >> 9, embed_mod_size); + run_line (embed_mod_cmd, 101); + grub_free (embed_mod); + continue; + } + else if (header->type == OBJ_TYPE_FONT) //嵌入式字库 { - chk &= 0xdf; - if (chk != 'S') break; + embed_font_size = header->size - header->pad_size - sizeof (struct grub_module_header); +// embed_font = grub_malloc (embed_font_size + 0x1ff); + embed_font = grub_memalign (512, embed_font_size); //对齐分配 + if (!embed_font) + continue; + +// embed_font = (char *)(grub_size_t)(((unsigned long long)(grub_size_t)embed_font + 0x1ff) & 0xfffffffffffffe00); + grub_memmove (embed_font, (char *) header + sizeof (struct grub_module_header), embed_font_size); + grub_sprintf (embed_font_path, "(md)0x%x+0x%x,0x%x", + ((grub_size_t) embed_font) >> 9, (embed_font_size + 0x1ff) >> 9, embed_font_size); + continue; } } -#ifdef SUPPORT_GRAPHICS -extern int font_func (char *, int); - font_func (NULL, 0); /* clear the font */ -#endif /* SUPPORT_GRAPHICS */ + return 1; +} - /* Start main routine here. */ - - if (debug_boot) - grub_printf("\rStarting cmain()... "); - - DEBUG_SLEEP + +//堆栈 +grub_size_t __stack_chk_guard; + +//构造堆栈值 +static __attribute__ (( noinline )) grub_size_t make_cookie ( void ) { + union { + struct { + unsigned int eax; + unsigned int edx; + } __attribute__ (( packed )); + unsigned long long raw; + } u; + grub_size_t cookie; + + //我们没有可行的熵来源。使用CPU时间戳计数器,在我们被调用时,它的低位至少有一些最小的随机性。 +#if defined(__i386__) || defined(__x86_64__) + __asm__ ( "rdtsc" : "=a" ( u.eax ), "=d" ( u.edx ) ); +#elif defined(__aarch64__) + __asm__ ( "mrs %0, CNTVCT_EL0\n\t" : "=r" ( u.raw ) ); +#endif + cookie = u.raw; + + //以充当失控的字符串终止符。使用移位而不是掩码来构造NUL,以避免在低阶比特中丢失有价值的熵。 + cookie <<= 8; + + return cookie; } + + //初始化堆栈cookie + //此函数本身不得使用堆栈保护 +void init_cookie ( void ) { + + ///设置堆栈cookie值 + //此函数本身不得使用堆栈保护,因为堆栈保护值的更改会触发误报。 + //遗憾的是,无法对函数进行注释以排除堆栈保护的使用。因此,我们必须依靠正确预测编译器对使用堆栈保护的决定。 + __stack_chk_guard = make_cookie(); +} + +char *grub_image; +//char *g4e_data; +char *PAGING_TABLES_BUF; +unsigned char *PRINTF_BUFFER; +char *MENU_TITLE; +char *cmd_buffer; +char *FSYS_BUF; +char *CMDLINE_BUF; +char *COMPLETION_BUF; +char *UNIQUE_BUF; +char *HISTORY_BUF; +char *WENV_ENVI; +char *BASE_ADDR; +char *BUFFERADDR; +char *CMD_RUN_ON_EXIT; +char *SCRATCHADDR; +char *mbr; +char *disk_buffer; +//struct fragment_map_slot *disk_fragment_map; +//char * + +void grub_console_init (void); +void grub_efidisk_init (void); +void grub_init (void); +grub_efi_loaded_image_t *image; +unsigned long long saved_mem_higher; +unsigned int saved_mem_upper; +unsigned int saved_mem_lower; +unsigned int free_mem_lower_start; + +void +grub_init (void) +{ + int i; + saved_mem_higher = 0; + saved_mem_upper = 0; + saved_mem_lower = 0; + free_mem_lower_start = 0; + + init_cookie(); //初始化堆栈 + grub_console_init (); + + image = grub_efi_get_loaded_image (grub_efi_image_handle); //通过映像句柄,获得加载映像grub_efi_loaded_image结构 + grub_image = image->image_base; //通过加载映像,获得BOOIA32.EFI映像基址 前部是映像头 struct grub_pe32_header //PE32 头 + //grub_image偏移1000是grldr起始,也就是bios模式的8200处.可使用*((char *)(grub_image)+0x508))取单字节的值. + g4e_data = grub_image + (grub_size_t)(*(unsigned int *)(grub_image + (grub_size_t)(*(unsigned int *)(grub_image + 0x3c)) + 0x28)); + + grub_efi_mm_init (); //内存管理初始化 + copy_grub4dos_self_address (); + + PAGING_TABLES_BUF = grub_malloc (0x4000); //分页表 + PRINTF_BUFFER = grub_malloc (0x40000); //打印 + MENU_TITLE = grub_malloc (0x800); //菜单标题 + cmd_buffer = grub_malloc (0x1000); //命令 + CMDLINE_BUF = grub_malloc (0x640); //命令行 + COMPLETION_BUF = grub_malloc (0x640); //完成 + UNIQUE_BUF = grub_zalloc (0x640); //UNI字符串 + HISTORY_BUF = grub_malloc (0x4000); //网络 + WENV_ENVI = grub_zalloc (0x200); //地址返回字符串 + BASE_ADDR = grub_zalloc (0x8200); //变量 + FSYS_BUF = grub_malloc (0x9010); //文件系统 + BUFFERADDR = grub_malloc (0x10000); //磁盘读写 + CMD_RUN_ON_EXIT = grub_zalloc (256); //命令退出时运行 必须预先清零,否则在 command_func 出错 + SCRATCHADDR = grub_malloc (0x1000); //临时 + mbr = grub_malloc (0x1000); //mbr + disk_buffer = grub_malloc (0x1000); //磁盘缓存 + disk_fragment_map = grub_zalloc (FRAGMENT_MAP_SLOT_SIZE); //碎片插槽 + map_start_sector = grub_zalloc(DRIVE_MAP_FRAGMENT * 8); //(*(grub_size_t **)IMG(0x8308))[36] + map_num_sectors = grub_zalloc(DRIVE_MAP_FRAGMENT * 8); +//buffer=grub_malloc (byte) 分配内存 +//buffer=grub_zalloc (byte) 分配内存, 并清零 +//buffer=grub_memalign (align,byte) 对齐分配内存 +//grub_free (buffer) 释放内存 + + efi_call_4 (grub_efi_system_table->boot_services->set_watchdog_timer, //引导服务->设置看门狗定时器 避免设备5分钟就重启. + 0, 0, 0, NULL); + + if ((i = checkkey ()) == 0x075200 || i == 0x0071 || (*(char *)(g4e_data + 5) & 0x40)) //按Insert键或者q键,或者8205位6置1,进入调试模式 + { + debug = 3; + printf ("Enter debugging mode!\n"); + getkey(); + } + + grub_efidisk_init (); //efidisk初始化 + get_embed(); + displaymem_func ((char *)"-init ", 1); //获得内存信息 + cmain (); +} \ No newline at end of file diff --git a/stage2/console.c b/stage2/console.c index 91f5178b..3763512e 100644 --- a/stage2/console.c +++ b/stage2/console.c @@ -51,31 +51,22 @@ unsigned long long console_color_64bit[COLOR_STATE_MAX] = { /* represents the user defined colors for heading line */ [COLOR_STATE_HEADING] = 0xAAAAAA, /* represents the user defined colors for notes */ - [COLOR_STATE_BORDER] = 0x3399 +// [COLOR_STATE_BORDER] = 0x3399 + [COLOR_STATE_BORDER] = 0xAAAAAA }; +unsigned char color_64_to_8 (unsigned long long color64); +unsigned char color_32_to_4 (unsigned int color32); +int grub_console_getkey (int flags); +static int console_startup_input (void); +void grub_console_init (void); +grub_efi_simple_text_input_ex_interface_t *text_input_ex; + -void -console_setcolorstate (color_state state) -{ - if (state >= COLOR_STATE_MAX) - state = COLOR_STATE_STANDARD; - current_color = console_color[state]; - current_color_64bit = console_color_64bit[state]; - if (state == COLOR_STATE_BORDER) - { - current_color &= 0xf; - current_color |= console_color[COLOR_STATE_NORMAL] & 0xf0; - current_color_64bit &= 0xffffff; - current_color_64bit |= console_color_64bit[COLOR_STATE_NORMAL] & 0xffffff00000000; - } -} -unsigned char color_64_to_8 (unsigned long long color64); -unsigned char color_32_to_4 (unsigned long color32); unsigned char -color_32_to_4 (unsigned long color32) +color_32_to_4 (unsigned int color32) { unsigned char r, g, b, col32, col4=0; r = color32 >> 16; @@ -115,7 +106,7 @@ color_64_to_8 (unsigned long long color64) return (color_32_to_4 (color64 >> 32) << 4) | color_32_to_4 (color64 & 0xffffff); } - +unsigned long long color_4_to_32 (unsigned char color4); unsigned long long color_4_to_32 (unsigned char color4) { @@ -141,24 +132,401 @@ color_4_to_32 (unsigned char color4) } } +unsigned long long color_8_to_64 (unsigned char color8); unsigned long long color_8_to_64 (unsigned char color8) { return (color_4_to_32 (color8 >> 4) << 32) | color_4_to_32 (color8 & 15); } +void console_setcolor(unsigned int state,unsigned long long color[]); void -console_setcolor(unsigned long state,unsigned long long color[]) +console_setcolor(unsigned int state,unsigned long long color[]) { int i; for(i=0;i< COLOR_STATE_MAX;++i) { if (!(state & (1<con_out; //系统表->简单文本输出接口 + + unsigned short str[3]; + int i = 0; + + if (unicode == '\n') + str[i++] = '\r'; + str[i++] = unicode; //Unicode码 + str[i] = 0; //结束符 + efi_call_2 (o->output_string, o, str); //回车,换行各行其是。到行尾可以自动换行。unicode16小尾。0x00结束。 + console_getxy (); + + return 1; +} + +void console_putstr_utf8 (char *str); +void +console_putstr_utf8 (char *str) //控制台打印utf字符串 +{ + while (*str) + console_print_unicode ((unsigned int)*str++, 255); +} + +void console_putstr_utf16(unsigned short *str); +void +console_putstr_utf16(unsigned short *str) //控制台打印unicode16字符串 +{ + while (*str) + console_print_unicode ((unsigned int)*str++, 255); +} + +struct uefi_keysym +{ + unsigned short scan_code; //扫描码 + unsigned short unicode_char; //unicode字符 +}; + +/* The table for key symbols. If the "shifted" member of an entry is + NULL, the entry does not have shifted state. */ +static struct uefi_keysym uefi_keysym_table[] = +{ +// {0x00, 0x0}, //空扫描代码 + {0x01, 0x4800}, //将光标上移一行 + {0x02, 0x5000}, //将光标下移一行. + {0x03, 0x4d00}, //将光标右移1列 + {0x04, 0x4b00}, //将光标左移1列. + {0x05, 0x4700}, //回家 Home + {0x06, 0x4f00}, //结束 end. + {0x07, 0x5200}, //插入 Insert. + {0x08, 0x5300}, //删除 Delete + {0x09, 0x4900}, //向上翻页 Page Up + {0x0a, 0x5100}, //向下翻页 Page Down + {0x0b, 0x3b00}, //F1 + {0x0c, 0x3c00}, //F2 + {0x0d, 0x3d00}, //F3 + {0x0e, 0x3e00}, //F4 + {0x0f, 0x3f00}, //F5 + {0x10, 0x4000}, //F6 + {0x11, 0x4100}, //F7 + {0x12, 0x4200}, //F8 + {0x13, 0x4300}, //F9 + {0x14, 0x4400}, //F10 + {0x17, 0x011b}, //逃离 Escape + {0x15, 0x8500}, //F11 uefi简单文本扩展协议 + {0x16, 0x8600}, //F12 uefi简单文本扩展协议 +}; + +static unsigned int find_uefi_unicode_char (unsigned short scan_code); +static unsigned int +find_uefi_unicode_char (unsigned short scan_code) +{ + int i; + + for (i = 0; i < (int)(sizeof (uefi_keysym_table) / sizeof (uefi_keysym_table[0]));i++) + { + if (scan_code == uefi_keysym_table[i].scan_code) + return uefi_keysym_table[i].unicode_char; + } + + return 0; +} + +static int grub_efi_translate_key (grub_efi_input_key_t key); +static int +grub_efi_translate_key (grub_efi_input_key_t key) //翻译键 ok +{ + if (key.scan_code != 0) //如果扫描码=0 + key.unicode_char = find_uefi_unicode_char (key.scan_code); + + return (key.scan_code << 16 | key.unicode_char); +} + +static int grub_console_getkey_con (struct grub_term_input *term __attribute__ ((unused))); +static int +grub_console_getkey_con (struct grub_term_input *term __attribute__ ((unused))) //控制台获得键_常规 ok +{ + grub_efi_simple_input_interface_t *i; //简单输入接口 + grub_efi_input_key_t key; //返回键值 + grub_efi_status_t status; //读击键成败 + + i = grub_efi_system_table->con_in; //系统表->简单输入接口 + status = efi_call_2 (i->read_key_stroke, i, &key); //读击键 + + if (status != GRUB_EFI_SUCCESS) //失败 + return GRUB_TERM_NO_KEY; + + return grub_efi_translate_key(key); //翻译键 +} + + +static int grub_console_getkey_ex(void); +static int +grub_console_getkey_ex(void) //控制台获得键扩展 ok +{ + grub_efi_key_data_t key_data; + grub_efi_status_t status; + grub_efi_uint32_t kss; + grub_efi_uint32_t key; + + grub_efi_simple_text_input_ex_interface_t *text_input = text_input_ex; + + status = efi_call_2 (text_input->read_key_stroke, text_input, &key_data); + + if (status != GRUB_EFI_SUCCESS) + return GRUB_TERM_NO_KEY; + + kss = key_data.key_state.key_shift_state; //键移位状态 32位 + key = grub_efi_translate_key(key_data.key); //翻译键(键信息) 从输入设备返回的EFI扫描代码和Unicode值。32位 + + if (key == GRUB_TERM_NO_KEY) //失败 + return GRUB_TERM_NO_KEY; + + if (kss & GRUB_EFI_SHIFT_STATE_VALID) //如果移位状态有效 + { + if ((kss & GRUB_EFI_LEFT_SHIFT_PRESSED //如果按下左移位键 0x00000002 //左SHIFT + || kss & GRUB_EFI_RIGHT_SHIFT_PRESSED) //或者按下右移位键 0x00000001 //右SHIFT + /*&& (key & GRUB_TERM_EXTENDED)*/) //并且有扩展标记 0x00800000 //扩展 + key |= GRUB_TERM_SHIFT; //则增加SHIFT标记 0x01000000 + if (kss & GRUB_EFI_LEFT_ALT_PRESSED //如果按下左更改键 0x00000020 //左ALT + || kss & GRUB_EFI_RIGHT_ALT_PRESSED) //或者按下右更改键 0x00000010 //右ALT + key |= GRUB_TERM_ALT; //则增加ALT标记 0x04000000 + if (kss & GRUB_EFI_LEFT_CONTROL_PRESSED //如果按下左控制键 0x00000008 //左CONTROL + || kss & GRUB_EFI_RIGHT_CONTROL_PRESSED)//或者按下右控制键 0x00000004 //右CONTROL + key |= GRUB_TERM_CTRL; //则增加CTRL标记 0x02000000 + } + + return key; +} + +static int console_startup_input (void); +static int +console_startup_input (void) //控制台输入初始化 判断是否支持扩展输入 ok +{ + grub_efi_guid_t text_input_ex_guid = + GRUB_EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID; + + grub_efi_simple_text_input_ex_interface_t *text_input = text_input_ex; + if (text_input) + return 0; + + text_input = grub_efi_open_protocol(grub_efi_system_table->console_in_handler, + &text_input_ex_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); //打开协议(系统表->控制台输入程序,guid,获得协议) + text_input_ex = (void *)text_input; + + return 0; +} + + +//如果键按下,返回:ah=键扫描码,al=ASCII字符; 如果没有按键: flags=0/1=返回-1/一直等待. +int grub_console_getkey (int flags); +int +grub_console_getkey (int flags) //控制台获得键 控制台终端输入->获得键 ok +{ + int key, tem; + struct grub_term_input *term; + +repeat: + if (text_input_ex) //如果支持扩展 + key = grub_console_getkey_ex(); //控制台获得键扩展 + else //不支持扩展 + key = grub_console_getkey_con(term); //控制台获得键常规 + + defer(1); + if (animated_enable) + { + tem = animated(); + if (tem == 0x3c00) + return 0x3c00; + } + if (DateTime_enable) + DateTime_refresh(); + if (ext_timer) + (*ext_timer)(0,-1); + if (timeout_enable) + timeout_refresh(); + + if (!key) + { + if (!flags) + return -1; + else + goto repeat; + } + + return remap_ascii_char(key); +} + +int console_checkkey (void); +int console_checkkey (void) //ok +{ + return grub_console_getkey(0); +} + +int console_getkey (void); +int console_getkey (void) //ok +{ + return grub_console_getkey(1); +} + +void get_console_mode (void); +void +get_console_mode (void) //获得控制台模式信息 ok +{ + grub_efi_simple_text_output_interface_t *o; //简单文本输出接口 + o = grub_efi_system_table->con_out; //系统表->简单文本输出接口 + + grub_efi_status_t status; + int columns, rows; + int i, j=3; + for (i=0; iquery_mode, o, i, (grub_efi_uintn_t *)(grub_size_t)&columns, (grub_efi_uintn_t *)(grub_size_t)&rows); + if (status == GRUB_EFI_SUCCESS) + j = o->mode->max_mode; + + grub_printf("\nmax_mode=%d,mode=%d,attribute=%d,column=%d,row=%d,visible=%d", + o->mode->max_mode,i,o->mode->attribute,columns,rows,o->mode->cursor_visible); + } +} + +int console_getxy (void); +int +console_getxy (void) //行(0为顶部) x=列(0为左部) 返回低4位; y=行(0为顶部) 返回高4位 ok +{ + grub_efi_simple_text_output_interface_t *o; //简单文本输出接口 + + o = grub_efi_system_table->con_out; //系统表->简单文本输出接口 + fontx = o->mode->cursor_column; + fonty = o->mode->cursor_row; + return (int) { fontx | (fonty<<4) }; //返回: 光标列,光标行 +} + +void console_gotoxy (int x, int y); +void +console_gotoxy (int x, int y) //控制台设置光标 ok +{ + grub_efi_simple_text_output_interface_t *o; //简单文本输出接口 + + o = grub_efi_system_table->con_out; //系统表->简单文本输出接口 + efi_call_3 (o->set_cursor_position, o, x, y); //执行: 设置光标位置 + fontx = x; + fonty = y; +} + +void console_cls (void); +void +console_cls (void) //控制台清屏 ok +{ + grub_efi_simple_text_output_interface_t *o; //简单文本输出接口 + grub_efi_int32_t orig_attr; + + o = grub_efi_system_table->con_out; //系统表->简单文本输出接口 + orig_attr = o->mode->attribute; //属性 + efi_call_2 (o->set_attributes, o, current_color & 0xf0); //执行: 设置属性 GRUB_EFI_BACKGROUND_BLACK=00 + efi_call_1 (o->clear_screen, o); //执行: 清除屏幕 + efi_call_2 (o->set_attributes, o, orig_attr); //执行: 设置属性 + fontx = 0; + fonty = 0; +} + +void console_setcolorstate (color_state state); +void +console_setcolorstate (color_state state) //设置控制台颜色--取颜色表中指定序号的颜色赋给控制台, 或者直接输入颜色 ok +{ + grub_efi_simple_text_output_interface_t *o; //简单文本输出接口 + o = grub_efi_system_table->con_out; //系统表->简单文本输出接口 + + if (state & 0x100) //是直接输入颜色 + { + current_color = state & 0x7f; //背景色是0-7 + goto abc; + } + if (state >= COLOR_STATE_MAX) + state = COLOR_STATE_STANDARD; + current_color = console_color[state]; + current_color_64bit = console_color_64bit[state]; + if (state == COLOR_STATE_BORDER) + { + current_color &= 0xf; + current_color |= console_color[COLOR_STATE_NORMAL] & 0xf0; + current_color_64bit &= 0xffffff; + current_color_64bit |= console_color_64bit[COLOR_STATE_NORMAL] & 0xffffff00000000; + } +abc: + efi_call_2 (o->set_attributes, o, current_color); +} + +unsigned int console_setcursor (unsigned int on); +unsigned int +console_setcursor (unsigned int on) //控制台设置光标 0/1=不显示/显示 +{ + grub_efi_simple_text_output_interface_t *o; //简单文本输出接口 + + o = grub_efi_system_table->con_out; //系统表->简单文本输出接口 + efi_call_2 (o->enable_cursor, o, on); + return on; +} + +int console_startup (void); +int +console_startup (void) //控制台输出初始化 ok +{ + grub_efi_set_text_mode (1); //efi设置文本模式 + return 0; +} + +void console_shutdown (void); +void +console_shutdown (void) //控制台输出关闭 +{ + grub_efi_set_text_mode (0); +} + +void grub_console_init (void); +void +grub_console_init (void) //控制台初始化 ok +{ + /* FIXME: it is necessary to consider the case where no console control 有必要考虑没有控制台控件存在的情况,但是默认情况下已经在文本模式中。 + is present but the default is already in text mode. */ + current_term = term_table; /* set terminal to console 将终端设置为控制台*/ + console_startup(); + console_startup_input(); +} +//------------------------------------------------------------------------- + +void grub_efidisk_fini (void); +void grub_efi_fini (void); +void +grub_efi_fini (void) +{ + grub_efidisk_fini (); + grub_efi_memory_fini (); +} + +void grub_machine_fini (void); +void +grub_machine_fini (void) +{ + grub_efi_fini (); +} + + + diff --git a/stage2/cpio.h b/stage2/cpio.h index 0a550976..177f568e 100644 --- a/stage2/cpio.h +++ b/stage2/cpio.h @@ -27,7 +27,7 @@ struct cpio_header { #define CPIO_MAGIC "070701" #define CPIO_MODE_DIR 0040000 #define CPIO_ALIGN 4 -static inline grub_u32_t cpio_image_align( grub_u32_t len ) +static inline unsigned int cpio_image_align( unsigned int len ) { return (len + (CPIO_ALIGN - 1)) & ~(CPIO_ALIGN - 1); } diff --git a/stage2/dec_lz4.c b/stage2/dec_lz4.c index 60f09606..d5fb4f22 100644 --- a/stage2/dec_lz4.c +++ b/stage2/dec_lz4.c @@ -27,8 +27,6 @@ #ifndef NO_DECOMPRESSION -//#define makeUInt32(b0,b1,b2,b3) (((unsigned long)(unsigned char)b0) + ((unsigned long)(unsigned char)b1<<8) + ((unsigned long)(unsigned char)b2<<16) + ((unsigned long)(unsigned char)b3<<24)) -//#define makeUInt64(b0,b1,b2,b3,b4,b5,b6,b7) (((unsigned long long)makeUInt32(b0,b1,b2,b3)) + ((unsigned long long)makeUInt32(b4,b5,b6,b7)<<32)) #define LZ4_MAGIC_NUMBER 0x184D2204 /* initial dic pos 64K */ @@ -42,43 +40,19 @@ struct { unsigned char flg, bd, hc; unsigned char flg_version, flg_bindep, flg_bchecksum, flg_csize, flg_cchecksum, flg_reserved; unsigned char bd_blockmaxsize, bd_reserved; - unsigned long blockMaxSize; /* max uncompressed size for one block can be 64K,256K,1M,4M */ - unsigned long headerSize; - unsigned long nextBlockSize; /* compressed size */ + unsigned int blockMaxSize; /* max uncompressed size for one block can be 64K,256K,1M,4M */ + unsigned int headerSize; + unsigned int nextBlockSize; /* compressed size */ unsigned long long content_size; unsigned long long cfilemax, cfilepos, ufilemax, ufilepos; unsigned long long dicFilePos; /* uncompress file pos for data at (dic + LZ4_DICPOSSTART) */ unsigned long long inpFilePos; - unsigned long dicPos, dicSize, inpPos, inpSize; + unsigned int dicPos, dicSize, inpPos, inpSize; unsigned char *inp; unsigned char *dic; } lz4dec; -/* -typedef struct { - unsigned long Magic;//Value : 0x184D2204 - union{ - unsigned char flg; - struct{ - unsigned char :2;//Reserved - unsigned char cchecksum:1; - unsigned char cSize:1; - unsigned char bChecksum:1; - unsigned char Indep:1; - unsigned char version:2; - } FLG; - }; - union{ - unsigned char bd; - struct{ - unsigned char :4;//Reserved - unsigned char blockMaxSize:3; - unsigned char :1;//Reserved - } BD; - }; - unsigned long long content_size; - unsigned char hc; -} __attribute__ ((packed)) lz4Frame; -*/ + +void dec_lz4_close(void); void dec_lz4_close(void) { @@ -86,11 +60,26 @@ dec_lz4_close(void) if (lz4dec.dic) { grub_free(lz4dec.dic); lz4dec.dic = 0; } } +/* +header: +00000000 04 22 4D 18 6C 70 00 40 60 00 00 00 00 00 4C 55 +00000010 80 0B 00 F0 6C 33 C0 8E D0 BC 00 7C FB 50 07 50 +偏移 字节 描述 +0 4 LZ4_MAGIC_NUMBER 魔法编号 +4 1 lz4dec.flg 属性 +5 1 lz4dec.bd 块最大尺寸=1,保留=0 +6 8 lz4dec.content_size 未压缩尺寸 +e 1 lz4dec.hc +f 4 lz4dec.nextBlockSize 下一块尺寸 +*/ +unsigned char dec_header[20]; +int dec_lz4_open(void); int dec_lz4_open(void) /* return 1=success or 0=failure */ { - unsigned char header[20]; +// unsigned char header[20]; + unsigned char *header = dec_header; if (no_decompression) return 0; @@ -98,12 +87,14 @@ dec_lz4_open(void) Make sure previously allocated memory blocks is freed. Don't need this line if grub_close is called for every openned file before grub_open is called for next file. */ dec_lz4_close(); - filepos = 0; - int bytestoread = (filemax<20) ? (int)filemax : 20; - int bytesread = (int)grub_read((unsigned long long)(unsigned long)(char *)header, bytestoread, GRUB_READ); +// int bytestoread = (filemax<20) ? (int)filemax : 20; + int bytestoread = 20; + int bytesread = (int)grub_read((unsigned long long)(grub_size_t)(char *)header, bytestoread, GRUB_READ); /* check header */ - if (bytesread < (4+2+1+4) || *(grub_u32_t*)(int)&header != LZ4_MAGIC_NUMBER) { + grub_u32_t* a = (grub_u32_t*)&header; +// if (bytesread < (4+2+1+4) || *(grub_u32_t*)(grub_size_t)&header != LZ4_MAGIC_NUMBER) { + if (bytesread < (4+2+1+4) || *a != LZ4_MAGIC_NUMBER) { /* file is not LZ4 frame */ filepos = 0; return 0; @@ -135,7 +126,7 @@ dec_lz4_open(void) /* grub_printf("bytesread %d < 4+2+8+1+4\n", bytesread); */ goto fail; } - lz4dec.content_size = *(grub_u64_t*)(int)&header[pos]; + lz4dec.content_size = *(grub_u64_t*)(grub_size_t)&header[pos]; pos += 8; } else { @@ -154,7 +145,9 @@ dec_lz4_open(void) } /* valid header */ lz4dec.headerSize = pos; - lz4dec.nextBlockSize = *(grub_u32_t*)(int)&header[pos]; + grub_u32_t* b = (grub_u32_t*)&header[pos]; +// lz4dec.nextBlockSize = *(grub_u32_t*)(grub_size_t)&header[pos]; + lz4dec.nextBlockSize = *b; pos += 4; lz4dec.cfilemax = filemax; lz4dec.cfilepos = pos; @@ -165,15 +158,15 @@ dec_lz4_open(void) if (lz4dec.inp == 0 || lz4dec.dic == 0) { if (lz4dec.inp) { grub_free(lz4dec.inp); lz4dec.inp = 0; } if (lz4dec.dic) { grub_free(lz4dec.dic); lz4dec.dic = 0; } - errnum = ERR_NOT_ENOUGH_MEMORY; + errnum = ERR_NOT_ENOUGH_MEMORY;; filepos = 0; return 0; } decomp_type = DECOMP_TYPE_LZ4; compressed_file = 1; - filemax = lz4dec.ufilemax; - filepos = lz4dec.ufilepos; - gzip_filemax = lz4dec.cfilemax; + filemax = lz4dec.ufilemax; //返回未压缩文件尺寸 + filepos = lz4dec.ufilepos; //返回0指针 + gzip_filemax = lz4dec.cfilemax; //返回压缩文件尺寸 lz4dec.inpSize = 0; lz4dec.inpPos = 0; lz4dec.dicPos = LZ4_DICPOSSTART; @@ -188,8 +181,9 @@ dec_lz4_open(void) return 0; } +unsigned long long dec_lz4_read(unsigned long long buf, unsigned long long len, unsigned int write); unsigned long long -dec_lz4_read(unsigned long long buf, unsigned long long len, unsigned long write) +dec_lz4_read(unsigned long long buf, unsigned long long len, unsigned int write) { unsigned long long outTx, outSkip; /* grub_printf("LZ4 read buf=%lX len=%lX dic=%X inp=%X\n",buf,len,lz4dec.dic,lz4dec.inp); @@ -211,9 +205,7 @@ dec_lz4_read(unsigned long long buf, unsigned long long len, unsigned long write /* if reading before dic, reset decompression to beginning */ if (lz4dec.ufilepos + LZ4_DICPOSSTART < lz4dec.dicFilePos) { filepos = lz4dec.headerSize; - grub_read((grub_u64_t)(int)&lz4dec.nextBlockSize, 4, GRUB_READ); -// unsigned char *p = lz4dec.inp; -// lz4dec.nextBlockSize =*(grub_u32_t*)(int)lz4dec.inp; + grub_read((grub_u64_t)(grub_size_t)&lz4dec.nextBlockSize, 4, GRUB_READ); lz4dec.inpSize = 0; lz4dec.inpPos = 0; lz4dec.dicPos = LZ4_DICPOSSTART; @@ -230,11 +222,11 @@ dec_lz4_read(unsigned long long buf, unsigned long long len, unsigned long write /* Copy uncompressed data from dic in range dic[0]...dic[dicPos-1] */ if (outSkip < lz4dec.dicPos) { - unsigned long outTxCur = lz4dec.dicPos - (unsigned long)outSkip; + unsigned int outTxCur = lz4dec.dicPos - (unsigned int)outSkip; if (outTxCur > len) - outTxCur = (unsigned long)len; + outTxCur = (unsigned int)len; if (buf) { - grub_memmove64(buf, (unsigned long)(lz4dec.dic + outSkip), outTxCur); + grub_memmove64(buf, (grub_size_t)(lz4dec.dic + outSkip), outTxCur); buf += outTxCur; } outSkip = lz4dec.dicPos; @@ -248,19 +240,19 @@ dec_lz4_read(unsigned long long buf, unsigned long long len, unsigned long write /*while (lz4dec.nextBlockSize && lz4dec.dicPos + lz4dec.blockMaxSize <= LZ4_DICBUFSIZE) */{ /* All existing wanted data from dic have been copied. We will have to decompress more data. */ /* Read next compressed block (with optional checksum) with next block size */ - unsigned long blockSize = lz4dec.nextBlockSize; + unsigned int blockSize = lz4dec.nextBlockSize; //grub_printf("blockSize %X\n",blockSize); if (blockSize == 0) break; int bUncompressedBlock = ((blockSize & 0x80000000) != 0); blockSize &= 0x7FFFFFFF; - unsigned long inSizeCur = blockSize + lz4dec.flg_bchecksum * 4 + 4; + unsigned int inSizeCur = blockSize + lz4dec.flg_bchecksum * 4 + 4; //grub_printf("read filepos %lX size %X inp %X\n", filepos, inSizeCur, lz4dec.inp); - inSizeCur = grub_read((grub_u64_t)(int)lz4dec.inp, inSizeCur, GRUB_READ); + inSizeCur = grub_read((grub_u64_t)(grub_size_t)lz4dec.inp, inSizeCur, GRUB_READ); lz4dec.inpSize = inSizeCur; //grub_printf(" inpSize %X filepos %lX\n", lz4dec.inpSize, filepos); lz4dec.inpPos = 0; // unsigned char *pNextBlockSize = lz4dec.inp + blockSize + lz4dec.flg_bchecksum * 4; - lz4dec.nextBlockSize = *(grub_u32_t*)(int)(lz4dec.inp + blockSize + lz4dec.flg_bchecksum * 4); + lz4dec.nextBlockSize = *(grub_u32_t*)(grub_size_t)(lz4dec.inp + blockSize + lz4dec.flg_bchecksum * 4); /* If dic is full, move 64K to beginning. */ if (lz4dec.dicPos + lz4dec.blockMaxSize > LZ4_DICBUFSIZE) @@ -281,8 +273,8 @@ dec_lz4_read(unsigned long long buf, unsigned long long len, unsigned long write /* Decompress LZ4 Block format*/ unsigned char *q = lz4dec.dic + lz4dec.dicPos; unsigned char *p = lz4dec.inp; - unsigned long outRem = LZ4_DICBUFSIZE - lz4dec.dicPos; - unsigned long inpRem = blockSize; + unsigned int outRem = LZ4_DICBUFSIZE - lz4dec.dicPos; + unsigned int inpRem = blockSize; while (1) { /* grub_printf("decompressing %X %X %X\n", q, p, inpRem); */ if (!inpRem) { @@ -292,7 +284,7 @@ dec_lz4_read(unsigned long long buf, unsigned long long len, unsigned long write /* read token */ unsigned char token = *(p++); --inpRem; /* read more literal length */ - unsigned long litlen = token >> 4; + unsigned int litlen = token >> 4; if (litlen == 15 && inpRem) { unsigned char c; do { @@ -320,9 +312,9 @@ dec_lz4_read(unsigned long long buf, unsigned long long len, unsigned long write } } /* read match offset */ - unsigned long matoff = (((unsigned long)p[0]) + ((unsigned long)p[1] << 8)); p += 2; inpRem -= 2; + unsigned int matoff = (((unsigned int)p[0]) + ((unsigned int)p[1] << 8)); p += 2; inpRem -= 2; /* read more match size */ - unsigned long matlen = (token & 15); + unsigned int matlen = (token & 15); if (matlen == 15) { unsigned char c; do { diff --git a/stage2/dec_lzma.c b/stage2/dec_lzma.c index d82b64be..7b2752c7 100644 --- a/stage2/dec_lzma.c +++ b/stage2/dec_lzma.c @@ -62,10 +62,11 @@ typedef unsigned short UInt16; typedef int Int32; typedef unsigned int UInt32; -typedef long long int Int64; -typedef unsigned long long int UInt64; +typedef long long Int64; +typedef unsigned long long UInt64; -typedef UInt32 SizeT; +//typedef UInt32 SizeT; +typedef grub_size_t SizeT; typedef int ptrdiff_t; typedef int Bool; @@ -443,7 +444,7 @@ And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without las = kMatchSpecLenStart + 1 : Flush marker = kMatchSpecLenStart + 2 : State Init Marker */ - +static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit); static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { UIntLzmaProb *probs = p->probs; @@ -741,6 +742,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte return SZ_OK; } +static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit); static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) { if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) @@ -767,6 +769,7 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) } } +static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit); static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { do @@ -800,6 +803,7 @@ typedef enum DUMMY_REP } ELzmaDummy; +static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize); static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) { UInt32 range = p->range; @@ -990,7 +994,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS return res; } - +static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data); static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) { p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); @@ -998,6 +1002,7 @@ static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) p->needFlush = 0; } +void LzmaDec_Init(CLzmaDec *p); void LzmaDec_Init(CLzmaDec *p) { p->dicFilePos = 0; @@ -1011,6 +1016,7 @@ void LzmaDec_Init(CLzmaDec *p) p->needInitState = 1; } +static void LzmaDec_InitStateReal(CLzmaDec *p); static void LzmaDec_InitStateReal(CLzmaDec *p) { UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); @@ -1023,6 +1029,7 @@ static void LzmaDec_InitStateReal(CLzmaDec *p) p->needInitState = 0; } +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { @@ -1157,32 +1164,41 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr #define cfm lzmadec.filec.fmax CLzmaDec lzmadec; - +/* +header: +00000000 5D 00 00 80 00 00 40 60 00 00 00 00 00 00 19 B0 +00000010 0D CD 06 0E 84 A2 6A 77 49 06 59 69 9D 7A E3 10 +偏移 字节 描述 +0 1 lzmadec.prop.lc,lp,pb 属性 +1 4 lzmadec.prop.dicSize 字典尺寸 +5 8 filemax 未压缩尺寸 +*/ +int dec_lzma_open (void); int dec_lzma_open (void) // return 1=success or 0=failure { - unsigned char header[13]; +// unsigned char header[13]; + unsigned char *header = dec_header; unsigned char d; - if (no_decompression) return 0; // Now it does not support openning more than 1 file at a time. // Make sure previously allocated memory blocks is freed. // Don't need this line if grub_close is called for every openned file before grub_open is called for next file. dec_lzma_close(); - - filepos = 0; - if (grub_read ((unsigned long long)(unsigned long)(char *)header, 13, 0xedde0d90) == 13) +// filepos = 0; + filepos = 13; +// if (grub_read ((unsigned long long)(grub_size_t)(char *)header, 13, 0xedde0d90) == 13) { // check header lzmadec.prop.dicSize = ReadUnalignedUInt32 (header + 1); - if (lzmadec.prop.dicSize == 0 || (0x80000000 % lzmadec.prop.dicSize)) + if (lzmadec.prop.dicSize == 0 || (0x80000000 % lzmadec.prop.dicSize)) //如果字典尺寸为零,或者字典尺寸大于2G,错误 { //grub_printf("Dictionary Size in LZMA header must be 2^n.\n"); goto fail; } - if (lzmadec.prop.dicSize < LZMA_DIC_MIN) + if (lzmadec.prop.dicSize < LZMA_DIC_MIN) //如果字典尺寸小于4k,错误 { //lzmadec.prop.dicSize = LZMA_DIC_MIN; goto fail; @@ -1194,16 +1210,14 @@ dec_lzma_open (void) lzmadec.prop.lc = d % 9; d /= 9; lzmadec.prop.lp = d % 5; lzmadec.prop.pb = d / 5; - ufm = ReadUnalignedUInt64 (header + 5); - if (ufm == -1ULL) + ufm = ReadUnalignedUInt64 (header + 5); //未压缩尺寸 + if (ufm == -1ULL) //如果未压缩尺寸=-1,错误 新的linux版本此参数就是-1!!! { - //grub_printf("Uncompressed Size should not be unknown.\n"); goto fail; } ufp = 0; dBS = lzmadec.prop.dicSize; - lzmadec.dic = (Byte*) grub_malloc (dBS); - //grub_printf("LZMA allocate memory\n"); + lzmadec.dic = (Byte*) grub_malloc (dBS);; if (lzmadec.dic) { lzmadec.numProbs = LzmaProps_GetNumProbs(&lzmadec.prop); @@ -1218,13 +1232,13 @@ dec_lzma_open (void) lzmadec.inpPos = 0; lzmadec.inpSize = 0; LzmaDec_Init(&lzmadec); - decomp_type = DECOMP_TYPE_LZMA; - compressed_file = 1; - cfm = filemax; filemax = ufm; - cfp = filepos; filepos = ufp; - gzip_filemax = cfm; - // success - //grub_printf("LZMA open success\n"); + decomp_type = DECOMP_TYPE_LZMA; //压缩类型 + compressed_file = 1; //压缩文件标记 + cfm = filemax; //保存压缩文件尺寸 + filemax = ufm; //返回未压缩文件尺寸 + cfp = filepos; //保存当前指针 + filepos = ufp; //返回0指针 + gzip_filemax = cfm; //返回压缩文件尺寸 errnum = 0; return 1; } @@ -1250,18 +1264,19 @@ dec_lzma_open (void) //grub_printf("LZMA allocate memory\n"); errnum = ERR_BAD_GZIP_HEADER; } + goto aaa; } - else +// else { fail: - //grub_printf("LZMA error reading header\n"); errnum = ERR_BAD_GZIP_HEADER; } - //grub_printf("LZMA open fail\n"); +aaa: filepos = 0; return 0; } +void dec_lzma_close (void); void dec_lzma_close (void) { @@ -1270,13 +1285,12 @@ dec_lzma_close (void) if (lzmadec.probs) { grub_free(lzmadec.probs); lzmadec.probs = 0; } } +unsigned long long dec_lzma_read (unsigned long long buf, unsigned long long len, unsigned int write); unsigned long long -dec_lzma_read (unsigned long long buf, unsigned long long len, unsigned long write) +dec_lzma_read (unsigned long long buf, unsigned long long len, unsigned int write) { UInt64 outTx, outSkip; UInt64 in_len = len, step_len = 0x800000ULL; - //grub_printf("LZMA read buf=%lX len=%lX dic=%X inp=%X\n",buf,len,lzmadec.dic,lzmadec.inp); - //getkey(); compressed_file = 0; @@ -1310,8 +1324,6 @@ dec_lzma_read (unsigned long long buf, unsigned long long len, unsigned long wri outSkip = ufp - dFP; if (len > 0x800000ULL) grub_printf("\r [0M/%ldM]",len>>20); - //grub_printf ("ufp=%lX dFP=%lX\n", ufp, dFP); - //getkey(); /* Copy uncompressed data from upper part of dic. dic[dicPos]...dic[dBS-1] */ if (dFP > ufp) @@ -1321,7 +1333,7 @@ dec_lzma_read (unsigned long long buf, unsigned long long len, unsigned long wri outTxCur = len; if (buf) { - grub_memmove64 (buf, (UInt32)(lzmadec.dic + outSkip + dBS), outTxCur); + grub_memmove64 (buf, (grub_size_t)(lzmadec.dic + outSkip + dBS), outTxCur); buf += outTxCur; } outSkip = 0; @@ -1335,22 +1347,16 @@ dec_lzma_read (unsigned long long buf, unsigned long long len, unsigned long wri SizeT inSizeCur, dicLimit; UInt32 dicPos; ELzmaStatus status; - //SRes res; /* Copy uncompressed data from lower part of dic. dic[0]...dic[dicPos-1] */ - //grub_printf ("Loop len=%lX outSkip=%lX dicPos=%X\n", - // len, outSkip, lzmadec.dicPos); - //getkey(); if (outSkip < lzmadec.dicPos) { UInt32 outTxCur = lzmadec.dicPos - outSkip; if (outTxCur > len) outTxCur = len; - //grub_printf ("Copy %X byte ", outTxCur); - //getkey(); if (buf) { - grub_memmove64 (buf, (UInt32)(lzmadec.dic + outSkip), outTxCur); + grub_memmove64 (buf, (grub_size_t)(lzmadec.dic + outSkip), outTxCur); buf += outTxCur; } outSkip = lzmadec.dicPos; @@ -1362,8 +1368,6 @@ dec_lzma_read (unsigned long long buf, unsigned long long len, unsigned long wri grub_printf("\r [%ldM/%ldM]",step_len>>20,in_len>>20); step_len += 0x800000ULL; } - //grub_printf (" remaining size %lX\n", len); - //getkey(); if (len == 0) break; } @@ -1374,11 +1378,7 @@ dec_lzma_read (unsigned long long buf, unsigned long long len, unsigned long wri UInt32 inTxCur = (filemax-filepos%X\n",lzmadec.inpSize); - //getkey(); + lzmadec.inpSize = grub_read((grub_size_t)(lzmadec.inp), inTxCur, 0xedde0d90); } inSizeCur = lzmadec.inpSize - lzmadec.inpPos; @@ -1386,8 +1386,6 @@ dec_lzma_read (unsigned long long buf, unsigned long long len, unsigned long wri if (lzmadec.dicPos == dBS) { lzmadec.dicPos = 0; - // if (outSkip < dBS) - // grub_printf ("\noutSkip(=%X) < dBS(=%X)\n", outSkip, dBS); outSkip -= dBS; } dicPos = lzmadec.dicPos; @@ -1395,15 +1393,10 @@ dec_lzma_read (unsigned long long buf, unsigned long long len, unsigned long wri dBS : dicPos + len; /* Do decompression. */ - //grub_printf ("DecodeToDic dicPos=%X limit=%X inPos=%X inSize=%X ", - // dicPos, dicLimit, lzmadec.inpPos, inSizeCur); - //getkey(); status = LZMA_STATUS_NOT_SPECIFIED; /*res =*/ LzmaDec_DecodeToDic (&lzmadec, dicLimit, lzmadec.inp + lzmadec.inpPos, &inSizeCur, LZMA_FINISH_ANY, &status); - //grub_printf ("->%X\n", inSizeCur); - //getkey(); lzmadec.inpPos += inSizeCur; if (inSizeCur == 0 && lzmadec.dicPos == dicPos) { @@ -1425,8 +1418,6 @@ dec_lzma_read (unsigned long long buf, unsigned long long len, unsigned long wri * fileu is not used */ - //grub_printf ("LZMA read end %lX\n", outTx); - //getkey(); if (in_len > 0x800000ULL) grub_printf("\r \r"); return outTx; diff --git a/stage2/dec_vhd.c b/stage2/dec_vhd.c index e265b38b..00270aee 100644 --- a/stage2/dec_vhd.c +++ b/stage2/dec_vhd.c @@ -27,55 +27,79 @@ #ifndef NO_DECOMPRESSION -typedef struct VHDFooter { - unsigned char cookie[8];//string conectix - grub_u32_t features; - grub_u32_t fileFormatVersion; - grub_u64_t dataOffset; - grub_u32_t timeStamp; - unsigned char creatorApplication[4]; - grub_u32_t creatorVersion; - grub_u32_t creatorHostOS; - grub_u64_t originalSize; - grub_u64_t currentSize; +typedef struct VHDFooter { //VHD页脚表 尺寸512 + unsigned char cookie[8]; //标记 字符串conectix + grub_u32_t features; //特征 + grub_u32_t fileFormatVersion; //文件格式版本 + grub_u64_t dataOffset; //数据偏移 结构的起始绝对字节位置,如果是动态磁盘,这表明了dd_hdr 的物理字节位置。如果是固定磁盘,似乎总是0xFFFFFFFF + grub_u32_t timeStamp; //时间戳 + unsigned char creatorApplication[4]; //创建者应用程序 + grub_u32_t creatorVersion; //创建者版本 + grub_u32_t creatorHostOS; //创建者主机操作系统 + grub_u64_t originalSize; //原始尺寸 虚拟出来的磁盘的可用寻址空间 + grub_u64_t currentSize; //当前尺寸 struct { - unsigned short cylinder; - unsigned char heads; - unsigned char sectorsPerTrack; + unsigned short cylinder; //柱面 + unsigned char heads; //磁头 + unsigned char sectorsPerTrack; //扇区 } diskGeometry; - grub_u32_t diskType; - grub_u32_t checksum; - unsigned char uniqueId[16]; - unsigned char savedState; - unsigned char reserved[427]; -} VHDFooter; - -#define VHD_FOOTER_COOKIE 0x78697463656E6F63ULL -#define VHD_DYNAMIC_COOKIE 0x6573726170737863ULL - -#define VHD_DISKTYPE_FIXED 2 -#define VHD_DISKTYPE_DYNAMIC 3 -#define VHD_DISKTYPE_DIFFERENCE 4 - -typedef struct VHDDynamicDiskHeader { - unsigned char cookie[8];//string cxsparse - grub_u64_t dataOffset; - grub_u64_t tableOffset; - grub_u32_t headerVersion; - grub_u32_t maxTableEntries; - grub_u32_t blockSize; - grub_u32_t checksum; - unsigned char parentUniqueID[16]; - grub_u32_t parentTimeStamp; - unsigned char reserved[4]; - unsigned char parentUnicodeName[512]; - unsigned char parentLocaterEntry[8][24]; - unsigned char reserved2[256]; -} VHDDynamicDiskHeader; + grub_u32_t diskType; //磁盘类型 2固定, 3动态, 4差分 + grub_u32_t checksum; //校验和 整个扇区所有字节(当然一开始不包括 checksum 本身)相加得到32位数,再按位取反. 计算范围为从开始的512字节 + unsigned char uniqueId[16]; //唯一Id + unsigned char savedState; //状态数据 + unsigned char reserved[427]; //保留 +} __attribute__ ((packed)) VHDFooter; -typedef struct VHDFileControl VHDFileControl; +#define VHD_FOOTER_COOKIE 0x78697463656E6F63ULL //VHD页脚表标记 字符串conectix +#define VHD_DYNAMIC_COOKIE 0x6573726170737863ULL //VHD动态磁盘头标记 字符串cxsparse + +#define VHD_DISKTYPE_FIXED 2 //固定类型 +#define VHD_DISKTYPE_DYNAMIC 3 //动态类型 +#define VHD_DISKTYPE_DIFFERENCE 4 //差分类型 + +typedef struct VHDDynamicDiskHeader { //VHD动态磁盘头 尺寸1024 + unsigned char cookie[8]; //标记 字符串cxsparse + grub_u64_t dataOffset; //数据偏移 总设置为0xFFFFFFFF + grub_u64_t tableOffset; //BAT结构偏移 在$VHD文件中的绝对字节位置 + grub_u32_t headerVersion; //版本 + grub_u32_t maxTableEntries; //BAT条目的最大值,实际上每个bat条目,就相当于一个块 + grub_u32_t blockSize; //块大小,几乎总是2MB + grub_u32_t checksum; //校验和 与VHD页脚表中的计算方式相同。计算范围为从开始的1024字节 + unsigned char parentUniqueID[16]; //父vhd的uuid 差异磁盘中非常重要 + grub_u32_t parentTimeStamp; //父磁盘的修改时间 + unsigned char reserved[4]; //保留 + unsigned char parentUnicodeName[512]; //父磁盘的unicode名称。可以更快地找到父磁盘,但找到后,还需通过uuid校验。 + unsigned char parentLocaterEntry[8][24]; //用来记录在不同平台上的父磁盘的名称 + unsigned char reserved2[256]; //保留 +} __attribute__ ((packed)) VHDDynamicDiskHeader; -struct VHDFileControl { +#if VHD_DIFFERENCE +typedef struct VHDFileControl { //VHD控制文件 + struct VHDFileControl *next; //下一个 + char *blockAllocationTable; //BAT指针 + char *blockBitmapAndData; //块缓存指针(也是块位图指针) + char *blockData; //块数据指针 + struct fragment_map_slot *SectorSequence; //扇区序列 + unsigned long long volumeSize; //解压后文件尺寸 + unsigned int currentBlockOffset; //当前块缓存 + unsigned int blockLBA; //逻辑块 + unsigned int blockSize; //块尺寸 + unsigned char blockSizeLog2; //块尺寸2的幂 + unsigned short blockBitmapSize; //块位图尺寸 + unsigned char diskType; //磁盘类型 + unsigned char from_drive; //from驱动器 + unsigned char to_drive; //to驱动器 + unsigned char index; //索引 + unsigned char start; //起始 + unsigned char end; //结束 + unsigned short fill0; + unsigned char fill1; +} __attribute__ ((packed)) VHDFileControl; + +typedef struct VHDFileControl VHDFileControl; +struct VHDFileControl *parentVHDFC; +#else +typedef struct VHDFileControl { unsigned long long cFileMax; unsigned long long volumeSize; unsigned long long tableOffset; @@ -88,13 +112,68 @@ struct VHDFileControl { unsigned char *blockBitmapAndData; unsigned char *blockData; unsigned long currentBlockOffset; - struct VHDFileControl *parentVHDFC; -}; +} __attribute__ ((packed)) VHDFileControl; + +typedef struct VHDFileControl VHDFileControl; +struct VHDFileControl *vhdfc = 0; +#endif + +#if VHD_DIFFERENCE +struct fragment_map_slot *SectorSequence; +VHDFileControl *vhdfc_data; +int start; +int vhd_vhdfc_index = -1; +unsigned char from_log2_sector; +unsigned char to_log2_sector; +unsigned short to_block_size; + +unsigned int log2pot32(unsigned int x); +grub_u32_t bswap_32(grub_u32_t *x); +void bswap_64(grub_u64_t *x); +void vhd_footer_in(VHDFooter *footer); +void vhd_header_in(VHDDynamicDiskHeader *header); + +unsigned int log2pot32(unsigned int x); +unsigned int log2pot32(unsigned int x) { + // x must be power of two + return ((x & 0xFFFF0000) ? 16 : 0) | ((x & 0xFF00FF00) ? 8 : 0) | ((x & 0xF0F0F0F0) ? 4 : 0) | ((x & 0xCCCCCCCC) ? 2 : 0) | ((x & 0xAAAAAAAA) ? 1 : 0); +} + +grub_u32_t bswap_32(grub_u32_t *x); +grub_u32_t bswap_32(grub_u32_t *x) +{ + grub_u32_t i = *x; + *x = ((i & 0xFF000000) >> 24) | + ((i & 0x00FF0000) >> 8) | + ((i & 0x0000FF00) << 8) | + ((i & 0x000000FF) << 24); + return *x; +} -extern unsigned long map_image_HPC; -extern unsigned long map_image_SPT; +void bswap_64(grub_u64_t *x); +void bswap_64(grub_u64_t *x) //字节交换 大尾转小尾 +{ + grub_u32_t hi = (grub_u32_t)*x; + grub_u32_t lo = (grub_u32_t)(*x >> 32); + *x = ((grub_u64_t)bswap_32(&hi)<<32)|bswap_32(&lo); +} + +void vhd_footer_in(VHDFooter *footer); +void vhd_footer_in(VHDFooter *footer) //VHD页脚表in +{ + bswap_64(&footer->dataOffset); //数据偏移 + bswap_64(&footer->currentSize); //当前尺寸 + bswap_32(&footer->diskType); //磁盘类型 +} -VHDFileControl *vhdfc; +void vhd_header_in(VHDDynamicDiskHeader *header); +void vhd_header_in(VHDDynamicDiskHeader *header) //VHD动态磁盘头in +{ + bswap_64(&header->tableOffset); //BAT结构偏移 + bswap_32(&header->maxTableEntries); //BAT条目的最大值 + bswap_32(&header->blockSize); //块尺寸 +} +#else unsigned int log2pot32(unsigned long x); grub_u32_t bswap_32(grub_u32_t *x); @@ -126,50 +205,323 @@ void bswap_64(grub_u64_t *x) void vhd_footer_in(VHDFooter *footer) { -// bswap_32(&footer->features); -// bswap_32(&footer->fileFormatVersion); - bswap_64(&footer->dataOffset); -// bswap_32(&footer->timeStamp); -// bswap_32(&footer->creatorVersion); -// bswap_32(&footer->creatorHostOS); -// bswap_64(&footer->originalSize); - bswap_64(&footer->currentSize); - bswap_32(&footer->diskType); -// bswap_32(&footer->checksum); +// bswap_64(&footer->dataOffset); +// bswap_64(&footer->currentSize); +// bswap_32(&footer->diskType); + int offse1 = offsetof(VHDFooter, dataOffset); + int offse2 = offsetof(VHDFooter, currentSize); + int offse3 = offsetof(VHDFooter, diskType); + bswap_64((grub_u64_t *)((char *)footer + offse1)); + bswap_64((grub_u64_t *)((char *)footer + offse2)); + bswap_32((grub_u32_t *)((char *)footer + offse3)); } void vhd_header_in(VHDDynamicDiskHeader *header) { -// bswap_64(&header->dataOffset); - bswap_64(&header->tableOffset); -// bswap_32(&header->headerVersion); - bswap_32(&header->maxTableEntries); - bswap_32(&header->blockSize); -// bswap_32(&header->checksum); -// bswap_32(&header->parentTimeStamp); +// bswap_64(&header->tableOffset); +// bswap_32(&header->maxTableEntries); +// bswap_32(&header->blockSize); + int offse1 = offsetof(VHDDynamicDiskHeader, tableOffset); + int offse2 = offsetof(VHDDynamicDiskHeader, maxTableEntries); + int offse3 = offsetof(VHDDynamicDiskHeader, blockSize); + bswap_64((grub_u64_t *)((char *)header + offse1)); + bswap_32((grub_u32_t *)((char *)header + offse2)); + bswap_32((grub_u32_t *)((char *)header + offse3)); } +#endif - +void dec_vhd_close(void); void dec_vhd_close(void) { +#if VHD_DIFFERENCE if (vhdfc) { if (vhdfc->blockAllocationTable) { grub_free(vhdfc->blockAllocationTable); + vhdfc->blockAllocationTable = 0; } if (vhdfc->blockBitmapAndData) { grub_free(vhdfc->blockBitmapAndData); + vhdfc->blockBitmapAndData = 0; } grub_free(vhdfc); - map_image_HPC = 0; - map_image_SPT = 0; + vhdfc = 0; + } + + if (parentVHDFC) { + if (parentVHDFC->blockAllocationTable) { + grub_free(parentVHDFC->blockAllocationTable); + parentVHDFC->blockAllocationTable = 0; + } + if (parentVHDFC->blockBitmapAndData) { + grub_free(parentVHDFC->blockBitmapAndData); + parentVHDFC->blockBitmapAndData = 0; + } + grub_free(parentVHDFC); + parentVHDFC = 0; + } +#else + if (vhdfc) + { + if (vhdfc->blockAllocationTable) + grub_free(vhdfc->blockAllocationTable); + if (vhdfc->blockBitmapAndData) + grub_free(vhdfc->blockBitmapAndData); + grub_free(vhdfc); + vhdfc = 0; + } +#endif +} + +#if VHD_DIFFERENCE +VHDFileControl *get_vhdfc_by_index(int index); +VHDFileControl * +get_vhdfc_by_index(int index) +{ + VHDFileControl *v; + for (v = vhdfc_data; v; v = v->next) + { + if (v->index == index) + return v; + } + return 0; +} + +char *parentName; +char parentUniqueID[16]; +int fill_vhdfc(int index, int vhd_start, VHDFooter *footer, VHDDynamicDiskHeader *dynaheader, VHDFileControl *vhdfc); +int +fill_vhdfc(int index, int vhd_start, VHDFooter *footer, VHDDynamicDiskHeader *dynaheader, VHDFileControl *vhdfc) //填充VHD控制文件 +{ + int i = 0; + struct fragment_map_slot* q = SectorSequence; + struct fragment *data = (struct fragment *)&q->fragment_data; + + //读VHD页脚表。 动态及差分VHD,起始1扇区是VHD页脚表。 + grub_SectorSequence_readwrite (current_drive, data, from_log2_sector, to_log2_sector, 0, sizeof(VHDFooter), (char *)footer, 0, GRUB_READ); + grub_u64_t* a = (grub_u64_t*)footer->cookie; + if (*a!=VHD_FOOTER_COOKIE) //比较VHD页脚表标记 + { + if (vhd_start) //如果索引为零并且没有页脚表,则可能不是VHD,也可能是固定VHD + goto quit; + //查固定类型的父VHD页脚表 + while (data[i].start_sector) //查找最后块 固定VHD的结构表在最后一个扇区。 + i++; + + vhd_read = 1; + grub_efidisk_readwrite (current_drive, data[i-1].start_sector + data[i-1].sector_count - 1, + sizeof(VHDFooter), (char *)footer, GRUB_READ); + vhd_read = 0; + + if (*(grub_u64_t*)footer->cookie != VHD_FOOTER_COOKIE) + goto quit; + } + + vhd_footer_in(footer); + if (!vhd_start && grub_memcmp ((const char *)parentUniqueID, (const char *)footer->uniqueId, 16)) //比较父VHD的guid + { + printf_debug ("GUID of parent VHD does not match.\n"); + goto quit; + } + + if (footer->diskType == VHD_DISKTYPE_FIXED) //磁盘类型是固定 + goto bbb; + if (footer->dataOffset + sizeof(VHDDynamicDiskHeader) > filemax) //数据偏移+VHD页脚表 > filemax, 退出 + goto quit; + + //读VHD动态磁盘头。 + filepos = footer->dataOffset; + grub_SectorSequence_readwrite (current_drive, data, from_log2_sector, to_log2_sector, filepos >> 9, + sizeof(VHDDynamicDiskHeader), (char *)dynaheader, 0, GRUB_READ); + +bbb: +/* +动态、差分缓存基址 |------0x200------|----------------------------------0x200000----------------------------------| + 位图起始 数据起始 + +固定(差分之父)缓存基址 |----------------------------------0x200000----------------------------------| + 数据起始 +*/ + + //设置VHD控制文件 + vhd_header_in(dynaheader); + vhdfc->diskType = footer->diskType; + vhdfc->volumeSize = footer->currentSize; + + if (footer->diskType == VHD_DISKTYPE_FIXED) //如果父磁盘类型是固定 + { + vhdfc->blockSize = 0x200000; + vhdfc->blockBitmapSize = 0; + } + else + { + vhdfc->blockSize = 0x200000; + vhdfc->blockBitmapSize = 0x200; + } + + vhdfc->blockSizeLog2 = 0x15; + vhdfc->currentBlockOffset = -1LL; + vhdfc->from_drive = 0x80 + harddrives_orig; + vhdfc->blockBitmapAndData = grub_malloc(vhdfc->blockBitmapSize + vhdfc->blockSize); + vhdfc->blockData = vhdfc->blockBitmapAndData + vhdfc->blockBitmapSize; + vhdfc->to_drive = current_drive; + vhdfc->SectorSequence = SectorSequence; + + if (vhd_start) + start = index; + + vhdfc->start = start; + vhdfc->index = index; + + if (footer->diskType != VHD_DISKTYPE_DIFFERENCE) //如果父磁盘类型不是差分 + vhdfc->end = index; + if (footer->diskType == VHD_DISKTYPE_FIXED) //如果父磁盘类型是固定 + goto ccc; + + unsigned int batSize = (dynaheader->maxTableEntries * 4 + 511)&(-512LL); + vhdfc->blockAllocationTable = grub_malloc(batSize); + + //读BAT结构 + filepos = dynaheader->tableOffset; + grub_SectorSequence_readwrite (vhdfc->to_drive, data, from_log2_sector, to_log2_sector, filepos >> 9, batSize, + vhdfc->blockAllocationTable, 0, GRUB_READ); + + if (footer->diskType == VHD_DISKTYPE_DIFFERENCE) //差分 + { + grub_memmove(&parentUniqueID, &dynaheader->parentUniqueID, 16); + //获取父VHD文件名 + GetParentUtf8Name (parentName, (grub_uint16_t *)&dynaheader->parentUnicodeName); } + +ccc: + return vhdfc->diskType; + +quit: + return 0; } +#endif +int dec_vhd_open(void); int dec_vhd_open(void) /* return 1=success or 0=failure */ { +#if VHD_DIFFERENCE + int diskType; + struct grub_disk_data *d; //磁盘数据 + VHDFileControl *v/*, *vhdfc*/; //VHD控制文件 + VHDFooter *footer = 0; + VHDDynamicDiskHeader *dynaheader = 0; + footer = grub_zalloc (sizeof(VHDFooter)); //分配页脚表 + if (!footer) + return 0; + dynaheader = grub_zalloc (sizeof(VHDDynamicDiskHeader)); //分配动态磁盘头 + if (!dynaheader) + goto quit; + parentName = grub_zalloc(256); + + if (filemax < 0x10000) return 0;//file is to small + /* Now it does not support openning more than 1 file at a time. 现在它不支持一次打开多个文件。 + Make sure previously allocated memory blocks is freed. 确保先前分配的内存块已释放。 + Don't need this line if grub_close is called for every openned file before grub_open is called for next file. */ + //如果在为下一个文件调用grub_open之前为每个打开的文件调用grub_close,则不需要此行。 + + if (vhd_file_name == 0) + goto quit; + + char *filename = vhd_file_name; + skip_to(0x200,filename); + char *suffix = &filename[strlen (filename) - 3]; //取尾缀 + if ((suffix[0] | 0x20) != 'v' || (suffix[1] | 0x20) != 'h' || (suffix[2] | 0x20) != 'd') + goto quit; + + dec_vhd_close(); + if (current_drive == 0x21 || current_drive == 0x7f) //为了网起 2024-12-12 + { + from_log2_sector = 9; //未考虑4k磁盘 + to_log2_sector = 9; + to_block_size = 512; + goto bbb; + } + d = get_device_by_drive (current_drive,0); + if (!d) + return 0; + from_log2_sector = 9; //未考虑4k磁盘 + to_log2_sector = d->from_log2_sector; + to_block_size = 1 << to_log2_sector; +bbb: + vhd_vhdfc_index++; + GetSectorSequence (vhd_file_name, &SectorSequence, 1); + if (!SectorSequence) + { + printf_debug ("Failed to obtain file sector sequence.\n"); + goto quit; + } + + vhdfc = (VHDFileControl*) grub_zalloc(sizeof(VHDFileControl)); //分配控制文件 + if (!vhdfc) + goto quit; + if (!vhd_vhdfc_index) + vhdfc_data = vhdfc; + else + { + for (v = vhdfc_data; v; v = v->next) + { + if (!v->next) + { + v->next = vhdfc; + break; + } + } + } + + diskType = fill_vhdfc (vhd_vhdfc_index,1,footer,dynaheader,vhdfc); + if (diskType == 0 || diskType == VHD_DISKTYPE_FIXED) //失败或固定 + goto quit; + + //如果是差分 + if (diskType == VHD_DISKTYPE_DIFFERENCE) + { +aaa: + vhd_vhdfc_index++; + GetSectorSequence (parentName, &SectorSequence, 0); //获得父VHD文件扇区序列 + if (!SectorSequence) + { + printf_debug ("Failed to obtain file sector sequence.\n"); + goto quit; + } + + vhdfc = (VHDFileControl*) grub_zalloc(sizeof(VHDFileControl)); //分配控制文件 + if (!vhdfc) + goto quit; + for (v = vhdfc_data; v; v = v->next) + { + if (!v->next) + { + v->next = vhdfc; + break; + } + } + + diskType = fill_vhdfc (vhd_vhdfc_index,0,footer,dynaheader,vhdfc); + if (diskType == VHD_DISKTYPE_DIFFERENCE) //如果父磁盘类型是差分 + { + goto aaa; + } + } + + compressed_file = 1; //压缩文件 + decomp_type = DECOMP_TYPE_VHD; //解压缩类型: VHD + filemax = vhdfc->volumeSize; //压缩文件尺寸 + +quit: + filepos = 0; +// grub_free(parentName); +// grub_free(dynaheader); + grub_free(footer); + errnum = ERR_NONE; + return compressed_file; +#else VHDFooter footer; VHDDynamicDiskHeader dynaheader; @@ -177,104 +529,298 @@ dec_vhd_open(void) /* Now it does not support openning more than 1 file at a time. Make sure previously allocated memory blocks is freed. Don't need this line if grub_close is called for every openned file before grub_open is called for next file. */ - dec_vhd_close(); +// dec_vhd_close(); memset(&footer, 0, sizeof(footer)); memset(&dynaheader, 0, sizeof(dynaheader)); - int bytesread = (int)grub_read((unsigned long)&footer, 0x200, 0xedde0d90); - bytesread = bytesread; - //if (bytesread < 511) { - // grub_printf("bytesread %d < 511\n",bytesread); - // goto quit; - //} + grub_read((unsigned long long)(grub_size_t)&footer, 8, 0xedde0d90); +//printf ("dec_vhd_open-1,%x\n",*(grub_u64_t*)&footer.cookie);//786974... if (*(grub_u64_t*)&footer.cookie!=VHD_FOOTER_COOKIE) { // grub_printf("cookie %lX != %lX\n", footer.cookie, VHD_FOOTER_COOKIE); goto quit; } + filepos = 0; + grub_read((unsigned long long)(grub_size_t)&footer, 0x200, 0xedde0d90); vhd_footer_in(&footer); - +//printf ("dec_vhd_open-2,%x\n",footer.diskType); if (footer.diskType != VHD_DISKTYPE_DYNAMIC) { /* Differencing disk and unknown diskType are not supported */ goto quit; } - -// if (footer.diskType == VHD_DISKTYPE_DYNAMIC) { - if (footer.dataOffset + sizeof(dynaheader) > filemax) { +//printf ("dec_vhd_open-3,%x,%x,%x\n",footer.dataOffset,sizeof(dynaheader),filemax); + if (footer.dataOffset + sizeof(dynaheader) > filemax) { // grub_printf("footer dataOffset %lX\n", dataOffset); goto quit; - } - filepos = footer.dataOffset; - bytesread = (int)grub_read((unsigned long)&dynaheader, sizeof(dynaheader), 0xedde0d90); -// } + } + filepos = footer.dataOffset; + grub_read((unsigned long long)(grub_size_t)&dynaheader, sizeof(dynaheader), 0xedde0d90); vhdfc = (VHDFileControl*) grub_malloc(sizeof(VHDFileControl)); if (!vhdfc) { goto quit; } - +//printf ("dec_vhd_open-4\n"); memset(vhdfc, 0, sizeof(VHDFileControl)); vhd_header_in(&dynaheader); vhdfc->cFileMax = filemax; vhdfc->volumeSize = footer.currentSize; vhdfc->diskType = footer.diskType; - //if (vhdfc->diskType == VHD_DISKTYPE_FIXED) { - //} else if (vhdfc->diskType == VHD_DISKTYPE_DYNAMIC) { - vhdfc->tableOffset = dynaheader.tableOffset; - vhdfc->blockSize = dynaheader.blockSize; - vhdfc->blockSizeLog2 = log2pot32(vhdfc->blockSize); - vhdfc->batEntries = dynaheader.maxTableEntries; - unsigned long batSize = (vhdfc->batEntries * 4 + 511)&(-512LL); - vhdfc->blockAllocationTable = grub_malloc(batSize); - vhdfc->blockBitmapSize = vhdfc->blockSize / (512 * 8); - vhdfc->blockBitmapAndData = grub_malloc(vhdfc->blockBitmapSize + vhdfc->blockSize); - vhdfc->blockData = vhdfc->blockBitmapAndData + vhdfc->blockBitmapSize; - filepos = vhdfc->tableOffset; - grub_read((grub_u64_t)(int)vhdfc->blockAllocationTable, batSize, GRUB_READ); - vhdfc->currentBlockOffset = -1LL; - //} - map_image_HPC = footer.diskGeometry.heads; - map_image_SPT = footer.diskGeometry.sectorsPerTrack; + vhdfc->tableOffset = dynaheader.tableOffset; + vhdfc->blockSize = dynaheader.blockSize; + vhdfc->blockSizeLog2 = log2pot32(vhdfc->blockSize); + vhdfc->batEntries = dynaheader.maxTableEntries; + unsigned long batSize = (vhdfc->batEntries * 4 + 511)&(-512LL); + vhdfc->blockAllocationTable = grub_malloc(batSize); + vhdfc->blockBitmapSize = vhdfc->blockSize / (512 * 8); + vhdfc->blockBitmapAndData = grub_malloc(vhdfc->blockBitmapSize + vhdfc->blockSize); + vhdfc->blockData = vhdfc->blockBitmapAndData + vhdfc->blockBitmapSize; + filepos = vhdfc->tableOffset; + grub_read((unsigned long long)(grub_size_t)vhdfc->blockAllocationTable, batSize, GRUB_READ); + vhdfc->currentBlockOffset = -1LL; compressed_file = 1; decomp_type = DECOMP_TYPE_VHD; filemax = vhdfc->volumeSize; +//printf ("dec_vhd_open-ok,%x\n",compressed_file); quit: filepos = 0; - +//printf ("dec_vhd_open-end,%x\n",compressed_file); errnum = ERR_NONE; return compressed_file; +#endif } +#if VHD_DIFFERENCE +static void read_differ_itself (int index1, int index2); +static void +read_differ_itself (int index1, int index2) +{ + unsigned int i, j, k, test; + VHDFileControl *vhdfc1, *vhdfc2; + vhdfc1 = get_vhdfc_by_index(index1); + vhdfc2 = get_vhdfc_by_index(index2); + unsigned int *bitmap = (unsigned int *)vhdfc1->blockBitmapAndData; + + for (i = 0; i < 0x80; i++) //1扇区0x80块 i是块号 + { + test = 0x80000000; //测试位 + j = 0; //块内位移 + + if (bitmap[i] != 0) + { + bswap_32(&bitmap[i]); + while (test) + { + if (bitmap[i] & test) //bitmap位为1, 直接读取子VHD + { + k = 0; //读扇区数 + while (bitmap[i] & test) //把bitmap位为1的扇区一起读 + { + test >>= 1; //下一测试位 + k++; //连续的读扇区数 + } + grub_memmove64((unsigned long long)(grub_size_t)(vhdfc2->blockData + (((i << 5) + j) << 9)), + (unsigned long long)(grub_size_t)(vhdfc1->blockData + (((i << 5) + j) << 9)), + 512 * k); + j += k; //块内位移数 + } + else //bitmap位为0, 跳过 + { + test >>= 1; + j++; + } + } + } + } +} +#endif + +int current_index = -1; +unsigned long long dec_vhd_read(unsigned long long buf, unsigned long long len, unsigned int write); unsigned long long -dec_vhd_read(unsigned long long buf, unsigned long long len, unsigned long write) +dec_vhd_read(unsigned long long buf, unsigned long long len, unsigned int write) { +#if VHD_DIFFERENCE + unsigned long long ret = 0; + int i, index = 0, parent = 0; + struct grub_disk_data *d; + struct fragment_map_slot *q; + struct fragment *data; + VHDFileControl *v; //VHD控制文件 +// compressed_file = 0; + + d = get_device_by_drive (current_drive,0); + if (!d) + return 0; + + if (vhd_file_name) + { + from_log2_sector = 9; //未考虑4k磁盘 + to_log2_sector = d->from_log2_sector; + to_block_size = 1 << to_log2_sector; + for (v = vhdfc_data; v; v = v->next) + { + if (v->index == vhd_vhdfc_index) + break; + } + index = v->start; + parent = vhd_vhdfc_index; + } + else + { + for (v = vhdfc_data; v; v = v->next) + { + if (v->from_drive == current_drive && v->end) + { + index = v->start; + parent = v->end; + break; + } + } + from_log2_sector = d->from_log2_sector; + to_log2_sector = d->to_log2_sector; + to_block_size = d->to_block_size; + } + + VHDFileControl *vhdfc_index, *vhdfc_parent; + vhdfc_index = get_vhdfc_by_index(index); + vhdfc_parent = get_vhdfc_by_index(parent); + + if (filepos + len > vhdfc_index->volumeSize) + len = (filepos <= vhdfc_index->volumeSize) ? vhdfc_index->volumeSize - filepos : 0; + // VHD_DISKTYPE_DYNAMIC + if (write == GRUB_WRITE) + { + errnum = ERR_WRITE_GZIP_FILE; + return 0; + } + unsigned long long uFilePos = filepos; + if (len > vhdfc_index->volumeSize - uFilePos) + len = vhdfc_index->volumeSize - uFilePos; + errnum = ERR_NONE; + unsigned long long rem = len; + unsigned int blockNumber; + unsigned long long blockOffset; + unsigned int offsetInBlock; + unsigned int txLen; + + while (rem) + { + blockNumber = (unsigned int)(uFilePos >> vhdfc_index->blockSizeLog2); //块号 + blockOffset = (unsigned long long)blockNumber << vhdfc_index->blockSizeLog2; //块起始 + offsetInBlock = (unsigned int)(uFilePos - blockOffset); //在块内偏移 + txLen = (rem < vhdfc_index->blockSize - offsetInBlock) ? rem : vhdfc_index->blockSize - offsetInBlock; //块内读尺寸 + vhdfc_index->blockLBA = *(grub_u32_t*)(vhdfc_index->blockAllocationTable + blockNumber * 4); //块逻辑扇区 + bswap_32(&vhdfc_index->blockLBA); //大尾转小尾 +#if 0 + if (vhdfc_index->diskType == VHD_DISKTYPE_DYNAMIC) //如果是动态 + { + if (current_index != index || blockOffset != vhdfc_index->currentBlockOffset) + { + if (vhdfc_index->blockLBA == 0xFFFFFFFF) + grub_memset64((unsigned long long)(grub_size_t)vhdfc_index->blockData, 0, vhdfc_index->blockBitmapSize); + else + { + q = vhdfc_index->SectorSequence; + data = (struct fragment *)&q->fragment_data; + grub_SectorSequence_readwrite (vhdfc_index->to_drive, data, from_log2_sector, to_log2_sector, vhdfc_index->blockLBA, + vhdfc_index->blockBitmapSize + vhdfc_index->blockSize, vhdfc_index->blockBitmapAndData, 0, GRUB_READ); + } + + vhdfc_index->currentBlockOffset = blockOffset; + current_index = index; + } + grub_memmove64(buf, (grub_size_t)(vhdfc_index->blockData + offsetInBlock), txLen); + } + else //如果是差分 +#endif + { +/* +vhdfc_index:是用户最后生成的差分磁盘。由用户使用map映射,挂钩,分配驱动器号。 +vhdfc_parent:是终极父磁盘,可能是固定磁盘或者动态磁盘。由本程序使用GetSectorSequence函数探测生成。 +vhdfc_i:中间的磁盘都是差分磁盘。由本程序使用GetSectorSequence函数探测生成。 +*/ + //读磁盘,更新缓存区 + if (current_index != index || blockOffset != vhdfc_index->currentBlockOffset) //如果块偏移不等于当前块偏移 + { + //确定磁盘的逻辑块,然后读父磁盘到各自的父缓存 + for (i = index; i <= parent; i++) + { + VHDFileControl *vhdfc_i; + vhdfc_i = get_vhdfc_by_index(i); + if (vhdfc_i->diskType == VHD_DISKTYPE_FIXED) //如果父磁盘类型是固定 + vhdfc_i->blockLBA = blockOffset >> 9; //父块逻辑扇区 + else + { + vhdfc_i->blockLBA = *(grub_u32_t*)(vhdfc_i->blockAllocationTable + blockNumber * 4); //父块逻辑扇区 + bswap_32(&vhdfc_i->blockLBA); + } + + if (vhdfc_i->blockLBA != 0xFFFFFFFF) //如果逻辑块不是‘-1’ + { + q = vhdfc_i->SectorSequence; + data = (struct fragment *)&q->fragment_data; + grub_SectorSequence_readwrite (vhdfc_i->to_drive, data, from_log2_sector, to_log2_sector, vhdfc_i->blockLBA, + vhdfc_i->blockBitmapSize + vhdfc_i->blockSize, vhdfc_i->blockBitmapAndData, 0, GRUB_READ); + } + else if (vhdfc_i->diskType == VHD_DISKTYPE_DYNAMIC) //如果父类型是动态 + { + grub_memset64((unsigned long long)(grub_size_t)vhdfc_i->blockData, 0, vhdfc_i->blockSize); //填充0 + } + } + + //各差分磁盘穿透进父磁盘进行补差 + for (i = parent - 1; i >= index; i--) + { + VHDFileControl *vhdfc_i; + vhdfc_i = get_vhdfc_by_index(i); + if (vhdfc_i->blockLBA != 0xFFFFFFFF) + read_differ_itself (i, parent); + } + vhdfc_index->currentBlockOffset = blockOffset; + current_index = index; + } + + grub_memmove64(buf, (unsigned long long)(grub_size_t)(vhdfc_parent->blockData + offsetInBlock), txLen); + } + + buf += txLen; + uFilePos += txLen; + rem -= txLen; + ret += txLen; + } + + filepos = uFilePos; +// compressed_file = 1; +// filemax = vhdfc->volumeSize; + return ret; +#else +//printf ("dec_vhd_read-0\n"); unsigned long long ret = 0; compressed_file = 0; filemax = vhdfc->cFileMax; if (filepos + len > vhdfc->volumeSize) len = (filepos <= vhdfc->volumeSize) ? vhdfc->volumeSize - filepos : 0; - //if (vhdfc->diskType == VHD_DISKTYPE_FIXED) { - // ret = grub_read(buf, len, write); - //} else { - // VHD_DISKTYPE_DYNAMIC - if (write == GRUB_WRITE) { - errnum = ERR_WRITE_GZIP_FILE; - return 0; - } - unsigned long long uFilePos = filepos; - if (len > vhdfc->volumeSize - uFilePos) - len = vhdfc->volumeSize - uFilePos; - errnum = ERR_NONE; - unsigned long long rem = len; - while (rem) { + // VHD_DISKTYPE_DYNAMIC + if (write == GRUB_WRITE) { + errnum = ERR_WRITE_GZIP_FILE; + return 0; + } +//printf ("dec_vhd_read-1\n"); + unsigned long long uFilePos = filepos; + if (len > vhdfc->volumeSize - uFilePos) + len = vhdfc->volumeSize - uFilePos; + errnum = ERR_NONE; + unsigned long long rem = len; + while (rem) { unsigned long blockNumber = (unsigned long)(uFilePos >> vhdfc->blockSizeLog2); unsigned long long blockOffset = (unsigned long long)blockNumber << vhdfc->blockSizeLog2; unsigned long offsetInBlock = (unsigned long)(uFilePos - blockOffset); unsigned long txLen = (rem < vhdfc->blockSize - offsetInBlock) ? rem : vhdfc->blockSize - offsetInBlock; grub_u32_t blockLBA = *(grub_u32_t*)(vhdfc->blockAllocationTable + blockNumber * 4); bswap_32(&blockLBA); - // grub_printf("read bn %x of %x txlen %x lba %x\n", blockNumber, offsetInBlock, txLen, blockLBA); + if (blockLBA == 0xFFFFFFFF) { // unused block on dynamic VHD. read zero grub_memset64(buf, 0, txLen); @@ -282,8 +828,8 @@ dec_vhd_read(unsigned long long buf, unsigned long long len, unsigned long write else { if (blockOffset != vhdfc->currentBlockOffset) { filepos = blockLBA * 512; - // grub_printf("read vhd lba %x filepos %lx\n", blockLBA, filepos); - unsigned long long nread = grub_read((unsigned long)vhdfc->blockBitmapAndData, vhdfc->blockBitmapSize + vhdfc->blockSize, GRUB_READ); + + unsigned long long nread = grub_read((unsigned long long)(grub_size_t)vhdfc->blockBitmapAndData, vhdfc->blockBitmapSize + vhdfc->blockSize, GRUB_READ); if (nread < vhdfc->blockBitmapSize + vhdfc->blockSize) break; vhdfc->currentBlockOffset = blockOffset; @@ -294,12 +840,13 @@ dec_vhd_read(unsigned long long buf, unsigned long long len, unsigned long write uFilePos += txLen; rem -= txLen; ret += txLen; - } - filepos = uFilePos; -// } + } +//printf ("dec_vhd_read-end\n"); + filepos = uFilePos; compressed_file = 1; filemax = vhdfc->volumeSize; return ret; +#endif } #endif /* ! NO_DECOMPRESSION */ diff --git a/stage2/disk_io.c b/stage2/disk_io.c index 170af3c4..597b550c 100644 --- a/stage2/disk_io.c +++ b/stage2/disk_io.c @@ -26,20 +26,23 @@ /* function declaration */ unsigned long long -gunzip_read_func (unsigned long long buf, unsigned long long len, unsigned long write); -unsigned long long -block_read_func (unsigned long long buf, unsigned long long len, unsigned long write); +gunzip_read_func (unsigned long long buf, unsigned long long len, unsigned int write); + +block_io_protocol_t blockio_template; + + +unsigned int fats_type; +unsigned int iso_type; /* instrumentation variables */ -//void (*disk_read_hook) (unsigned long long, unsigned long, unsigned long long) = NULL; -void (*disk_read_func) (unsigned long long, unsigned long, unsigned long long) = NULL; +void (*disk_read_func) (unsigned long long, unsigned int, unsigned long long) = NULL; /* Forward declarations. */ static int next_bsd_partition (void); static int next_pc_slice (void); static int next_gpt_slice(void); static char open_filename[512]; -static unsigned long relative_path; +static unsigned int relative_path; int print_possibilities; @@ -70,10 +73,10 @@ int print_possibilities; static int unique; static char *unique_string; -static unsigned long long cur_part_offset; -static unsigned long cur_part_addr; -static unsigned long long cur_part_start; -static unsigned long cur_part_entry; +//static unsigned long long cur_part_offset; +//static unsigned int cur_part_addr; +//static unsigned long long cur_part_start; +//static unsigned int cur_part_entry; static int do_completion; static int set_filename(char *filename); @@ -93,22 +96,18 @@ static enum part_choice; -//unsigned long i; - /* The first sector of stage2 can be reused as a tmp buffer. * Do NOT write more than 512 bytes to this buffer! * The stage2-body, i.e., the pre_stage2, starts at 0x8200! * Do NOT overwrite the pre_stage2 code at 0x8200! */ -char *mbr = (char *)0x8000; /* 512-byte buffer for any use. */ +//char *mbr = (char *)0x8000; /* 512-byte buffer for any use. */ -static unsigned long dest_partition; -static unsigned long long part_offset; -static unsigned long entry; -static unsigned long ext_offset; +static unsigned int dest_partition; +//static unsigned int entry; -static unsigned long bsd_part_no; -static unsigned long pc_slice_no; +static unsigned int bsd_part_no; +static unsigned int pc_slice_no; unsigned long long fsmax; struct fsys_entry fsys_table[NUM_FSYS + 1] = @@ -132,32 +131,32 @@ struct fsys_entry fsys_table[NUM_FSYS + 1] = # ifdef FSYS_NTFS {"ntfs", ntfs_mount, ntfs_read, ntfs_dir, 0, 0}, # endif -# ifdef FSYS_MINIX - {"minix", minix_mount, minix_read, minix_dir, 0, 0}, -# endif -# ifdef FSYS_REISERFS - {"reiserfs", reiserfs_mount, reiserfs_read, reiserfs_dir, 0, reiserfs_embed}, -# endif -# ifdef FSYS_VSTAFS - {"vstafs", vstafs_mount, vstafs_read, vstafs_dir, 0, 0}, -# endif -# ifdef FSYS_JFS - {"jfs", jfs_mount, jfs_read, jfs_dir, 0, jfs_embed}, -# endif -# ifdef FSYS_XFS - {"xfs", xfs_mount, xfs_read, xfs_dir, 0, 0}, -# endif -# ifdef FSYS_UFS2 - {"ufs2", ufs2_mount, ufs2_read, ufs2_dir, 0, ufs2_embed}, -# endif +//# ifdef FSYS_MINIX +// {"minix", minix_mount, minix_read, minix_dir, 0, 0}, +//# endif +//# ifdef FSYS_REISERFS +// {"reiserfs", reiserfs_mount, reiserfs_read, reiserfs_dir, 0, reiserfs_embed}, +//# endif +//# ifdef FSYS_VSTAFS +// {"vstafs", vstafs_mount, vstafs_read, vstafs_dir, 0, 0}, +//# endif +//# ifdef FSYS_JFS +// {"jfs", jfs_mount, jfs_read, jfs_dir, 0, jfs_embed}, +//# endif +//# ifdef FSYS_XFS +// {"xfs", xfs_mount, xfs_read, xfs_dir, 0, 0}, +//# endif +//# ifdef FSYS_UFS2 +// {"ufs2", ufs2_mount, ufs2_read, ufs2_dir, 0, ufs2_embed}, +//# endif # ifdef FSYS_ISO9660 {"iso9660", iso9660_mount, iso9660_read, iso9660_dir, 0, 0}, # endif /* XX FFS should come last as it's superblock is commonly crossing tracks on floppies from track 1 to 2, while others only use 1. */ -# ifdef FSYS_FFS - {"ffs", ffs_mount, ffs_read, ffs_dir, 0, ffs_embed}, -# endif +//# ifdef FSYS_FFS +// {"ffs", ffs_mount, ffs_read, ffs_dir, 0, ffs_embed}, +//# endif # ifdef FSYS_INITRD {"initrdfs", initrdfs_mount, initrdfs_read, initrdfs_dir, initrdfs_close, 0}, # endif @@ -166,7 +165,7 @@ struct fsys_entry fsys_table[NUM_FSYS + 1] = /* The register ESI should contain the address of the partition to be used for loading a chain-loader when chain-loading the loader. */ -unsigned long boot_part_addr = 0; +unsigned int boot_part_addr = 0; /* * Global variables describing details of the filesystem @@ -181,410 +180,267 @@ int fsys_type = NUM_FSYS; struct geometry buf_geom; struct geometry tmp_geom; /* tmp variable used in many functions. */ -struct geometry fd_geom[4]; -struct geometry hd_geom[8]; int rawread_ignore_memmove_overflow = 0;/* blocklist_func() set this to 1 */ -unsigned long emu_iso_sector_size_2048 = 0; - -/* Convert unicode filename to UTF-8 filename. N is the max UTF-16 characters - * to be converted. The caller should asure there is enough room in the UTF8 - * buffer. Return the length of the converted UTF8 string. - */ -unsigned long -unicode_to_utf8 (unsigned short *filename, unsigned char *utf8, unsigned long n) -{ - unsigned short uni; - unsigned long j, k; - - for (j = 0, k = 0; j < n && (uni = filename[j]); j++) - { - if (uni <= 0x007F) - { -#if 0 - if (uni != ' ') -#endif - utf8[k++] = uni; -#if 0 - else - { - /* quote the SPACE with a backslash */ - utf8[k++] = '\\'; - utf8[k++] = uni; - } -#endif - } - else if (uni <= 0x07FF) - { - utf8[k++] = 0xC0 | (uni >> 6); - utf8[k++] = 0x80 | (uni & 0x003F); - } - else - { - utf8[k++] = 0xE0 | (uni >> 12); - utf8[k++] = 0x80 | ((uni >> 6) & 0x003F); - utf8[k++] = 0x80 | (uni & 0x003F); - } - } - utf8[k] = 0; - return k; -} - -#define FOUR_CHAR(x0,x1,x2,x3) (((unsigned long)(char)(x0))|((unsigned long)(char)(x1)<<8)|((unsigned long)(char)(x2)<<16)|((unsigned long)(char)(x3)<<24)) +unsigned int emu_iso_sector_size_2048 = 0; -static int -rawdisk_read (unsigned long drive, unsigned long long sector, unsigned long nsec, unsigned long segment) -{ - const unsigned long BADDATA1 = FOUR_CHAR('B','A','D','?'); - unsigned long *plast; /* point to buffer of last sector to be read */ - int r; - /* Write "BAD?" data to last sector buffer */ - /* No need to fill the whole sector. Just 16 bytes should be enought to avoid most false-positive case. */ - plast = (unsigned long *)((segment<<4)+(nsec-1)*buf_geom.sector_size); - plast[3] = plast[2] = plast[1] = plast[0] = BADDATA1; - r = biosdisk(BIOSDISK_READ, drive, &buf_geom, sector, nsec, segment); - if (r) // error - return r; - /* Check for bad data in last read sector */ - if (plast[0]!=BADDATA1 || plast[1]!=BADDATA1 || plast[2]!=BADDATA1 || plast[3]!=BADDATA1) - return 0; // not "BAD?", success - - printf_warning("\nFatal! Inconsistent data read from (0x%X)%ld+%d\n",drive,sector,nsec); - return -1; // error -} - -/* Read bytes from DRIVE to BUF. The bytes start at BYTE_OFFSET in absolute - * sector number SECTOR and with BYTE_LEN bytes long. +/* Read bytes from DRIVE to BUF. The bytes start at BYTE_OFFSET in absolute 从驱动器DRIVE中读取字节到缓存BUF。 + * sector number SECTOR and with BYTE_LEN bytes long. 字节开始于绝对扇区号SECTOR的偏移BYTE_OFFSET,字节长BYTE_LEN。 */ +//原读(驱动器号,扇区号,字节偏移,字节长度,缓存,读/写) 返回: 0/1=失败/成功 +//1. 如果缓存驱动器号≠驱动器号, 获取磁盘信息 +//2. 处理读列表块, 处理磁盘读挂钩 +//3. 处理写磁盘 +//4. 将字节长度分解为64k(10000字节)片段,磁盘每次读64k尺寸 +//5. 首先从磁盘读数据到临时缓存BUFFERADDR, 然后复制到目标缓存buf +int rawread (unsigned int drive, unsigned long long sector, unsigned int byte_offset, unsigned long long byte_len, unsigned long long buf, unsigned int write); int -rawread (unsigned long drive, unsigned long long sector, unsigned long byte_offset, unsigned long long byte_len, unsigned long long buf, unsigned long write) +rawread (unsigned int drive, unsigned long long sector, unsigned int byte_offset, unsigned long long byte_len, unsigned long long buf, unsigned int write) { - unsigned long slen, sectors_per_vtrack; - unsigned long sector_size_bits = log2_tmp (buf_geom.sector_size); - - if (write != 0x900ddeed && write != 0xedde0d90 && write != GRUB_LISTBLK) - return !(errnum = ERR_FUNC_CALL); + if (write != 0x900ddeed && write != 0xedde0d90 && write != GRUB_LISTBLK) //如果“write”不是写/读/块列表. 则错误 + return !(errnum = ERR_FUNC_CALL); errnum = 0; - if (write == 0x900ddeed && ! buf) + if (write == 0x900ddeed && ! buf) //如果是写, 而没有缓存, 假写 return 1; -// /* right now safely disable writing 64-bit sector number */ -// if (write == 0x900ddeed && (sector >> 32)) -// return !(errnum = ERR_WRITE); - /* Reset geometry and invalidate track buffer if the disk is wrong. */ + //如果磁盘错误,请重置几何并使缓冲区无效。 + //如果缓存驱动器≠驱动器, 获得磁盘信息 if (buf_drive != drive) { - if (get_diskinfo (drive, &buf_geom, 0)) - return !(errnum = ERR_NO_DISK); - buf_drive = drive; - buf_track = -1; - sector_size_bits = log2_tmp (buf_geom.sector_size); + if (get_diskinfo (drive, &buf_geom, 0)) //如果'获得磁盘信息'返回非0, 错误 + return !(errnum = ERR_NO_DISK); + buf_drive = drive; + buf_track = -1; } + //如果是列表块, 完成它 if (write == GRUB_LISTBLK) { - if (disk_read_func) (*disk_read_func)(sector, byte_offset, byte_len); + if (disk_read_func) (*disk_read_func)(sector, byte_offset, byte_len); return 1; } - + //如果缓存为零, 不是正常读写, 完成它 if (!buf) { /* Don't waste time reading from disk, just call disk_read_func. */ - - if (disk_read_func) - { - unsigned long sectorsize = buf_geom.sector_size; - if (byte_offset) + //不要浪费时间从磁盘读取,只需调用disk_read_func“。 + if (disk_read_func) //如果disk_read_func挂钩 + { + unsigned int sectorsize = buf_geom.sector_size; //扇区尺寸 + if (byte_offset) //如果有偏移 { - unsigned long len = sectorsize - byte_offset; - if (len > byte_len) len = byte_len; - (*disk_read_func) (sector++, byte_offset, len); - byte_len -= len; + unsigned int len = sectorsize - byte_offset; //长度=扇区尺寸-偏移 + if (len > byte_len) len = byte_len; //如果长度>请求长度,则长度=请求长度 + (*disk_read_func) (sector++, byte_offset, len); //向(*disk_read_func)所代表的函数赋值并执行 + byte_len -= len; //请求长度-长度 } - if (byte_len) + if (byte_len) //如果请求长度非零 { - while (byte_len > sectorsize) - { - (*disk_read_func) (sector++, 0, sectorsize); - byte_len -= sectorsize; + while (byte_len > sectorsize) //条件:请求长度>扇区大小 + { + (*disk_read_func) (sector++, 0, sectorsize); //向(*disk_read_func)所代表的函数赋值并执行 + byte_len -= sectorsize; //请求长度-扇区尺寸 + } + (*disk_read_func) (sector, 0, byte_len); //向(*disk_read_func)所代表的函数赋值并执行 + } } - (*disk_read_func) (sector, 0, byte_len); - } - } - return 1; + return 1; } - while (byte_len > 0) + unsigned long long back_filePos = filepos; + //正常读写 + while (byte_len > 0) //如果请求字节长度>0 { - unsigned long soff, num_sect, size; - unsigned long long track; - char *bufaddr; - unsigned long bufseg; - - size = (byte_len > BUFFERLEN)? BUFFERLEN: (unsigned long)byte_len; + unsigned int num_sect, size; //缓存扇区数, 实际读写字节 + char *bufaddr; //实际读写位置 - /* Sectors that need to read. */ - slen = ((byte_offset + size + buf_geom.sector_size - 1) >> sector_size_bits); - - if ((buf_geom.flags & BIOSDISK_FLAG_LBA_EXTENSION) && (! (buf_geom.flags & BIOSDISK_FLAG_BIFURCATE) || (drive & 0xFFFFFF00) == 0x100)) + num_sect = (BUFFERLEN >> buf_geom.log2_sector_size); //缓存扇区数 缓存字节=0x10000 + //如果缓存无效, 或者扇区号不在缓存范围, 则更新缓存区 + if (buf_track == (unsigned long long)-1 || sector < buf_track || sector >= (buf_track + num_sect)) + { + buf_track = sector & ~((0x1000 >> buf_geom.log2_sector_size) - 1); //4k对齐 +#if VHD_DIFFERENCE + if (buf_geom.vhd_disk & 1) + { + filepos = buf_track << 9; + dec_vhd_read ((unsigned long long)(grub_size_t)BUFFERADDR,BUFFERLEN,0xedde0d90); + } + else +#endif + if (grub_efidisk_readwrite (buf_drive, buf_track, BUFFERLEN, BUFFERADDR, 0xedde0d90)) { - /* LBA */ - sectors_per_vtrack = (BUFFERLEN >> sector_size_bits); - - /* Get the first sector number in the track. */ - soff = ((unsigned long)sector) & (sectors_per_vtrack - 1); + buf_track = -1; /* invalidate the buffer */ + return !(errnum = ERR_READ); + } + } + //实际读写位置 + bufaddr = BUFFERADDR + ((sector - buf_track) << buf_geom.log2_sector_size) + byte_offset; + //实际读写字节 + if (byte_len > (unsigned long long)(BUFFERLEN - (bufaddr - BUFFERADDR))) + size = BUFFERLEN - (bufaddr - BUFFERADDR); + else + size = byte_len; - /* buffer can be 64K for CDROM, but 63.5K(127 sectors) for HDD. */ - if (sector_size_bits == 9) /* 512-byte sector size */ - { - /* BUFFERLEN must be 64K */ - sectors_per_vtrack = 127; - //soff = sector % sectors_per_vtrack; - if (sector >> 32) + if (write == 0x900ddeed) //如果写 { - // 16 == (0x100000000 % 127) - soff = (((unsigned long)(sector >> 32) % 127) * 16 + - ((unsigned long)sector % 127)) % 127; + //如果待写数据与原数据一致, 则跳过 + if (grub_memcmp64 (buf, (unsigned long long)(grub_size_t)bufaddr, size) == 0) + goto next; /* no need to write */ + //更新缓冲区数据 + grub_memmove64 ((unsigned long long)(grub_size_t)bufaddr, buf, size); /* update data at bufaddr */ + /* write it! */ + //更新打开的文件 + if (grub_efidisk_readwrite (buf_drive, buf_track, BUFFERLEN, BUFFERADDR, 0x900ddeed)) + return !(errnum = ERR_WRITE); + goto next; } - else + + /* Use this interface to tell which sectors were read and used. */ + //使用此接口可以判断哪些扇区被读取和使用。正常读写或略 + if (disk_read_func) { - soff = ((unsigned long)sector) % sectors_per_vtrack; + unsigned long long sector_num = sector; + unsigned int length = buf_geom.sector_size - byte_offset; + if (length > size) + length = size; + (*disk_read_func) (sector_num++, byte_offset, length); + length = size - length; + if (length > 0) + { + while (length > buf_geom.sector_size) + { + (*disk_read_func) (sector_num++, 0, buf_geom.sector_size); + length -= buf_geom.sector_size; + } + (*disk_read_func) (sector_num, 0, length); + } } - } - } - else - { - /* CHS */ - if (sector >> 32) /* sector exceeding 32 bit, too big */ - return !(errnum = ERR_READ); - - sectors_per_vtrack = buf_geom.sectors; - - /* Get the first sector number in the track. */ - soff = ((unsigned long)sector) % sectors_per_vtrack; - } - - /* Get the starting sector number of the track. */ - track = sector - soff; - - /* max number of sectors to read in the track. */ - num_sect = sectors_per_vtrack - soff; - - /* Read data into the track buffer; Not all sectors in the track would be filled in. */ - bufaddr = ((char *) BUFFERADDR + (soff << sector_size_bits) + byte_offset); - bufseg = BUFFERSEG; - - if (track != buf_track) - { - unsigned long long read_start = track; /* = sector - soff <= sector */ - unsigned long read_len = sectors_per_vtrack; /* >= num_sect */ - - buf_track = track; - - /* If more than one track need to read, only read the portion needed - * rather than the whole track with data that won't be used. */ - if (slen > num_sect) - { - buf_track = -1; /* invalidate the buffer */ - read_start = sector; /* read the portion from this sector */ - read_len = num_sect; /* to the end of the track */ - //bufaddr = (char *) BUFFERADDR + byte_offset; - bufseg = BUFFERSEG + (soff << (sector_size_bits - 4)); - } - - if (rawdisk_read (drive, read_start, read_len, bufseg)) - { - buf_track = -1; /* invalidate the buffer */ - /* On error try again to load only the required sectors. */ - if (slen > num_sect || slen == read_len) - return !(errnum = ERR_READ); - bufseg = BUFFERSEG + (soff << (sector_size_bits - 4)); - if (rawdisk_read (drive, sector, slen, bufseg)) - return !(errnum = ERR_READ); - //bufaddr = (char *) BUFFERADDR + byte_offset; - /* slen <= num_sect && slen < sectors_per_vtrack */ - num_sect = slen; - } - } /* if (track != buf_track) */ - /* num_sect is sectors that has been read at BUFADDR and will be used. */ - if (size > (num_sect << sector_size_bits) - byte_offset) - size = (num_sect << sector_size_bits) - byte_offset; - - if (write == 0x900ddeed) - { - if (grub_memcmp64 (buf, (unsigned long long)(unsigned int)bufaddr, size) == 0) - goto next; /* no need to write */ - buf_track = -1; /* invalidate the buffer */ - grub_memmove64 ((unsigned long long)(unsigned int)bufaddr, buf, size); /* update data at bufaddr */ - /* write it! */ - bufseg = BUFFERSEG + (soff << (sector_size_bits - 4)); - if (biosdisk (BIOSDISK_WRITE, drive, &buf_geom, sector, num_sect, bufseg)) - return !(errnum = ERR_WRITE); - goto next; - } - /* Use this interface to tell which sectors were read and used. */ - if (disk_read_func) - { - unsigned long long sector_num = sector; - unsigned long length = buf_geom.sector_size - byte_offset; - if (length > size) - length = size; - (*disk_read_func) (sector_num++, byte_offset, length); - length = size - length; - if (length > 0) - { - while (length > buf_geom.sector_size) - { - (*disk_read_func) (sector_num++, 0, buf_geom.sector_size); - length -= buf_geom.sector_size; - } - (*disk_read_func) (sector_num, 0, length); - } - } - - grub_memmove64 (buf, (unsigned long long)(unsigned int)bufaddr, size); - if (errnum == ERR_WONT_FIT) - { - if (! rawread_ignore_memmove_overflow && buf) - return 0; - errnum = 0; - buf = 0/*NULL*/; /* so that further memcheck() always fail */ - } - else + grub_memmove64 (buf, (unsigned long long)(grub_size_t)bufaddr, size); + if (errnum == ERR_WONT_FIT) + { + if (! rawread_ignore_memmove_overflow && buf) + return 0; + errnum = 0; + buf = 0/*NULL*/; /* so that further memcheck() always fail */ + } + else next: - buf += size; - byte_len -= size; /* byte_len always >= size */ - sector += num_sect; - byte_offset = 0; - } /* while (byte_len > 0) */ - + buf += size; + + byte_len -= size; /* byte_len always >= size */ + sector += (size + byte_offset) >> buf_geom.log2_sector_size; + byte_offset = 0; + } /* while (byte_len > 0) */ + + filepos = back_filePos + byte_len; return 1;//(!errnum); } - +//设备读(扇区号,字节偏移,字节长度,缓冲区,读/写) 卷读(分区读) +//1. 如果是光盘, 调整扇区号, 按每扇区200字节计 +//2. 检查分区边界 +//3. 调整字节偏移,使其在1扇区内 +//4. 相对逻辑扇区+分区起始=绝对逻辑扇区 +int devread (unsigned long long sector, unsigned long long byte_offset, unsigned long long byte_len, unsigned long long buf, unsigned int write); int -devread (unsigned long long sector, unsigned long long byte_offset, unsigned long long byte_len, unsigned long long buf, unsigned long write) +devread (unsigned long long sector, unsigned long long byte_offset, unsigned long long byte_len, unsigned long long buf, unsigned int write) { - unsigned long sector_size_bits = log2_tmp(buf_geom.sector_size); - unsigned long rw_flag = write; - + unsigned int rw_flag = write; +#if 0 //太旧版本不再支持了 2023-05-24 if (rw_flag != 0x900ddeed && rw_flag != 0xedde0d90 && rw_flag != GRUB_LISTBLK) - {//for old devread with 32-bit byte_offset compatibility. - rw_flag = *(unsigned long*)(&write - 1); + {//for old devread with 32-bit byte_offset compatibility. 为了兼容旧驱动器的32位byte_offset + rw_flag = *(unsigned int*)(&write - 1); if (rw_flag != 0x900ddeed && rw_flag != 0xedde0d90) return !(errnum = ERR_FUNC_CALL); buf = *(unsigned long long*)(&write - 3); byte_len = *(unsigned long long*)(&write - 5); - byte_offset = (unsigned long)byte_offset; + byte_offset = (unsigned int)byte_offset; } - - if (emu_iso_sector_size_2048) +#endif + if (emu_iso_sector_size_2048) //如果是读光盘 { - emu_iso_sector_size_2048 = 0; - sector <<= (ISO_SECTOR_BITS - sector_size_bits); + emu_iso_sector_size_2048 = 0; //修改为每扇区0x200字节 + sector <<= (ISO_SECTOR_BITS - buf_geom.log2_sector_size); //0b-09 } /* Check partition boundaries */ - if (((unsigned long long)(sector + ((byte_offset + byte_len - 1) >> sector_size_bits)) >= (unsigned long long)part_length) && part_start) + //检查分区边界 + //如果(扇区号+(字节偏移+字节长度-1)/扇区尺寸)>=分区长度,并且分区起始不为零 + if (((unsigned long long)(sector + ((byte_offset + byte_len - 1) >> buf_geom.log2_sector_size)) >= (unsigned long long)part_length) && part_start) return !(errnum = ERR_OUTSIDE_PART); /* Get the read to the beginning of a partition. */ - sector += byte_offset >> sector_size_bits; - byte_offset &= buf_geom.sector_size - 1; - - if (disk_read_hook && (((unsigned long)debug) >= 0x7FFFFFFF)) + //获取分区的开头。调整字节偏移,使其在1扇区内 + sector += byte_offset >> buf_geom.log2_sector_size; //扇区号+(字节偏移/扇区尺寸) + byte_offset &= buf_geom.sector_size - 1; //字节偏移&(扇区尺寸-1) + //如果磁盘读挂钩,并且debug) >= 0x7FFFFFFF,打印"扇区号,字节偏移,字节长度" + if (disk_read_hook && (((unsigned int)debug) >= 0x7FFFFFFF)) printf ("<%ld, %ld, %ld>", (unsigned long long)sector, (unsigned long long)byte_offset, (unsigned long long)byte_len); - /* Call RAWREAD, which is very similar, but: - * -- It takes an extra parameter, the drive number. - * -- It requires that "sector" is relative to the beginning of the disk. - * -- It doesn't handle offsets across the sector boundary. + /* Call RAWREAD, which is very similar, but: //调用RAWREAD,这是非常相似,但是 + * -- It takes an extra parameter, the drive number. //- 它需要一个额外的参数,驱动器号。 + * -- It requires that "sector" is relative to the beginning of the disk. //- 它要求,“扇区”是相对于在磁盘开始,即绝对逻辑扇区。 + * -- It doesn't handle offsets across the sector boundary. //- 它不处理跨扇区边界的偏移量。 */ return rawread (current_drive, (sector += part_start), byte_offset, byte_len, buf, rw_flag); } -/* Write 1 sector at BUF onto sector number SECTOR on drive DRIVE. - * Only a 512-byte sector should be written with this function. - * Return: +/* Write 1 sector at BUF onto sector number SECTOR on drive DRIVE. 从缓存区写1扇区到扇区号sector + * Only a 512-byte sector should be written with this function. 只有512字节的扇区可以使用这个功能。 + * Return: 返回0/1=失败/成功 * 1 success * 0 failure */ +int rawwrite (unsigned int drive, unsigned long long sector, unsigned long long buf); int -rawwrite (unsigned long drive, unsigned long long sector, unsigned long long buf) +rawwrite (unsigned int drive, unsigned long long sector, unsigned long long buf) { /* Reset geometry and invalidate track buffer if the disk is wrong. */ + //如果磁盘错误,请重置几何形状并使轨道缓冲区无效。 if (buf_drive != drive) { - if (get_diskinfo (drive, &buf_geom, 0)) + if (get_diskinfo (drive, &buf_geom, 0)) return !(errnum = ERR_NO_DISK); - buf_drive = drive; - buf_track = -1; + buf_drive = drive; + buf_track = -1; } - /* skip the write if possible. */ - if (rawdisk_read(drive, sector, 1, SCRATCHSEG)) /* use buf_geom */ - { + /* skip the write if possible. 如果可能的话,跳过写*/ + if (grub_efidisk_readwrite (drive, sector, buf_geom.sector_size, SCRATCHADDR, 0xedde0d90)) + { errnum = ERR_READ; return 0; } - if (! grub_memcmp64 ((unsigned long long) SCRATCHADDR, buf, SECTOR_SIZE)) + if (! grub_memcmp64 ((unsigned long long)(grub_size_t)SCRATCHADDR, buf, SECTOR_SIZE)) return 1; - grub_memmove64 ((unsigned long long) SCRATCHADDR, buf, SECTOR_SIZE); - if (biosdisk (BIOSDISK_WRITE, drive, &buf_geom, sector, 1, SCRATCHSEG)) + grub_memmove64 ((unsigned long long)(grub_size_t)SCRATCHADDR, buf, SECTOR_SIZE); + if (grub_efidisk_readwrite (drive, sector, buf_geom.sector_size, SCRATCHADDR, 0x900ddeed)) { errnum = ERR_WRITE; return 0; } -#if 1 - //if (buf_drive == drive && sector - sector % buf_geom.sectors == buf_track) - if (buf_drive == drive && sector >= buf_track && sector - buf_track < buf_geom.sectors) - { - /* Update the cache. */ - grub_memmove64 (BUFFERADDR + ((sector - buf_track) << SECTOR_BITS), buf, SECTOR_SIZE); - } -#else - if (sector - sector % buf_geom.sectors == buf_track) - /* Clear the cache. */ - buf_track = -1; -#endif - return 1; } -int -devwrite (unsigned long long sector, unsigned long long sector_count, unsigned long long buf) -{ - unsigned long i; - - for (i = 0; i < sector_count; i++) - { - if (! rawwrite (current_drive, (part_start + sector + i), buf + (i << SECTOR_BITS))) - return 0; - } - return 1; -} - - -#if 1 +int set_bootdev (int hdbias); int set_bootdev (int hdbias) { int i, j; -// if (kernel_type != KERNEL_TYPE_FREEBSD && kernel_type != KERNEL_TYPE_NETBSD) -// return 0; /* Copy the boot partition information to 0x7be-0x7fd for chain-loading. */ - if ((current_drive & 0x80) && cur_part_addr) + if ((current_drive & 0x80)/* && cur_part_addr*/) { - if (rawread (current_drive, cur_part_offset, 0, SECTOR_SIZE, (unsigned long long)(unsigned long) SCRATCHADDR, 0xedde0d90)) +#if 0 + if (rawread (current_drive, cur_part_offset, 0, SECTOR_SIZE, (unsigned long long)(grub_size_t)SCRATCHADDR, 0xedde0d90)) { char *dst, *src; @@ -609,6 +465,7 @@ set_bootdev (int hdbias) { return 0; } +#endif } /* @@ -627,12 +484,12 @@ set_bootdev (int hdbias) return MAKEBOOTDEV (j, (i >> 4), (i & 0xF), ((current_drive - hdbias) & 0x7F), ((current_partition >> 8) & 0xFF)); } -#endif /* * This prints the filesystem type or gives relevant information. */ +void print_fsys_type (void); void print_fsys_type (void) { @@ -643,6 +500,7 @@ print_fsys_type (void) if (fsys_type != NUM_FSYS) { #ifdef FSYS_PXE + #if 0 #ifdef FSYS_IPXE if (fsys_table[fsys_type].mount_func == pxe_mount) { @@ -650,6 +508,7 @@ print_fsys_type (void) return; } #endif + #endif #endif if (fsys_table[fsys_type].mount_func == fat_mount) { @@ -699,13 +558,14 @@ print_fsys_type (void) if (current_partition == 0xFFFFFF) printf ("using whole disk\n"); else - printf ("partition type 0x%02X\n", (unsigned long)(unsigned char)current_slice); + printf ("partition type 0x%02X\n", (unsigned int)(unsigned char)current_slice); } /* Get next BSD partition in current PC slice. */ +static int next_bsd_partition (void); static int -next_bsd_partition (/*unsigned long drive, unsigned long *partition, int *type, unsigned long *start, unsigned long *len, char *buf*/void) +next_bsd_partition (void) { int i; bsd_part_no = (*next_partition_partition & 0xFF00) >> 8; @@ -722,7 +582,7 @@ next_bsd_partition (/*unsigned long drive, unsigned long *partition, int *type, /* Read the BSD label. */ if (! rawread (next_partition_drive, *next_partition_start + BSD_LABEL_SECTOR, - 0, SECTOR_SIZE, (unsigned long long)(unsigned int)next_partition_buf, 0xedde0d90)) + 0, SECTOR_SIZE, (unsigned long long)(grub_size_t)next_partition_buf, 0xedde0d90)) return 0; /* Check if it is valid. */ @@ -755,7 +615,6 @@ next_bsd_partition (/*unsigned long drive, unsigned long *partition, int *type, return 1; } } - errnum = ERR_NO_PART; return 0; } @@ -767,8 +626,11 @@ next_bsd_partition (/*unsigned long drive, unsigned long *partition, int *type, static char primary_partition_table[64]; static int partition_table_type = 0; static unsigned int gpt_part_max; +static int next_gpt_slice(void); static int next_gpt_slice(void) { + grub_packed_guid_t GPT_EFI_SYSTEM_PART_GUID = GRUB_GPT_PARTITION_TYPE_EFI_SYSTEM; //EFI系统 + // (0xc12a7328, 0xf81f, 0x11d2, 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b) redo: if (++pc_slice_no >= gpt_part_max) { @@ -776,28 +638,40 @@ static int next_gpt_slice(void) return 0; } grub_u64_t sector = *next_partition_entry + (pc_slice_no >> 2); - if (! rawread (next_partition_drive, sector,(pc_slice_no & 3) * sizeof(GPT_ENT) , sizeof(GPT_ENT), (unsigned long long)(unsigned int)next_partition_buf, 0xedde0d90)) + if (! rawread (next_partition_drive, sector,(pc_slice_no & 3) * sizeof(GPT_ENT) , sizeof(GPT_ENT), (unsigned long long)(grub_size_t)next_partition_buf, 0xedde0d90)) return 0; - P_GPT_ENT PI = (P_GPT_ENT)(unsigned int)next_partition_buf; + P_GPT_ENT PI = (P_GPT_ENT)(grub_size_t)next_partition_buf; + if (PI->starting_lba == 0LL /*|| PI->starting_lba > 0xFFFFFFFFL*/) { - errnum = ERR_NO_PART; - return 0; +// return 0; + goto redo; //避免分区项空洞 2023-06-20 } + //skip MS_Reserved Partition - if (memcmp(PI->type.raw,"\x16\xE3\xC9\xE3\x5C\x0B\xB8\x4D\x81\x7D\xF9\x2D\xF0\x02\x15\xAE",16) == 0 && next_partition_dest == 0xffffff) + if (memcmp(PI->type.raw,"\x16\xE3\xC9\xE3\x5C\x0B\xB8\x4D\x81\x7D\xF9\x2D\xF0\x02\x15\xAE",16) == 0/* && next_partition_dest == 0xffffff*/) goto redo; + + partition_activity_flag = 0; //活动分区 + if (grub_memcmp ((const char *)&PI->type, (const char *)&GPT_EFI_SYSTEM_PART_GUID, 16) == 0) //判断EFI系统分区 + partition_activity_flag = 0x80; //活动分区 *next_partition_start = PI->starting_lba; *next_partition_len = (unsigned long long)(PI->ending_lba - PI->starting_lba + 1); *next_partition_partition = (pc_slice_no << 16) | 0xFFFF; *next_partition_type = PC_SLICE_TYPE_GPT; + grub_memmove(&partition_signature, &PI->uid, 16); //GPT分区GUID return 1; } +static int is_gpt_part(void); static int is_gpt_part(void) { GPT_HDR hdr; - if (! rawread (next_partition_drive, 1, 0, sizeof(hdr), (unsigned long long)(unsigned int)&hdr, 0xedde0d90)) + struct grub_disk_data *d=0; //磁盘数据 + d = get_device_by_drive (current_drive,0); + if (!d) + return 0; + if (! rawread (next_partition_drive, 1, 0, sizeof(hdr), (unsigned long long)(grub_size_t)&hdr, 0xedde0d90)) return 0; if (hdr.hdr_sig != GPT_HDR_SIG) /* Signature ("EFI PART") */ return 0; @@ -812,15 +686,16 @@ static int is_gpt_part(void) *next_partition_entry = hdr.hdr_lba_table;/* Partition entries starting LBA */ gpt_part_max = hdr.hdr_entries;/* Number of partition entries */ partition_table_type = PC_SLICE_TYPE_GPT; + grub_memmove(&d->disk_signature, &hdr.hdr_uuid, 16); //GPT磁盘GUID return 1; } +static int next_pc_slice (void); static int next_pc_slice (void) { redo: pc_slice_no = (*next_partition_partition & 0xFF0000) >> 16; - if (pc_slice_no == 0xFE) { errnum = ERR_PARTITION_LOOP; @@ -840,18 +715,19 @@ next_pc_slice (void) { return next_gpt_slice(); } - /* Read the MBR or the boot sector of the extended partition. */ - if (! rawread (next_partition_drive, *next_partition_offset, 0, SECTOR_SIZE, (unsigned long long)(unsigned int)next_partition_buf, 0xedde0d90)) + if (! rawread (next_partition_drive, *next_partition_offset, 0, SECTOR_SIZE, (unsigned long long)(grub_size_t)next_partition_buf, 0xedde0d90)) return 0; - if (pc_slice_no == -1 && next_partition_buf[0x1C2] == '\xEE' && is_gpt_part()) + + if (pc_slice_no == (unsigned int)-1 && next_partition_buf[0x1C2] == '\xEE' && is_gpt_part()) { if (next_partition_dest != 0xffffff) pc_slice_no = (next_partition_dest>>16) - 1; return next_gpt_slice(); } - + if (*(unsigned int *)&next_partition_buf[0x1b4] == 0x46424246 && !fb_status) + fb_status = 0xff3f003f | ((unsigned char)next_partition_drive << 8); /* Check if it is valid. */ if (! PC_MBR_CHECK_SIG (next_partition_buf)) { @@ -859,7 +735,6 @@ next_pc_slice (void) errnum = ERR_BAD_PART_TABLE; return 0; } - /* backup partition table in the MBR */ if (*next_partition_offset == 0) { @@ -893,7 +768,6 @@ next_pc_slice (void) if (*next_partition_entry == PC_SLICE_MAX) { int i; - /* Search the first extended partition in current table. */ for (i = 0; i < PC_SLICE_MAX; i++) { @@ -901,62 +775,56 @@ next_pc_slice (void) { /* Found. Set the new offset and the entry number, and restart this function. */ -#if 1 - unsigned long long tmp_start = (unsigned long long)(unsigned long)(PC_SLICE_START (next_partition_buf, i)); - unsigned long long tmp_ext_offset = (unsigned long long)(unsigned long)(*next_partition_ext_offset); + + unsigned long long tmp_start = (unsigned long long)(grub_size_t)(PC_SLICE_START (next_partition_buf, i)); + unsigned long long tmp_ext_offset = (unsigned long long)(grub_size_t)(*next_partition_ext_offset); unsigned long long tmp_offset = tmp_ext_offset + tmp_start; /* if overflow ... */ -#if 0 - if (((unsigned long *)(&tmp_offset))[1]) //if (tmp_offset >= 0x100000000ULL) - continue; -#else + /* use this to keep away from the gcc bug. * (tmp_offset >= 0x100000000ULL) is also OK, but * (((unsigned long *)(&tmp_offset))[1]) is not OK with the buggy gcc. */ if (tmp_offset >> 32) //if (tmp_offset >= 0x100000000ULL) continue; -#endif + *next_partition_offset = tmp_offset; if (! *next_partition_ext_offset) *next_partition_ext_offset = tmp_start; -#else - if (! *next_partition_ext_offset) - *next_partition_offset = (*next_partition_ext_offset = tmp_start); - else - *next_partition_offset = (*next_partition_ext_offset + tmp_start); -#endif + *next_partition_entry = -1; -#if 0 - return next_pc_slice (); /* FIXME: Recursive!!!! */ -#else goto redo; -#endif } } - errnum = ERR_NO_PART; + if (next_partition_dest != 0xffffff) + errnum = ERR_NO_PART; + return 0; } { - unsigned long long tmp_start = (unsigned long long)(unsigned long)(PC_SLICE_START (next_partition_buf, *next_partition_entry)); + unsigned long long tmp_start = (unsigned long long)(grub_size_t)(PC_SLICE_START (next_partition_buf, *next_partition_entry)); unsigned long long tmp_offset = *next_partition_offset; tmp_start += tmp_offset; *next_partition_start = tmp_start; *next_partition_type = PC_SLICE_TYPE (next_partition_buf, *next_partition_entry); *next_partition_len = PC_SLICE_LENGTH (next_partition_buf, *next_partition_entry); + if (pc_slice_no == -1) + { + grub_memset (&partition_signature, 0, 16); + *(unsigned int *)partition_signature = PC_DISK_SIG (next_partition_buf); //MBR分区签名(使用磁盘签名) 逻辑分区的PC_DISK_SIG (next_partition_buf)无效 + } + partition_activity_flag = PC_SLICE_FLAG(next_partition_buf, *next_partition_entry); /* if overflow ... */ -#if 0 - if (((unsigned long *)(&tmp_start))[1]) //if (tmp_start >= 0x100000000ULL) -#else + /* use this to keep away from the gcc bug. * (tmp_start >= 0x100000000ULL) is also OK, but * (((unsigned long *)(&tmp_start))[1]) is not OK with the buggy gcc. */ if (tmp_start >> 32) //if (tmp_offset >= 0x100000000ULL) -#endif + //if (((int)pc_slice_no) >= PC_SLICE_MAX - 1) /* yes, on overflow it is always a logical partition. */ goto next_entry; @@ -987,36 +855,19 @@ next_pc_slice (void) *next_partition_len = 0; } } - -#if 0 - /* disable partition id 00. */ - if (((int)pc_slice_no) >= PC_SLICE_MAX - 1 /* if it is a logical partition */ - && *next_partition_type == PC_SLICE_TYPE_NONE) /* ignore the partition with id=00. */ - goto next_entry; -#else - /* enable partition id 00. */ -#endif } -#if 0 - if (((int)pc_slice_no) < PC_SLICE_MAX - 1 - || ! IS_PC_SLICE_TYPE_EXTENDED (*next_partition_type)) - pc_slice_no++; -#else + if (((int)pc_slice_no) >= PC_SLICE_MAX - 1 && IS_PC_SLICE_TYPE_EXTENDED (*next_partition_type)) goto next_entry; -#if 1 /* disable partition length of 0. */ if (((int)pc_slice_no) >= PC_SLICE_MAX - 1 /* if it is a logical partition */ && *next_partition_len == 0) /* ignore the partition with length=0. */ goto next_entry; -#else - /* enable partition length of 0. */ -#endif pc_slice_no++; -#endif + *next_partition_partition = (pc_slice_no << 16) | 0xFFFF; return 1; } @@ -1033,15 +884,11 @@ next_pc_slice (void) a BSD label sector, and it must be at least 512 bytes length. When calling this function first, *PARTITION must be initialized to 0xFFFFFF. The return value is zero if fails, otherwise non-zero. */ +int next_partition (void); int -next_partition (/*unsigned long drive, unsigned long dest, - unsigned long *partition, int *type, - unsigned long *start, unsigned long *len, - unsigned long *offset, int *entry, - unsigned long *ext_offset, char *buf*/void) +next_partition (void) { - /* Start the body of this function. */ - + /* Start the body of this function. */ if ((current_drive == NETWORK_DRIVE) || (current_drive == PXE_DRIVE) || (current_drive == FB_DRIVE)) return 0; @@ -1054,7 +901,7 @@ next_partition (/*unsigned long drive, unsigned long dest, *next_partition_type = PC_SLICE_TYPE_FREEBSD; /* Get next BSD partition, if any. */ - if (next_bsd_partition (/*next_partition_drive, next_partition_partition, next_partition_type, next_partition_start, next_partition_len, next_partition_buf*/)) + if (next_bsd_partition ()) return 1; /* If the destination partition is a BSD partition and current @@ -1067,23 +914,23 @@ next_partition (/*unsigned long drive, unsigned long dest, /* Ignore the error. */ errnum = ERR_NONE; } + return next_pc_slice (); } +static void attempt_mount (void); static void attempt_mount (void) { - int cdrom = (current_drive != NETWORK_DRIVE && current_drive != PXE_DRIVE && current_drive != FB_DRIVE && buf_geom.sector_size == 2048); + int cdrom = (current_drive >= 0xa0 && current_drive != 0xffff); for (fsys_type = 0; fsys_type < NUM_FSYS; fsys_type++) { -// if (fsys_type >= 4) continue; - if (cdrom && fsys_table[fsys_type].mount_func != iso9660_mount) + if ((cdrom && fsys_table[fsys_type].mount_func != iso9660_mount) || !(fsys_table[fsys_type].mount_func)) continue; if (errnum = 0, ((fsys_table[fsys_type].mount_func) ())) break; } - if (fsys_type == NUM_FSYS && errnum == ERR_NONE) errnum = ERR_FSYS_MOUNT; } @@ -1093,7 +940,7 @@ attempt_mount (void) * This performs a "mount" on the current device, both drive and partition * number. */ - +int open_device (void); int open_device (void) { @@ -1106,30 +953,7 @@ open_device (void) return 1; } - - /* For simplicity. */ -static unsigned long next_part (void); -static unsigned long -next_part (void) -{ - unsigned long i; - next_partition_drive = current_drive; - next_partition_dest = dest_partition; - next_partition_partition = ¤t_partition; - next_partition_type = ¤t_slice; - next_partition_start = &part_start; - next_partition_len = &part_length; - next_partition_offset = &part_offset; - next_partition_entry = &entry; - next_partition_ext_offset = &ext_offset; - next_partition_buf = mbr; - i = next_partition (); - bsd_part_no = (current_partition >> 8) & 0xFF; - pc_slice_no = current_partition >> 16; - return i; -} - - +static void check_and_print_mount (void); static void check_and_print_mount (void) { @@ -1144,12 +968,12 @@ check_and_print_mount (void) /* Open a partition. */ +int real_open_partition (int flags); int real_open_partition (int flags) { dest_partition = current_partition; grub_memset(vol_name, 0, 256); - cur_part_offset = 0; /* network drive */ if ((current_drive == NETWORK_DRIVE) || (current_drive==PXE_DRIVE)) { @@ -1158,13 +982,13 @@ real_open_partition (int flags) } if (current_drive == FB_DRIVE) - { - bsd_evil_hack = 0; - current_slice = 0; - part_start = 0; - part_length = 0; - return 1; - } + { + bsd_evil_hack = 0; + current_slice = 0; + part_start = 0; + part_length = 0; + return 1; + } if (! sane_partition ()) return 0; @@ -1175,15 +999,15 @@ real_open_partition (int flags) /* Make sure that buf_geom is valid. */ if (buf_drive != current_drive) - { - if (get_diskinfo (current_drive, &buf_geom, 0)) { - errnum = ERR_NO_DISK; - return 0; + if (get_diskinfo (current_drive, &buf_geom, 0)) + { + errnum = ERR_NO_DISK; + return 0; + } + buf_drive = current_drive; + buf_track = -1; } - buf_drive = current_drive; - buf_track = -1; - } part_length = buf_geom.total_sectors; if (buf_geom.sector_size == 2048) @@ -1199,143 +1023,174 @@ real_open_partition (int flags) /* Initialize CURRENT_PARTITION for next_partition. */ current_partition = 0xFFFFFF; - while (next_part ()) - { - loop_start: - - cur_part_offset = part_offset; - cur_part_addr = BOOT_PART_TABLE + (entry << 4); - cur_part_start = part_start; - cur_part_entry = entry; - - /* If this is a valid partition... */ - if (current_slice) + //next_partition_buf = mbr; + struct grub_part_data *q; + int i; + for (i=0; (flags ? (i < 16) : (i < 1)); i++) { - /* Display partition information. */ - if (flags && ! IS_PC_SLICE_TYPE_EXTENDED (current_slice)) - { - if (! do_completion) - { - //if (current_drive & 0x80) - { - int active = (PC_SLICE_FLAG (mbr, entry) == PC_SLICE_FLAG_BOOTABLE); - grub_printf (" Partition num: %d%s, ", - (unsigned long)(unsigned char)(current_partition >> 16), (active ? ", active": "")); - } - - if (! IS_PC_SLICE_TYPE_BSD (current_slice)) - check_and_print_mount (); - else - { - int got_part = 0; - int saved_slice = current_slice; - - while (next_part ()) - { - if (bsd_part_no == 0xFF) - break; - - if (! got_part) - { - grub_printf ("[BSD sub-partitions immediately follow]\n"); - got_part = 1; - } - - grub_printf (" BSD Partition num: \'%c\', ", - (bsd_part_no + 'a')); - check_and_print_mount (); - } - - if (! got_part) - grub_printf (" No BSD sub-partition found, partition type 0x%x\n", - saved_slice); + if (flags) + q = get_partition_info (current_drive, (i<<16 | 0xffff)); + else + q = get_partition_info (current_drive, dest_partition); + if (!q) + continue; - if (errnum) - { - errnum = ERR_NONE; - break; - } + loop_start: + + current_partition = q->partition; + bsd_part_no = (current_partition >> 8) & 0xFF; + pc_slice_no = current_partition >> 16; + current_slice = q->partition_type; + + part_start = q->partition_start; +// cur_part_start = part_start; +// cur_part_offset = q->partition_offset; +// cur_part_addr = BOOT_PART_TABLE + (q->partition_entry << 4); +// cur_part_entry = q->partition_entry; - goto loop_start; - } - } - else + /* If this is a valid partition... */ + if (current_slice) { - if (bsd_part_no != 0xFF) - { - char str[16]; - - if (! (current_drive & 0x80) - || (dest_partition >> 16) == pc_slice_no) - grub_sprintf (str, "%c)", (bsd_part_no + 'a')); - else - grub_sprintf (str, "%d,%c)", - pc_slice_no, (bsd_part_no + 'a')); - print_a_completion (str, 0); - } - else if (! IS_PC_SLICE_TYPE_BSD (current_slice)) - { - char str[8]; - - grub_sprintf (str, "%d)", pc_slice_no); - print_a_completion (str, 0); - } - } - } - - errnum = ERR_NONE; - - /* Check if this is the destination partition. */ - if (! flags - && (dest_partition == current_partition - || ((dest_partition >> 16) == 0xFF + /* Display partition information. */ + if (flags && ! IS_PC_SLICE_TYPE_EXTENDED (current_slice)) + { + if (! do_completion) + { +// int active = (PC_SLICE_FLAG (mbr, entry) == PC_SLICE_FLAG_BOOTABLE); + int active = q->partition_activity_flag; + grub_printf (" Partition num: %d%s, ", + (unsigned int)(unsigned char)(current_partition >> 16), (active ? ", active": "")); + + if (! IS_PC_SLICE_TYPE_BSD (current_slice)) + check_and_print_mount (); + else + { + int got_part = 0; + + + int saved_slice = current_slice; + + int j; + for (j=0; (flags ? (j < 16) : (j < 1)); j++) + { + if (flags) + q = get_partition_info (current_drive, (j<<16 | 0xffff)); + else + q = get_partition_info (current_drive, dest_partition); + if (!q) + continue; + current_partition = q->partition; + bsd_part_no = (current_partition >> 8) & 0xFF; + pc_slice_no = current_partition >> 16; + + if (bsd_part_no == 0xFF) + break; + + if (! got_part) + { + grub_printf ("[BSD sub-partitions immediately follow]\n"); + got_part = 1; + } + + grub_printf (" BSD Partition num: \'%c\', ", + (bsd_part_no + 'a')); + check_and_print_mount (); + } + if ((flags && j == 16) || (!flags && j == 1)) + { + return !(errnum = ERR_NO_PART); + } + if (! got_part) + grub_printf (" No BSD sub-partition found, partition type 0x%x\n", + saved_slice); + + if (errnum) + { + errnum = ERR_NONE; + break; + } + + goto loop_start; + } + }//if (! do_completion) + else + { + if (bsd_part_no != 0xFF) + { + char str[16]; + + if (! (current_drive & 0x80) + || (dest_partition >> 16) == pc_slice_no) + grub_sprintf (str, "%c)", (bsd_part_no + 'a')); + else + grub_sprintf (str, "%d,%c)", + pc_slice_no, (bsd_part_no + 'a')); + print_a_completion (str, 0); + } + else if (! IS_PC_SLICE_TYPE_BSD (current_slice)) + { + char str[8]; + + grub_sprintf (str, "%d)", pc_slice_no); + print_a_completion (str, 0); + } + } + }//if (flags && ! IS_PC_SLICE_TYPE_EXTENDED (current_slice)) + + errnum = ERR_NONE; + + /* Check if this is the destination partition. */ + if (! flags + && (dest_partition == current_partition + || ((dest_partition >> 16) == 0xFF && ((dest_partition >> 8) & 0xFF) == bsd_part_no))) - return 1; + return 1; + }//if (current_slice) + }// while (next_part ()) + if ((flags && i == 16) || (!flags && i == 1)) + { + return !(errnum = ERR_NO_PART); } - } if (flags) - { - if (! (current_drive & 0x80)) { - current_partition = 0xFFFFFF; - check_and_print_mount (); - } + if (! (current_drive & 0x80)) + { + current_partition = 0xFFFFFF; + check_and_print_mount (); + } - errnum = ERR_NONE; - return 1; - } + errnum = ERR_NONE; + return 1; + } return 0; } - +int open_partition (void); int open_partition (void) { return real_open_partition (0); } - +static int sane_partition (void); static int sane_partition (void) { /* network drive */ - if (current_drive == PXE_DRIVE) + if (current_drive == PXE_DRIVE) //0x21 + return 1; + + /* ram drive */ + if (current_drive == ram_drive) return 1; -// -// /* ram drive */ -// if (current_drive == ram_drive) -// return 1; if (!(current_partition & 0xFF000000uL) /* the drive field must be 0 */ -// && ((current_drive & 0xFFFFFF7F) < 8 /* and the drive must be < 8 ... */ -// || current_drive == cdrom_drive) /* ... or it is cdrom */ && (current_partition & 0xFF) == 0xFF /* the low byte is not used and must be 0xFF */ && ((current_partition & 0xFF00) == 0xFF00 /* the higher byte must be 0xFF for normal ... */ - || (current_partition & 0xFF00) < 0x800) /* ... or < 8 for BSD partitions */ - /*&& ((current_partition >> 16) == 0xFF*/ /* the partition field must be whole-drive for floppy */ - /* || (current_drive & 0x80)) */) /* ... or it is hard drive */ + || (current_partition & 0xFF00) < 0x800) /* ... or < 8 for BSD partitions */ + ) /* ... or it is hard drive */ return 1; errnum = ERR_DEV_VALUES; @@ -1344,11 +1199,11 @@ sane_partition (void) /* Parse a device string and initialize the global parameters. */ +char * set_device (char *device); char * set_device (char *device) { int result = 0; - errnum = 0; incomplete = 0; disk_choice = 1; @@ -1363,7 +1218,7 @@ set_device (char *device) if (*device == '(' && *(++device)) { if (*device == ')') /* the device "()" is for the current root */ - { + { current_partition = saved_partition; return device + 1; } @@ -1374,7 +1229,7 @@ set_device (char *device) #ifdef FSYS_PXE || (*device == 'p' && pxe_entry) #endif /* FSYS_PXE */ - || (*device == 'c' && (cdrom_drive != GRUB_INVALID_DRIVE || atapi_dev_count))) + || (*device == 'c' /*&& (cdrom_drive != GRUB_INVALID_DRIVE || atapi_dev_count)*/)) { /* user has given '([fhn]', check for resp. add 'd' and let disk_choice handle what disks we have */ @@ -1388,7 +1243,34 @@ set_device (char *device) else if (*(device + 1) == 'd' && !*(device + 2)) return device + 2; } + + if (pxe_entry && *(device+3) == 'p') + { + if (grub_memcmp(device,"tftp",4) == 0) + { + if (cur_pxe_type) + cur_pxe_type = 0; + current_drive = PXE_DRIVE; //0x21 + device += 4; + } + else if (grub_memcmp(device,"http",4) == 0) + { + if (!cur_pxe_type && !only_tftp) + cur_pxe_type = 1; + current_drive = PXE_DRIVE; //0x21 + device += 4; + if (*(device + 4) == 's') + { + device++; + pxe_http_type = 1; //https + } + else + pxe_http_type = 0; //http + } + goto aaa; + } + if ((*device == 'f' || *device == 'h' || *device == 'm' @@ -1396,38 +1278,48 @@ set_device (char *device) || *device == 'b' #ifdef FSYS_PXE || (*device == 'p' && pxe_entry) + #if 0 #ifdef FSYS_IPXE || (*device == 'w' && has_ipxe) #endif + #endif #endif #ifdef FSYS_FB || (*device == 'u' && fb_status) #endif - || (*device == 'c' && (cdrom_drive != GRUB_INVALID_DRIVE || atapi_dev_count))) + || (*device == 'c' /*&& (cdrom_drive != GRUB_INVALID_DRIVE || atapi_dev_count)*/)) && *(++device, device++) != 'd') errnum = ERR_NUMBER_PARSING; - #ifdef FSYS_PXE if (ch == 'p' && pxe_entry) - current_drive = PXE_DRIVE; + current_drive = PXE_DRIVE; //0x21 else + #if 0 #ifdef FSYS_IPXE if (ch == 'w' && has_ipxe) { - current_drive = PXE_DRIVE; - current_partition = IPXE_PART; + current_drive = PXE_DRIVE; //0x21 + current_partition = IPXE_PART; //0x45585069 } else #endif + #endif #endif /* FSYS_PXE */ + #ifdef FSYS_FB if (ch == 'u' && fb_status) current_drive = FB_DRIVE; else #endif /* FSYS_FB */ { - if (ch == 'c' && cdrom_drive != GRUB_INVALID_DRIVE && *device == ')') - current_drive = cdrom_drive; + if (ch == 'c' /*&& cdrom_drive != GRUB_INVALID_DRIVE*/ && *device == ')') //(cd) + { + current_drive = (unsigned char)(0xa0 + cdrom_orig); + } + else if (ch == 'f' && *device == ')') //(fd) + { + current_drive = (unsigned char)(floppies_orig); + } else if (ch == 'm') { current_drive = 0xffff; @@ -1450,10 +1342,10 @@ set_device (char *device) current_drive = boot_drive; return device + 1; } - else if (ch == 'h' && (*device == ',' || *device == ')')) + else if (ch == 'h' && (*device == ',' || *device == ')')) //(hd) { /* it is (hd) for the next new drive that can be added. */ - current_drive = (unsigned char)(0x80 + (*(unsigned char *)0x475)); + current_drive = (unsigned char)(0x80 + harddrives_orig); } else { @@ -1462,30 +1354,46 @@ set_device (char *device) safe_parse_maxint (&device, &ull); current_drive = ull; disk_choice = 0; - if (ch == 'h') + + if (ch == 'h') //(hd-1) 取最后一块硬盘 { if ((long long)ull < 0) { - if ((-ull) <= (unsigned long long)(*(unsigned char *)0x475)) - current_drive = (unsigned char)(0x80 + (*(unsigned char *)0x475) + current_drive); + if ((-ull) <= (unsigned long long)harddrives_orig) + current_drive = (unsigned char)(0x80 + harddrives_orig + current_drive); else - return (char *)!(errnum = ERR_DEV_FORMAT); + return (char *)(grub_size_t)!(errnum = ERR_DEV_FORMAT); } else current_drive |= 0x80; } - //else if (ch == 'c' && cdrom_drive != GRUB_INVALID_DRIVE && current_drive < 8) - //{ - // if (cdrom_drives[current_drive] != GRUB_INVALID_DRIVE) - // current_drive = cdrom_drives[current_drive]; - //} - else if (ch == 'c' && atapi_dev_count && current_drive < (unsigned long)atapi_dev_count) + else if (ch == 'c') + { + if ((long long)ull < 0) + { + if ((-ull) <= (unsigned long long)cdrom_orig) + current_drive = (unsigned char)(0xa0 + cdrom_orig + current_drive); + else + return (char *)(grub_size_t)!(errnum = ERR_DEV_FORMAT); + } + else + current_drive |= 0xa0; + } + else if (ch == 'f') { - current_drive += min_cdrom_id; + if ((long long)ull < 0) + { + if ((-ull) <= (unsigned long long)floppies_orig) + current_drive = (unsigned char)(0 + floppies_orig + current_drive); + else + return (char *)(grub_size_t)!(errnum = ERR_DEV_FORMAT); + } + else + current_drive |= 0; } } } } - +aaa: if (errnum) return 0; @@ -1518,7 +1426,6 @@ set_device (char *device) if (*device == ',') device++; - if (*device >= 'a' && *device <= 'h') { current_partition = (((*(device++) - 'a') << 8) @@ -1530,7 +1437,6 @@ set_device (char *device) part_choice ++; current_partition = ((*(device++) - 'a') << 8) | 0xFF00FF; } - if (*device == ')') { if (part_choice == PART_DISK) @@ -1546,7 +1452,6 @@ set_device (char *device) if (! sane_partition ()) return 0; - if (result) return device + 1; else @@ -1555,19 +1460,18 @@ set_device (char *device) incomplete = 1; errnum = ERR_DEV_FORMAT; } - return 0; } +static char *setup_part (char *filename); static char * setup_part (char *filename) { relative_path = 1; - if (*filename == '(') { relative_path = 0; - if ((filename = set_device (filename)) == 0) + if ((filename = (char *)set_device (filename)) == 0) { current_drive = GRUB_INVALID_DRIVE; return 0; @@ -1582,7 +1486,7 @@ setup_part (char *filename) else if (saved_drive != current_drive || saved_partition != current_partition || (*filename == '/' && fsys_type == NUM_FSYS) - || buf_drive == -1) + || buf_drive == (unsigned int)-1) { current_drive = saved_drive; current_partition = saved_partition; @@ -1595,7 +1499,6 @@ setup_part (char *filename) # endif /* ! NO_BLOCK_FILES */ open_device (); } - if (errnum && (*filename == '/' || errnum != ERR_FSYS_MOUNT)) return 0; else @@ -1607,25 +1510,18 @@ setup_part (char *filename) return filename; } - -///* Reposition a file offset. */ -//unsigned long -//grub_seek (unsigned long offset) -//{ -// if (offset > filemax /*|| offset < 0*/) -// return -1; -// -// filepos = offset; -// return offset; -//} +static int set_filename(char *filename); static int set_filename(char *filename) { - char ch = nul_terminate(filename); + char ch = 0; + if (current_drive != 0x21) + ch = nul_terminate(filename); //以00替换止字符串的空格,回车,换行,水平制表符 int i = grub_strlen(filename); int j = grub_strlen(saved_dir); int k; - if (i >= sizeof(open_filename) || (relative_path && grub_strlen(saved_dir)+i >= sizeof(open_filename))) + grub_memset (open_filename, 0, 512); + if (i >= (int)sizeof(open_filename) || (relative_path && grub_strlen(saved_dir)+i >= (int)sizeof(open_filename))) return !(errnum = ERR_WONT_FIT); if (relative_path) @@ -1635,24 +1531,31 @@ static int set_filename(char *filename) for (k = 0; filename[k]; k++) { - if (filename[k] == '"' || filename[k] == '\\' ) + if (current_drive != 0x21 && (filename[k] == '"' || filename[k] == '\\')) continue; else open_filename[j++] = filename[k]; } - open_filename[j] = 0; - filename[i] = ch; - +// open_filename[j] = 0; + if (current_drive != 0x21) + filename[i] = ch; return 1; } +int dir (char *dirname); int dir (char *dirname) { - int ret; + int ret, test = 0; #ifndef NO_DECOMPRESSION compressed_file = 0; #endif /* NO_DECOMPRESSION */ + if (grub_memcmp (dirname, "--test", 6) == 0) //ls --test /efi/grub/menu.lst 探测文件存在否。不打印信息,存在返回1,否则0. + { + test = 1; + dirname += 6; + dirname = skip_to (0, dirname); + } if (!(dirname = setup_part (dirname))) return 0; @@ -1663,29 +1566,40 @@ dir (char *dirname) if (fsys_type == NUM_FSYS) return !(errnum = ERR_FSYS_MOUNT); - if (set_filename(dirname) == 0) + if (set_filename((char *)dirname) == 0) return 0; /* set "dir" function to list completions */ print_possibilities = 1; - + if (test) + putchar_hooked = (unsigned char*)1; //不打印ls_func信息 ret = (*(fsys_table[fsys_type].dir_func)) (open_filename); if (!ret && !errnum) errnum = ERR_FILE_NOT_FOUND; + if (test) + { + errnum = 0; + putchar_hooked = 0; + } + return ret; } /* If DO_COMPLETION is true, just print NAME. Otherwise save the unique part into UNIQUE_STRING. */ +void print_a_completion (char *filename, int case_insensitive); void print_a_completion (char *name, int case_insensitive) { - char tem[256]; - char *p = tem; +// char tem[256]; +// char *p = tem; /* If NAME is "." or "..", do not count it. */ if (grub_strcmp (name, ".") == 0 || grub_strcmp (name, "..") == 0) return; + char *tem = grub_malloc (256); + char *p = tem; + while (*name) { if (*name == ' ') @@ -1721,13 +1635,14 @@ print_a_completion (char *name, int case_insensitive) grub_printf (" %s", name); unique++; + grub_free (tem); } /* * This lists the possible completions of a device string, filename, or * any sane combination of the two. */ - +int print_completions (int is_filename, int is_completion); int print_completions (int is_filename, int is_completion) { @@ -1754,7 +1669,7 @@ print_completions (int is_filename, int is_completion) continue; if (substring (buf, (*builtin)->name, 0) <= 0) - print_a_completion ((*builtin)->name, 0); + print_a_completion ((char *)(*builtin)->name, 0); } if (is_completion && *unique_string) @@ -1781,7 +1696,7 @@ print_completions (int is_filename, int is_completion) return unique - 1; } - if (*buf == '/' || (ptr = set_device (buf)) || incomplete) + if (*buf == '/' || (ptr = (char *)set_device (buf)) || incomplete) { errnum = 0; @@ -1791,7 +1706,6 @@ print_completions (int is_filename, int is_completion) { /* disk completions */ int j; -// struct geometry tmp_geom; if (! is_completion) grub_printf (" Possible disks are: "); @@ -1807,20 +1721,21 @@ print_completions (int is_filename, int is_completion) k < (ptr && (*(ptr-1) == 'd' && *(ptr-2) == 'f') ? 1:2); k++) { -#define HARD_DRIVES (*((char *)0x475)) -#define FLOPPY_DRIVES ((*(char*)0x410 & 1)?(*(char*)0x410 >> 6) + 1 : 0) + +#define HARD_DRIVES harddrives_orig +#define FLOPPY_DRIVES floppies_orig for (j = 0; j < (k ? HARD_DRIVES : FLOPPY_DRIVES); j++) #undef HARD_DRIVES #undef FLOPPY_DRIVES { - unsigned long i; + unsigned int i; i = (k * 0x80) + j; if ((disk_choice || i == current_drive) && ! get_diskinfo (i, &tmp_geom, 0)) { char dev_name[8]; - grub_sprintf (dev_name, "%cd%d", (k ? 'h':'f'), (unsigned long)j); + grub_sprintf (dev_name, "%cd%d", (k ? 'h':'f'), (unsigned int)j); print_a_completion (dev_name, 0); } } @@ -1832,43 +1747,22 @@ print_completions (int is_filename, int is_completion) && (!ptr || *(ptr-1) == '(' || (*(ptr-1) == 'd' && *(ptr-2) == 'r'))) - print_a_completion ("rd", 0); - - if (cdrom_drive != GRUB_INVALID_DRIVE - && (disk_choice || cdrom_drive == current_drive) - && (!ptr - || *(ptr-1) == '(' - || (*(ptr-1) == 'd' && *(ptr-2) == 'c'))) - print_a_completion ("cd", 0); - - if (atapi_dev_count && (!ptr || *(ptr-1) == '(' || (*(ptr-1) == 'd' && *(ptr-2) == 'c'))) - { - for (j = 0; j < (unsigned long)atapi_dev_count; j++) - if (disk_choice || min_cdrom_id + j == current_drive) - { - char dev_name[8]; - - grub_sprintf (dev_name, "cd%d", (unsigned long)j); - print_a_completion (dev_name, 0); - } - } - + print_a_completion ((char *)"rd", 0); # ifdef FSYS_PXE if (pxe_entry && (disk_choice || PXE_DRIVE == current_drive) && (!ptr || *(ptr-1) == '(' || (*(ptr-1) == 'd' && *(ptr-2) == 'p'))) - print_a_completion ("pd", 0); + print_a_completion ((char *)"pd", 0); # endif /* FSYS_PXE */ - # ifdef FSYS_FB if (fb_status && (disk_choice || FB_DRIVE == current_drive) && (!ptr || *(ptr-1) == '(' || (*(ptr-1) == 'd' && *(ptr-2) == 'u'))) - print_a_completion ("ud", 0); + print_a_completion ((char *)"ud", 0); #endif /* FSYS_FB */ if (is_completion && *unique_string) @@ -2005,7 +1899,7 @@ struct BLK_BUF { /* * This is the generic file open function. */ - +int grub_open (char *filename); int grub_open (char *filename) { @@ -2018,10 +1912,8 @@ grub_open (char *filename) /* if any "dir" function uses/sets filepos, it must set it to zero before returning if opening a file! */ filepos = 0; - if (!(filename = setup_part (filename))) return 0; - #ifndef NO_BLOCK_FILES block_file = 0; #endif /* NO_BLOCK_FILES */ @@ -2031,6 +1923,7 @@ grub_open (char *filename) if (*filename != '/') { +#if 0 #ifdef FSYS_IPXE if (has_ipxe) { @@ -2042,15 +1935,18 @@ grub_open (char *filename) } } #endif +#endif + if (current_drive == 0x21) //2024-12-12 + { + fsys_type = 0; + goto not_block_file; + } #ifdef NO_BLOCK_FILES return !(errnum = ERR_BAD_FILENAME); #else char *ptr = filename; - //unsigned long list_addr = FSYS_BUF + 12; /* BLK_BLKLIST_START */ struct BLK_LIST_ENTRY *p_blklist = blk_buf.blklist; filemax = 0; - - //while (list_addr < FSYS_BUF + 0x77F9) /* BLK_MAX_ADDR */ while (p_blklist < blk_max_ptr) { unsigned long long tmp; @@ -2078,7 +1974,6 @@ grub_open (char *filename) be remounted */ fsys_type = NUM_FSYS; - //*((unsigned long*)list_addr) = tmp; /* BLK_BLKSTART */ p_blklist->start = tmp; ptr++; /* skip the plus sign */ @@ -2090,12 +1985,9 @@ grub_open (char *filename) if (!tmp || (*ptr && *ptr != ',' && *ptr != '/' && !isspace (*ptr))) break; /* failure */ - //*((unsigned long*)(list_addr+4)) = tmp; /* BLK_BLKLENGTH */ p_blklist->length = tmp; - //tmp *= buf_geom.sector_size; filemax += tmp * buf_geom.sector_size; - //list_addr += 8; /* BLK_BLKLIST_INC_VAL */ ++p_blklist; if (*ptr != ',') @@ -2103,24 +1995,16 @@ grub_open (char *filename) ptr++; /* skip the comma sign */ } /* while (list_addr < FSYS_BUF + 0x77F9) */ - return !(errnum = ERR_BAD_FILENAME); -// if (list_addr < FSYS_BUF + 0x77F9 && ptr != filename) -// { block_file: block_file = 1; - //(*((unsigned long*)FSYS_BUF))= 0; /* BLK_CUR_FILEPOS */ - //(*((unsigned long*)(FSYS_BUF+4))) = FSYS_BUF + 12; /* let BLK_CUR_BLKLIST = BLK_BLKLIST_START */ - //(*((unsigned long*)(FSYS_BUF+8))) = 0; /* BLK_CUR_BLKNUM */ blk_buf.cur_filepos = 0; blk_buf.cur_blklist = blk_buf.blklist; blk_buf.cur_blknum = 0; blk_sector_bit = 9; while((buf_geom.sector_size >> blk_sector_bit) > 1) ++blk_sector_bit; - // if ((1<length - blk_buf.cur_blknum) * (buf_geom.sector_size) - - off; + tmp = (unsigned long long)(blk_buf.cur_blklist->length - blk_buf.cur_blknum) * (buf_geom.sector_size) - off; if (tmp > 0x40000000) tmp = 0x40000000; - size = (tmp > len) ? (unsigned long)len : (unsigned long)tmp; + size = (tmp > len) ? (unsigned int)len : (unsigned int)tmp; } disk_read_func = disk_read_hook; /* read current block and put it in the right place in memory */ - //devread ((*((unsigned long*)(*((unsigned long*)(FSYS_BUF+4))))) + (*((unsigned long*)(FSYS_BUF+8))), - // off, size, buf, write); devread (blk_buf.cur_blklist->start + blk_buf.cur_blknum, off, size, buf, write); disk_read_func = NULL; @@ -2274,30 +2151,28 @@ block_read_func (unsigned long long buf, unsigned long long len, unsigned long w unsigned long long grub_read_loop_threshold = 0x800000ULL; // 8MB unsigned long long grub_read_step = 0x800000ULL; // 8MB +unsigned long long grub_read (unsigned long long buf, unsigned long long len, unsigned int write); unsigned long long -grub_read (unsigned long long buf, unsigned long long len, unsigned long write) +grub_read (unsigned long long buf, unsigned long long len, unsigned int write) { -// if (write != 0x900ddeed && write != 0xedde0d90) -// return !(errnum = ERR_FUNC_CALL); - -// if (filepos > filemax) -// filepos = filemax; if (filepos >= filemax) - return 0;//!(errnum = ERR_FILELENGTH); +// return !(errnum = ERR_FILELENGTH); + return 0; if (len > filemax - filepos) len = filemax - filepos; /* if target file position is past the end of the supported/configured filesize, then - there is an error */ + there is an error + 如果目标文件位置超过了支持/配置的文件大小的末尾,则存在错误 + */ if (filepos + len > fsmax) return !(errnum = ERR_FILELENGTH); errnum = 0; - - unsigned long long (*read_func) (unsigned long long _buf, unsigned long long _len, unsigned long _write); - + unsigned long long (*read_func) (unsigned long long _buf, unsigned long long _len, unsigned int _write); + //1. 确定读方法 #ifndef NO_DECOMPRESSION if (compressed_file) { @@ -2316,28 +2191,26 @@ grub_read (unsigned long long buf, unsigned long long len, unsigned long write) } else #endif /* NO_BLOCK_FILES */ - if (fsys_type == NUM_FSYS) return !(errnum = ERR_FSYS_MOUNT); else read_func = fsys_table[fsys_type].read_func; - /* Now, read_func is ready. */ - if ((!buf) || (len < grub_read_loop_threshold) -#ifdef FSYS_IPXE - || fsys_table[fsys_type].read_func == pxe_read -#endif + //2.读文件 + if ((!buf) //缓存为零 + || (len < grub_read_loop_threshold) //尺寸小于8MB + || fsys_table[fsys_type].read_func == pxe_read //网起 #ifndef NO_DECOMPRESSION - || (compressed_file && decomp_type == DECOMP_TYPE_LZMA) + || (compressed_file && decomp_type == DECOMP_TYPE_LZMA) //压缩文件并且是LZMA类型 #endif /* NO_DECOMPRESSION */ ) { - /* Do whole request at once. */ + /* Do whole request at once. 一次性完成全部请求。*/ return read_func(buf, len, write); } else { - /* Transfer small amount of data at a time and print progress. */ + /* Transfer small amount of data at a time and print progress. 一次传输少量数据并打印进度。*/ unsigned long long byteread = 0; unsigned long long remaining = len; while (remaining) @@ -2352,16 +2225,13 @@ grub_read (unsigned long long buf, unsigned long long len, unsigned long write) buf += ret1; /* Don't do this if buf is 0 */ remaining -= ret1; } -#if 0 - if (remaining) - grub_printf("\r[%ldM/%ldM]\n",byteread>>20,len>>20); - else -#endif + grub_printf("\r \r"); return byteread; } } +void grub_close (void); void grub_close (void) { @@ -2379,3 +2249,3048 @@ grub_close (void) if (fsys_table[fsys_type].close_func != 0) (*(fsys_table[fsys_type].close_func)) (); } + +int get_diskinfo (unsigned int drive, struct geometry *geometry, unsigned int partition); +int +get_diskinfo (unsigned int drive, struct geometry *geometry, unsigned int partition) +{ + struct grub_disk_data *p; //磁盘数据 + + if (drive == 0xffff || drive == ram_drive) + { + geometry->sector_size = 512; + if (drive == ram_drive) //2024-12-12 + geometry->total_sectors = rd_size >> 9; + else + geometry->total_sectors = -1; + geometry->log2_sector_size = 9; + return 0; + } + + p = get_device_by_drive (drive,0); + if (p) + { + geometry->sector_size = 1 << p->from_log2_sector; +// geometry->total_sectors = p->sector_count; + geometry->total_sectors = p->total_sectors; + geometry->log2_sector_size = p->from_log2_sector; +#if VHD_DIFFERENCE + geometry->vhd_disk = p->vhd_disk; +#endif + return 0; //成功 + } + + return 1; +} + +//============================================================================================================================== + + +//disk.h +/* The sector size. */ +#define GRUB_DISK_SECTOR_SIZE 0x200 +#define GRUB_DISK_SECTOR_BITS 9 + +//efidisk +void partition_info_init (struct efidisk_data *devices); +/* GUID. */ +static grub_efi_guid_t block_io_guid = GRUB_EFI_BLOCK_IO_GUID; + +//struct grub_part_data* partition_info_tmp = 0; +struct grub_disk_data* previous_struct = 0; + +//由枚举磁盘调用 +//static struct grub_disk_data *make_devices (void); +//static struct grub_disk_data * +static struct efidisk_data *make_devices (void); +static struct efidisk_data * +make_devices (void) //制作设备 +{ + grub_efi_uintn_t num_handles; //句柄数 api返回 + grub_efi_handle_t *handles; //句柄集 api返回 + grub_efi_handle_t *handle; //句柄 + struct efidisk_data *devices = 0; + + /* Find handles which support the disk io interface. 查找支持磁盘IO接口的句柄 */ + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &block_io_guid, + 0, &num_handles); //定位句柄 返回句柄集及句柄数 + if (! handles) //如果没有句柄集 + return 0; + printf_debug ("make_devices:\n"); + /* Make a linked list of devices. 制作设备的链表 */ + for (handle = handles; num_handles--; handle++) + { + grub_efi_device_path_t *dp; //设备路径 + grub_efi_device_path_t *ldp; //最后一个设备路径 + struct efidisk_data *d; //磁盘数据 + grub_efi_block_io_t *bio; + + dp = grub_efi_get_device_path (*handle); //获得设备路径 通过协议 + if (! dp) //如果失败,继续 + continue; + if (debug > 1) + { + grub_efi_print_device_path(dp); + getkey(); + } + + ldp = grub_efi_find_last_device_path (dp); //查找最后设备路径 + if (! ldp) //如果失败,继续 + continue; + + bio = grub_efi_open_protocol (*handle, &block_io_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); //打开协议 获得协议 块输入输出 + if (! bio) //如果失败,继续 + /* This should not happen... Why? 这不应该发生…为什么 */ + continue; + /* iPXE adds stub Block IO protocol to loaded image device handle. It is IPXE将存根块IO协议添加到加载的图像设备句柄。 + completely non-functional and simply returns an error for every method. 它完全是非功能性的,只为每个方法返回一个错误。 + So attempt to detect and skip it. Magic number is literal "iPXE" and 因此,尝试检测并跳过它。幻数是字面“IPXE”和检查块大小. + check block size as well */ + /* FIXME: shoud we close it? We do not do it elsewhere 我们关闭它吗?我们不在别处做 */ + if (bio->media && bio->media->media_id == 0x69505845U && + bio->media->block_size == 1) + continue; + + d = grub_zalloc (sizeof (*d)); //分配内存 + if (! d) //如果分配内存失败 + { + /* Uggh. */ + grub_free (handles); //释放内存 + while (devices) //设备存在 + { + d = devices->next; + grub_free (devices); //释放设备 + devices = d; + } + return 0; + } + + //填充设备结构 + d->device_handle = *handle; + d->device_path = dp; + d->last_device_path = ldp; + d->block_io = bio; + + if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE) //4 媒体类型 + { + if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE) //1 硬盘子类型 + { +// d->partition_number = ((grub_efi_hard_drive_device_path_t *)ldp)->partition_number; + d->partition_start = ((grub_efi_hard_drive_device_path_t *)ldp)->partition_start; + d->partition_size = ((grub_efi_hard_drive_device_path_t *)ldp)->partition_size; +// grub_memcpy (&d->partition_signature, &((grub_efi_hard_drive_device_path_t *)ldp)->partition_signature, 16); + } + else if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE) //2 光盘子类型 + { +// d->partition_number = ((grub_efi_cdrom_device_path_t *)ldp)->boot_entry; + d->partition_start = ((grub_efi_cdrom_device_path_t *)ldp)->boot_start; + d->partition_size = ((grub_efi_cdrom_device_path_t *)ldp)->boot_size; + } + } + d->next = devices; + devices = d; + } + + grub_free (handles); + return devices; +} + + +/* Find the parent device.*/ +//由命名设备调用 +//static struct grub_disk_data *find_parent_device (struct grub_disk_data *devices, struct grub_disk_data *d); +//static struct grub_disk_data * +//find_parent_device (struct grub_disk_data *devices, +// struct grub_disk_data *d) //查找父设备 +static struct efidisk_data *find_parent_device (struct efidisk_data *devices, struct efidisk_data *d); +static struct efidisk_data * +find_parent_device (struct efidisk_data *devices, + struct efidisk_data *d) //查找父设备(设备句柄集,设备句柄) +{ + grub_efi_device_path_t *dp, *ldp; //设备路径 +// struct grub_disk_data *parent; //磁盘数据 + struct efidisk_data *parent; //磁盘数据 + + dp = grub_efi_duplicate_device_path (d->device_path); //复制设备路径 + if (! dp) //如果为零 + return 0; + + ldp = grub_efi_find_last_device_path (dp); //查找最后设备路径 + //把最后设备路径修改为结束 + ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; //0x7f + ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; //0xff + ldp->length = sizeof (*ldp); + + for (parent = devices; parent; parent = parent->next) + { + /* Ignore itself. 忽略自己*/ + if (parent == d) //如果父=自己, 继续 + continue; + + if (grub_efi_compare_device_paths (parent->device_path, dp) == 0) //比较父与复制的设备路径, 如果相同, 结束循环 + break; + } + + grub_free (dp); //释放复制设备路径产生的内存 + return parent; //返回父 +} + +/* Add a device into a list of devices in an ascending order. 以升序将设备添加到设备列表中 */ +//由命名设备调用 +//static void add_device (unsigned char disk_type, struct grub_disk_data *d); +//static void +//add_device (unsigned char disk_type, struct grub_disk_data *d) //增加设备 添加d到devices +static void add_device (unsigned char disk_type, struct efidisk_data *d); +static void +add_device (unsigned char disk_type, struct efidisk_data *d) //增加设备 添加d到devices +{ + struct grub_disk_data **p; //磁盘数据 + struct grub_disk_data *n; //磁盘数据 +// struct efidisk_data **p; //磁盘数据 +// struct efidisk_data *n; //磁盘数据 +#if 0 +// for (p = (struct grub_disk_data **)(grub_size_t)&disk_data; *p; p = &((*p)->next)) + for (p = (struct efidisk_data **)(grub_size_t)&disk_data; *p; p = &((*p)->next)) + { + int ret; + + ret = grub_efi_compare_device_paths (grub_efi_find_last_device_path ((*p)->device_path), + grub_efi_find_last_device_path (d->device_path)); //比较devices与d的设备路径 返回: 0/1/-1=相等/不相等/包含 + if (ret == 0) //如果相同 + ret = grub_efi_compare_device_paths ((*p)->device_path, + d->device_path); //再比较一次设备路径 有必要??? + if (ret == 0) //如果相同, 返回(不添加) + return; + else if (ret > 0) //如果不同, 退出循环 + break; + } +#else + p = (struct grub_disk_data **)(grub_size_t)&disk_data; +#endif + n = grub_zalloc (sizeof (*n)); //分配内存cdrom_orig + if (! n) + return; + n->device_handle = d->device_handle; +// n->device_path = d->device_path; + n->block_io = d->block_io; + n->from_log2_sector = log2_tmp(d->block_io->media->block_size); + n->total_sectors = d->block_io->media->last_block + 1; + + n->next = (*p); //下一个 //0 + (*p) = n; //保存已分配内存 + if (disk_type == DISK_TYPE_CD) + { + n->disk_type = DISK_TYPE_CD; + cdrom_orig++; + } + else if (disk_type == DISK_TYPE_HD) + { + n->disk_type = DISK_TYPE_HD; + harddrives_orig++; + } + else if (disk_type == DISK_TYPE_FD) + { + n->disk_type = DISK_TYPE_FD; + floppies_orig++; + } +} + +//由枚举磁盘调用 +/* Name the devices. 命名设备 */ +//static void name_devices (struct grub_disk_data *devices); +//static void +//name_devices (struct grub_disk_data *devices) //命名设备 +static void name_devices (struct efidisk_data *devices); +static void +name_devices (struct efidisk_data *devices) //命名设备 +{ + struct efidisk_data *d; //磁盘数据 + printf_debug ("name_devices:\n"); + /* First, identify devices by media device paths. 首先,识别媒体设备路径类型的设备 */ + for (d = devices; d; d = d->next) + { + grub_efi_device_path_t *dp; //设备路径 + dp = d->last_device_path; //最后设备路径 + if (! dp) //如果为零,继续 + continue; + + if (debug > 1) + grub_efi_print_device_path(d->device_path); + + if (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE) //如果设备路径类型=4, 是媒体类型 + { + int is_hard_drive = 0; //初始化'是硬盘' + + switch (GRUB_EFI_DEVICE_PATH_SUBTYPE (dp)) //设备子类型 + { + case GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE: //1 硬盘子类型 + is_hard_drive = 1; + /* Intentionally fall through. 故意落空 */ + case GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE: //2 光盘子类型 + { //注意: 包含硬盘,光盘 + struct efidisk_data *parent, *parent2; //磁盘数据 + parent = find_parent_device (devices, d); //查找父设备 + printf_debug ("parent=%x\n",parent); + if (!parent) //如果父设备不存在, 是孤立分区,退出 + { + printf_debug("skipping orphaned partition.\n"); //"跳过孤立分区:" + break; + } + if (debug > 1) + grub_efi_print_device_path(parent->device_path); + parent2 = find_parent_device (devices, parent); //查找祖父设备 + printf_debug ("parent2=%x\n",parent2); + if (parent2) //如果存在祖父设备, 是子分区,退出 + { + if (debug > 1) + grub_efi_print_device_path(parent2->device_path); +//USB分区路径:ACPI(a0341d0,0)/PCI(0,14)/USB(0,1)/UNIT(2)/HD(1,ff,3bd301,eca51e20,MBR) +//USB设备路径:ACPI(a0341d0,0)/PCI(0,14)/USB(0,1)/UNIT(2) + printf_debug ("parent->last_device_path->type=%d, parent->last_device_path->subtype=%d\n",parent->last_device_path->type,parent->last_device_path->subtype); + if (parent->last_device_path->type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE //3 + && parent->last_device_path->subtype == GRUB_EFI_USB_LOGICAL_UNIT_DEVICE_PATH_SUBTYPE) //17 支持USB逻辑单元设备 2023-05-04 + { + goto aaa; + } + printf_debug("skipping subpartition.\n"); //"跳过子分区" + /* Mark itself as used. 标记为已使用 */ + d->last_device_path = 0; + break; + } +aaa: + printf_debug ("parent->last_device_path=%x\n",parent->last_device_path); + if (!parent->last_device_path) //如果父设备->最后设备路径不存在, 已保留最后一个分区,退出. //此处的作用是: 5个gpt分区,只保留了最后一个分区,其他个分区过滤了. + { + printf_debug("skipping existing partitions.\n"); //跳过存在的分区 + d->last_device_path = 0; + break; + } + if (debug > 1) + grub_efi_print_device_path(parent->last_device_path); + if (is_hard_drive) //如果是硬盘 + { + printf_debug ("adding a hard drive by a partition.\n"); //"通过分区添加硬盘驱动器" + add_device (DISK_TYPE_HD, parent); //增加设备->硬盘 + } + else //如果不是硬盘 + { + printf_debug ("adding a cdrom by a partition.\n"); //"通过分区添加光盘驱动器" + add_device (DISK_TYPE_CD, parent); //增加设备->光盘 + } + + /* Mark the parent as used. 将父项标记为已使用 */ + parent->last_device_path = 0; + } + /* Mark itself as used. 标记自己使用 */ + d->last_device_path = 0; //此处的作用是: 5个gpt分区,只保留了最后一个分区,其他个分区过滤了. + break; + + default: + printf_debug ("skipping other type.\n"); //"跳过其他类型:" + /* For now, ignore the others. 现在,忽略其他 */ + break; + } + } + else + { + printf_debug ("skipping non-media.\n"); //"跳过非媒体:" + } + if (debug > 1) + { + printf_debug ("process next.\n"); //处理下一项 + getkey(); + } + } +#if 0 + //其次,识别其他类型的设备 光驱,软驱等等 + /* Let's see what can be added more. 让我们看看可以增加什么 */ + for (d = devices; d; d = d->next) + { + grub_efi_device_path_t *dp; //磁盘数据 + grub_efi_block_io_media_t *m; //块io媒体 + int is_floppy = 0; //初始化'是软盘' + + dp = d->last_device_path; //最后设备路径 + if (! dp) //如果为零 + continue; + /* Ghosts proudly presented by Apple. 苹果骄傲地展示鬼魂 */ //绕过苹果设备 + if (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE //设备路径类型=4 + && GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) + == GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE) //并且设备子类型=3 + { + grub_efi_vendor_device_path_t *vendor = (grub_efi_vendor_device_path_t *) dp; //供应商设备路径 + const struct grub_efi_guid apple = GRUB_EFI_VENDOR_APPLE_GUID; //供应商苹果 GUID + + if (vendor->header.length == sizeof (*vendor) //如果句柄尺寸=供应商设备路径尺寸 + && grub_memcmp ((const char *)&vendor->vendor_guid, (const char *)&apple, sizeof (vendor->vendor_guid)) == 0 //并且比较苹果guid一致 + && find_parent_device (devices, d)) //并且查找根设备成功 + continue; //则继续 + } + + m = d->block_io->media; + if (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_ACPI_DEVICE_PATH_TYPE //设备路径类型=2 + && GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) + == GRUB_EFI_ACPI_DEVICE_PATH_SUBTYPE) //设备子类型=1 + { + grub_efi_acpi_device_path_t *acpi = (grub_efi_acpi_device_path_t *) dp;//acpi设备路径 + /* Floppy EISA ID. 软盘EISA ID */ + if (acpi->hid == 0x60441d0 || acpi->hid == 0x70041d0 + || acpi->hid == 0x70141d1) + is_floppy = 1; //是软盘 + } + if (is_floppy) //如果是软盘, 增加软盘 + { + if (debug > 1) + { + grub_printf ("adding a floppy: "); //"增加软盘" + grub_efi_print_device_path (d->device_path); //efi打印设备路径 + } + add_device (DISK_TYPE_FD, d); //增加设备->软盘 + } + else if (m->read_only && m->block_size > GRUB_DISK_SECTOR_SIZE) //如果是只读,并且扇区尺寸>512, 增加光盘 + { + /* This check is too heuristic, but assume that this is a + CDROM drive. 这个检查太有启发性了,但是假设这是CDROM驱动器 */ + if (debug > 1) + { + grub_printf ("adding a cdrom by guessing: "); //“通过猜测添加CDROM:” + grub_efi_print_device_path (d->device_path); //efi打印设备路径 + } + add_device (DISK_TYPE_CD, d); //增加设备->光盘 + } + else //否则增加硬盘 + { + /* The default is a hard drive. 默认是硬盘驱动器 */ + if (debug > 1) + { + grub_printf ("\nadding a hard drive by guessing: "); //“通过猜测添加硬盘驱动器:” + grub_efi_print_device_path (d->device_path); //efi打印设备路径 + } + add_device (DISK_TYPE_HD, d); //增加设备->硬盘 实机启动,遇到光驱,死机。 + } + } +#endif +} + +//由枚举磁盘,efidisk结束,获取设备句柄调用 +static void free_efidisk_data (struct efidisk_data *devices); +static void +free_efidisk_data (struct efidisk_data *devices) //释放磁盘数据 +{ + struct efidisk_data *p, *q; + + for (p = devices; p; p = q) + { + q = p->next; + grub_free (p); + } +} +#if 0 +static void free_efipart_data (struct efipart_data *partitions); +static void +free_efipart_data (struct efipart_data *partitions) //释放磁盘数据 +{ + struct efipart_data *p, *q; + p = partitions; + + while (p) + { + q = p->next; + grub_free (p); + p = q; + } +} +#endif +static void free_disk_data (struct grub_disk_data *devices); +static void +free_disk_data (struct grub_disk_data *devices) //释放磁盘数据 +{ + struct grub_disk_data *p, *q; + + for (p = devices; p; p = q) + { + q = p->next; + grub_free (p); + } +} + +static void free_part_data (struct grub_part_data *partitions); +static void +free_part_data (struct grub_part_data *partitions) //释放分区数据 +{ + struct grub_part_data *p, *q; + p = partitions; + + while (p) + { + q = p->next; + grub_free (p); + p = q; + } +} +#if UNMAP +void uninstall (unsigned int drive, struct grub_disk_data *d); +void +uninstall (unsigned int drive, struct grub_disk_data *d) //释放磁盘映射 +{ + struct grub_part_data *p, *p_previous = 0; + grub_efi_boot_services_t *b = grub_efi_system_table->boot_services; + grub_efi_guid_t dp_guid = GRUB_EFI_DEVICE_PATH_GUID; + grub_efi_guid_t blk_io_guid = GRUB_EFI_BLOCK_IO_GUID; + grub_efi_device_path_t *dp; + + //核减相应驱动器数 + if (cdrom_orig && drive >= 0xa0) + cdrom_orig--; + else if (harddrives_orig && drive >= 0x80) + harddrives_orig--; + else if (floppies_orig) + floppies_orig--; + + //卸载映射内存 + if (d->to_drive == 0xff && d->to_log2_sector != 0xb) //内存映射 + efi_call_2 (b->free_pages, d->start_sector << 9, d->sector_count >> 3); //释放页 2024-09-01 + + //卸载虚拟磁盘 + if (d->vdisk) //是映射磁盘,并且挂载 + efi_call_2 (b->free_pages, (grub_efi_physical_address_t)(grub_size_t)d->vdisk, sizeof(grub_efivdisk_t) >> 3); //释放页 + + if (d->vdisk || !d->sector_count) //是映射磁盘,并且挂载,或者是原生磁盘 + { +#if defined(__i386__) + int offse = offsetof(struct grub_disk_data, device_handle); +#endif + dp = grub_efi_get_device_path (d->device_handle); //获得设备路径 + efi_call_6 (b->install_multiple_protocol_interfaces, //安装多协议接口 +#if defined(__i386__) + (void **)((char *)d + offse), +#else + &d->device_handle, //指向协议接口的指针(如果要分配新句柄,则指向NULL的指针) +#endif + &dp_guid, //指向协议GUID的指针 +// d->device_path, //指向设备路径的指针 + dp, //指向设备路径的指针 + &blk_io_guid, //指向io设备接口的指针 + (block_io_protocol_t *)d->block_io, //指向block_io设备接口的指针 + NULL); + } + + //卸载映射磁盘 + if (d == disk_data) //首位 + { + if (d->next == 0) + disk_data = 0; + else + disk_data = d->next; + } + else if (previous_struct) //其他 + previous_struct->next = d->next; + + grub_free (d); + + //卸载映射分区 + if (drive < 0x80) //排除软盘 + return; + for (p = partition_info; p; p_previous = p, p = p->next) + { + if (p->drive != drive) + continue; + + if (p == partition_info) //首位 + { + if (p->next == 0) + partition_info = 0; + else + partition_info = p->next; + } + else if (p_previous) //其他 + p_previous->next = p->next; + + grub_free (p); + } + return; +} +#endif +/* Enumerate all disks to name devices. 枚举所有磁盘到名称设备 */ +//由efidisk初始化调用 +void enumerate_disks (void); +void +enumerate_disks (void) //枚举磁盘 +{ + struct efidisk_data *devices; + + devices = make_devices (); //制作设备 + if (! devices) //如果失败 + return; + + name_devices (devices); //命名设备 + //free_efidisk_data (devices); //释放 + struct grub_disk_data *d; //磁盘数据 + int cd= 0xa0, hd = 0x80, fd = 0; + for (d = disk_data; d; d = d->next) + { + switch(d->disk_type) + { + case DISK_TYPE_CD: + d->drive = cd++; + break; + case DISK_TYPE_HD: + d->drive = hd++; + break; + default: + d->drive = fd++; + break; + } + } + partition_info_init (devices); + free_efidisk_data (devices); //释放 +} + +grub_efi_device_path_t *efi_file_path; +//grub_efi_handle_t efi_handle; +void * grub_memalign (grub_size_t align, grub_size_t size); + + +struct grub_disk_data *get_device_by_drive (unsigned int drive, unsigned int map); +struct grub_disk_data * +get_device_by_drive (unsigned int drive, unsigned int map) //由驱动器号获得设备信息指针(驱动器号,搜索范围) map=0/1=全范围/仅搜索映射驱动器 +{ + struct grub_disk_data *d; //磁盘数据 + + if (drive == FB_DRIVE && fb_status) + drive = (unsigned char)(fb_status >> 8); + for (d = disk_data; d; d = d->next) //从设备结构起始查 + { + if (d->drive == drive && (map?d->sector_count:1)) + return d; + previous_struct = d; + } + + return 0; +} + + +int grub_SectorSequence_readwrite (int drive, struct fragment *data, unsigned char from_log2_sector, unsigned char to_log2_sector, + grub_disk_addr_t sector, grub_size_t size, char *buf, unsigned long long lba_byte, int read_write); +int +grub_SectorSequence_readwrite (int drive, struct fragment *data, unsigned char from_log2_sector, unsigned char to_log2_sector, + grub_disk_addr_t sector, grub_size_t size, char *buf, unsigned long long lba_byte, int read_write) +{ + struct grub_disk_data *df=0, *dt=0; //磁盘数据 + grub_efi_block_io_t *bio=0; //块io + grub_efi_status_t status; //状态 + unsigned int offset, read_len; + unsigned long long read_start/*, lba_byte = 0*/; + unsigned long long fragment_len = 0, total = 0; + unsigned char from_log2, to_log2; + unsigned short to_block_size; + unsigned int j=0; + + df = get_device_by_drive (drive,0); + if (!df) + return 1; + + if (from_log2_sector) + { + from_log2 = from_log2_sector; + to_log2 = to_log2_sector; + } + else + { + from_log2 = df->from_log2_sector; + to_log2 = df->to_log2_sector; + } + to_block_size = 1 << to_log2; + + if (!lba_byte) + lba_byte = (sector << from_log2); //from驱动器起始逻辑扇区lba转起始字节 + //内存驱动器 + if (df->to_drive == 0xff && to_log2 == 9) //如果是内存驱动器, 映射盘加载到内存 + { + lba_byte += (df->start_sector << 9); //加映射起始(字节) + if (read_write == 0xedde0d90) //读 + grub_memmove64 ((unsigned long long)(grub_size_t)buf, lba_byte, size); + else + grub_memmove64 (lba_byte, (unsigned long long)(grub_size_t)buf, size); + + return 0; + } + + //确定to驱动器起始相对逻辑扇区号 + sector = lba_byte >> to_log2; + //确定to驱动器起始偏移字节 + offset = lba_byte & (to_block_size - 1); + //判断有无碎片 + if (!data) //没有碎片 + { + sector += df->start_sector; //加映射起始(扇区或字节) + fragment_len = size; + } + else +//有碎片 +// To_count(0) To_count(1) To_count(2) To_count(3) +// ├──────────┼───────────┼─────────────┼────────────┤ 逻辑扇区 从To_start(0)起始,扇区不连续 +//To_start(0) To_start(1) To_start(2) To_start(3) +// Form_len +// ├---------------------------------------├----------------------┤ 虚拟扇区 从0起始(相对于逻辑扇区To_start(0)),扇区连续 +// 0 Form_statr + +// |-----------8-----------|------4-----|----------7---------| +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 +// |-------------9------------|---------6--------| +// 0 sector + { + while (1) + { + total += data[j++].sector_count; + if (sector < total) //确定起始位置的条件 + break; + } + //确定本碎片最大访问字节 + fragment_len = (total - sector) << to_log2; + //确定Form扇区起始的确切位置(To_start(j)+偏移) + sector += data[j-1].start_sector + data[j-1].sector_count - total; + } + + if (df->to_drive) + dt = get_device_by_drive (df->to_drive,0); + else + dt = get_device_by_drive (drive,0); + if (!dt) + return 1; + bio = dt->block_io; //块io + //避免出界 + if (size > ((bio->media->last_block - sector + 1) << to_log2)) + size = (bio->media->last_block - sector + 1) << to_log2; + while (size) + { + //判断本碎片可否一次访问完毕 + if (size > fragment_len) + read_len = fragment_len; + else + read_len = size; + + //首先处理偏移, 实际读写字节(disk_drive_map[i].to_block_size - offset) + if (offset || size < to_block_size) //如果有偏移字节 + { + status = efi_call_5 (((read_write == 0x900ddeed) ? bio->write_blocks : bio->read_blocks), bio, + bio->media->media_id, sector, to_block_size, disk_buffer); //读写(读/写,本身块io,media_id,扇区,字节尺寸,缓存) + read_start = (unsigned long long)(grub_size_t)disk_buffer + offset; //读写起始 + read_len = to_block_size - offset; //读写尺寸 + if (read_len > size) + read_len = size; + if (read_write == 0xedde0d90) //读 + grub_memmove64 ((unsigned long long)(grub_size_t)buf, read_start, read_len); + else //写 + { + grub_memmove64 (read_start, (unsigned long long)(grub_size_t)buf, read_len); + status = efi_call_5 (((read_write == 0x900ddeed) ? bio->write_blocks : bio->read_blocks), bio, + bio->media->media_id, sector, to_block_size, disk_buffer); //读写(读/写,本身块io,media_id,扇区,字节尺寸,缓存) + } + + buf = (void *)((grub_size_t)buf + read_len); + fragment_len -= read_len; + size -= read_len; + offset = 0; + } + else + { + read_len &= ~(to_block_size -1); + size -= read_len; + status = efi_call_5 (((read_write == 0x900ddeed) ? bio->write_blocks : bio->read_blocks), bio, + bio->media->media_id, sector, read_len, buf); //读写(读/写,本身块io,media_id,扇区,字节尺寸,缓存) + buf = (void *)((grub_size_t)buf + read_len); + fragment_len -= read_len; + } + //判断是否需要再读 + if (!size) + return status; + //确定本碎片还可以访问扇区数 + if (/*df->fragment && */!fragment_len) //肯定有碎片, 否则fragment_len=size, 既然len不为零, 则fragment_len也不会为零. 2024-12-12 + { + sector = data[j].start_sector; + fragment_len = data[j].sector_count << to_log2; + j++; + } + else //不能确定有无碎片 + { + sector += (read_len + to_block_size - 1) >> to_log2; + } + } + return 1; +} +#if VHD_DIFFERENCE +int vhd_read = 0; +#endif +//由磁盘读,磁盘写调用 +//efi磁盘读写(驱动器号,扇区号,读字节数,缓存区,读/写) 返回: 0/1=成功/失败 +//1. 磁盘数据对齐 +int grub_efidisk_readwrite (int drive, grub_disk_addr_t sector, grub_size_t size, char *buf, int read_write); +int +grub_efidisk_readwrite (int drive, grub_disk_addr_t sector, + grub_size_t size, char *buf, int read_write) +{ + struct grub_disk_data *df=0, *dm; //磁盘数据 + struct grub_part_data *dp; + grub_efi_block_io_t *bio=0; //块io + grub_efi_status_t status; //状态 + grub_size_t io_align; //对齐 + char *aligned_buf; //对齐缓存 + struct fragment_map_slot *q; + struct fragment *data=0; + unsigned char from_drive; //驱动器 + unsigned long long lba_byte = 0; + + if (read_write != 0xedde0d90 && read_write != 0x900ddeed) //如果不是读/写, 错误 + return 1; + //虚拟分区 + if ((drive & 0xffff00) == 0xffff00) + { + int partition = (drive >> 8) & 0x0fffff; +// int cd_count = drive >> 28; + drive &= 0xff; + if (drive >= 0xa0) + { +// drive = 0x60 + cd_count; + dp = get_partition_info (drive, 0); + if (!dp) + return 1; + +// lba_byte = (sector << 9) + size + (dp->partition_start << 11); + lba_byte = (sector + dp->partition_start) << 9; + if (read_write == 0x900ddeed) //写 + grub_memmove64 (lba_byte, (unsigned long long)(grub_size_t)buf, size); + else + grub_memmove64 ((unsigned long long)(grub_size_t)buf, lba_byte, size); + + return 0; + } + + if (drive >= 0x80) + { + df = get_device_by_drive (drive,0); + if (!df) + return 1; + dp = get_partition_info (drive, partition); + if (!dp) + return 1; + lba_byte = (sector + dp->partition_start) << df->from_log2_sector; + //网起 + if (df->to_drive == 0x21) + { + int back = current_drive; + current_drive = 0x21; + filepos = lba_byte; + pxe_read((unsigned long long)(grub_size_t)buf, size, GRUB_READ); + current_drive = back; + return 0; + } + } + } + //md或者rd + if (drive == 0xffff || (drive == (int)ram_drive && rd_base != -1ULL)) + { + unsigned long long disk_sector; + unsigned long long buf_address; + unsigned long long tmp; + + tmp = ((sector << 9) + size); + if (drive == (int)ram_drive) + tmp += rd_base; + else + tmp += md_part_base; + if (tmp > 0x100000000ULL && ! is64bit) + return 1; /* failure */ + disk_sector = ((sector<<9) + ((drive==0xffff) ? md_part_base : rd_base)); + buf_address = (unsigned long long)(grub_size_t)buf; + + if (read_write == 0x900ddeed) //写 + grub_memmove64 (disk_sector, buf_address, size); + else + grub_memmove64 (buf_address, disk_sector, size); + + return 0; /* success */ + } + + if (!df) + { + df = get_device_by_drive (drive,0); + if (!df) + return 1; + //网起 + if (df->to_drive == 0x21) + { + int back = current_drive; + current_drive = 0x21; + filepos = sector << df->from_log2_sector; //14000 + pxe_read((unsigned long long)(grub_size_t)buf, size, GRUB_READ); //81920-83967,800 + current_drive = back; + return 0; + } + } +#if VHD_DIFFERENCE + //动态vhd处理 + if (df->vhd_disk & 1 && !vhd_read) //vhd不加载到内存,并且不是dec_vhd读磁盘 + { +// filepos = sector << 9; + filepos = lba_byte; //2024-09-01 + dec_vhd_read ((unsigned long long)(grub_size_t)buf, (unsigned long long)size, read_write); + return 0; + } +#endif + //判断是原生磁盘还是映射磁盘 + from_drive = drive; + dm = get_device_by_drive (from_drive,1); + if (!dm) //映射磁盘 + goto not_map; + +//启动hdd_cs.img, 驱动器号 80 +//map /boot/imgs/z.iso (0xa0) 插槽: a0 80 0b 09 01 00 508 1c00 +//a0(from)映射到80(to) (hd0)508+20,fc8+20,b2828+20,b2968+a0,b2e88+20,b4588+180,b6a68+1960 +//z.iso的引导镜像efi.img 驱动器号 ffffa0, 起始2b, 尺寸b40 +//参数 from_log2_sector=b, to_log2_sector=9 +//读efi.img drive=ffffa0 sector=0 size=200; drive=ffffa0 sector=13 size=2000 +//0+(2b<>9=ac 从b2968+4c读1扇区 +//(13<<9)+(2b<>9=bf 从b2968+5f读10扇区 + + if (df->fragment) + { + //从碎片插槽查找Form驱动器 +// q = (struct fragment_map_slot *)&disk_fragment_map; + q = (struct fragment_map_slot *)disk_fragment_map; + q = fragment_map_slot_find (q, from_drive); + //确定Form扇区起始在哪个碎片 +// data = (struct fragment *)&q->fragment_data; + int offse = offsetof(struct fragment_map_slot, fragment_data); + data = (struct fragment *)((char *)q + offse); + } + status = grub_SectorSequence_readwrite (from_drive, data, 0, 0, sector, size, buf, lba_byte, read_write); + return status; + +not_map: + bio = df->block_io; //块io + //避免出界 + if (size > ((bio->media->last_block - sector + 1) << df->from_log2_sector)) + size = (bio->media->last_block - sector + 1) << df->from_log2_sector; + /* Set alignment to 1 if 0 specified 如果0指定,则将对齐设置为1*/ + io_align = bio->media->io_align ? bio->media->io_align : 1; //对齐, 如果没有指定则为1 + if ((grub_addr_t) buf & (io_align - 1)) //如果缓存未对齐 + { + aligned_buf = (char *)grub_memalign (io_align, size); //使用对齐方式分配内存 + if (! aligned_buf) + return (errnum = ERR_UNALIGNED); + if (read_write == 0x900ddeed) //写 + grub_memcpy (aligned_buf, buf, size); + } + else + { + aligned_buf = buf; + } + + status = efi_call_5 (((read_write == 0x900ddeed) ? bio->write_blocks : bio->read_blocks), bio, + bio->media->media_id, (grub_efi_uint64_t) sector, + (grub_efi_uintn_t) size, aligned_buf); //读写(读/写,本身块io,media_id,扇区,字节尺寸,对齐缓存) + + if ((grub_addr_t) buf & (io_align - 1)) //如果缓存未对齐 + { + if (read_write == 0xedde0d90) //读 + grub_memcpy (buf, aligned_buf, size); + grub_free (aligned_buf); + } + + if (status == GRUB_EFI_NO_MEDIA) + return (errnum = ERR_DEV_VALUES); + else if (status != GRUB_EFI_SUCCESS) + return ((read_write == 0x900ddeed) ? (errnum = ERR_WRITE) : (errnum = ERR_READ)); + + return 0; +} + + +void +partition_info_init (struct efidisk_data *devices) +{ + struct grub_disk_data *d; + struct efidisk_data *d1; + struct grub_part_data *p; + struct grub_part_data *p_final = 0; + grub_efi_device_path_t *dp = 0, *ldp = 0, *dp1; //路径 + int drive; + unsigned int back_saved_drive = saved_drive; + unsigned int back_current_drive = current_drive; + unsigned int back_saved_partition = saved_partition; + unsigned int back_current_partition = current_partition; + + if (partition_info) + free_part_data (partition_info); + partition_info = 0; + + for (drive = 0x80; (drive&0xf) < harddrives_orig; drive++) + { + unsigned int part = 0xFFFFFF; + unsigned long long start, len, offset; + unsigned int type, entry1, ext_offset1; + saved_drive = current_drive = drive; + saved_partition = current_partition = part; + d = get_device_by_drive(drive,0); + if (!d) + return; + while (( next_partition_drive = drive, //驱动器 + next_partition_dest = 0xFFFFFF, //搜索目标分区. 即要查找的分区,找到后结束查询. 若要例遍所有分区,则设置为0xffffff. + next_partition_partition = &part, //当前分区 + next_partition_type = &type, //分区类型 + next_partition_start = &start, //分区起始 + next_partition_len = &len, //分区尺寸 + next_partition_offset = &offset, //分区偏移 扩展分区表位置. 偏移3f扇区即逻辑分区起始. + next_partition_entry = &entry1, //分区入口 对于mbr分区,视乎是主分区标号, 对于gpt分区,视乎都是2. + next_partition_ext_offset = &ext_offset1, //扩展分区偏移 扩展分区表基地址,位于主分区. 所有的扩展分区表的起始地址,都是相对地址. + next_partition_buf = mbr, //缓存 + next_partition ())) + { + if (*next_partition_type == 0 || *next_partition_type == 5 || *next_partition_type == 0xf) + continue; + + p = grub_zalloc (sizeof (*p)); //分配内存 + if(! p) //如果分配内存失败 + return; + + //填充设备结构 //(hd0,0) (hd0,2) (hd0,3) (hd0,4) (hd1,0) (hd1,1) (hd1,2) (hd1,4) (hd1,5) (hd1,6) + p->drive = drive; //80 80 80 80 81 81 81 81 81 81 + p->partition = *next_partition_partition; //ffff 2ffff 3ffff 4ffff ffff 1ffff 2ffff 4ffff 5ffff 6ffff + p->partition_type = *next_partition_type; //ee ee ee ee 07 0f 0 07 07 07 + p->partition_start = *next_partition_start; //800 50800 b4800 118800 3f a0029cc 0 a002a0b 1a207094 2a40b71d + p->partition_size = *next_partition_len; //40000 64000 64000 cbddf a00298d 30382275 0 1020464a 1020464a ff79524 + p->partition_offset = *next_partition_offset; //0 0 0 0 0 0 0 a0029cc 1a207055 2a40b6de + p->partition_entry = *next_partition_entry; //2 2 2 2 0 1 2 0 0 0 + p->partition_ext_offset = *next_partition_ext_offset; //0 0 0 0 0 0 0 a0029cc a0029cc a0029cc + p->partition_activity_flag = partition_activity_flag; +// p->next = partition_info; //0 dfb0110 dfb00e0 dfb00b0 dfb0080 dfb0050 dfaff90 dfaff60 + p->next = 0; + if (!partition_info) //执行find时,分区顺序为0,1,2.... 2023-07-24 + { + partition_info = p; + p_final = p; + } + else + { + p_final->next = p; + p_final = p; + } + + grub_memcpy (&p->partition_signature, &partition_signature, 16); + //从efidisk_data中查找有关信息 + for (d1 = devices; d1; d1 = d1->next) + { + d = get_device_by_drive (drive, 0); + if (!d) //如果设备=0, 错误 2023-03-26 + return; + dp1 = grub_efi_get_device_path (d->device_handle); //获得设备路径 + if (grub_efi_compare_device_paths (dp1, d1->device_path) == -1) + { + if (d1->partition_start == p->partition_start && d1->partition_size == p->partition_size) + { + p->part_handle = d1->device_handle; + } + } + } + +// partition_info = p; //dfb0110 dfb00e0 dfb00b0 dfb0080 dfb0050 dfaff90 dfaff60 dfaff30 + } + if (get_efi_device_boot_path (drive, 0)) + { + part_data = get_partition_info (drive, part_data->partition); + if (part_data) //2023-03-26 + part_data->partition_boot = 1; + } + } + saved_drive = back_saved_drive; + current_drive = back_current_drive; + saved_partition = back_saved_partition; + current_partition = back_current_partition; + + for (d = disk_data; d && cdrom_orig; d = d->next) //从设备结构起始查; 只要设备存在,并且驱动器号不为零; + { + if (d->disk_type != DISK_TYPE_CD) + continue; + + get_efi_device_boot_path(d->drive, 0); +//PciRoot(0)/Pci(1,1)/Ata(Primary,Master,0)/HD(1,MBR,88776655,20,100000) +//PciRoot(0)/Pci(1,1)/Ata(Secondary,Master,0)/CDROM(0,35,1680)/HD(1,MBR,0,0,1680) a0,1,0,1680,1,35,1680; ok fb形态的MBR,有分区表 +//PciRoot(0)/Pci(1,1)/Ata(Secondary,Master,0)/CDROM(0,35,1680) a0,0,35,1680,1,35,1680; err 这个不能启动 +//PciRoot(0)/Pci(1,1)/Ata(Secondary,Master,0)/CDROM(1,2b,5ea) a0,1,2b,5ea,91,2b,5ea; ok 正常的MBR, bios/uefi双启动 +//PciRoot(0)/Pci(1,1)/Ata(Secondary,Master,0)/CDROM(0,1a5,4) a0,0,1a5,4,91,2b,5ea; 这是bios启动入口 + + p = grub_zalloc (sizeof (*p)); //分配内存 + if(! p) //如果分配内存失败 + return; + + p->drive = d->drive; + p->part_handle = 0; + p->partition = 0xffff; + p->partition_start = 0; + p->partition_size = 0; + p->partition_boot = 1; +// p->next = partition_info; +// partition_info = p; + if (!partition_info) //执行find时,分区顺序为0,1,2.... 2023-07-24 + { + partition_info = p; + p_final = p; + } + else + { + p_final->next = p; + p_final = p; + } + + for (d1 = devices; d1; d1 = d1->next) + { + dp = d1->device_path; + ldp = grub_efi_find_last_device_path (dp); //查找最后设备路径 + dp1 = grub_efi_get_device_path (d->device_handle); //获得设备路径 + if (debug > 1) + { + grub_efi_print_device_path (dp); //efi打印设备路径 + grub_efi_print_device_path (dp1); + } + if (grub_efi_compare_device_paths (dp1, dp) == -1) + { + for (; ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp); dp = GRUB_EFI_NEXT_DEVICE_PATH (dp)) + { + if (((grub_efi_vendor_device_path_t*)dp)->header.type == 4 && + ((grub_efi_vendor_device_path_t*)dp)->header.subtype == 2 && + ((grub_efi_cdrom_device_path_t*)dp)->boot_entry == cd_boot_entry && + ((grub_efi_cdrom_device_path_t*)dp)->boot_start == cd_boot_start) //不能比较cd_boot_size,很可能与UEFI固件给出的值不同 + { + if (((grub_efi_vendor_device_path_t*)ldp)->header.subtype == 1) + { + p->part_handle = d1->device_handle; + p->partition_start = d1->partition_start; + p->partition_size = d1->partition_size; + } + else + { + p->boot_start = d1->partition_start; + p->boot_size = d1->partition_size; //启动时,光盘镜像的引导尺寸是1,实际是b40,但是UEFI构件将光盘引导镜像尺寸识别为444,因此必须保存444值。 + if (p->part_handle == 0) + p->part_handle = d1->device_handle; + } + } + } + } + } + } +} + +struct grub_part_data *get_partition_info (int drive, int partition); +struct grub_part_data * +get_partition_info (int drive, int partition) //获得分区信息指针 +{ + struct grub_part_data *dp; + + if (drive < 0x80/* || drive > 0x8f*/) + return 0; + if (drive >= 0xa0) + partition = 0xffff; + for (dp = partition_info; dp; dp = dp->next) + { + if (dp->drive == drive && (int)dp->partition == partition) + return dp; + } + return 0; +} + +struct grub_part_data *get_boot_partition (int drive); //获得分区信息指针 +struct grub_part_data * +get_boot_partition (int drive) //获得启动分区 +{ + struct grub_part_data *dp; + + for (dp = partition_info; dp; dp = dp->next) + { + if (dp->drive == drive && dp->partition_boot) + return dp; + } + return 0; +} + +void grub_efidisk_fini (void); +void +grub_efidisk_fini (void) //efidisk结束 +{ + free_disk_data (disk_data); //释放设备 光盘 +// disk_data = 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//kern.misc.c +/* +计算原理: +1. 二进制数字和 +0xn3n2n1n0 = n3*2^3 + n2*2^2 + n1*2^1 + n0*2^0 = 2(2(2(n3) + n2) + n1) + n0 +左移一位相当于乘以2。n3乘以3次,n2乘以2次,n1乘以1次,n0没有乘。 +2. 逐步重新计算被除数,即被除数逐步向左移位 +0xn3n2n1n0 = 2(n3) + n2 -> 2(2(n3) + n2) + n1 -> 2(2(2(n3) + n2) + n1) + n0 +3. 等号两边同乘一数仍然相等 +被除数/除数=商 == 2被除数/除数=2商 +*/ +//N除以D,返回商,并将余数存储在*R中 +grub_uint64_t grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r); +grub_uint64_t +grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r) //64位除法(32位gcc编译不支持64位除法) +{ + /* This algorithm is typically implemented by hardware. The idea 该算法通常由硬件实现。 + is to get the highest bit in N, 64 times, by keeping 其思想是通过保持上限(N*2^i)=(Q*D+M), + upper(N * 2^i) = (Q * D + M), where upper 获得N中的最高位64次,其中上限表示128位空间中的高64位。 + represents the high 64 bits in 128-bits space. */ + unsigned bits = 64; //循环计数 + grub_uint64_t q = 0; //商 + grub_uint64_t m = 0; //余数 + unsigned char q_sign = 0; //商符号 0/1=正/负 + unsigned char m_sign = 0; //余数符号 0/1=正/负 + + /* ARM and IA64 don't have a fast 32-bit division. ARM和IA64没有快速的32位除法。 + Using that code would just make us use software division routines, calling 使用该代码只会让我们使用软件划分例程, + ourselves indirectly and hence getting infinite recursion. 间接调用我们自己,从而获得无限递归。 + */ +#if 1 + /* Skip the slow computation if 32-bit arithmetic is possible. 如果可以使用32位算法,则跳过慢速计算*/ + if (n <= 0xffffffff && d <= 0xffffffff) + { + if (r) + *r = ((unsigned int)n) % (unsigned int)d; + + return ((unsigned int)n) / (unsigned int)d; + } +#endif + if ((n & (1ULL << 63)) != (d & (1ULL << 63))) //确定商的符号 正/正=正 负/负=正 正/负=负 负/正=负 + q_sign = 1; + if (n & (1ULL << 63)) //如果被除数为负, 则取补数 + { + n = ~n + 1; + m_sign = 1; //确定余数的符号 + } + if (d & (1ULL << 63)) //如果除数为负, 则取补数 + d = ~d + 1; + + while (!(n & (1ULL << 63))) //把原始被除数首位1移动到最左(第63位) + { + bits--; + n <<= 1; + } + + while (bits--) //重复次数 连上面的总共64次 + { + //重新计算的被除数及商同时乘以2 + m <<= 1; //重新计算的被除数乘以2 + q <<= 1; //商乘以2 + //逐步重新计算被除数 + if (n & (1ULL << 63)) //如果原始被除数首位为1,则参与运算 + m |= 1; //重新计算的被除数+1 + n <<= 1; //原始被除数乘以2,为下一次计算做准备 + //除法计算:使用减法求商。减除数,增加商 + if (m >= d) //如果重新计算的被除数>=除数 + { + q |= 1; //商+1 + m -= d; //重新计算的被除数-除数 + } + } + + if (q_sign) //如果商为负, 则商取补 + q = ~q + 1; + if (m_sign) //如果余数为负, 则余数取补 + m = ~m + 1; + + if (r) + *r = m; + + return q; +} + +#if 0 +grub_uint64_t __umoddi3 (grub_uint64_t a, grub_uint64_t b); +grub_uint64_t +__umoddi3 (grub_uint64_t a, grub_uint64_t b) +{ + grub_uint64_t ret; + grub_divmod64 (a, b, &ret); + return ret; +} + +grub_uint64_t __udivdi3 (grub_uint64_t a, grub_uint64_t b); +grub_uint64_t +__udivdi3 (grub_uint64_t a, grub_uint64_t b) +{ + return grub_divmod64 (a, b, 0); +} +#endif +#if !GDPUP +static grub_efi_uintn_t device_path_node_length (const void *node); +static grub_efi_uintn_t +device_path_node_length (const void *node) //设备路径节点长度 pppp +{ + return grub_get_unaligned16 ((grub_efi_uint16_t *) + &((grub_efi_device_path_protocol_t *)(node))->length); +} + +grub_efi_uintn_t grub_efi_get_dp_size (const grub_efi_device_path_protocol_t *dp); +grub_efi_uintn_t +grub_efi_get_dp_size (const grub_efi_device_path_protocol_t *dp) //获得路径尺寸 pppp +{ + grub_efi_device_path_t *p; + grub_efi_uintn_t total_size = 0; + for (p = (grub_efi_device_path_t *) dp; ; p = GRUB_EFI_NEXT_DEVICE_PATH (p)) + { + total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p); + if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p)) + break; + } + return total_size; +} + +static void set_device_path_node_length (void *node, grub_efi_uintn_t len); +static void +set_device_path_node_length (void *node, grub_efi_uintn_t len) //设置设备路径节点长度 pppp +{ + grub_set_unaligned16 ((grub_efi_uint16_t *) + &((grub_efi_device_path_protocol_t *)(node))->length, + (grub_efi_uint16_t)(len)); +} + +grub_efi_device_path_protocol_t*grub_efi_create_device_node (grub_efi_uint8_t node_type, grub_efi_uintn_t node_subtype, + grub_efi_uint16_t node_length); +grub_efi_device_path_protocol_t* +grub_efi_create_device_node (grub_efi_uint8_t node_type, grub_efi_uintn_t node_subtype, + grub_efi_uint16_t node_length) //创建设备节点(类型,子类型,尺寸) pppp +{ + grub_efi_device_path_protocol_t *dp; + if (node_length < sizeof (grub_efi_device_path_protocol_t)) + return NULL; + dp = grub_zalloc (node_length); //分配缓存, 并清零 + + if (dp != NULL) + { + dp->type = node_type; //类型 + dp->subtype = node_subtype; //子类型 + set_device_path_node_length (dp, node_length); //设置设备路径节点长度 + } + return dp; +} + +grub_efi_device_path_protocol_t* grub_efi_append_device_path (const grub_efi_device_path_protocol_t *dp1, + const grub_efi_device_path_protocol_t *dp2); +grub_efi_device_path_protocol_t* +grub_efi_append_device_path (const grub_efi_device_path_protocol_t *dp1, + const grub_efi_device_path_protocol_t *dp2) //附加设备路径 pppp +{ + grub_efi_uintn_t size; + grub_efi_uintn_t size1; + grub_efi_uintn_t size2; + grub_efi_device_path_protocol_t *new_dp; + grub_efi_device_path_protocol_t *tmp_dp; + // If there's only 1 path, just duplicate it. + if (dp1 == NULL) + { + if (dp2 == NULL) + return grub_efi_create_device_node (GRUB_EFI_END_DEVICE_PATH_TYPE, //0x7f + GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, //0xff + sizeof (grub_efi_device_path_protocol_t));//创建设备节点(类型,子类型,尺寸) + else + return grub_efi_duplicate_device_path (dp2); + } + if (dp2 == NULL) + grub_efi_duplicate_device_path (dp1); + // Allocate space for the combined device path. It only has one end node of + // length EFI_DEVICE_PATH_PROTOCOL. + size1 = grub_efi_get_dp_size (dp1); + size2 = grub_efi_get_dp_size (dp2); + size = size1 + size2 - sizeof (grub_efi_device_path_protocol_t); + new_dp = grub_malloc (size); + + if (new_dp != NULL) + { + new_dp = grub_memcpy (new_dp, dp1, size1); + // Over write FirstDevicePath EndNode and do the copy + tmp_dp = (grub_efi_device_path_protocol_t *) + ((char *) new_dp + (size1 - sizeof (grub_efi_device_path_protocol_t))); + grub_memcpy (tmp_dp, dp2, size2); + } + return new_dp; +} + +grub_efi_device_path_protocol_t*grub_efi_append_device_node (const grub_efi_device_path_protocol_t *device_path, + const grub_efi_device_path_protocol_t *device_node); +grub_efi_device_path_protocol_t* +grub_efi_append_device_node (const grub_efi_device_path_protocol_t *device_path, + const grub_efi_device_path_protocol_t *device_node) //附加设备节点 pppp +{ + grub_efi_device_path_protocol_t *tmp_dp; + grub_efi_device_path_protocol_t *next_node; + grub_efi_device_path_protocol_t *new_dp; + grub_efi_uintn_t node_length; + if (device_node == NULL) + { + if (device_path == NULL) + return grub_efi_create_device_node (GRUB_EFI_END_DEVICE_PATH_TYPE, //0x7f + GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, //0xff + sizeof (grub_efi_device_path_protocol_t));//创建设备节点(类型,子类型,尺寸) + else + return grub_efi_duplicate_device_path (device_path); + } + // Build a Node that has a terminator on it + node_length = device_path_node_length (device_node); + + tmp_dp = grub_malloc (node_length + sizeof (grub_efi_device_path_protocol_t)); + if (tmp_dp == NULL) + return NULL; + tmp_dp = grub_memcpy (tmp_dp, device_node, node_length); + // Add and end device path node to convert Node to device path + next_node = GRUB_EFI_NEXT_DEVICE_PATH (tmp_dp); + next_node->type = GRUB_EFI_END_DEVICE_PATH_TYPE; //0x7f + next_node->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; //0xff + next_node->length = sizeof (grub_efi_device_path_protocol_t); + // Append device paths + new_dp = grub_efi_append_device_path (device_path, tmp_dp); + grub_free (tmp_dp); + return new_dp; +} +#endif + +//======================================================================================================================================== +grub_efivdisk_t *vdisk; +grub_efivdisk_t *vpart; +static grub_efi_boolean_t get_mbr_info (struct grub_part_data *p); +static grub_efi_boolean_t +get_mbr_info (struct grub_part_data *p) //获得mbr磁盘信息 +{ + grub_efi_device_path_t *tmp_dp; + struct grub_disk_data *d; + d = get_device_by_drive(p->drive,0); + if (!d) + return 0; + + //创建设备节点 +#if GDPUP + grub_efi_boot_services_t *b; //引导服务 + b = grub_efi_system_table->boot_services; //系统表->引导服务 + grub_efi_device_pate_utilities_protocol_t *DPUP; //设备路径实用程序协议 + grub_efi_guid_t dpup_guid = GRUB_EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID; + DPUP = grub_efi_locate_protocol (&dpup_guid, 0); //EFI定位协议 + tmp_dp = (grub_efi_device_path_t *)efi_call_3 (DPUP->CreateDeviceNode, + GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, //0x04 媒体类型 + GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE, //0x01 硬件子类型 + sizeof(grub_efi_hard_drive_device_path_t)); //节点尺寸 +#else + tmp_dp = grub_efi_create_device_node ( + GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, //0x04 媒体类型 + GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE, //0x01 硬件子类型 + sizeof(grub_efi_hard_drive_device_path_t)); //节点尺寸 +#endif + if (ext_start_lba) //如果是逻辑分区,首先安装扩展分区路径 + { + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_number = ext_num + 1; //分区号 + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_start = ext_start_lba; //分区起始 扇区 + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_size = ext_total_sectors; //分区尺寸 扇区 + grub_memmove(&((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_signature, &p->partition_signature, 16); //分区签名 + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partmap_type = 1; //分区格式类型 + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->signature_type = 1; //签名类型 + vpart->dp = grub_efi_append_device_node (vdisk->dp, tmp_dp); //附加设备节点 + if (tmp_dp) + grub_free (tmp_dp); + tmp_dp = grub_efi_create_device_node ( + GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, //0x04 媒体类型 + GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE, //0x01 硬件子类型 + sizeof(grub_efi_hard_drive_device_path_t)); //节点尺寸 + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_number = (p->partition >> 16) - 3; //分区号 + } + else + { + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_number = (p->partition >> 16) + 1; //分区号 + grub_memmove(&((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_signature, &p->partition_signature, 16); //分区签名 + } + + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_start = p->partition_start; //分区起始 扇区 + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_size = p->partition_size; //分区尺寸 扇区 +// grub_memmove(&((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_signature, &p->partition_signature, 16); //分区签名 + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partmap_type = 1; //分区格式类型 + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->signature_type = 1; //签名类型 + //附加设备节点 +#if GDPUP + vpart->dp = (grub_efi_device_path_t *)efi_call_2 (DPUP->AppendDeviceNode, + vdisk->dp, //设备路径 + tmp_dp); //设备节点 + efi_call_1 (b->free_pool, tmp_dp); //释放数据 使用DPUP->CreateDeviceNode创建的tmp_dp只能使用b->free_pool释放 +#else + if (ext_start_lba) + vpart->dp = grub_efi_append_device_node (vpart->dp, tmp_dp); //附加设备节点 + else + vpart->dp = grub_efi_append_device_node (vdisk->dp, tmp_dp); //附加设备节点 + if (tmp_dp) //如果存在 使用grub_efi_create_device_node创建的tmp_dp可以释放; 使用DPUP->CreateDeviceNode创建的tmp_dp,可能被DPUP->AppendDeviceNode释放, + grub_free (tmp_dp); //因此再释放报错!!! + if (debug > 1) + grub_efi_print_device_path (vpart->dp); //efi打印设备路径 +#endif + printf_debug ("part_map: type=mbr start=%lx size=%lx\n", p->partition_start,p->partition_size); + vpart->media.block_size = vdisk->media.block_size; + + return TRUE; +} + +static grub_efi_boolean_t get_gpt_info (struct grub_part_data *p); +static grub_efi_boolean_t +get_gpt_info (struct grub_part_data *p) //获得gpt磁盘信息 +{ + grub_efi_device_path_t *tmp_dp; + + //创建设备节点 +#if GDPUP + grub_efi_boot_services_t *b; //引导服务 + b = grub_efi_system_table->boot_services; //系统表->引导服务 + grub_efi_device_pate_utilities_protocol_t *DPUP; //设备路径实用程序协议 + grub_efi_guid_t dpup_guid = GRUB_EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID; + DPUP = grub_efi_locate_protocol (&dpup_guid, 0); //EFI定位协议 + tmp_dp = (grub_efi_device_path_t *)efi_call_3 (DPUP->CreateDeviceNode, + GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, //0x04 媒体类型 + GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE, //0x01 硬件子类型 + sizeof(grub_efi_hard_drive_device_path_t)); //节点尺寸 +#else + tmp_dp = grub_efi_create_device_node ( + GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, //0x04 媒体类型 + GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE, //0x01 硬件子类型 + sizeof(grub_efi_hard_drive_device_path_t)); //节点尺寸 +#endif + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_number = (p->partition >> 16) + 1; //分区号 + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_start = p->partition_start; //分区起始 扇区 + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_size = p->partition_size; //分区尺寸 扇区 + grub_memmove(&((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_signature, &p->partition_signature, 16); //分区签名 + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partmap_type = 2; //分区格式类型 + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->signature_type = 2; //签名类型 + //附加设备节点 +#if GDPUP + vpart->dp = (grub_efi_device_path_t *)efi_call_2 (DPUP->AppendDeviceNode, + vdisk->dp, //设备路径 + tmp_dp); //设备节点 + efi_call_1 (b->free_pool, tmp_dp); //释放数据 使用DPUP->CreateDeviceNode创建的tmp_dp只能使用b->free_pool释放 +#else + vpart->dp = grub_efi_append_device_node (vdisk->dp, tmp_dp); //附加设备节点 + if (tmp_dp) //如果存在 使用grub_efi_create_device_node创建的tmp_dp可以释放; 使用DPUP->CreateDeviceNode创建的tmp_dp,可能被DPUP->AppendDeviceNode释放, + grub_free (tmp_dp); //因此再释放报错!!! + if (debug > 1) + grub_efi_print_device_path (vpart->dp); //efi打印设备路径 +#endif + printf_debug ("part_map: type=gpt start=%lx size=%lx\n", p->partition_start,p->partition_size); + vpart->media.block_size = vdisk->media.block_size; + + return TRUE; +} + +static grub_efi_boolean_t get_iso_info (struct grub_part_data *p); +static grub_efi_boolean_t +get_iso_info (struct grub_part_data *p) //获得光盘信息 +{ + grub_efi_device_path_t *tmp_dp; + + //创建设备节点 +#if GDPUP + grub_efi_boot_services_t *b; //引导服务 + b = grub_efi_system_table->boot_services; //系统表->引导服务 + grub_efi_device_pate_utilities_protocol_t *DPUP; //设备路径实用程序协议 + grub_efi_guid_t dpup_guid = GRUB_EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID; + DPUP = grub_efi_locate_protocol (&dpup_guid, 0); //EFI定位协议 + tmp_dp = (grub_efi_device_path_t *)efi_call_3 (DPUP->CreateDeviceNode, + GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, //0x04 媒体类型 + GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE, //0x02 光盘子类型 + sizeof(grub_efi_cdrom_device_path_t)); //节点尺寸 +#else + tmp_dp = grub_efi_create_device_node ( + GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, //0x04 媒体类型 + GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE, //0x02 光盘子类型 + sizeof(grub_efi_cdrom_device_path_t)); //节点尺寸 +#endif + ((grub_efi_cdrom_device_path_t *)tmp_dp)->boot_entry = p->boot_entry; //引导入口 + ((grub_efi_cdrom_device_path_t *)tmp_dp)->boot_start = p->boot_start; //引导起始 扇区 + ((grub_efi_cdrom_device_path_t *)tmp_dp)->boot_size = p->boot_size; //引导尺寸 扇区 + //附加设备节点 +#if GDPUP + vpart->dp = (grub_efi_device_path_t *)efi_call_2 (DPUP->AppendDeviceNode, + vdisk->dp, //设备路径 + tmp_dp); //设备节点 + efi_call_1 (b->free_pool, tmp_dp); //释放数据 使用DPUP->CreateDeviceNode创建的tmp_dp只能使用b->free_pool释放 +#else + vpart->dp = grub_efi_append_device_node (vdisk->dp, tmp_dp); //附加设备节点 + if (tmp_dp) //如果存在 使用grub_efi_create_device_node创建的tmp_dp可以释放; 使用DPUP->CreateDeviceNode创建的tmp_dp,可能被DPUP->AppendDeviceNode释放, + grub_free (tmp_dp); //因此再释放报错!!! +#endif + + if (cd_Image_disk_size) //如果引导镜像有分区表,安装硬盘路径 + { + tmp_dp = grub_efi_create_device_node ( + GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, //0x04 媒体类型 + GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE, //0x01 硬件子类型 + sizeof(grub_efi_hard_drive_device_path_t)); //节点尺寸 + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_number = 1; //分区号 + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_start = p->partition_start; //分区起始 扇区 + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_size = p->partition_size; //分区尺寸 扇区 + grub_memmove(&((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_signature, &p->partition_signature, 16); //分区签名 + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partmap_type = 1; //分区格式类型 + ((grub_efi_hard_drive_device_path_t*)tmp_dp)->signature_type = 1; //签名类型 + vpart->dp = grub_efi_append_device_node (vpart->dp, tmp_dp); //附加设备节点 + if (tmp_dp) + grub_free (tmp_dp); + } + + if (debug > 1) + grub_efi_print_device_path (vpart->dp); //efi打印设备路径 + printf_debug ("part_map: type=iso start=%x size=%x\n", p->boot_start,p->boot_size); + vpart->media.block_size = 0x200; + + return TRUE; +} +////////////////////////////////////////////////////////////////////////////////////////////////////// +//vboot.c +void copy_file_path (grub_efi_file_path_device_path_t *fp, + const char *str, grub_efi_uint16_t len); +void +copy_file_path (grub_efi_file_path_device_path_t *fp, + const char *str, grub_efi_uint16_t len) +{ + grub_efi_char16_t *p, *path_name; + grub_efi_uint16_t size; + + fp->header.type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE; + fp->header.subtype = GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE; + + path_name = grub_malloc (len * sizeof (grub_efi_char16_t)); + if (!path_name) + return; + +// size = grub_utf8_to_ucs2 (path_name, len, +// (const grub_uint8_t *) str, len, 0); + size = utf8_to_multimode ((void *)path_name, (unsigned char *)str, len, 1); + for (p = path_name; p < path_name + size; p++) + if (*p == '/') + *p = '\\'; + + grub_memcpy (fp->path_name, path_name, size * sizeof (*fp->path_name)); + /* File Path is NULL terminated */ + fp->path_name[size++] = '\0'; + fp->header.length = size * sizeof (grub_efi_char16_t) + sizeof (*fp); + grub_free (path_name); +} + +grub_efi_device_path_t * grub_efi_file_device_path (grub_efi_device_path_t *dp, const char *filename); +grub_efi_device_path_t * +grub_efi_file_device_path (grub_efi_device_path_t *dp, const char *filename)//文件设备路径(设备路径, 文件名) +{ + char *dir_start = 0; + grub_size_t size; + grub_efi_device_path_t *d; + grub_efi_device_path_t *file_path=0; + + dir_start = grub_strchr (filename, ')'); //在字符串中查找字符 查到,返回第一个匹配的字符串位置;否则返回0 + if (! dir_start) + dir_start = (char *) filename; //"/EFI/BOOT/bootia32.EFI" + else + dir_start++; + + size = 0; + d = dp; + while (1) + { + size += GRUB_EFI_DEVICE_PATH_LENGTH (d); //尺寸+设备路径尺寸 + if ((GRUB_EFI_END_ENTIRE_DEVICE_PATH (d))) //如果是结束符,退出 + break; + d = GRUB_EFI_NEXT_DEVICE_PATH (d); //下一设备路径 + } + /* File Path is NULL terminated. Allocate space for 2 extra characters 文件路径以空结尾。分配2个额外字符空间 */ + /* FIXME why we split path in two components? 修正为什么我们把路径分成两部分*/ + file_path = grub_malloc (size //路径尺寸 + + ((grub_strlen (dir_start) + 2) //文件名尺寸+2 + * sizeof (grub_efi_char16_t)) //2 + + sizeof (grub_efi_file_path_device_path_t) * 2); //文件路径结构*2 + if (! file_path) + return 0; + + grub_memcpy (file_path, dp, size); //复制路径 + + /* Fill the file path for the directory. 填写目录的文件路径。*/ + d = (grub_efi_device_path_t *) ((char *) file_path + + ((char *) d - (char *) dp)); //跳过路径 移动到 7f ff 04 00 之前 + + copy_file_path ((grub_efi_file_path_device_path_t *) d, + dir_start, grub_strlen (dir_start)); + + + /* Fill the file path for the file. 填充文件的文件路径。*/ + + /* Fill the end of device path nodes. */ + d = GRUB_EFI_NEXT_DEVICE_PATH (d); + d->type = GRUB_EFI_END_DEVICE_PATH_TYPE;; //0x7f + d->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; //0xff + d->length = sizeof (*d); + + return file_path; +} + +//map.lib.vdisc.c +grub_efi_boolean_t guidcmp (const grub_packed_guid_t *g1, const grub_packed_guid_t *g2); +grub_efi_boolean_t +guidcmp (const grub_packed_guid_t *g1, const grub_packed_guid_t *g2) //比较guid +{ + grub_efi_uint64_t g1_low, g2_low; + grub_efi_uint64_t g1_high, g2_high; + g1_low = grub_get_unaligned64 ((const grub_efi_uint64_t *)g1); + g2_low = grub_get_unaligned64 ((const grub_efi_uint64_t *)g2); + g1_high = grub_get_unaligned64 ((const grub_efi_uint64_t *)g1 + 1); + g2_high = grub_get_unaligned64 ((const grub_efi_uint64_t *)g2 + 1); + return (grub_efi_boolean_t) (g1_low == g2_low && g1_high == g2_high); +} + +grub_packed_guid_t *guidcpy (grub_packed_guid_t *dst, const grub_packed_guid_t *src); +grub_packed_guid_t * +guidcpy (grub_packed_guid_t *dst, const grub_packed_guid_t *src) +{ + grub_set_unaligned64 ((grub_efi_uint64_t *)dst, + grub_get_unaligned64 ((const grub_efi_uint64_t *)src)); + grub_set_unaligned64 ((grub_efi_uint64_t *)dst + 1, + grub_get_unaligned64 ((const grub_efi_uint64_t*)src + 1)); + return dst; +} + +grub_packed_guid_t VDISK_GUID = //打包guid 虚拟磁盘GUID +{ 0xebe35ad8, 0x6c1e, 0x40f5, + { 0xaa, 0xed, 0x0b, 0x91, 0x9a, 0x46, 0xbf, 0x4b } +}; + +static void gen_uuid (void); +static void +gen_uuid (void) //获得uuid +{ + VDISK_GUID.data1++; +} + +//vpart.c +//创建设备节点; 附加设备节点; 安装多协议接口; 连接控制器; +//不安装虚拟分区,一般情况可以正常启动。但是对于4k磁盘,则必须安装。(可能使UEFI对4k磁盘正常不充分) +//如果光盘的启动镜像是软盘时,虽然可以安装成功,但是在load_image时失败,找不到(0x800000000000000e)。 +//如果光盘的启动镜像是硬盘(有分区表)时,可以安装成功,在load_image时也成功。 +//结论:光盘启动,不能安装虚拟分区。 +grub_efi_status_t vpart_install (int drive, struct grub_part_data *part); //安装虚拟分区 +grub_efi_status_t +vpart_install (int drive, struct grub_part_data *part) //安装虚拟分区 +{ + grub_efi_status_t status; + grub_efi_boot_services_t *b; + b = grub_efi_system_table->boot_services; + grub_efi_boolean_t present = 0; + struct grub_disk_data *d; + d = get_device_by_drive(drive,0); + if (!d) //如果设备=0, 错误 2023-03-26 + return GRUB_EFI_NOT_FOUND; + vpart = 0; + vpart = grub_zalloc (sizeof(grub_efivdisk_t)); + if (vpart == 0) + { + printf_errinfo ("failed to install virtual vpart: insufficient memory\n"); //无法安装虚拟分区,内存不足 + return GRUB_EFI_BUFFER_TOO_SMALL; + } + + /* guid */ + grub_efi_guid_t dp_guid = GRUB_EFI_DEVICE_PATH_GUID; //设备路径GUID + grub_efi_guid_t blk_io_guid = GRUB_EFI_BLOCK_IO_GUID; //块IO_GUID + if (current_drive >= 0xa0) + present = get_iso_info (part); + else if (part->partition_type == 0xee) + present = get_gpt_info (part); + else + present = get_mbr_info (part); + if (!present) + { + grub_printf ("NOT FOUND\n"); + return GRUB_EFI_NOT_FOUND; + } + grub_memcpy (&vpart->block_io, &blockio_template, sizeof (block_io_protocol_t)); + + vpart->from_handle = NULL; + vpart->block_io.media = &vpart->media; + vpart->media.media_id = d->drive | (part->partition << 8) | cd_map_count++ << 28; + vpart->media.removable_media = FALSE; + vpart->media.media_present = TRUE; + vpart->media.logical_partition = TRUE; + vpart->media.write_caching = FALSE; + vpart->media.io_align = 0x10; + vpart->media.read_only = vdisk->media.read_only; + + if (drive >= 0xa0) +// vpart->media.last_block = (part->boot_size >> 2) - 1; + vpart->media.last_block = part->boot_size - 1; + else + vpart->media.last_block = part->partition_size - 1; + + status = efi_call_6 (b->install_multiple_protocol_interfaces, //安装多协议接口 + &vpart->from_handle, //指向协议接口的指针(如果要分配新句柄,则指向NULL的指针) + &dp_guid, vpart->dp, //指向协议GUID的指针,指向设备路径的指针 + &blk_io_guid, &vpart->block_io, NULL); //指向io设备接口的指针,指向block_io设备接口的指针,NULL + if(status != GRUB_EFI_SUCCESS) + { + printf_warning ("failed to install virtual partition: install_multiple_protocol_interfaces.(%x)\n",status); //无法安装虚拟分区 +// return GRUB_EFI_NOT_FOUND; + } + //此函数要读磁盘 + status = efi_call_4 (b->connect_controller, vpart->from_handle, NULL, NULL, TRUE); //引导服务->连接控制器,要连接驱动程序的控制器的句柄,驱动程序绑定协议的有序列表句柄的指针,指向设备路径的指针,如果为true则递归调用ConnectController(), + if(status != GRUB_EFI_SUCCESS) + { + printf_warning ("failed to install virtual partition: connect_controller.(%d)\n",(int)status); //无法安装虚拟分区 +// return GRUB_EFI_NOT_FOUND; + } + + part->part_handle = vpart->from_handle; +// part->part_path = vpart->dp; + + return GRUB_EFI_SUCCESS; +} +//获得uuid; 创建设备节点; 附加设备节点; 安装多协议接口; 连接控制器; +//如果只安装vdisk(即不安装vpart),可以同时自动安装磁盘及各分区,此时通过磁盘号(a0,80等等)读写。 +//如果先成功安装vpart,则后安装vdisk时,已经安装的分区不再重复安装,此时通过磁盘号(ffffa0,1ffff80等等)读写。 +//如果后安装vpart,则安装无效,即不再重复安装分区! +//如果光盘只安装vdisk,当启动镜像是软盘时,安装路径是:VenHw(......)/CDROM(1,2b,1680)/\EFI\BOOT\BOOTX64.EFI +//如果光盘只安装vdisk,当启动镜像是硬盘(有分区表)时,安装路径是:VenHw(......)/CDROM(1,2b,1680)/HD(1,MBR,0,0,1680)/\EFI\BOOT\BOOTX64.EFI +// (UEFI版本2.28,2.3c是这样。但是版本1.0a与上一条相同。) +//启动磁盘接口的信息包含:句柄指针,设备路径指针,块IO指针。 +//有些Linux光盘,它有分区表,有些主板和VirtualBox虽然识别为CDROM,但是其内容是分区表的,不能启动,必须安装分区。 +grub_efi_status_t vdisk_install (int drive, int partition); +grub_efi_status_t +vdisk_install (int drive, int partition) //安装虚拟磁盘(驱动器号) +{ + grub_efi_status_t status; //状态 + grub_efi_device_path_t *tmp_dp = 0, *ldp = 0; //路径 + grub_efi_boot_services_t *b; //引导服务 + b = grub_efi_system_table->boot_services; //系统表->引导服务 + grub_efi_handle_t *handles; //句柄集 api返回 + grub_efi_handle_t *handle; //句柄 + grub_efi_uintn_t count0 = 0, count1 = 0; + struct grub_part_data *p = 0; + struct grub_disk_data *d; + d = get_device_by_drive(drive,0); //由驱动器号获得设备 + if (!d) //如果设备=0, 错误 2023-03-26 + return GRUB_EFI_NOT_FOUND; + grub_efi_guid_t dp_guid = GRUB_EFI_DEVICE_PATH_GUID; //设备路径GUID + grub_efi_guid_t blk_io_guid = GRUB_EFI_BLOCK_IO_GUID; //块IO_GUID + vdisk = 0; + vdisk = grub_zalloc (sizeof(grub_efivdisk_t)); + if (vdisk == 0) + { + printf_errinfo ("failed to install virtual disk: insufficient memory\n"); //无法安装虚拟磁盘,内存不足 + return GRUB_EFI_BUFFER_TOO_SMALL; + } + + gen_uuid (); //获得uuid +#if GDPUP + grub_efi_device_pate_utilities_protocol_t *DPUP; //设备路径实用程序协议 + grub_efi_guid_t dpup_guid = GRUB_EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID; + DPUP = grub_efi_locate_protocol (&dpup_guid, 0); //EFI定位协议 + //创建设备节点 + tmp_dp = (grub_efi_device_path_t *)efi_call_3 (DPUP->CreateDeviceNode, + GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE, //0x01 硬件设备路径类型 + GRUB_EFI_VENDOR_DEVICE_PATH_SUBTYPE, //0x04 供应商设备路径子类型 + sizeof(grub_efi_vendor_device_path_t)); //节点尺寸 + + guidcpy ((grub_packed_guid_t *)&((grub_efi_vendor_device_path_t *)tmp_dp)->vendor_guid, (grub_packed_guid_t *)&VDISK_GUID); //复制guid + //附加设备节点 + vdisk->dp = (grub_efi_device_path_t *)efi_call_2 (DPUP->AppendDeviceNode, + NULL, //设备路径 + tmp_dp); //设备节点 + + status = efi_call_1 (b->free_pool, tmp_dp); //释放数据 使用DPUP->CreateDeviceNode创建的tmp_dp只能使用b->free_pool释放 +#else + tmp_dp = grub_efi_create_device_node (GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE, GRUB_EFI_VENDOR_DEVICE_PATH_SUBTYPE, //0x01,0x04 硬件设备路径类型,供应商设备路径子类型 + sizeof(grub_efi_vendor_device_path_t)); //创建设备节点 + + guidcpy ((grub_packed_guid_t *)&((grub_efi_vendor_device_path_t *)tmp_dp)->vendor_guid, (grub_packed_guid_t *)&VDISK_GUID); //复制guid + vdisk->dp = grub_efi_append_device_node (NULL, tmp_dp); //附加设备节点 + + if (tmp_dp) //如果存在 使用grub_efi_create_device_node创建的tmp_dp可以释放; 使用DPUP->CreateDeviceNode创建的tmp_dp,可能被DPUP->AppendDeviceNode释放, + grub_free (tmp_dp); //因此再释放报错!!! +#endif + + /* vdisk 虚拟磁盘*/ + vdisk->from_handle = NULL; //句柄 + /* block_io 块io*/ + grub_memcpy (&vdisk->block_io, &blockio_template, sizeof (block_io_protocol_t)); + block_io_protocol_this = (grub_size_t)&vdisk->block_io; + /* media 媒体*/ + vdisk->block_io.media = &vdisk->media; //媒体地址 + vdisk->media.media_id = d->drive; //驱动器号 + vdisk->media.removable_media = FALSE; //可移动媒体 + vdisk->media.media_present = TRUE; //媒体展示 + vdisk->media.logical_partition = FALSE; //逻辑分区 + vdisk->media.write_caching = FALSE; //写缓存 + vdisk->media.io_align = 0x10; //对齐 + vdisk->media.read_only = 0; //只读 + vdisk->media.block_size = 1 << d->from_log2_sector; +// d->device_path = vdisk->dp; + d->block_io = (grub_efi_block_io_t *)&vdisk->block_io; + d->vdisk = vdisk; +// d->last_device_path = 0; + +// vdisk->media.last_block = d->sector_count - 1;//最后块 + vdisk->media.last_block = d->total_sectors - 1;//最后块 + /* info 打印信息*/ + printf_debug ("disk_map: addr=%lx size=%lx blksize=%x\n", d->start_sector, d->sector_count, 1 << d->from_log2_sector); + + if (drive >= 0x80) + { + part_data = get_partition_info (drive, partition); + if (!part_data) + return GRUB_EFI_NOT_FOUND; + vpart_install (drive, part_data); //安装虚拟分区 + } + status = efi_call_6 (b->install_multiple_protocol_interfaces, //安装多协议接口 + &vdisk->from_handle, //指向协议接口的指针(如果要分配新句柄,则指向NULL的指针) + &dp_guid, vdisk->dp, //指向协议GUID的指针,指向设备路径的指针 + &blk_io_guid, &vdisk->block_io, NULL); //指向io设备接口的指针,指向block_io设备接口的指针,NULL + //刚刚获得from_handle + d->device_handle = vdisk->from_handle; + if (status != GRUB_EFI_SUCCESS) //安装失败 + { + printf_errinfo ("failed to install virtual disk: install_multiple_protocol_interfaces.(%d)\n",(int)status); //无法安装虚拟磁盘 + return status; + } + + /* Find handles which support the disk io interface. 查找支持磁盘IO接口的句柄 */ + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &block_io_guid, + 0, &count0); //定位句柄 返回句柄集及句柄数 + + //此函数要读磁盘 + status = efi_call_4 (b->connect_controller, vdisk->from_handle, NULL, NULL, TRUE); //引导服务->连接控制器,要连接驱动程序的控制器的句柄,驱动程序绑定协议的有序列表句柄的指针,指向设备路径的指针,如果为true则递归调用ConnectController(), + if (status != GRUB_EFI_SUCCESS) //安装失败 + { + printf_errinfo ("failed to install virtual disk: connect_controller.(%d)\n",(int)status); //无法安装虚拟磁盘 + return status; + } + + //获取安装硬盘未安装分区的句柄 + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &block_io_guid, + 0, &count1); //定位句柄 返回句柄集及句柄数 + + printf_debug ("count0=%x, count1=%x\n",count0,count1); + count1 -= count0; + handles += count0; + for (handle = handles; count1--; handle++) + { + tmp_dp = grub_efi_get_device_path (*handle); //获得设备路径 + ldp = grub_efi_find_last_device_path (tmp_dp); //获得最后设备路径 + if (debug > 1) + grub_efi_print_device_path (tmp_dp); //efi打印设备路径 + + for (; ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (tmp_dp); tmp_dp = GRUB_EFI_NEXT_DEVICE_PATH (tmp_dp)) + { + if (((grub_efi_vendor_device_path_t*)tmp_dp)->header.type != 4) //不是供应商设备,继续 + continue; + + for (p = partition_info; p; p = p->next) //查分区信息 + { + if (p->drive != drive) //不是当前驱动器继续 + continue; + + if (((grub_efi_vendor_device_path_t*)tmp_dp)->header.subtype == 1) + { + if (((grub_efi_hard_drive_device_path_t*)ldp)->partition_start == p->partition_start && + ((grub_efi_hard_drive_device_path_t*)ldp)->partition_size == p->partition_size) + { + p->part_handle = *handle; + break; + } + } + } + } + } + +#if 0 //获取光盘、硬盘启动分区的句柄 + grub_efi_uintn_t Installed = 0; + /* Find handles which support the disk io interface. 查找支持磁盘IO接口的句柄 */ + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &block_io_guid, + 0, &count1); //定位句柄 返回句柄集及句柄数 + + printf_debug ("count0=%x, count1=%x\n",count0,count1); + count1 -= count0; + handles += count0; + for (handle = handles; count1--; handle++) + { + tmp_dp = grub_efi_get_device_path (*handle); //获得设备路径 + ldp = grub_efi_find_last_device_path (tmp_dp); //查找最后设备路径 + if (debug > 1) + grub_efi_print_device_path (tmp_dp); //efi打印设备路径 + + for (; ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (tmp_dp); tmp_dp = GRUB_EFI_NEXT_DEVICE_PATH (tmp_dp)) + { + if (((grub_efi_vendor_device_path_t*)tmp_dp)->header.type != 4) //不是供应商设备,继续 + continue; + + for (p = partition_info; p; p = p->next) + { + if (p->drive != drive) + continue; + + if (((grub_efi_vendor_device_path_t*)tmp_dp)->header.subtype == 2 && + ((grub_efi_cdrom_device_path_t*)tmp_dp)->boot_entry == cd_boot_entry && + ((grub_efi_cdrom_device_path_t*)tmp_dp)->boot_start == cd_boot_start) //不能比较cd_boot_size,很可能与UEFI固件给出的值不同 + { + if (((grub_efi_vendor_device_path_t*)ldp)->header.subtype == 1) + { + p->part_handle = *handle; + Installed = 1; + } + else + { + p->boot_size = ((grub_efi_cdrom_device_path_t*)tmp_dp)->boot_size; //虽然add_part_data已经设置,但是使用UEFI固件给出的值更保险。 + if (p->part_handle == 0) + { + p->part_handle = *handle; + Installed = 1; + } + } + break; + } + else if (((grub_efi_vendor_device_path_t*)tmp_dp)->header.subtype == 1) + { + if (((grub_efi_hard_drive_device_path_t*)ldp)->partition_start == p->partition_start && + ((grub_efi_hard_drive_device_path_t*)ldp)->partition_size == p->partition_size) + { + p->part_handle = *handle; + Installed = 1; + printf_debug ("part_handle=%x\n",p->part_handle); + break; + } + } + } + break; + } + if (!Installed) + return (errnum = 0x1234); //设置错误号>=MAX_ERR_NUM,不打印err_list[errnum],错误信息由相应程序处理。设置错误号,可以避免死机。 2023-03-15 + } +#endif + return GRUB_EFI_SUCCESS; +} + +static grub_efi_status_t (EFIAPI *orig_locate_handle) + (grub_efi_locate_search_type_t search_type, + grub_efi_guid_t *protocol, + void *search_key, + grub_efi_uintn_t *buffer_size, + grub_efi_handle_t *buffer) = NULL; + +static int +compare_guid (grub_efi_guid_t *a, grub_efi_guid_t *b) +{ + int i; + if (a->data1 != b->data1 || a->data2 != b->data2 || a->data3 != b->data3) + return 0; + for (i = 0; i < 8; i++) + { + if (a->data4[i] != b->data4[i]) + return 0; + } + return 1; +} + +static grub_efi_handle_t saved_handle; + +static grub_efi_status_t EFIAPI +locate_handle_wrapper (grub_efi_locate_search_type_t search_type, + grub_efi_guid_t *protocol, + void *search_key, + grub_efi_uintn_t *buffer_size, + grub_efi_handle_t *buffer) +{ + grub_efi_uintn_t i; + grub_efi_handle_t handle = NULL; + grub_efi_status_t status = GRUB_EFI_SUCCESS; + grub_efi_guid_t guid = GRUB_EFI_BLOCK_IO_GUID; + + status = efi_call_5 (orig_locate_handle, search_type, + protocol, search_key, buffer_size, buffer); + + if (status != GRUB_EFI_SUCCESS || !protocol) + return status; + + if (!compare_guid (&guid, protocol)) + return status; + + for (i = 0; i < (*buffer_size) / sizeof(grub_efi_handle_t); i++) + { + if (buffer[i] == saved_handle) //11328c18 + { + handle = buffer[0]; //handle=11b3d398 + buffer[0] = buffer[i]; //buffer[0]=11328c18 + buffer[i] = handle; //buffer[i]=11b3d398 + break; + } + } + + return status; +} + +static int image_is_64_bit (grub_pe_header_t *pe_hdr); +static int +image_is_64_bit (grub_pe_header_t *pe_hdr) //映像是64位 +{ + /* .Magic is the same offset in all cases 魔法在所有情况下都是相同的偏移*/ + if (pe_hdr->pe32plus.optional_header.magic == GRUB_PE32_PE64_MAGIC) //0x20b + return 1; + return 0; +} + +static grub_efi_boolean_t read_header (void *data, grub_efi_uint32_t size, + pe_coff_loader_image_context_t *context); +static grub_efi_boolean_t +read_header (void *data, grub_efi_uint32_t size, + pe_coff_loader_image_context_t *context) //读取标头 +{ + char *msdos = (char *) data; + grub_pe_header_t *pe_hdr = (grub_pe_header_t *)data; + + if (size < sizeof (*pe_hdr)) + { + printf_errinfo ("Invalid image\n"); + return 0; + } + + if (grub_memcmp (msdos, "MZ", 2) == 0) + { + grub_uint32_t off = *((grub_uint32_t *) (msdos + 0x3c)); + pe_hdr = (grub_pe_header_t *) ((char *)data + off); + } + + if (grub_memcmp (pe_hdr->pe32plus.signature, "PE\0\0", 4) != 0 || +#if defined(__x86_64__) + ! image_is_64_bit (pe_hdr) || + pe_hdr->pe32plus.coff_header.machine != GRUB_PE32_MACHINE_X86_64) +#else + image_is_64_bit (pe_hdr) || + pe_hdr->pe32.coff_header.machine != GRUB_PE32_MACHINE_I386) +#endif + { + printf_errinfo ("Not supported image\n"); + return 0; + } + +#if defined(__x86_64__) + context->number_of_rva_and_sizes = pe_hdr->pe32plus.optional_header.num_data_directories; + context->size_of_headers = pe_hdr->pe32plus.optional_header.header_size; + context->image_size = pe_hdr->pe32plus.optional_header.image_size; + context->image_address = pe_hdr->pe32plus.optional_header.image_base; + context->entry_point = pe_hdr->pe32plus.optional_header.entry_addr; + context->reloc_dir = &pe_hdr->pe32plus.optional_header.base_relocation_table; + context->sec_dir = &pe_hdr->pe32plus.optional_header.certificate_table; + context->number_of_sections = pe_hdr->pe32plus.coff_header.num_sections; + context->pe_hdr = pe_hdr; + context->first_section = (struct grub_pe32_section_table *)((char *)(&pe_hdr->pe32plus.optional_header) + pe_hdr->pe32plus.coff_header.optional_header_size); +#else + context->number_of_rva_and_sizes = pe_hdr->pe32.optional_header.num_data_directories; + context->size_of_headers = pe_hdr->pe32.optional_header.header_size; + context->image_size = pe_hdr->pe32.optional_header.image_size; + context->image_address = pe_hdr->pe32.optional_header.image_base; + context->entry_point = pe_hdr->pe32.optional_header.entry_addr; + context->reloc_dir = &pe_hdr->pe32.optional_header.base_relocation_table; + context->sec_dir = &pe_hdr->pe32.optional_header.certificate_table; + context->number_of_sections = pe_hdr->pe32.coff_header.num_sections; + context->pe_hdr = pe_hdr; + context->first_section = (struct grub_pe32_section_table *)((char *)(&pe_hdr->pe32.optional_header) + pe_hdr->pe32.coff_header.optional_header_size); +#endif + return 1; +} + +static void* image_address (void *image, grub_efi_uint64_t sz, grub_efi_uint64_t adr); +static void* +image_address (void *image_, grub_efi_uint64_t sz, grub_efi_uint64_t adr) //映像地址 +{ + if (adr > sz) + return NULL; + + return ((grub_uint8_t*)image_ + adr); +} + +static grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table); +static grub_efi_status_t +relocate_coff (pe_coff_loader_image_context_t *context, + struct grub_pe32_section_table *section, + void *orig, void *data) //重新定位coff +{ + struct grub_pe32_data_directory *reloc_base, *reloc_base_end; + grub_efi_uint64_t adjust; + struct grub_pe32_fixup_block *reloc, *reloc_end; + char *fixup, *fixup_base, *fixup_data = NULL; + grub_efi_uint16_t *fixup_16; + grub_efi_uint32_t *fixup_32; + grub_efi_uint64_t *fixup_64; + grub_efi_uint64_t size = context->image_size; + void *image_end = (char *)orig + size; + int n = 0; + + if (image_is_64_bit (context->pe_hdr)) + context->pe_hdr->pe32plus.optional_header.image_base = + (grub_uint64_t)(unsigned long)data; + else + context->pe_hdr->pe32.optional_header.image_base = + (grub_uint32_t)(unsigned long)data; + + /* Alright, so here's how this works: + * + * context->reloc_dir gives us two things: + * - the VA the table of base relocation blocks are (maybe) to be + * mapped at (reloc_dir->rva) + * - the virtual size (reloc_dir->size) + * + * The .reloc section (section here) gives us some other things: + * - the name! kind of. (section->name) + * - the virtual size (section->virtual_size), which should be the same + * as RelocDir->Size + * - the virtual address (section->virtual_address) + * - the file section size (section->raw_data_size), which is + * a multiple of optional_header->file_alignment. Only useful for image + * validation, not really useful for iteration bounds. + * - the file address (section->raw_data_offset) + * - a bunch of stuff we don't use that's 0 in our binaries usually + * - Flags (section->characteristics) + * + * and then the thing that's actually at the file address is an array + * of struct grub_pe32_fixup_block structs with some values packed behind + * them. The block_size field of this structure includes the + * structure itself, and adding it to that structure's address will + * yield the next entry in the array. + */ + + reloc_base = image_address (orig, size, section->raw_data_offset); + reloc_base_end = image_address (orig, size, section->raw_data_offset + + section->virtual_size); + + printf_debug ("chain: relocate_coff(): reloc_base %x reloc_base_end %x\n", + reloc_base, reloc_base_end); //9b77000 9b7c000; + + if (!reloc_base && !reloc_base_end) + return GRUB_EFI_SUCCESS; + + if (!reloc_base || !reloc_base_end) + { + printf_errinfo ("Reloc table overflows binary\n"); + return GRUB_EFI_UNSUPPORTED; + } + + adjust = (grub_uint64_t)(grub_efi_uintn_t)data - context->image_address; + if (adjust == 0) + return GRUB_EFI_SUCCESS; + + while (reloc_base < reloc_base_end) + { + grub_uint16_t *entry; + reloc = (struct grub_pe32_fixup_block *)((char*)reloc_base); + + if ((reloc_base->size == 0) || + (reloc_base->size > context->reloc_dir->size)) + { + printf_errinfo ("Reloc %x block size %x is invalid\n", reloc_base->size); + return GRUB_EFI_UNSUPPORTED; + } + + entry = &reloc->entries[0]; + reloc_end = (struct grub_pe32_fixup_block *)((char *)reloc_base + reloc_base->size); + + if ((void *)reloc_end < orig || (void *)reloc_end > image_end) + { + printf_errinfo ("Reloc entry %x overflows binary\n"); + return GRUB_EFI_UNSUPPORTED; + } + + fixup_base = image_address(data, size, reloc_base->rva); + + if (!fixup_base) + { + printf_errinfo ("Reloc %x Invalid fixupbase\n"); + return GRUB_EFI_UNSUPPORTED; + } + + while ((void *)entry < (void *)reloc_end) + { + fixup = fixup_base + (*entry & 0xFFF); + switch ((*entry) >> 12) + { + case GRUB_PE32_REL_BASED_ABSOLUTE: + break; + case GRUB_PE32_REL_BASED_HIGH: + fixup_16 = (grub_uint16_t *)fixup; + *fixup_16 = (grub_uint16_t)(*fixup_16 + ((grub_uint16_t)((grub_uint32_t)adjust >> 16))); + if (fixup_data != NULL) + { + *(grub_uint16_t *) fixup_data = *fixup_16; + fixup_data = fixup_data + sizeof (grub_uint16_t); + } + break; + case GRUB_PE32_REL_BASED_LOW: + fixup_16 = (grub_uint16_t *)fixup; + *fixup_16 = (grub_uint16_t) (*fixup_16 + (grub_uint16_t)adjust); + if (fixup_data != NULL) + { + *(grub_uint16_t *) fixup_data = *fixup_16; + fixup_data = fixup_data + sizeof (grub_uint16_t); + } + break; + case GRUB_PE32_REL_BASED_HIGHLOW: + fixup_32 = (grub_uint32_t *)fixup; + *fixup_32 = *fixup_32 + (grub_uint32_t)adjust; + if (fixup_data != NULL) + { + fixup_data = (char *)ALIGN_UP ((grub_addr_t)fixup_data, sizeof (grub_uint32_t)); + *(grub_uint32_t *) fixup_data = *fixup_32; + fixup_data += sizeof (grub_uint32_t); + } + break; + case GRUB_PE32_REL_BASED_DIR64: + fixup_64 = (grub_uint64_t *)fixup; + *fixup_64 = *fixup_64 + (grub_uint64_t)adjust; + if (fixup_data != NULL) + { + fixup_data = (char *)ALIGN_UP ((grub_addr_t)fixup_data, sizeof (grub_uint64_t)); + *(grub_uint64_t *) fixup_data = *fixup_64; + fixup_data += sizeof (grub_uint64_t); + } + break; + default: + printf_errinfo ("Reloc %x unknown relocation type %x\n", (*entry) >> 12); + return GRUB_EFI_UNSUPPORTED; + } + entry += 1; + } + reloc_base = (struct grub_pe32_data_directory *)reloc_end; + n++; + } + + return GRUB_EFI_SUCCESS; +} + +static grub_efi_device_path_t * +grub_efi_get_media_file_path (grub_efi_device_path_t *dp) //获取媒体文件路径 +{ + while (1) + { + grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); //路径 + grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); //子路径 + + if (type == GRUB_EFI_END_DEVICE_PATH_TYPE) //(0xff & 0x7f) + break; + else if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE //4 + && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE) //4 + return dp; //找到 + + dp = GRUB_EFI_NEXT_DEVICE_PATH (dp); //下一路径 + } + + return NULL; //没有找到 +} + +grub_efi_device_path_t *boot_file = NULL; +grub_efi_char16_t *cmdline; +grub_ssize_t cmdline_len; +grub_efi_handle_t dev_handle; + +static grub_efi_boolean_t handle_image (void *data, grub_efi_uint32_t datasize); +static grub_efi_boolean_t +handle_image (void *data, grub_efi_uint32_t datasize) //句柄映像 +{ + grub_efi_loaded_image_t *li, li_bak; + grub_efi_status_t efi_status; + void *buffer = NULL; + char *buffer_aligned = NULL; + grub_efi_uint32_t i; + struct grub_pe32_section_table *section; + char *base, *end; + pe_coff_loader_image_context_t context; + grub_uint32_t section_alignment; + grub_uint32_t buffer_size; + int found_entry_point = 0; + + if (read_header (data, datasize, &context)) //读取标头 + { + printf_debug ("chain: Succeed to read header\n"); //"读取标头成功" + } + else + { + printf_debug ("chain: Failed to read header\n"); //"读取标头失败" + goto error_exit; + } + + /* + * The spec says, uselessly, of SectionAlignment: 规范中无用地提到了截面对齐: + * ===== + * The alignment (in bytes) of sections when they are loaded into 节加载到内存中时的对齐方式(以字节为单位)。它必须大于或等于FileAlignment。 + * memory. It must be greater than or equal to FileAlignment. The 默认值是体系结构的页面大小。 + * default is the page size for the architecture. + * ===== + * Which doesn't tell you whose responsibility it is to enforce the 这并不能告诉你谁有责任强制执行“违约”,或者何时执行。 + * "default", or when. It implies that the value in the field must 这意味着字段中的值必须是>FileAlignment(定义也很差), + * be > FileAlignment (also poorly defined), but it appears visual + * studio will happily write 512 for FileAlignment (its default) and 但visual studio似乎很乐意为FileAlignment(默认值)写512, + * 0 for SectionAlignment, intending to imply PAGE_SIZE. 为SectionAlignment写0,这意味着PAGE_SIZE。 + * + * We only support one page size, so if it's zero, nerf it to 4096. 我们只支持一个页面大小,所以如果它为零,请将其缩小到4096。 + */ + section_alignment = context.section_alignment; + if (section_alignment == 0) //如果区段对齐=0 + section_alignment = 4096; + + buffer_size = context.image_size + section_alignment; //缓存尺寸=映像尺寸+区段对齐 + printf_debug ("chain: image size is %08lx, datasize is %08x\n", //"映像大尺寸67000,数据尺寸为67000" + (long unsigned)context.image_size, datasize); + + efi_status = grub_efi_allocate_pool (GRUB_EFI_LOADER_DATA, buffer_size, &buffer); //分配池 + + if (efi_status != GRUB_EFI_SUCCESS) //失败 + { + printf_errinfo ("out of memory\n"); //"内存不足" + goto error_exit; + } + + buffer_aligned = (char *)ALIGN_UP ((grub_addr_t)buffer, section_alignment); //向上对齐缓存 + + if (!buffer_aligned) //失败 + { + printf_errinfo ("out of memory\n"); //"内存不足" + goto error_exit; + } + + grub_memcpy (buffer_aligned, data, context.size_of_headers); //复制数据 + + entry_point = image_address (buffer_aligned, context.image_size, + context.entry_point); //EFI映像入口点 + + printf_debug ("chain: entry_point: %x\n", entry_point); //"入口点: 9a47000" + if (!entry_point) //失败 + { + printf_errinfo ("invalid entry point\n"); //"无效入口点" + goto error_exit; + } + + char *reloc_base, *reloc_base_end; + + reloc_base = image_address (buffer_aligned, context.image_size, + context.reloc_dir->rva); //重新定位基准 + /* RelocBaseEnd here is the address of the last byte of the table RelocBaseEnd这里是表的最后一个字节的地址*/ + reloc_base_end = image_address (buffer_aligned, context.image_size, + context.reloc_dir->rva + + context.reloc_dir->size - 1); + printf_debug ("chain: reloc_base: %x reloc_base_end: %x\n", //"重定位基准:9aa8000, 重定位基准结束:9aacfff" + reloc_base, reloc_base_end); + struct grub_pe32_section_table *reloc_section = NULL; + + section = context.first_section; + for (i = 0; i < context.number_of_sections; i++, section++) + { + char name[9]; + + base = image_address (buffer_aligned, context.image_size, + section->virtual_address); //基地址 + end = image_address (buffer_aligned, context.image_size, + section->virtual_address + section->virtual_size -1); //结束地址 + + grub_strncpy(name, section->name, 9); //复制字符串 + name[8] = '\0'; + printf_debug ("chain: Section %x \"%s\" at %x..%x\n", i, + name, base, end); +//第0".text节,第9a47000...9a86fff页; +//第1".data节,第9a87000...9aa6fff页; +//第2"mods节,第9aa7000...9aa7fff页; +//第3".rtloc节,第9aa8000...9aacfff页; + if (end < base) + { + printf_errinfo ("chain: base is %x but end is %x... bad.\n", //"底部是%x,但末端是%x...令人不快的" + base, end); + printf_errinfo ("Image has invalid negative size\n"); //"映像的负尺寸无效" + goto error_exit; + } + + if (section->virtual_address <= context.entry_point && + (section->virtual_address + section->raw_data_size - 1) + > context.entry_point) + { + found_entry_point++; + printf_debug ("chain: section contains entry point\n"); //"部分包含入口点" + } + + /* We do want to process .reloc, but it's often marked 我们确实想处理.reloc,但它通常被标记为可丢弃,所以我们不想记住它 + * discardable, so we don't want to memcpy it. */ + if (grub_memcmp (section->name, ".reloc\0\0", 8) == 0) + { + if (reloc_section) + { + printf_errinfo ("Image has multiple relocation sections\n"); //映像有多个重新定位节 + goto error_exit; + } + + /* If it has nonzero sizes, and our bounds check 如果它的大小为非零,并且我们的边界检查是有意义的, + * made sense, and the VA and size match RelocDir's 并且VA和大小与RelocDir的版本匹配,那么我们相信这个节表 + * versions, then we believe in this section table. */ + if (section->raw_data_size && section->virtual_size && + base && end && reloc_base == base && reloc_base_end == end) + { + printf_debug ("chain: section is relocation section\n"); //"节是重新定位节" + reloc_section = section; + } + else + { + printf_debug ("chain: section is not reloc section?\n"); //"区段不是重新定位区段?" + printf_debug ("chain: rds: 0x%08x, vs: %08x\n", //"rds: 0x%08x, vs: %08x" + section->raw_data_size, section->virtual_size); + printf_debug ("chain: base: %x end: %x\n", base, end); + printf_debug ("chain: reloc_base: %x reloc_base_end: %x\n", + reloc_base, reloc_base_end); + } + } + + printf_debug ("chain: Section characteristics are %08x\n", section->characteristics); //60000020; c0000040; c0000040; 42000040; + printf_debug ("chain: Section virtual size: %08x\n", section->virtual_size); //40000; 20000; 1000; 5000; + printf_debug ("chain: Section raw_data size: %08x\n", section->raw_data_size); //40000; 20000; 1000; 5000; + if (section->characteristics & GRUB_PE32_SCN_MEM_DISCARDABLE) + { + printf_debug ("chain: Discarding section\n"); //"丢弃节" + continue; + } + + if (!base || !end) + { + printf_errinfo ("Invalid section size\n"); //"无效的节大小" + goto error_exit; + } + + if (section->characteristics & GRUB_PE32_SCN_CNT_UNINITIALIZED_DATA) + { + if (section->raw_data_size != 0) + printf_debug ("chain: UNINITIALIZED_DATA section has data?\n"); //"UNINITIALIZED_DATA部分是否有数据?" + } + else if (section->virtual_address < context.size_of_headers || + section->raw_data_offset < context.size_of_headers) + { + printf_errinfo ("Section %x is inside image headers\n", i); //"第%d节在映像标题内" + goto error_exit; + } + + if (section->raw_data_size > 0) + { + printf_debug ("chain: copying 0x%08x bytes to %x\n", + section->raw_data_size, base); //40000 to 9a47000; 20000 to 9a87000; 10000 to 9aa5000; + grub_memcpy (base, + (grub_efi_uint8_t*)data + section->raw_data_offset, + section->raw_data_size); //复制 + } + + if (section->raw_data_size < section->virtual_size) + { + printf_debug ("chain: padding with 0x%08x bytes at %x\n", //"在%x处填充0x%08x字节" + section->virtual_size - section->raw_data_size, + base + section->raw_data_size); + grub_memset (base + section->raw_data_size, 0, + section->virtual_size - section->raw_data_size); + } + + printf_debug ("chain: finished section %s\n", name); //已完成节.text; .data; mods; + } + /* 5 == EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC 映像目录条目BASEREL*/ + if (context.number_of_rva_and_sizes <= 5) + { + printf_debug ("chain: image has no relocation entry\n"); //"映像没有重新定位条目" + goto error_exit; + } + + if (context.reloc_dir->size && reloc_section) + { + /* run the relocation fixups 运行重新定位修复程序*/ + efi_status = relocate_coff (&context, reloc_section, data, + buffer_aligned); + if (efi_status != GRUB_EFI_SUCCESS) + { + printf_errinfo ("relocation failed\n"); //"重新定位失败" + goto error_exit; + } + } + + if (!found_entry_point) + { + printf_errinfo ("entry point is not within sections\n"); //"入口点不在区间内" + goto error_exit; + } + + if (found_entry_point > 1) + { + printf_errinfo ("%d sections contain entry point\n", //"%d节包含入口点" + found_entry_point); + goto error_exit; + } + + li = grub_efi_get_loaded_image (grub_efi_image_handle); //fc71040; + if (!li) + { + printf_errinfo ("no loaded image available\n"); //"没有可用的加载映像" + goto error_exit; + } + + grub_memcpy (&li_bak, li, sizeof (grub_efi_loaded_image_t)); + li->image_base = buffer_aligned; + li->image_size = context.image_size; + li->load_options = cmdline; + li->load_options_size = cmdline_len; + li->file_path = grub_efi_get_media_file_path (boot_file); + li->device_handle = dev_handle; + + if (!li->file_path) + { + printf_errinfo ("no matching file path found\n"); //"没有匹配的文件路径foun" + goto error_exit; + } + + printf_debug ("chain: booting via entry point\n"); //"通过入口点引导" + efi_status = efi_call_2 (entry_point, grub_efi_image_handle, + grub_efi_system_table); //EFI映像输入点 + + printf_debug ("chain: entry_point returned %lx\n", (long int) efi_status); //"返回入口点%ld" + grub_memcpy (li, &li_bak, sizeof (grub_efi_loaded_image_t)); + efi_status = grub_efi_free_pool (buffer); //释放池 + return 1; + +error_exit: + printf_debug ("chain: error_exit: errnum: %x\n", errnum); //"错误退出:errnum:%d" + if (buffer) + grub_efi_free_pool (buffer); + + return 0; +} + +//定位句柄缓冲,获得文件设备路径,加载映像 +grub_efi_handle_t grub_load_image (grub_efi_device_path_t *path, const char *filename, void *boot_image); //虚拟磁盘引导 +grub_efi_handle_t +grub_load_image (grub_efi_device_path_t *path, const char *filename, void *boot_image) //虚拟磁盘引导 +{ + grub_efi_status_t status; + grub_efi_handle_t boot_image_handle = NULL; + grub_efi_boot_services_t *b; + b = grub_efi_system_table->boot_services; //系统表->引导服务 + + boot_file = grub_efi_file_device_path (path, filename); //文件设备路径(获得设备路径,可移动媒体文件名) "/EFI/BOOT/boot + if (!boot_file) + { + grub_printf ("Invalid device path\n"); //"无效的设备路径" + return NULL; + } + if (debug > 1) + grub_efi_print_device_path(boot_file); + if (!boot_image) + { + //加载映像 将EFI映像加载到内存中 此函数要读磁盘 + status = efi_call_6 (b->load_image, TRUE, //启动策略. 如果为true,则表示请求来自引导管理器,并且引导管理器正尝试将设备路径作为引导选择加载 + grub_efi_image_handle, //调用方的映像句柄. 此字段用于为正在加载的映像初始化EFI加载的映像协议的父句柄字段。 + boot_file, //从中加载映像的设备句柄特定文件路径 + NULL, //缓存指针. 如果不为空,则是指向包含要加载的映像副本的内存位置的指针。 + 0, //缓存字节尺寸。如果缓存为空,则忽略 + &boot_image_handle); //指向成功加载映像时创建的返回映像句柄的指针。(void **) + } + else + { + status = efi_call_6 (b->load_image, 0, + grub_efi_image_handle, + boot_file, + boot_image, + filemax, + &boot_image_handle); //调用(装载镜像,0,镜像句柄,文件路径,引导镜像,尺寸,镜像句柄地址) + } + + if (status == GRUB_EFI_SECURITY_VIOLATION) //违反安全规定 移植自grub2 2023-09-15 + { + /* If it failed with security violation while not in secure boot mode, 如果它在不处于安全引导模式时由于安全违规而失败, + the firmware might be broken. We try to workaround on that by forcing 固件可能已损坏。我们试图通过强制使用SB方法来解决这个问题! + the SB method! (bsc#887793) */ + printf_debug ("LoadImage failed with EFI_SECURITY_VIOLATION.\n"); //"LoadImage因EFI安全违规而失败" + + if (boot_image) + { + handle_image ((void *)(unsigned long)boot_image, filemax); //成功后不返回 + return 0; + } + else + { + grub_efi_physical_address_t address; + grub_efi_uintn_t pages; + char arg[64] = {0}; + + if (current_drive < 0xa0) //硬盘 + { + part_data = get_boot_partition (current_drive); + if (!part_data) + return 0; + sprintf (arg, "(%d,%d)%s\0", current_drive, part_data->partition >> 16, EFI_REMOVABLE_MEDIA_FILE_NAME); + } + else //光盘 + { + sprintf (arg, "(%d)%s\0", part_data->partition_activity_flag, EFI_REMOVABLE_MEDIA_FILE_NAME); + } + dev_handle = part_data->part_handle; + + grub_open (arg); + if (errnum) + return 0; + + pages = ((filemax + ((1 << 12) - 1)) >> 12); //计算页 + status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES, + GRUB_EFI_LOADER_CODE, + pages, &address); //调用(分配页面,分配类型->任意页面,存储类型->装载程序代码(1),分配页,地址) + if (status != GRUB_EFI_SUCCESS) //失败退出 + { + printf_errinfo ("Failed to allocate %u pages\n",(unsigned int) pages); + grub_close (); + return 0; + } + + boot_image = (void *) ((grub_addr_t) address); //引导镜像地址 + if (grub_read ((unsigned long long)(grub_size_t)boot_image, filemax, 0xedde0d90) != filemax) + { + printf_errinfo ("premature end of file %s",arg); + grub_close (); + return 0; + } + grub_close (); + + handle_image ((void *)(unsigned long)boot_image, filemax); //成功后不返回 + return 0; + } + return 0; + } + + if (status != GRUB_EFI_SUCCESS) //失败 + { + printf_warning ("Failed to load virtual disk image.(%d)\n",(int)status); + boot_image_handle = NULL; + } + +// *devhandle = *handle; + if (current_drive >= 0xa0) + { + //windows启动cdrom时,只启动第一个cdrom,因此如果有多个cdrom,必须把要启动的cdrom移动到第一位。 + struct grub_disk_data *d; + d = get_device_by_drive (current_drive,0); + if (!d) //如果设备=0, 错误 2023-03-26 + return NULL; + saved_handle = d->device_handle; //不能使用“*devhandle”。启动WePE_64_V2.2.iso时错误提示:0xc000000f。可能对应的块IO驱动不对。 + if (!orig_locate_handle) + { + orig_locate_handle = (void *) b->locate_handle; + b->locate_handle = (void *) locate_handle_wrapper; + } + } + + if (boot_file) + grub_free (boot_file); + return boot_image_handle; //返回映像句柄的指针 +} + + + +grub_efi_status_t EFIAPI blockio_read_write (block_io_protocol_t *this, grub_efi_uint32_t media_id, + grub_efi_lba_t lba, grub_efi_uintn_t len, void *buf, int read_write); +grub_efi_status_t EFIAPI +blockio_read_write (block_io_protocol_t *this, grub_efi_uint32_t media_id, + grub_efi_lba_t lba, grub_efi_uintn_t len, void *buf, int read_write) //读(自身,媒体id,起始逻辑扇区,读字节尺寸,缓存) +{ + grub_efi_uintn_t block_num; + + if (!buf) //如果缓存为零 + return GRUB_EFI_INVALID_PARAMETER; + + if (!len) //如果尺寸为零 + return GRUB_EFI_SUCCESS; + + //如果尺寸未对齐扇区块 + if ((len % this->media->block_size) != 0) + return GRUB_EFI_BAD_BUFFER_SIZE;//BufferSize参数不是设备内部块大小的倍数。 + + block_num = len / this->media->block_size; + //如果读写数据越界 可以包含"如果扇区号越界" + if ((lba + block_num - 1) > this->media->last_block) + return GRUB_EFI_INVALID_PARAMETER;//读取请求包含无效的lba,或者缓冲区未正确对齐。 + + int err = grub_efidisk_readwrite (media_id, lba, len, buf, read_write); + + if (!err) + return GRUB_EFI_SUCCESS; + else + return GRUB_EFI_DEVICE_ERROR; +} + +/* +读 +GRUB_EFI_SUCCESS 数据已从设备中正确读取。 +GRUB_EFI_DEVICE_ERROR 设备在尝试执行读取操作时报告了一个错误。 +GRUB_EFI_NO_MEDIA 设备中没有媒体。 +GRUB_EFI_MEDIA_CHANGED MediaId不适用于当前媒体。 +GRUB_EFI_BAD_BUFFER_SIZE BufferSize参数不是设备内部块大小的倍数。 +GRUB_EFI_INVALID_PARAMETER 读取请求包含无效的lba,或者缓冲区未正确对齐。 + +写 +GRUB_EFI_SUCCESS 数据已正确写入设备。 +GRUB_EFI_DEVICE_ERROR 设备在尝试执行写入操作时报告了一个错误。 +GRUB_EFI_NO_MEDIA 设备中没有媒体。 +GRUB_EFI_MEDIA_CHANGED MediaId不适用于当前媒体。 +GRUB_EFI_BAD_BUFFER_SIZE BufferSize参数不是设备内部块大小的倍数。 +GRUB_EFI_INVALID_PARAMETER 写入请求包含无效的lba,或者缓冲区未正确对齐。 +GRUB_EFI_WRITE_PROTECTED 无法写入设备。 +*/ + +static grub_efi_status_t EFIAPI blockio_reset (block_io_protocol_t *this,grub_efi_boolean_t extended); +static grub_efi_status_t EFIAPI +blockio_reset (block_io_protocol_t *this, + grub_efi_boolean_t extended) +{ + return GRUB_EFI_SUCCESS; +} + +static grub_efi_status_t EFIAPI blockio_read (block_io_protocol_t *this, grub_efi_uint32_t media_id, + grub_efi_lba_t lba, grub_efi_uintn_t len, void *buf); +static grub_efi_status_t EFIAPI +blockio_read (block_io_protocol_t *this, grub_efi_uint32_t media_id, + grub_efi_lba_t lba, grub_efi_uintn_t len, void *buf) +{ + return blockio_read_write (this, media_id, lba, len, buf, 0xedde0d90); +} + +static grub_efi_status_t EFIAPI blockio_write (block_io_protocol_t *this, grub_efi_uint32_t media_id, + grub_efi_lba_t lba, grub_efi_uintn_t len, void *buf); +static grub_efi_status_t EFIAPI +blockio_write (block_io_protocol_t *this, grub_efi_uint32_t media_id, + grub_efi_lba_t lba, grub_efi_uintn_t len, void *buf) +{ + return blockio_read_write (this, media_id, lba, len, buf, 0x900ddeed); +} + +static grub_efi_status_t EFIAPI blockio_flush (block_io_protocol_t *this); +static grub_efi_status_t EFIAPI +blockio_flush (block_io_protocol_t *this) +{ + return GRUB_EFI_SUCCESS; +} + +#define EFI_BLOCK_IO_PROTOCOL_REVISION 0x00010000 + +block_io_protocol_t blockio_template = +{ + EFI_BLOCK_IO_PROTOCOL_REVISION, + (grub_efi_block_io_media_t *) 0, + blockio_reset, + blockio_read, + blockio_write, + blockio_flush +}; + +#if 0 +static EFI_LOCATE_HANDLE g_org_locate_handle = NULL; + +/* Fixup the 1st cdrom influnce for Windows boot 修复Windows引导的第一个cdrom影响 */ +static grub_efi_status_t EFIAPI grub_wrapper_locate_handle //包装器定位句柄 + (grub_efi_locate_search_type_t search_type, + grub_efi_guid_t *protocol, + void *search_key, + grub_efi_uintn_t *buffer_size, + grub_efi_handle_t *buffer); +{ + UINTN i; + EFI_HANDLE Handle = NULL; + EFI_STATUS Status = EFI_SUCCESS; + + Status = g_org_locate_handle(SearchType, Protocol, SearchKey, BufferSize, Buffer); //定位句柄 + + if (EFI_SUCCESS == Status && Protocol && //没有错误,协议存在 + CompareGuid(&gEfiBlockIoProtocolGuid, Protocol)) //比较Guid + { + for (i = 0; i < (*BufferSize) / sizeof(EFI_HANDLE); i++) // + { + if (Buffer[i] == gBlockData.Handle) //如果等于块数据.句柄, 则调换句柄到第一位置 + { + Handle = Buffer[0]; + Buffer[0] = Buffer[i]; + Buffer[i] = Handle; + break; + } + } + } + return Status; +} + +EFI_STATUS grub_hook_1st_cdrom_start(VOID) //钩第一光盘开始 +{ + g_org_locate_handle = gBS->LocateHandle; + gBS->LocateHandle = ventoy_wrapper_locate_handle; //包装器定位句柄 + return EFI_SUCCESS; +} + +EFI_STATUS grub_hook_1st_cdrom_stop(VOID) //钩第一光盘结束 +{ + gBS->LocateHandle = g_org_locate_handle; + g_org_locate_handle = NULL; + return EFI_SUCCESS; +} +#endif + +grub_efi_handle_t pd_handle; +grub_efi_device_path_t *pd_dp; +//void GRUB_MOD_INIT_efinet(void); +//int force_pxe_as_boot_device = 0; +void grub_efidisk_init (void); +void +grub_efidisk_init (void) //efidisk初始化 +{ +// debug = 3; //启动调试 + if ((*(char *)IMG(0x8205) & 0x40)) + debug = 3; + grub_efidisk_fini(); + enumerate_disks (); //枚举磁盘 + +#if defined(__i386__) + is64bit = check_64bit_and_PAE (); +#else + is64bit = 3; +#endif + + if (!image) + return; + +/* image->device_handle是装载映像句柄,通过它可以获得起始驱动器。但是它不一定等于grub_disk_data->handle。 + qemu启动一个设备,image->device_handle = grub_disk_data->handle. + qemu启动一个光盘,再附加一个硬盘,image->device_handle即不等于光盘的grub_disk_data->handle,也不等于硬盘的grub_disk_data->handle。 + 但是由image->device_handle获得设备路径,与光盘的设备路径相同。 +*/ + /* Set root drive and partition. 设置根驱动器和分区。*/ + grub_efi_device_path_t *dp, *ldp; //设备路径 + dp = grub_efi_get_device_path (image->device_handle); //获得设备路径 + + if (! dp) //如果为零, 错误 + return; + printf_debug("grub_efidisk_init:\n"); + ldp = grub_efi_find_last_device_path (dp); //查找最后设备路径 + if (debug > 1) + { + grub_efi_print_device_path(ldp); + } + printf_debug("PATH_TYPE=%x, PATH_SUBTYPE=%x\n",GRUB_EFI_DEVICE_PATH_TYPE (ldp),GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp)); +//03 0b 25 00 00 0c 29 83 - 7a 6b 00 00 00 00 00 00 网络 +//00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 +//00 00 00 00 00 7f ff 04 - 00 +//硬盘 +// |hid |uid ACPI设备路径类型,ACPI设备路径子类型 注: 这是电脑真实的设备路径!! +//02 01 0c 00 d0 41 03 0a - 00 00 00 00 +// |功能 |设备 硬件设备路径类型,PCI设备路径子类型 +//01 01 06 00 01 01 +// |主次 |从主 |逻辑单元 消息传递设备路径类型,ATAPI设备路径子类型 注: 这是电脑真实的设备路径!! +//03 01 08 00 00 00 00 00 +// |分区号 |分区起始 |分区尺寸 |分区签名 |分区格式类型/签名类型 媒体设备路径类型,硬盘驱动器设备路径子类型 注: 这是UEFI提供的设备路径 +//04 01 2a 00 01 00 00 00 - 3f 00 00 00 00 00 00 00 - c1 cf 01 00 00 00 00 00 - ab cd ef 12 00 00 00 00 - 00 00 00 00 00 00 00 00 - 01 01 7f ff 04 00 +//04 01 2a 00 01 00 00 00 - 00 08 00 00 00 00 00 00 - 00 00 04 00 00 00 00 00 - b4 02 50 fc 4d 3c 8c 43 - bc 04 aa ef 87 c0 ae 24 - 02 02 7f ff 04 00 + +//#ifdef FSYS_PXE + if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE) //如果最后设备路径类型是通讯设备路径 3 + { + if (! ((*(char *)IMG(0x8205)) & 0x01)) /* if it is not disable pxe 如果没有禁用pxe */ + { + printf_debug ("pxe_init:\n"); + int err = pxe_init (); + printf_debug ("pxe_init_err=%x\n",err); + if (err) + goto aaa; + + boot_drive = PXE_DRIVE; //0x21 + printf_debug ("boot_drive=%x\n", boot_drive); + saved_drive = boot_drive; + current_drive = boot_drive; + install_partition = 0xFFFFFF; + saved_partition = install_partition; + current_partition = install_partition; + run_line((char *)"set ?_BOOT=%@root%",1); + *saved_dir = 0; + pd_handle = image->device_handle; //2023-11-24 + pd_dp = dp; + printf_debug ("cmain: About to enter the menu.\n"); + if (debug > 1) + getkey(); + + return; + } + } +aaa: +//#endif /* FSYS_PXE */ + for (; ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp); dp = GRUB_EFI_NEXT_DEVICE_PATH (dp)) + { + if (((grub_efi_vendor_device_path_t*)dp)->header.type == 4 && ((grub_efi_vendor_device_path_t*)dp)->header.subtype == 1) //硬盘 + { + part_start = ((grub_efi_hard_drive_device_path_t *)ldp)->partition_start; //分区起始 + part_length = ((grub_efi_hard_drive_device_path_t *)ldp)->partition_size; //分区尺寸 + break; + } + if (((grub_efi_vendor_device_path_t*)dp)->header.type == 4 && ((grub_efi_vendor_device_path_t*)dp)->header.subtype == 2) //光盘 + { + part_start = ((grub_efi_cdrom_device_path_t *)dp)->boot_start; //分区起始 + part_length = ((grub_efi_cdrom_device_path_t *)dp)->boot_size; //分区尺寸 + break; + } + } + + if (debug > 1) + { + grub_printf("part_start=%x, part_length=%x.\n",part_start,part_length); + getkey(); + } + + int ret = 0; + struct grub_part_data *fq; + struct grub_disk_data *d; + for (fq = partition_info; fq; fq = fq->next) + { + if ((GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) == 1 && fq->partition_start == part_start && fq->partition_size == part_length) //如果是硬盘 + || (GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) == 2 && fq->boot_start == part_start && fq->boot_size == part_length)) //如果是光盘 + { + boot_drive = fq->drive; + install_partition = fq->partition; + break; + } + } + //硬盘启动调整引导驱动器为0x80 + if (boot_drive != 0x80 && boot_drive > 0x80 && boot_drive <= 0x8f) + { + ret = 0x80; + + for (d = disk_data; d; d = d->next) + { + if (d->drive == boot_drive) + d->drive = ret; + else if (d->drive == ret) + d->drive = boot_drive; + } + + for (fq = partition_info; fq; fq = fq->next) + { + if (fq->drive == boot_drive) + fq->drive = ret; + else if (fq->drive == ret) + fq->drive = boot_drive; + } + boot_drive = 0x80; + } + //初始值: boot_drive=current_drive=0xFFFFFFFF saved_drive=0 + //初始值: install_partition=0x00FFFFFF saved_partition=current_partition=0 + saved_drive = boot_drive; + current_drive = boot_drive; + saved_partition = install_partition; + current_partition = install_partition; + ret = find_specified_file (current_drive, current_partition, "/efi/grub/menu.lst"); + if (!ret || boot_drive == 0xFFFFFFFF) + run_line((char *)"find --set-root /efi/grub/menu.lst",1); +//初始化变量空间 + run_line((char *)"set ?_BOOT=%@root%",1); +// QUOTE_CHAR = '\"'; + *saved_dir = 0; + return; +} diff --git a/stage2/dosstart.S b/stage2/dosstart.S deleted file mode 100644 index 757e7007..00000000 --- a/stage2/dosstart.S +++ /dev/null @@ -1,17404 +0,0 @@ -/* - * dosstart.S -- DOS EXE and Linux kernel startup code for GNU GRUB - * Copyright (C) 2003-2007 Tinybit(tinybit@tom.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* Note for License: Since we have copied the Linux kernel code and the - * Linux kernel follows GPL2, so only GPL2 is adoptable and it rules here. - */ - -/* - * This program is used to generate the grub.exe file, which can boot off DOS - * directly or, in another way, boot off Linux through KEXEC. - * - * Use the following shell command to generate the grub.exe file: - * - * cat dosstart pre_stage2 > grub.exe - * - */ - -#define ASM_FILE -#include -#include - -#define ABS_PSP(x) (x - _start - 0x200) -#define ABS_START(x) (x - _start - 0x200) -#define ABS_FINAL(x) (x - pre_stage2_start + 0x200) - -/* HMA_backup immediately follows the main body of stage2, para aligned */ - -#define HMA_backup (ABS_PSP(STAGE2_SIZE+0x1010+pre_stage2_start+15)/16) - -#ifdef BAD_BIOS - .file "badgrubstart.S" -#else - .file "dosstart.S" -#endif - - .text - - .code16 /* for real mode */ - - .globl start, _start -_start: -_start1: - - /* 1 sector of EXE header is used by DOS. Actually only the leading - * 32 bytes are used for EXE header. At offset 0x20(=32) begins the - * DOS device driver structure. And at offset 0x1f1(=497) begins - * the Linux kernel structure. - */ - - /* - * The dos startup code counts N=(pre_stage2_start-_start)/512 sectors: - * - * 1 sector for DOS EXE header, followed by (N-1) sectors of code. - * Of the (N-1) code sectors, the first (N-2) sectors are preparational - * sectors, and the last sector is called the FINAL sector. The - * FINAL sector contains code that finally launches the stage2 code. - * So pay special attention to the FINAL sector. Do not destroy - * the FINAL sector upon memory move operations. - */ - - .byte 0x4d, 0x5a /* 'MZ', the EXE magic number. */ - - . = _start + 0x02 - - /* EXE file last sector in bytes. Urrh... Place a jump instruction - * here, hopefully working :) - */ - //.word ((STAGE2_SIZE + 0x1010 + pre_stage2_start - _start) % 512) -#if 0 - .byte 0xEB, 0x18 /* jmp 1f */ -#else - jmp grldr_start -#endif - - . = _start + 0x04 - -#define exe_sectors ((STAGE2_SIZE+0x1010+pre_stage2_start-_start+511)/512) - - .word exe_sectors /* total sectors the EXE file occupies */ - - .word 0 /* relocation table entries */ - - .word 0x0002 /* header size in 16-byte paragraphs. */ - /* 0x0002 paragraphs == 32 bytes */ - - .word 0x1000 + 0x0300 + 0x0040 #; MinAlloc paragraphs: - #; 64KB for HMA_backup - #; 12KB for VCPI page_info - #; 1KB for restoring EBDA - - .word 0x1000 + 0x0300 + 0x0040 #; MaxAlloc paragraphs: - #; no more memory needed, so - #; MaxAlloc == MinAlloc - - .word 0x001E /* initial SS, relative to START segment */ - - .word ABS_START(dos_stack) /* initial SP, rich room for stack */ - .word 0 /* checksum, ignored by dos */ - .word ABS_START(_dos_start) /* initial IP */ - .word 0x001E /* initial CS, relative to START segment */ - .word 0x001C /* displacement of the relocation table */ - .word 0 /* overlay serial number. 0 for main program */ - -1: - /* this is not used if it does not jump here at offset 02 */ - jmp grldr_start - //.byte 0xE9 /* jmp grldr_real_start */ - //.word (grldr_real_start - 1f) -1: - - /* DOS program begins at _dos_start. CS==SS==START, DS==ES==PSP */ - - /* For DOS device driver, _START + 0x20 locates CS:0000 */ - -#----------------------------------------------------------------------------- -# DOS device driver structure begins here -#----------------------------------------------------------------------------- - - . = _start + 0x20 - -#if 0 - -# SKELETON.ASM - A SKELETON DEVICE DRIVER V1.0 -# (C) COPYRIGHT 1994 G.KLEIN -# -#This file contains structures, sample code and information intended -# to aid in building a device driver. It is set up as a skeleton, i.e. -# hardly any working code is provided. Only the Initialisation command -# is implemented - it displays a signon message and the commandline -# it was loaded from (excluding the "device[high]=" part). Sample code -# is provided both to let the driver load as to let it unload itself -# from memory after the initialisation command is processed. There is -# also a bit of code showing how to implement the driver as an EXE file, -# with different code depending on weather it is loaded from config.sys -# or from the command prompt. -#Although the major part of this file contains structures and other info, -# is assembles to a "working" device driver. It can be loaded from -# config.sys, and displays a signon message. When run from the commandline, -# it also displays a (different) message. It has been tested with and -# assembles "out of the box" under TASM V2.0 and MASM V5.0. -#The contents of this file is copyrighted. It may be used freely for -# whatever purpose you see it fit. Although a big effort has been made -# to ensure all information in this file is correct, no guarantees can -# be given. Any comments you may have on this file or the (correctness of) -# the information therein are welcome. Here is how you can reach me: -# -# Fidonet: Gertjan Klein @ 2:280/901.14 -# Internet: gklein@hacktic.nl (Gertjan Klein) -# as of Sept. 1994: gklein@xs4all.nl (Gertjan Klein) - - -##################################################################### - -#Some structures describing the request headers for the various commands. -# In the comment field, a "<" means this is input to the command, and ">" -# means this is output from the command. It is indicated weather the -# command applies to block (B) or character (C) device drivers, or both -# (B/C). If a command is defined later then version 2.0, the DOS version -# in which it first appears is placed in parenthesis. This also applies -# to the fields in the request headers. - -rh0 struc #0 - Initialisation (B/C) -rh0_len db ? # < Length of packet -rh0_unit db ? #Unused -rh0_cmd db 0 # < Device driver command -rh0_stat dw ? # > Status returned by device driver -rh0_rsvd db 8 dup (?) #Reserved -rh0_units db ? # > Number of units (B) -rh0_break dd ? # < End of driver memory (5.0+) - # > Break address (new end drvr mem) -rh0_bpb dd ? # < Pointer to cmdline (inc. name) - # > Pointer to BPB pointers array (B) -rh0_drv_ltr db ? # < First available drive (B, 3.0+) -rh0_msgflag dw ? # > 1 To make DOS show errors (5.0+) -rh0 ends - -rh1 struc #1 - Media Check (B) -rh1_len db ? # < Length of packet -rh1_unit db ? # < Unit code -rh1_cmd db 1 # < Device driver command -rh1_stat dw ? # > Status returned by device driver -rh1_rsvd db 8 dup (?) #Reserved -rh1_media db ? # < Current media descriptor -rh1_md_stat db ? # > Media status (changed/not/?) -rh1_volID dd ? # > Ptr to Volume ID (3.0+) -rh1 ends - -rh2 struc #2 - Get BPB (B) -rh2_len db ? # < Length of packet -rh2_unit db ? # < Unit code -rh2_cmd db 2 # < Device driver command -rh2_stat dw ? # > Status returned by device driver -rh2_rsvd db 8 dup (?) #Reserved -rh2_media db ? # < Current media descriptor -rh2_buff dd ? # < Pointer to buffer -rh2_bpb dd ? # > Pointer to BPB -rh2 ends - -rh3 struc #3 - IOCTL input (B/C) -rh3_len db ? # < Length of packet -rh3_unit db ? # < Unit code (B) -rh3_cmd db 3 # < Device driver command -rh3_stat dw ? # > Status returned by device driver -rh3_rsvd db 8 dup (?) #Reserved -rh3_media db ? #Unused -rh3_buff dd ? # < Pointer to buffer -rh3_count dw ? # < Transfer count (bytes) - # > Nr of bytes read -rh3 ends - -rh4 struc #4 - Input (B/C) -rh4_len db ? # < Length of packet -rh4_unit db ? # < Unit code (B) -rh4_cmd db 4 # < Device driver command -rh4_stat dw ? # > Status returned by device driver -rh4_rsvd db 8 dup (?) #Reserved -rh4_media db ? # < Media descriptor byte (B) -rh4_buff dd ? # < Pointer to data transfer area -rh4_count dw ? # < Transfer count (B:sectors,C:bytes) - # > Nr of sectors/bytes read -rh4_start dw ? # < Start sector number (B) -rh4_volID dd ? # > Pointer to volume ID (B, 5.0+) -rh4_HugeStart dd ? # < 32-bits start sector (B, 5.0+) - # (if rh4_count = 0FFFFh) -rh4 ends - -rh5 struc #5 - Non-destructive input (C) -rh5_len db ? # < Length of packet -rh5_unit db ? #Unused -rh5_cmd db 5 # < Device driver command -rh5_stat dw ? # > Status returned by device driver -rh5_rsvd db 8 dup (?) #Reserved -rh5_char db ? # > Character returned -rh5 ends - -rh6 struc #6 - Input status (C) -rh6_len db ? # < Length of packet -rh6_unit db ? #Unused -rh6_cmd db 6 # < Device driver command -rh6_stat dw ? # > Status returned by device driver -rh6_rsvd db 8 dup (?) #Reserved -rh6 ends - -rh7 struc #7 - Input flush (C) -rh7_len db ? # < Length of packet -rh7_unit db ? #Unused -rh7_cmd db 7 # < Device driver command -rh7_stat dw ? # > Status returned by device driver -rh7_rsvd db 8 dup (?) #Reserved -rh7 ends - -rh8 struc #8 - Output (B/C) -rh8_len db ? # < Length of packet -rh8_unit db ? # < Unit code (B) -rh8_cmd db 8 # < Device driver command -rh8_stat dw ? # > Status returned by device driver -rh8_rsvd db 8 dup (?) #Reserved -rh8_media db ? # < Media descriptor byte (B) -rh8_buff dd ? # < Pointer to data transfer area -rh8_count dw ? # < Transfer count (B:sectors,C:bytes) - # > Nr of sectors/bytes read -rh8_start dw ? # < Start sector number (B) -rh8_volID dd ? # > Pointer to volume ID (B, 5.0+) -rh8_HugeStart dd ? # < 32-bits start sector (B, 5.0+) - # (if rh8_count = 0FFFFh) -rh8 ends - -rh9 struc #9 - Output with verify (B/C) -rh9_len db ? # < Length of packet -rh9_unit db ? # < Unit code (B) -rh9_cmd db 9 # < Device driver command -rh9_stat dw ? # > Status returned by device driver -rh9_rsvd db 8 dup (?) #Reserved -rh9_media db ? # < Media descriptor byte (B) -rh9_buff dd ? # < Pointer to data transfer area -rh9_count dw ? # < Transfer count (B:sectors,C:bytes) - # > Nr of sectors/bytes read -rh9_start dw ? # < Start sector number (B) -rh9_volID dd ? # > Pointer to volume ID (B, 5.0+) -rh9_HugeStart dd ? # < 32-bits start sector (B, 5.0+) - # (if rh9_count = 0FFFFh) -rh9 ends - -rh0A struc #0Ah - Output status (C) -rh0A_len db ? # < Length of packet -rh0A_unit db ? #Unused -rh0A_cmd db 0ah # < Device driver command -rh0A_stat dw ? # > Status returned by device driver -rh0A_rsvd db 8 dup (?) #Reserved -rh0A ends - -rh0B struc #0Bh - Output flush (C) -rh0B_len db ? # < Length of packet -rh0B_unit db ? #Unused -rh0B_cmd db 0bh # < Device driver command -rh0B_stat dw ? # > Status returned by device driver -rh0B_rsvd db 8 dup (?) #Reserved -rh0B ends - -rh0C struc #0Ch - IOCTL output (B/C) -rh0C_len db ? # < Length of packet -rh0C_unit db ? # < Unit code (B) -rh0C_cmd db 0ch # < Device driver command -rh0C_stat dw ? # > Status returned by device driver -rh0C_rsvd db 8 dup (?) #Reserved -rh0C_media db ? #Unused -rh0C_buff dd ? # < Pointer to buffer -rh0C_count dw ? # < Transfer count (bytes) - # > Nr of bytes written -rh0C ends - -rh0D struc #0Dh - Open (B/C) (3.0+) -rh0D_len db ? # < Length of packet -rh0D_unit db ? # < Unit code (B) -rh0D_cmd db 0dh # < Device driver command -rh0D_stat dw ? # > Status returned by device driver -rh0D_rsvd db 8 dup (?) #Reserved -rh0D ends - -rh0E struc #0Eh - Close (B/C) (3.0+) -rh0E_len db ? # < Length of packet -rh0E_unit db ? # < Unit code (B) -rh0E_cmd db 0eh # < Device driver command -rh0E_stat dw ? # > Status returned by device driver -rh0E_rsvd db 8 dup (?) #Reserved -rh0E ends - -rh0F struc #0Fh - Removable media (B) (3.0+) -rh0F_len db ? # < Length of packet -rh0F_unit db ? # < Unit code -rh0F_cmd db 0fh # < Device driver command -rh0F_stat dw ? # > Status returned by device driver -rh0F_rsvd db 8 dup (?) #Reserved -rh0F ends - -rh10 struc #10h - Output until busy (C) (3.0+) -rh10_len db ? # < Length of packet -rh10_unit db ? #Unused -rh10_cmd db 10h # < Device driver command -rh10_stat dw ? # > Status returned by device driver -rh10_rsvd db 8 dup (?) #Reserved -rh10_media db ? #Unused -rh10_buff dd ? # < Pointer to buffer -rh10_count dw ? # < Transfer count (B:sectors,C:bytes) - # > Nr of sectors/bytes written -rh10 ends - -#Commands 11h and 12h are undefined - -rh13 struc #13h - Generic IOCTL (3.2+:B, 3.3+:B/C) -rh13_len db ? # < Length of packet -rh13_unit db ? # < Unit code (B) -rh13_cmd db 13h # < Device driver command -rh13_stat dw ? # > Status returned by device driver -rh13_rsvd db 8 dup (?) #Reserved -rh13_major db ? # < Category -rh13_minor db ? # < Minor function -rh13_SI dw ? # < Contents of SI register -rh13_DI dw ? # < Contents of DI register -rh13_pkt dd ? # < Pointer to generic IOCTL req. -rh13 ends - -#Commands 14 to 16 are undefined - -rh17 struc #17h - Get device (B) (3.2+) -rh17_len db ? # < Length of packet -rh17_unit db ? # < Unit number to check - # > Last active drive (or 0) -rh17_cmd db 17h # < Device driver command -rh17_stat dw ? # > Status returned by device driver -rh17_rsvd db 8 dup (?) #Reserved -rh17 ends - -rh18 struc #18h - Set device (B) (3.2+) -rh18_len db ? # < Length of packet -rh18_unit db ? # < Unit to make active -rh18_cmd db 18h # < Device driver command -rh18_stat dw ? # > Status returned by device driver -rh18_rsvd db 8 dup (?) #Reserved -rh18 ends - -rh19 struc #19h - IOCTL query (B/C) (5.0+) -rh19_len db ? # < Length of packet -rh19_unit db ? # < Unit code (B) -rh19_cmd db 19h # < Device driver command -rh19_stat dw ? # > Status returned by device driver -rh19_rsvd db 8 dup (?) #Reserved -rh19_major db ? # < Category -rh19_minor db ? # < Minor function -rh19_SI dw ? # < Contents of SI register -rh19_DI dw ? # < Contents of DI register -rh19_pkt dd ? # < Pointer to IOCTL query req. -rh19 ends - -#endif - -nxtdev: .long -1 #Pointer to next device driver in chain -attr: .word 0x8000 #Attribute: character device -strat: .word strategy - nxtdev #Address of strategy routine -intr: .word interrupt - nxtdev #Address of interrupt routine -dname: .ascii "GRUB4DOS" #Name of the device driver (C), or - # (1 byte:) number of devices (B) - -#The attribute word is defined as follows: -# Bit 0: (C): 1 if driver is stdin -# 1: (C): 1 if driver is stdout -# (B): 1 if driver supports 32-bit sector addressing -# (commands 4, 8 and 9) -# 2: (C): 1 if driver is NUL device (only allowed for DOS's own driver) -# 3: (C): 1 if driver is clock device -# 4: (C): 1 if driver supports fast character I/O (int 29h) -# 5: undefined -# 6: (C/B): 0 if driver supports commands 17h and 18h and/or 13h -# (get/set logical drive and generic IOCTL) -# 7: (C/B): 1 if driver supports IOCTL query (command 19h) -# 8: undefined -# 9: undefined -# 10: undefined -# 11: (C/B): 1 if driver supports commands 0dh, 0eh and 0fh -# (Open/close device and removable media) -# 12: (C): 1 if driver supports output until busy (command 10h) -# (B): 1 if driver requires first FAT sector for build BPB -# (command 2) -# 13: undefined -# 14: (C/B): 1 if driver supports IOCTL read and write (commands 3 -# and 0ch) -# 15: (C): 1 if driver supports a character device -# (B): 0 if driver supports a block device - -strategy: - movw %es, %cs:(RhSeg - nxtdev) #Save request header segment - movw %bx, %cs:(RhOffs - nxtdev) #Save request header offset - lret #Return to caller - -#----------------------------------------------------------------------------- -# DOS device driver structure ends here -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# GRLDR structure for sector 0 begins here -#----------------------------------------------------------------------------- - - - . = _start + 0x40 - -grldr_start: - - cli - xorw %bx, %bx - movw %bx, %ss - movw $0x0580, %sp /* temp safe stack */ - call 1f -1: - popw %bx /* BX=Instruction Pointer of 1b */ - subw $(1b - _start), %bx /* CS:BX = _start */ - - shrw $4, %bx - movw %cs, %ax - addw %ax, %bx /* BX:0000 = _start */ - - pushw %bx /* new CS */ - #;pushw $(1f - _start) - .byte 0x6A, (1f - _start) - lret - . = . - (. - _start) / 0x80 -1: - addw $((pre_stage2_start - _start + STAGE2_SIZE - 4) >> 4), %bx - movw %bx, %ds - - cmpl $0xCE1A02B0, ((STAGE2_SIZE - 4) & 0x0F) - pushw %cs - popw %ds - je grldr_real_start /* whole image loaded. boot it! */ - - /* CS:0000=DS:0000=_start1 */ - - /* we are loaded by BIOS or another boot loader */ - -#define MONITOR 0x8410 /* for 4-sector NTFS boot record */ -#define GRLDR_CS 0x2000 /* grldr code segment */ - - pushw $GRLDR_CS - popw %ss - movw $0x9000, %sp /* SS:SP=0x9d000, keep away from EBDA data */ - sti - - /* Extended BIOS Data Area should not take up space below 0x9d000 */ - - /* - * 0x07c00-0x07dff This sector. Another boot loader load us here - * 0x0d000-0x14dff partition/floppy boot track(bootsector,etc) - * 0x94000-0x9bdff master boot track(MBR,etc,usually 63 sectors) - * 0x9be00-0x9c3ff 3 sectors for temp extended partition entries - * 0x9c400-0x9cfff 6 sectors for stack - */ - -#define FS_BOOT 0xd00 /* segment of partition boot track */ - - pushw %ss /* SS=CS */ - popw %es /* ES=CS */ - -// movw $(((pre_stage2_start - _start1) >> 9) + 0x200), %ax -// movw %ax, %bp /* save AX to BP: read 1 track */ -// xorw %bx, %bx /* ES=CS */ - movw $((pre_stage2_start - _start1) >> 9), %cx -1: - movw $0x0201, %ax /* read 1 sector */ - movw %cx, %bx - decw %bx - shlw $9, %bx - movw $0x0080, %dx - pushw %cx - pushw %bx - call int13 - popw %bx - popw %cx - jc 1f - loop 1b - negb %ah /* set CF=1 if non-zero */ -1: - pushw %cs /* DS=0 */ - popw %ds /* DS=CS */ - pushfw /* CF=1 on error */ - - /* CS=DS=old segment. ES=SS=new segment. */ - - /* Move the code and error messages from DS:0000 to 9400:0000, do not - * touch the partition table - */ - xorw %si, %si - xorw %di, %di - movw $223, %cx /* 223 words = 446 bytes = 0x1be bytes */ - cld - repz movsw /* SI=DI=0x1be, CX=0 */ - - /********************************************************************/ - /* At this moment we are still not sure whether the helper is ok. */ - /********************************************************************/ - -disk_serial_number_structure: - - movw $(grldr_signature - _start1), %bx /* BX=0x1FFC */ - - /* if the boot loader has loaded more than one sector, we use them */ - movl $0x62557247, %eax /* "GrUb" */ - -disk_serial_number_structure_end: - - cmpl %eax, (%bx) /* DS=old segment of 07C0:0000 */ - jne 1f - - /* The MOVE_HELPER code is in the old segment of 07C0:0000 */ - - call move_helper /* SI=0x1be, CX=0 */ -1: - - /* Jump to new segment! */ -#if 1 - ljmp $GRLDR_CS, $(1f - _start1) -#else - pushw %ss /* 0x9400 */ - - //pushw $(1f - _start1) - .byte 0x6A, (1f - _start1) - - lret - . = . - (. - _start1) / 0x80 -#endif -1: - - /* We are at the new segment. CS=ES=SS=new segment. */ - - /* But DS is still old segment. */ - - pushw %ss - popw %ds - - /* CS=DS=ES=SS=new segment. */ - - //movw $0x01be, %si - - /* check the existence of helper */ - cmpl %eax, (%bx) - - jne Error_or_prev_MBR /* Missing helper */ - - popfw /* CF=1 on error */ - jc try_floppy /* harddisk (hd0) failed, try floppy (fd0) */ - - /*********************************/ - /* Helper is successfully loaded */ - /*********************************/ -1: - pushw %cs - popw %ds - lodsw - movb %ah, %dh /* head number */ - lodsw - movw %ax, %cx /* sector and cylinder number */ - andb $63, %al - jz helper_call_c - - movb $0x01, %al -7: - movw $3, %di /* retry 3 times on read failure */ -2: - movb $0x02, %ah - pushw $FS_BOOT - popw %es /* ES=FS_BOOT */ - xorw %bx, %bx /* read partition boot track to FS_BOOT:0000 */ - - pushaw - call int13 /* read partition boot track to FS_BOOT:0000 */ - popaw - - jnc helper_call - - pushaw - xorw %ax, %ax - call int13 - popaw - decw %di - - jnz 2b - -helper_call_c: - - stc - -helper_call: - /* find GRLDR in this partition - * before the call: - * CF=1 : indicates an invalid or corrupt entry - * CF=0 : indicates a valid entry - * - * on return: - * CF=1 : means "below", try next entry - * CF=0,ZF=1 : means "equal", helper did nothing, so we need - * a further try to boot via NT bootsector - * CF=0,ZF=0 : means "above", helper succeeded, boot it now - */ - call helper_start /* change to jmp 6f if helper not present */ - ja filesystem_boot /* helper succeeded, directly boot it */ -6: - -add_sub_si: - - /* extended partition check routine will adjust this to - * - * 0x83, 0xEE, 0x04 for "subw $4, %si" - * - * or - * - * 0x83, 0xC6, 0xFC for "addw $-4, %si" - * - * so that SI keeps the value 0x1fe. - */ - addw $12, %si /* 0x83, 0xC6, 0x0C */ - - . = add_sub_si + 3 - - /* extended partition check routine will adjust the word 0x1fe at - * (add_sub_si + 5). The value 0x1ff or greater indicates there are - * entries need to be treated. The value 0x1fe indicates no entries - * left, and the floppy should be checked. - */ - - cmpw $0x01fe, %si /* 0x81, 0xFE, 0xfe, 0x01 */ - /* All entries checked done? */ - jb 1b /* No, check the next entry */ - ja 5f /* floppy already checked. Fail and hang */ - -try_floppy: - - movw $0x31b2, %si /* a value big enough */ - movb $4, %al - movw $1, %cx - xorw %dx, %dx - jmp 7b - -5: -Error_or_prev_MBR: - - /* GRLDR not found, print "Error" or launch previous MBR */ - movw $(message_string - _start1), %si - - call print_message /* CS:SI points to message string */ -3: jmp 3b - -int13: - pushw %ds - pushw %es -// pushw %bx - pushw %dx - pushw %si - pushw %di - pushw %bp - stc - int $0x13 - popw %bp - popw %di - popw %si - popw %dx -// popw %bx - popw %es - popw %ds - ret - -filesystem_boot: - /* The partition boot record successfully modified, just boot it */ - - /* - * The boot might fail, but we want to take back the control. - * So we save the registers now. - */ - pushw %ds - pushw %es - pushal - - /* DS=CS=GRLDR_CS, ES=FS_BOOT */ - - /* save GRLDR_CS */ - - movw %es, %bx # save old ES to BX - - cli - lgdt gdt9 - _start1 - movl %cr0, %eax - orb $1, %al - movl %eax, %cr0 - - movw $8, %si - movw %si, %es - - xorl %esi, %esi - xorl %edi, %edi - movl $(0x9000 / 4), %ecx - - cld - repz movsl - - movw $16, %si - movw %si, %es - - andb $0xfe, %al - movl %eax, %cr0 - - movw %bx, %es # restore ES from BX - - /* move FS_BOOT:0000 to 0:7c00 */ - /* for 4-sector NTFS boot record */ - movw $0x0400, %cx /* move 4 sectors, the old FS_BOOT:0000 will keep untouched. */ - xorw %si, %si - pushw %si /* SI=0, for the segment of 0000:7c00 */ - movw $0x7c00, %di - pushw %di /* DI=0x7c00, for the offset of 0000:7c00 */ - pushw %es /* ES=FS_BOOT */ - popw %ds /* DS=FS_BOOT */ - pushw %si /* SI=0 */ - popw %es /* ES=0 */ - cld - repz movsw - - movw $MONITOR, %di - movw $(restore_GRLDR_CS - _start1), %si - movw $((gdt9_end - restore_GRLDR_CS) / 4), %cx - cld - repz cs movsl /* CS segment override prefix(=0x2E) */ - - pushw %es /* ES=0 */ - popw %ds /* DS=0 */ - sti - lret //ljmp $0, $0x7c00 - -try_next_partition: - - cli - movw $GRLDR_CS, %ax - movw %ax, %ss - movw $(0x9000-36), %sp - sti - - /* restore the registers and continue */ - popal - popw %es - popw %ds - jmp add_sub_si - - /* prints string CS:SI (modifies AX BX SI) */ -3: - //xorw %bx, %bx /* video page 0 */ - movb $0x0e, %ah /* print char in AL */ - int $0x10 /* via TTY mode */ - -print_message: - - lodsb %cs:(%si), %al /* get token */ - cmpb $0, %al /* end of string? */ - jne 3b - ret - -message_string: - - .ascii "\r\nMissing helper.\0" - - /* Make sure the above code does not occupy the partition table */ - - /* offset value here must be less than or equal to 0x1be */ - . = . - ((. - _start1) / 0x1bf) - -// /* offset value here must be less than or equal to 0x1b8 */ -// . = . - ((. - _start1) / 0x1b9) - -#----------------------------------------------------------------------------- -# GRLDR structure for sector 0 ends here -#----------------------------------------------------------------------------- - -/* stolen from linux-2.6.13.1/arch/i386/boot/bootsect.S */ - -/* - * bootsect.S Copyright (C) 1991, 1992 Linus Torvalds - * - * modified by Drew Eckhardt - * modified by Bruce Evans (bde) - * modified by Chris Noe (May 1999) (as86 -> gas) - * gutted by H. Peter Anvin (Jan 2003) - * - * BIG FAT NOTE: We are in real mode using 64k segments. Therefore segment - * addresses must be multiplied by 16 to obtain their respective linear - * addresses. To avoid confusion, linear addresses are written using leading - * hex while segment addresses are written as segment:offset. - * - */ - - -#----------------------------------------------------------------------------- -# Linux kernel structure begins here -#----------------------------------------------------------------------------- - - /* external programs can use this to locate pre_stage2_start. */ - - . = _start + 0x1f0 - -dosstart_sects: .byte ((pre_stage2_start - _start) >> 9) - - # Kernel attributes; used by setup - - . = _start + 0x1f1 - -setup_sects: .byte ((startup_32 - _start) >> 9) - 1 -root_flags: .word 1 /* ROOT_RDONLY */ -syssize: .word 0x7F00 /* system size: # of 16-byte clicks to load */ -swap_dev: .word 0 /* now written by "build" */ -ram_size: .word 0 /* RAMDISK */ -vid_mode: .word 0xFFFF /* SVGA_MODE = NORMAL_VGA = 80x25 mode */ -root_dev: .word 0 /* now written by "build" */ -boot_flag: .word 0xAA55 - - . = _start + 0x200 - - /* For Linux kernel and DOS EXE, START locates CS:0000 */ - -#----------------------------------------------------------------------------- -# DOS device driver and EXE use 9 sectors here for storing registers and -# the 4096-byte command line. The command line is at offset 0x0081. -#----------------------------------------------------------------------------- - -/* stolen from linux-2.6.13.1/arch/i386/boot/setup.S */ - -/* - * setup.S Copyright (C) 1991, 1992 Linus Torvalds - * - * setup.s is responsible for getting the system data from the BIOS, - * and putting them into the appropriate places in system memory. - * both setup.s and system has been loaded by the bootblock. - * - * This code asks the bios for memory/disk/other parameters, and - * puts them in a "safe" place: 0x90000-0x901FF, ie where the - * boot-block used to be. It is then up to the protected mode - * system to read them from there before the area is overwritten - * for buffer-blocks. - * - * Move PS/2 aux init code to psaux.c - * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92 - * - * some changes and additional features by Christoph Niemann, - * March 1993/June 1994 (Christoph.Niemann@linux.org) - * - * add APM BIOS checking by Stephen Rothwell, May 1994 - * (sfr@canb.auug.org.au) - * - * High load stuff, initrd support and position independency - * by Hans Lermen & Werner Almesberger, February 1996 - * , - * - * Video handling moved to video.S by Martin Mares, March 1996 - * - * - * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david - * parsons) to avoid loadlin confusion, July 1997 - * - * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999. - * - * - * Fix to work around buggy BIOSes which don't use carry bit correctly - * and/or report extended memory in CX/DX for e801h memory size detection - * call. As a result the kernel got wrong figures. The int15/e801h docs - * from Ralf Brown interrupt list seem to indicate AX/BX should be used - * anyway. So to avoid breaking many machines (presumably there was a reason - * to orginally use CX/DX instead of AX/BX), we do a kludge to see - * if CX/DX have been changed in the e801 call and if so use AX/BX . - * Michael Miller, April 2001 - * - * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes - * by Robert Schwebel, December 2001 - */ - -//#include -//#include -//#include -//#include -//#include -//#include - -start: -#if 0 - jmp trampoline -#else - jmp start_of_setup # short jump -#endif - - . = _start + 0x202 - -# This is the setup header, and it must start at %cs:2 (old 0x9020:2) - - .ascii "HdrS" # header signature - .word 0x0203 # header version number (>= 0x0105) - # or else old loadlin-1.5 will fail) -realmode_swtch: .word 0, 0 # default_switch, SETUPSEG -start_sys_seg: .word 0x1000 # SYSSEG - .word 0 // kernel_version - start - # pointing to kernel version string - # above section of header is compatible - # with loadlin-1.5 (header v1.5). Don't - # change it. - -type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin, - # Bootlin, SYSLX, bootsect...) - # See Documentation/i386/boot.txt for - # assigned ids - -# flags, unused bits must be zero (RFU) bit within loadflags -loadflags: - .byte 1 # LOADED_HIGH - -setup_move_size: .word 0x8000 # size to move, when setup is not - # loaded at 0x90000. We will move setup - # to 0x90000 then just before jumping - # into the kernel. However, only the - # loader knows how much data behind - # us also needs to be loaded. - -code32_start: # here loaders can put a different - # start address for 32-bit code. - .long 0x100000 # 0x100000 = default for big kernel - -ramdisk_image: .long 0 # address of loaded ramdisk image - # Here the loader puts the 32-bit - # address where it loaded the image. - # This only will be read by the kernel. - -ramdisk_size: .long 0 # its size in bytes - -bootsect_kludge: - .long 0 # obsolete - -heap_end_ptr: .word modelist-start+1024 - # (Header version 0x0201 or later) - # space from here (exclusive) down to - # end of setup code can be used by setup - # for local heap purposes. - -pad1: .word 0 -cmd_line_ptr: .long 0 # (Header version 0x0202 or later) - # If nonzero, a 32-bit pointer - # to the kernel command line. - # The command line should be - # located between the start of - # setup and the end of low - # memory (0xa0000), or it may - # get overwritten before it - # gets read. If this field is - # used, there is no longer - # anything magical about the - # 0x90000 segment; the setup - # can be located anywhere in - # low memory 0x10000 or higher. - -ramdisk_max: .long 0x1FFFFFFF # (-0xC0000000-(512 << 20)-1) & 0x7fffffff - # (Header version 0x0203 or later) - # The highest safe address for - # the contents of an initrd - -trampoline: - -#if 0 - call start_of_setup -#else - //jmp start_of_setup # short jump - nop - nop - nop -#endif - -#----------------------------------------------------------------------------- -# GRLDR structure for BOOT.INI begins here -#----------------------------------------------------------------------------- - - . = _start + 0x233 - - .byte 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 - .byte 0x90, 0x90, 0x90, 0x90 - - . = _start + 0x240 - - .byte 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 - .byte 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 - - . = _start + 0x250 - - .byte 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 - .byte 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 - - . = _start + 0x260 - - .byte 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 - - . = _start + 0x26a - - jmp grldr_start - -#----------------------------------------------------------------------------- -# GRLDR structure for BOOT.INI ends here -#----------------------------------------------------------------------------- - -start_of_setup: - -# Now we want to move to protected mode ... - -# call this just before protected mode transition - cli # no interrupts allowed ! - movb $0x80, %al # disable NMI for bootup sequence - outb %al, $0x70 - -# load the segment descriptors - movw %cs, %ax # aka SETUPSEG - movw %ax, %ds -# we get the code32 start address and modify the below 'jmpi' -# (loader may have changed it) - movl code32_start - start, %eax - movl %eax, code32 - start - -# -# Enable A20. This is at the very best an annoying procedure. -# A20 code ported from SYSLINUX 1.52-1.63 by H. Peter Anvin. -# AMD Elan bug fix by Robert Schwebel. -# - movw $(a20_control_begin_string - start), %si - call prtstr - - movw $0x00ff, %cx # try so many times on failure - movw $0x0101, %dx # non-zero means `enable' - call enable_disable_a20 - jz 3f - movw $(a20_control_fail_string - start), %si - call prtstr -1: - hlt - jmp 1b -3: - movw $(a20_control_ok_string - start), %si - call prtstr - -# set up gdt and idt - lidt idt_48 - start # load idt with 0,0 - xorl %eax, %eax # Compute gdt_base - movw %ds, %ax # (Convert %ds:gdt to a linear ptr) - shll $4, %eax - addl $gdt - start, %eax - movl %eax, (gdt_48 - start+2) - lgdt gdt_48 - start # load gdt - -# make sure any possible coprocessor is properly reset.. - xorw %ax, %ax - outb %al, $0xf0 - call delay - - outb %al, $0xf1 - call delay - -# well, that went ok, I hope. Now we mask all interrupts - the rest -# is done in init_IRQ(). - movb $0xFF, %al # mask all interrupts for now - outb %al, $0xA1 - call delay - - movb $0xFB, %al # mask all irq's but irq2 which - outb %al, $0x21 # is cascaded - -# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't -# need no steenking BIOS anyway (except for the initial loading :-). -# The BIOS-routine wants lots of unnecessary data, and it's less -# "interesting" anyway. This is how REAL programmers do it. -# -# Well, now's the time to actually move into protected mode. To make -# things as simple as possible, we do no register set-up or anything, -# we let the gnu-compiled 32-bit programs do that. We just jump to -# absolute address 0x1000 (or the loader supplied one), -# in 32-bit protected mode. -# -# Note that the short jump isn't strictly needed, although there are -# reasons why it might be a good idea. It won't hurt in any case. - - /* ramooflax cannot deal with LMSW. use MOV CR0 instead. 2012-11-11 */ - //movw $1, %ax # protected mode (PE) bit - //lmsw %ax # This is it! - movl $1, %eax - movl %eax, %cr0 - jmp flush_instr - -flush_instr: - xorw %bx, %bx # Flag to indicate a boot - xorl %esi, %esi # Pointer to real-mode code - movw %cs, %si - subw $0x20, %si # SI = INITSEG - shll $4, %esi # Convert to 32-bit pointer - -# jump to startup_32 in arch/i386/boot/compressed/head.S -# -# NOTE: For high loaded big kernels we need a -# jmpi 0x100000,__BOOT_CS -# -# but we yet haven't reloaded the CS register, so the default size -# of the target offset still is 16 bit. -# However, using an operand prefix (0x66), the CPU will properly -# take our 48 bit far pointer. (INTeL 80386 Programmer's Reference -# Manual, Mixing 16-bit and 32-bit code, page 16-6) - - .byte 0x66, 0xea # prefix + jmpi-opcode -code32: .long 0x100000 # for big kernels - .word 0x10 // __BOOT_CS - -//# Here's a bunch of information about your current kernel.. -//kernel_version: .ascii UTS_RELEASE -// .ascii " (" -// .ascii LINUX_COMPILE_BY -// .ascii "@" -// .ascii LINUX_COMPILE_HOST -// .ascii ") " -// .ascii UTS_VERSION -// .byte 0 - -#----------------------------------------------------------------------------- -# GRLDR structure for sector 1 begins here -#----------------------------------------------------------------------------- - -grldr_real_start: - - cli - //xorw %bx, %bx - //movw %bx, %ss - //movw $0x0580, %sp /* temp safe stack */ - movw %cs, %bp /* save CS to BP */ - call 1f -1: - popw %bx /* BX=Instruction Pointer of 1b */ - subw $(1b - _start), %bx /* CS:BX = _start */ - //movw %bx, %cx - shrw $4, %bx - addw %bp, %bx - //movw %cs, %ax - //addw %ax, %bx /* BX:0000 = _start */ - - pushw %bx /* new CS */ - pushw $(1f - _start) - lret -1: - movw %ds, %cx /* CX==BP==0x7C0 for pxe enabled */ - pushw %cs - popw %ds - - /* CS=DS=BX, CS:0000 = _start1 */ - - addw $((pre_stage2_start - _start) >> 4), %bx - - /* BX:0000 = pre_stage2_start */ - - cmpw $0x7C0, %bp - jne 1f - cmpw %bp, %cx - je 2f -1: - //orb $0x01, (pre_stage2_start - _start + 5) /* disable pxe */ -2: - cmpw $0x820, %bx - jb 2f - - movw $((0x8200 - (pre_stage2_start - _start) - 0x400) >> 4), %cx - - /* Now CS(=DS) >= CX+0x40 */ - - movw %cx, %es - xorw %di, %di - xorw %si, %si - - ///////////////////////////////////////////////////////////// - // - // CS - // DS 0x820 BX - // _start----------------pre_stage2_start - // CX+0x40---------------0x820 - // CX - // ES - // - ///////////////////////////////////////////////////////////// - - movw $0x200, %cx /* move 2 sectors */ - cld - repz movsw - - pushw %es /* ES:0000 = _start */ - pushw $(1f - _start) - lret /* CS=ES, CS:0000 = _start */ -1: - - /* move BX:0000 to 0820:0000 upward since BX >= 0x820 */ - - cld - - movw %bx, %ds - movw $0x820, %bx - movw %bx, %es - - xorw %si, %si - xorw %di, %di - - movw $6, %bx /* 64K pages: 0x20000 - 0x7ffff */ -1: - movw $0x8000, %cx - repz movsw - movw %ds, %ax - addw $0x1000, %ax - movw %ax, %ds - movw %es, %ax - addw $0x1000, %ax - movw %ax, %es - decw %bx - jnz 1b - - jmp 3f -2: - - /* move BX:0000 to 0820:0000 downward since BX < 0x820 */ - - std - - addw $0x7000, %bx - movw %bx, %ds - movw $0x7820, %bx - movw %bx, %es - - movw $0xfffe, %si - movw %si, %di - - movw $8, %bx /* 64K pages: 0x08200 - 0x881ff */ -1: - movw $0x8000, %cx - repz movsw - movw %ds, %ax - subw $0x1000, %ax - movw %ax, %ds - movw %es, %ax - subw $0x1000, %ax - movw %ax, %es - decw %bx - jnz 1b - - cld - -3: - -#if 0 - /* put the config file name */ - xorw %ax, %ax - movw %ax, %es - movw %ax, %ds - - xorl %ebp, %ebp - - movb %dh, 0x820A /* this is the boot partition number */ - - #; clear saved_entryno so that force_cdrom_as_boot_device be cleared - #; later in common.c - - movl %ebp, 0x820C /* EBP=0, clear saved_entryno */ - - movw $0x0010, %cx /* set max length of grub version string */ - movw $0x8212, %di /* version string */ - cld - /* AL is already 0. Locate the end of version string */ - repnz scasb /* find the location of the default config file name */ - - jcxz 1f /* failed, will not use the default config file name */ - - movw $0x4e, %cx /* max length of config file name */ - - movw %cs, %si /* CS:0000 = _start */ - shlw $4, %si /* 0000:SI = _start */ - - addw $(default_config_file_grldr - _start), %si - - cld - repz movsb /* move file name to the config-file field of stage2 */ -1: - - xorw %ax, %ax - movw %ax, %ss - movw $0x2000, %sp - - movw $0x0003, %ax /* set display mode: 80*25 color text */ - int $0x10 - - ljmp $0, $0x8200 - -default_config_file_grldr: - .ascii "/menu.lst" - - .byte 0 /* mark the end of ascii zero string */ -#else - xorl %eax, %eax - movw %ax, %es - movw %ax, %ds - //movw %ax, %ss - //movw $0x2000, %sp - - #; clear saved_entryno so that force_cdrom_as_boot_device be cleared - #; later in common.c - - movl %eax, 0x820C /* EAX=0, clear saved_entryno */ - - ljmp $0, $0x8200 -#endif - -#----------------------------------------------------------------------------- -# GRLDR structure for sector 1 ends here -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# GRLDR structure for sector 2-3 begins here -#----------------------------------------------------------------------------- - - . = _start1 + 0x400 - -#define ALTERNATIVE_KERNEL - - -/* - * The following is based on FreeDOS, modified heavily by Tinybit in Feb, 2004 - * - * Merges LBA and CHS boot sectors to ONE FAT32 boot sector! - * - * Memory layout for GRLDR FAT32 single stage boot process: - * - * ... - * |-------| 1FE0:7E00 - * |BOOTSEC| (GRUB does not use this relocation area) - * |RELOC. | (overwritten by kernel loaded) - * |-------| 1FE0:7C00 - * ... - * |-------| - * |KERNEL | (overwrites bootsec reloc.) - * |LOADED | (holds 1 sector directory buffer before kernel load) - * |-------| 2000:0000 - * ... - * |-------| 0000:7E00 - * |BOOTSEC| GRUB always run inside this sector, - * |ORIGIN | no relocation. - * |-------| 0000:7C00 - * ... - * |-------| 0060:0200 - * | FAT | (only 1 sector buffered) - * |-------| 0060:0000 - * ... - * - */ - -/* -; This is an LBA-enabled FreeDOS FAT32 boot sector (single sector!). -; You can use and copy source code and binaries under the terms of the -; GNU Public License (GPL), version 2 or newer. See www.gnu.org for more. - -; Based on earlier work by FreeDOS kernel hackers, modified heavily by -; Eric Auer and Jon Gentle in 7 / 2003. -; -; Features: Uses LBA and calculates all variables from BPB/EBPB data, -; thus making partition move / resize / image-restore easier. FreeDOS -; can boot from FAT32 partitions which start > 8 GB boundary with this -; boot sector. Disk geometry knowledge is not needed for booting. -; -; Windows uses 2-3 sectors for booting (sector stage, statistics sector, -; filesystem stage). Only using 1 sector for FreeDOS makes multi-booting -; of FreeDOS and Windows on the same filesystem easier. -; -; Requirements: LBA BIOS and 386 or better CPU. Use the older CHS-only -; boot sector if you want FAT32 on really old PCs (problems: you cannot -; boot from > 8 GB boundary, cannot move / resize / ... without applying -; SYS again if you use the CHS-only FAT32 boot sector). -; -; FAT12 / FAT16 hints: Use the older CHS-only boot sector unless you -; have to boot from > 8 GB. The LBA-and-CHS FAT12 / FAT16 boot sector -; needs applying SYS again after move / resize / ... a variant of that -; boot sector without CHS support but with better move / resize / ... -; support would be good for use on LBA harddisks. - - -; Memory layout for the FreeDOS FAT32 single stage boot process: - -; ... -; |-------| 1FE0:7E00 -; |BOOTSEC| -; |RELOC. | -; |-------| 1FE0:7C00 -; ... -; |-------| 2000:0200 -; | FAT | (only 1 sector buffered) -; |-------| 2000:0000 -; ... -; |-------| 0000:7E00 -; |BOOTSEC| overwritten by the kernel, so the -; |ORIGIN | bootsector relocates itself up... -; |-------| 0000:7C00 -; ... -; |-------| -; |KERNEL | maximum size 134k (overwrites bootsec origin) -; |LOADED | (holds 1 sector directory buffer before kernel load) -; |-------| 0060:0000 -; ... -*/ - -#define BOOTGRUB /* undef this if compiled for loading FreeDOS */ -//#undef BOOTGRUB - -#ifdef BOOTGRUB -#define LOADSEG 0x2000 -#define FATSEG 0x0060 -#else -#define LOADSEG 0x0060 -#define FATSEG 0x2000 -#endif - -Entry_32: - jmp 1f - - . = Entry_32 + 0x02 - - /* The default mode is CHS. This is for maximum compatiblity with - * small-sized disks, e.g., floppies. - * - * Valid values are 0x90 for CHS mode, or 0x0e for LBA mode. - * - * If the BIOS int13 supports LBA, this byte can be safely set to 0x0e. - * - * Some USB BIOSes might have bugs when using CHS mode, so the format - * program should set this byte to 0x0e. It seems that (generally) all - * USB BIOSes have LBA support. - * - * If the format program does not know whether the BIOS has LBA - * support, it may operate this way: - * - * if (partition_start + total_sectors_in_partition) exceeds the CHS - * addressing ability(especially when it is greater than 1024*256*63), - * the caller should set this byte to 0x0e, otherwise, set to 0x90. - */ - - .byte 0x90 /* for CHS. Another possible value is 0x0e for LBA */ - - - . = Entry_32 + 0x03 - -#ifdef BOOTGRUB - .ascii "MSWIN4.1" /* OEM name string (of OS which formatted the disk). */ -#endif - - . = Entry_32 + 0x0b - - .word 0x200 /* bytes per sector. Must be 512 */ - - . = Entry_32 + 0x0d - - /* Sectors per cluster. Valid values are 1, 2, 4, 8, 16, 32, 64 and 128. - * But a cluster size larger than 32K should not occur. - */ - - .byte 1 /* sectors per cluster */ - - . = Entry_32 + 0x0e - - /* Reserved sectors(number of sectors before the first FAT, - * including the boot sector), usually 1. - */ - - .word 1 /* reserved sectors */ - - . = Entry_32 + 0x10 - - /* Number of FATs(nearly always 2). */ - - .byte 2 /* number of FATs */ - - . = Entry_32 + 0x11 - - /* (Maximum number of root directory entries)Must be 0. */ - - .word 0 /* Max dir entries for FAT12/FAT16 */ - - . = Entry_32 + 0x13 - - /* (Total number of sectors for small disks only)Must be 0. */ - - .word 0 /* total sectors for FAT12/FAT16 */ - - . = Entry_32 + 0x15 - - /* Media descriptor byte, pretty meaningless now. */ - - .byte 0xf8 /* media descriptor */ - - . = Entry_32 + 0x16 - - /* (Sectors per FAT)Must be 0. */ - - .word 0 /* sectors per FAT for FAT12/FAT16 */ - - . = Entry_32 + 0x18 - - .word 18 /* sectors per track */ - - . = Entry_32 + 0x1a - - .word 2 /* number of heads */ - - . = Entry_32 + 0x1c - - /* Number of hidden sectors (those preceding the boot sector). - * Also referred to as the starting sector of the partition. - * For floppies, it should be 0. - */ - - .long 0 /* hidden sectors */ - - . = Entry_32 + 0x20 - - /* Total number of sectors in the filesystem. */ - - .long 0 /* total sectors for FAT32 */ - - . = Entry_32 + 0x24 - - /* FAT32 sectors per FAT. */ - - .long 0 - - . = Entry_32 + 0x28 - - /* If bit 7 is clear then all FATs are updated, otherwise bits 0-3 - * give the current active FAT, all other bits are reserved. - * This word is not used by grldr boot code. - */ - - .word 0 - - . = Entry_32 + 0x2a - - /* High byte is major revision number, low byte is minor revision - * number, currently both are 0. - * This word is not used by grldr boot code. - */ - - .word 0 - - . = Entry_32 + 0x2c - - /* Root directory starting cluster. */ - - .long 0 - - . = Entry_32 + 0x30 - - /* File system information sector number. - * This word is not used by grldr boot code. - */ - - .word 0 - - . = Entry_32 + 0x32 - - /* If non-zero this gives the sector which holds a copy of the - * boot record, usually 6. - * This word is not used by grldr boot code. - */ - - .word 6 - - . = Entry_32 + 0x34 - - /* Reserved, 12 bytes, set to 0. */ - - .long 0 - .long 0 - .long 0 - - . = Entry_32 + 0x40 - - /* drive number of the boot device. - * This byte is ignored for read. The program will write DL onto - * this byte. The caller should set drive number in DL. - * We assume all BIOSes pass correct drive number in DL. - * That is to say, buggy BIOSes are not supported!! - */ - - .byte 0 - - . = Entry_32 + 0x41 - - /* partition number of this filesystem in the boot drive. - * This byte is ignored for read. The boot code will write partition - * number onto this byte. See Entry + 0x5d below. - */ - - .byte 0 - - . = Entry_32 + 0x42 - - /* Signature (must be 28h or 29h to be recognised by NT). */ - - .byte 0x29 /* extended boot signature for FAT12/FAT16 */ - - . = Entry_32 + 0x43 - - .long 0x0AC4AF63 /* volume serial number */ - - . = Entry_32 + 0x47 - - .ascii "NO NAME " /* volume label, 11 bytes. */ - - . = Entry_32 + 0x52 - - .ascii "FAT32 " /* filesystem ID, 8 bytes. */ - -/* -; bp is initialized to 7c00h -; %define bsOemName bp+0x03 ; OEM label (8) -%define bsBytesPerSec bp+0x0b ; bytes/sector (dw) -%define bsSecPerClust bp+0x0d ; sectors/allocation unit (db) -%define bsResSectors bp+0x0e ; # reserved sectors (dw) -%define bsFATs bp+0x10 ; # of fats (db) -; %define bsRootDirEnts bp+0x11 ; # of root dir entries (dw, 0 for FAT32) - ; (FAT32 has root dir in a cluster chain) -; %define bsSectors bp+0x13 ; # sectors total in image (dw, 0 for FAT32) - ; (if 0 use nSectorHuge even if FAT16) -; %define bsMedia bp+0x15 ; media descriptor: fd=2side9sec, etc... (db) -; %define sectPerFat bp+0x16 ; # sectors in a fat (dw, 0 for FAT32) - ; (FAT32 always uses xsectPerFat) -%define sectPerTrack bp+0x18 ; # sectors/track -; %define nHeads bp+0x1a ; # heads (dw) -%define nHidden bp+0x1c ; # hidden sectors (dd) -; %define nSectorHuge bp+0x20 ; # sectors if > 65536 (dd) -%define xsectPerFat bp+0x24 ; Sectors/Fat (dd) - ; +0x28 dw flags (for fat mirroring) - ; +0x2a dw filesystem version (usually 0) -%define xrootClst bp+0x2c ; Starting cluster of root directory (dd) - ; +0x30 dw -1 or sector number of fs.-info sector - ; +0x32 dw -1 or sector number of boot sector backup - ; (+0x34 .. +0x3f reserved) -%define drive bp+0x40 ; Drive number - bp+0x41 ; partition number for GRLDR - -%define fat_sector bp+0x44 ; last accessed FAT sector (dd) - ; (overwriting unused bytes) -%define fat_start bp+0x48 ; first FAT sector (dd) - ; (overwriting unused bytes) -%define data_start bp+0x4c ; first data sector (dd) - ; (overwriting unused bytes) - -*/ - /* not used: [0x42] = byte 0x29 (ext boot param flag) - * [0x43] = dword serial - * [0x47] = label (padded with 00, 11 bytes) - * [0x52] = "FAT32",32,32,32 (not used by Windows) - * ([0x5a] is where FreeDOS parts start) - */ - - . = Entry_32 + 0x5a -1: - cli - cld - -#ifdef BOOTGRUB - - . = Entry_32 + 0x5c - - /* the byte at offset 0x5d stores the real partition number for read. - * the format program or the caller should set it to a correct value. - * For floppies, it should be 0xff, which stands for whole drive. - */ - - movb $0xff, %dh /* boot partition number */ - - cmpb $0xff, %dh /* is floppy? */ - jne 1f - movb $0, %dl /* yes, let drive number = 0 */ -1: -#endif - - xorw %ax, %ax - movw $0x7c00, %bp - -#ifndef BOOTGRUB - movw %ax, %ds - movw $0x1fe0, %ax - movw %ax, %es - movw %bp, %si /* move from 0000:7c00 */ - movw %bp, %di /* move to 1fe0:7c00 */ - movw $0x0100, %cx /* one sector to move */ - repz movsw - ljmp $0x1fe0, $(1f - Entry_32 + 0x7c00) -1: -#endif - movw %ax, %ss /* stack and BP-relative moves up, too */ - leaw -0x20(%bp), %sp - sti - movw %dx, 0x40(%bp) /* BIOS passes drive number in DL */ - - pushw %ss - movb $0x41, %ah - movw $0x55AA, %bx - int $0x13 - popw %ds - jc 1f /* No EBIOS */ - cmpw $0xAA55, %bx - jne 1f /* No EBIOS */ - testb $1, %cl - jz 1f /* No EBIOS */ - /* EBIOS supported */ - movb $0x42, (ebios_32 - 1 - Entry_32 + 0x7c00) -1: - pushw %ss - popw %es - -/* figure out where FAT and DATA area starts - * (modifies EAX EDX, sets fat_start and data_start variables) - */ - xorl %eax, %eax - movl %eax, 0x44(%bp) /* init buffer status */ - - /* first, find fat_start */ - movw 0x0e(%bp), %ax /* reserved sectors */ - addl 0x1c(%bp), %eax /* hidden sectors */ - movl %eax, 0x48(%bp) /* first FAT sector */ - movl %eax, 0x4c(%bp) /* first data sector, initial value */ - - /* next, find data_start */ - movl 0x10(%bp), %eax /* number of fats, no movzbl needed: the */ - /* 2 words at 0x11(%bp) are 0 for fat32. */ - mull 0x24(%bp) /* sectors per fat (EDX=0) */ - addl %eax, 0x4c(%bp) /* first DATA sector */ - -/* Searches for the file in the root directory. - * Returns: EAX = first cluster of file - */ - - movl 0x2c(%bp), %eax /* root dir cluster */ - -1: - pushl %eax /* save cluster */ - call cluster_to_lba_32 - /* EDX is sectors per cluster, EAX is sector number */ - movw $(msg_BootError_32 - Entry_32 + 0x7c00), %si - jc boot_error_32 /* EOC encountered */ - -2: - lesw (loadseg_off_32 - Entry_32)(%bp), %bx /* load to loadseg:0 */ - call readDisk_32 - - xorw %di, %di - - /* Search for kernel file name, and find start cluster */ -3: - movw $11, %cx - movw $(filename_32 - Entry_32 + 0x7c00), %si - repz cmpsb - jz 1f /* note that di now is at dirent+11 */ - - addw $0x20, %di - andw $-0x20, %di /* 0xffe0 */ - cmp 0x0b(%bp), %di /* bytes per sector */ - jnz 3b /* next directory entry */ - - decw %dx /* initially DX holds sectors per cluster */ - jnz 2b /* loop over sectors in cluster */ - - popl %eax /* restore current cluster */ - call next_cluster_32 - jmp 1b /* read next cluster */ - -#ifndef ALTERNATIVE_KERNEL -loadseg_off_32: - .word 0 - .word LOADSEG -#endif - -1: - /* kernel directory entry is found */ - pushw %es:(0x14-11)(%di) /* get cluster number HI */ - pushw %es:(0x1a-11)(%di) /* get cluster number LO */ - popl %eax /* convert to 32bit */ - - xorw %bx, %bx /* read kernel at ES:BX=LOADSEG:0 */ - -/* read kernel */ - -2: - pushl %eax - call cluster_to_lba_32 - /* EDX is sectors per cluster, EAX is sector number */ - jnc 1f - - /* EOC encountered - done */ -#ifdef BOOTGRUB - movw 0x40(%bp), %dx /* boot_drive and boot_partition */ -#else - movb 0x40(%bp), %bl /* FreeDOS kernel uses BL, not DL, for drive */ -#endif - pushw %dx /* for loading grub.exe */ - ljmp *(loadseg_off_32 - Entry_32)(%bp) - -1: - call readDisk_32 - decw %dx /* initially DX holds sectors per cluster */ - jnz 1b /* loop over sectors in cluster */ - - popl %eax - call next_cluster_32 - jmp 2b - -/* given a cluster number, find the number of the next cluster in - * the FAT chain. Needs fat_start. - * input: EAX - cluster - * EDX = 0 - * output: EAX - next cluster - * EDX = undefined - */ - -next_cluster_32: - pushw %es - /* pushw %di */ - pushw %bx /* hi word of EBX never used */ - -#if 1 - /* xorl %edx, %edx */ - shll $2, %eax /* 32bit FAT */ - movzwl 0x0b(%bp), %ebx /* bytes per sector */ - divl %ebx /* residue is in EDX */ - /* movw %dx, %di */ -#else - shll $2, %eax /* 32bit FAT */ - ;xchgw %ax, %di /* movw %ax, %di */ - movw %ax, %di - ;shlw $2, %di /* 32bit FAT */ - - pushw %cx - movw 0x0b(%bp), %bx /* bytes per sector */ - bsfw %bx, %cx - ;decw %cx - ;decw %cx - decw %bx - andw %bx, %di /* mask to sector size */ - shrl %cl, %eax - popw %cx -#endif - addl 0x48(%bp), %eax /* add the first FAT sector number. */ - /* EAX=absolute sector number */ - movw $FATSEG, %bx - movw %bx, %es - xorw %bx, %bx - - /* is it the last accessed and already buffered FAT sector? */ - cmpl 0x44(%bp), %eax - jz 1f - movl %eax, 0x44(%bp) /* mark sector EAX as buffered */ - call readDisk_32 /* read sector EAX to buffer */ -1: -#if 1 - //.byte 0x67, 0x26, 0x80, 0x62, 0x03, 0x0f - addr32 andb $0x0f, %es:3(%edx) /* mask out top 4 bits */ - - //.byte 0x67, 0x66, 0x26, 0x8b, 0x02 - addr32 movl %es:(%edx), %eax /* read next cluster number */ -#else - andb $0x0f, %es:3(%di) /* mask out top 4 bits */ - movl %es:(%di), %eax /* read next cluster number */ -#endif - popw %bx - /* popw %di */ - popw %es - ret - -/* Convert cluster number to the absolute sector number - * ... or return carry if EndOfChain! Needs data_start. - * input: EAX - target cluster - * output: EAX - absolute sector - * EDX - [bsSectPerClust] (byte) - * carry clear - * (if carry set, EAX/EDX unchanged, end of chain) - */ - -cluster_to_lba_32: - cmpl $0x0ffffff8, %eax /* check End Of Chain */ - cmc - jb 1f /* carry is stored if EOC */ - - /* sector = (cluster-2) * clustersize + data_start */ - decl %eax - decl %eax - - movzbl 0x0d(%bp), %edx /* sectors per cluster */ - pushw %dx /* only DX would change */ - mull %edx /* EDX = 0 */ - popw %dx - addl 0x4c(%bp), %eax /* data_start */ - /* here, carry is cleared (unless parameters are wrong) */ -1: - ret - -/* Read a sector from disk, using LBA or CHS - * input: EAX - 32-bit DOS sector number - * ES:BX - destination buffer - * (will be filled with 1 sector of data) - * output: ES:BX points one byte after the last byte read. - * EAX - next sector - */ - -readDisk_32: - pushal - xorl %edx, %edx /* EDX:EAX = LBA */ - pushl %edx /* hi 32bit of sector number */ - pushl %eax /* lo 32bit of sector number */ - pushw %es /* buffer segment */ - pushw %bx /* buffer offset */ - pushw $1 /* 1 sector to read */ - pushw $16 /* size of this parameter block */ - - xorl %ecx, %ecx - pushl 0x18(%bp) /* lo:sectors per track, hi:number of heads */ - popw %cx /* ECX = sectors per track */ - divl %ecx /* residue is in EDX */ - /* quotient is in EAX */ - incw %dx /* sector number in DL */ - popw %cx /* ECX = number of heads */ - pushw %dx /* push sector number into stack */ - xorw %dx, %dx /* EDX:EAX = cylinder * TotalHeads + head */ - divl %ecx /* residue is in EDX, head number */ - /* quotient is in EAX, cylinder number */ - xchgb %dl, %dh /* head number should be in DH */ - /* DL = 0 */ - popw %cx /* pop sector number from stack */ - xchgb %al, %ch /* lo 8bit cylinder should be in CH */ - /* AL = 0 */ - shlb $6, %ah /* hi 2bit cylinder ... */ - orb %ah, %cl /* ... should be in CL */ - - movw $0x201, %ax /* read 1 sector */ -ebios_32: /* ebios_32 - 1 points to 0x02 that can be changed to 0x42 */ - - movw %sp, %si /* DS:SI points to disk address packet */ - movb 0x40(%bp), %dl /* hard disk drive number */ - pushw %es - pushw %ds - int $0x13 - popw %ds - popw %es - popaw /* remove parameter block from stack */ - popal - jc disk_error_32 /* disk read error, jc 1f if caller handles */ - incl %eax /* next sector */ - addw 0x0b(%bp), %bx /* bytes per sector */ - jnc 1f /* 64K bound check */ - pushw %dx - movw %es, %dx - addb $0x10, %dh /* add 1000h to ES */ - /* here, carry is cleared */ - movw %dx, %es - popw %dx -1: - /* carry stored on disk read error */ - ret - -// . = . - (. - readDisk_32)/91 - -msg_DiskReadError_32: - - .ascii "disk error\0" - -msg_BootError_32: - - .ascii "No " - -filename_32: - -#ifdef BOOTGRUB - .ascii "GRUB EXE\0" -#else - .ascii "KERNEL SYS\0" -#endif - -#ifdef ALTERNATIVE_KERNEL -filename_end_32: - - . = Entry_32 + 0x1e8 - -loadseg_off_32: - .word 0 - .word LOADSEG - - . = Entry_32 + 0x1ec - -boot_image_ofs_32: - - .word (filename_32 - Entry_32)+(filename_end_32 - filename_32 - 1)*2048 -#endif - - . = Entry_32 + 0x1ee - -disk_error_32: - - movw $(msg_DiskReadError_32 - Entry_32 + 0x7c00), %si - -boot_error_32: - -/* prints string DS:SI (modifies AX BX SI) */ - -//print_32: -1: - lodsb (%si), %al /* get token */ - //xorw %bx, %bx /* video page 0 */ - movb $0x0e, %ah /* print it */ - int $0x10 /* via TTY mode */ - cmpb $0, %al /* end of string? */ - jne 1b /* until done */ - - /* The caller will change this to - * ljmp $0x9400, $(try_next_partition - _start1) - */ - -1: jmp 1b - - . = Entry_32 + 0x1fc - - .word 0, 0xAA55 /* Win9x uses all 4 bytes as magic value here */ - - . = Entry_32 + 0x200 - - . = _start1 + 0x600 - - //.arch i8086, nojumps - .arch i186, nojumps -/* - * The following is based on FreeDOS, modified heavily by Tinybit in Feb, 2004 - * - * Merges FAT12 and FAT16 boot sectors to ONE FAT boot sector! - * - * Memory layout for GRLDR FAT single stage boot process: - * - * +--------+ - * | | - * |GRLDR | also used as max 128k FAT buffer - * |LOADED | before GRLDR loading starts - * |--------| 2000:0000 - * | | - * |--------| 0000:7E00 - * |BOOTSECT| - * |ORIGIN | - * |--------| 0000:7C00 - * | | - * |--------| 0000:3000 - * |CLUSTER | - * |LIST | - * |--------| 0000:2000 - * | | - * +--------+ - */ - -/* -; -; File: -; boot.asm -; Description: -; DOS-C boot -; -; Copyright (c) 1997; -; Svante Frey -; All Rights Reserved -; -; This file is part of DOS-C. -; -; DOS-C is free software; you can redistribute it and/or -; modify it under the terms of the GNU General Public License -; as published by the Free Software Foundation; either version -; 2, or (at your option) any later version. -; -; DOS-C is distributed in the hope that it will be useful, but -; WITHOUT ANY WARRANTY; without even the implied warranty of -; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -; the GNU General Public License for more details. -; -; You should have received a copy of the GNU General Public -; License along with DOS-C; see the file COPYING. If not, -; write to the Free Software Foundation, 675 Mass Ave, -; Cambridge, MA 02139, USA. -; -; -; +--------+ 1FE0:7E00 -; |BOOT SEC| -; |RELOCATE| -; |--------| 1FE0:7C00 -; | | -; |--------| 1FE0:3000 -; | CLUSTER| -; | LIST | -; |--------| 1FE0:2000 -; | | -; |--------| 0000:7E00 -; |BOOT SEC| overwritten by max 128k FAT buffer -; |ORIGIN | and later by max 134k loaded kernel -; |--------| 0000:7C00 -; | | -; |--------| -; |KERNEL | also used as max 128k FAT buffer -; |LOADED | before kernel loading starts -; |--------| 0060:0000 -; | | -; +--------+ -*/ - -#ifdef BOOTGRUB -#define LOADSEG_12_16 0x2000 -#define FATBUF 0x2000 /* offset of temp buffer for FAT chain */ -#else -#define LOADSEG_12_16 0x0060 -#define FATBUF 0x2000 /* offset of temp buffer for FAT chain */ -#endif - -Entry_12_16: - jmp 1f - - . = Entry_12_16 + 0x02 - - /* The default mode is CHS. This is for maximum compatiblity with - * small-sized disks, e.g., floppies. - * - * Valid values are 0x90 for CHS mode, or 0x0e for LBA mode. - * - * If the BIOS int13 supports LBA, this byte can be safely set to 0x0e. - * - * Some USB BIOSes might have bugs when using CHS mode, so the format - * program should set this byte to 0x0e. It seems that (generally) all - * USB BIOSes have LBA support. - * - * If the format program does not know whether the BIOS has LBA - * support, it may operate this way: - * - * if (partition_start + total_sectors_in_partition) exceeds the CHS - * addressing ability(especially when it is greater than 1024*256*63), - * the caller should set this byte to 0x0e, otherwise, set to 0x90. - */ - - .byte 0x90 /* for CHS. Another possible value is 0x0e for LBA */ - - - . = Entry_12_16 + 0x03 - -#ifdef BOOTGRUB - .ascii "MSWIN4.1" -#endif - - . = Entry_12_16 + 0x0b - - .word 0x200 /* bytes per sector */ - - . = Entry_12_16 + 0x0d - - .byte 1 /* sectors per cluster */ - - . = Entry_12_16 + 0x0e - - .word 1 /* reserved sectors */ - - . = Entry_12_16 + 0x10 - - .byte 2 /* number of FATs */ - - . = Entry_12_16 + 0x11 - - .word 224 /* Max dir entries */ - - . = Entry_12_16 + 0x13 - - .word 2880 /* total sectors in the filesystem */ - - . = Entry_12_16 + 0x15 - - .byte 0xf0 /* media descriptor */ - - . = Entry_12_16 + 0x16 - - .word 9 /* sectors per FAT */ - - . = Entry_12_16 + 0x18 - - .word 18 /* sectors per track */ - - . = Entry_12_16 + 0x1a - - .word 2 /* number of heads */ - - . = Entry_12_16 + 0x1c - - .long 0 /* hidden sectors */ - - . = Entry_12_16 + 0x20 - - .long 0 /* total sectors for large partitions */ - - . = Entry_12_16 + 0x24 - - /* drive number of the boot device. - * This byte is ignored for read. The program will write DL onto - * this byte. The caller should set drive number in DL. - * We assume all BIOSes pass correct drive number in DL. - * That is to say, buggy BIOSes are not supported!! - */ - - .byte 0 - - . = Entry_12_16 + 0x25 - - /* partition number of this filesystem in the boot drive. - * This byte is ignored for read. The boot code will write partition - * number onto this byte. See Entry_12_16 + 0x41 below. - */ - - .byte 0 - - . = Entry_12_16 + 0x26 - - .byte 0x29 /* extended boot signature */ - - . = Entry_12_16 + 0x27 - - .long 0x0AC4AF63 /* volume serial number */ - - . = Entry_12_16 + 0x2b - - .ascii "NO NAME " /* volume label */ - - . = Entry_12_16 + 0x36 - - .ascii "FAT12 " /* filesystem ID */ - -/* -; bp is initialized to 7c00h -%define bsOemName bp+0x03 ; OEM label -%define bsBytesPerSec bp+0x0b ; bytes/sector -%define bsSecPerClust bp+0x0d ; sectors/allocation unit -%define bsResSectors bp+0x0e ; # reserved sectors -%define bsFATs bp+0x10 ; # of fats -%define bsRootDirEnts bp+0x11 ; # of root dir entries -%define bsSectors bp+0x13 ; # sectors total in image -%define bsMedia bp+0x15 ; media descrip: fd=2side9sec, etc... -%define sectPerFat bp+0x16 ; # sectors in a fat -%define sectPerTrack bp+0x18 ; # sectors/track -%define nHeads bp+0x1a ; # heads -%define nHidden bp+0x1c ; # hidden sectors -%define nSectorHuge bp+0x20 ; # sectors if > 65536 -%define drive bp+0x24 ; drive number - bp+0x25 ; partition number for GRLDR -%define extBoot bp+0x26 ; extended boot signature -%define volid bp+0x27 -%define vollabel bp+0x2b -%define filesys bp+0x36 - -%define RootDirSecs bp+0x26 ; # of sectors root dir uses - ; (overwriting unused bytes) -%define fat_start bp+0x28 ; first FAT sector - ; (overwriting unused bytes) -%define root_dir_start bp+0x2c ; first root directory sector - ; (overwriting unused bytes) -%define data_start bp+0x30 ; first data sector - ; (overwriting unused bytes) -%define data_clusters bp+0x34 ; # of clusters in data area - ; (overwriting unused bytes) - bp+0x36 ; bytes per FAT( > 0x1800 means FAT16) - ; (overwriting unused bytes) -*/ - /* not used: [0x26] = byte 0x29 (ext boot param flag) - * [0x27] = dword serial - * [0x2b] = label (padded with 00, 11 bytes) - * [0x36] = "FAT12" or "FAT16",32,32,32 (not used by Windows) - * ([0x3e] is where FreeDOS parts start) - */ - - . = Entry_12_16 + 0x3e -1: - cli - cld - -#ifdef BOOTGRUB - - . = Entry_12_16 + 0x40 - - /* the byte at offset 0x41 stores the real partition number for read. - * the format program or the caller should set it to a correct value. - * For floppies, it should be 0xff, which stands for whole drive. - */ - - movb $0xff, %dh /* boot partition number */ - - cmpb $0xff, %dh /* is floppy? */ - jne 1f - movb $0, %dl /* yes, let drive number = 0 */ -1: -#endif - - xorw %ax, %ax - movw $0x7c00, %bp - -#ifdef BOOTGRUB - - movw %ax, %ss /* stack and BP-relative moves up, too */ - leaw -0x20(%bp), %sp - - sti /* after stack setup, we can use stack */ - - movw %dx, 0x24(%bp) /* BIOS passes drive number in DL */ - - pushaw /* AX=0 */ - - movb $0x41, %ah - movw $0x55AA, %bx - pushw %dx - int $0x13 - popw %dx - pushw %ss /* SS=0 */ - popw %ds /* DS=0 */ - - jc 1f /* No EBIOS */ - cmpw $0xAA55, %bx - jne 1f /* No EBIOS */ - testb $1, %cl - jz 1f /* No EBIOS */ - testb %dl, %dl /* floppy? */ - jns 1f /* yes, only use CHS for FAT12/16 on floppy. */ - /* EBIOS supported */ - movb $0x42, (ebios_12_16 - 1 - Entry_12_16 + 0x7c00) -1: - popaw /* AX=0 */ - - movw %ax, %es /* ES=0 */ - - /* AX=SS=DS=ES=0, BP=0x7C00 */ - -#else - movw %ax, %ds - movw %bp, %si /* move from 0000:7c00 */ - movw %bp, %di /* move to 1fe0:7c00 */ - movb %dl, 0x24(%si) /* BIOS passes drive number in DL */ -// xchgw %ax, %dx /* let DX = 0 */ - movw $0x1fe0, %ax - movw %ax, %es - movw $0x0100, %cx /* one sector to move */ - repz movsw - /* CX = 0 */ - ljmp $0x1fe0, $(1f - Entry_12_16 + 0x7c00) -1: - movw %ax, %ss /* stack and BP-relative moves up, too */ - leaw -0x20(%bp), %sp - - sti /* after stack setup, we can use stack */ - - pushw %ax /* AX=0x1FE0 */ - movb $0x41, %ah - movw $0x55AA, %bx - int $0x13 - popw %ds /* DS=0x1FE0 */ - - jc 1f /* No EBIOS */ - cmpw $0xAA55, %bx - jne 1f /* No EBIOS */ - testb $1, %cl - jz 1f /* No EBIOS */ - /* EBIOS supported */ - movb $0x42, (ebios_12_16 - 1 - Entry_12_16 + 0x7c00) -1: - xorw %ax, %ax /* AX=0 */ - -#endif - - /* GET DRIVE PARMS: Calculate start of some disk areas */ -1: -#if 0 - .arch i486, nojumps - - movzwl 0x0e(%bp), %ebx /* reserved sectors */ - addl 0x1c(%bp), %ebx /* hidden sectors */ - movl %ebx, 0x28(%bp) /* ---- FAT start */ - - movzbl 0x10(%bp), %eax /* number of FATs */ - movzwl 0x16(%bp), %ecx /* sectors per FAT */ - mull %ecx /* EDX=0, EAX=total sectors for FAT */ - addl %eax, %ebx - movl %ebx, 0x2c(%bp) /* ---- RootDir start */ - - /* Calculate how many sectors the root directory occupies */ - - movzwl 0x0b(%bp), %ecx /* bytes per sector, should be 512 */ - - movzwl 0x11(%bp), %eax /* max number of RootDir entries */ - shll $5, %eax /* total bytes RootDir occupies */ - addl %ecx, %eax - decl %eax - /* xorl %edx, %edx */ /* EDX=0 */ - divl %ecx /* EAX=AX=sectors for RootDir */ - - movw %ax, 0x26(%bp) /* sectors for RootDir */ - - addl %eax, %ebx - movl %ebx, 0x30(%bp) /* ---- DataArea start */ - - . = . - (. - 1b)/66 - - .arch i186, nojumps -#else - movw 0x1c(%bp), %si /* number of hidden sectors(lo) */ - movw 0x1e(%bp), %di /* number of hidden sectors(hi) */ - addw 0x0e(%bp), %si /* number of reserved sectors */ - adcw %ax, %di /* DI:SI = first FAT sector */ - /* AX = 0 */ - - movw %si, 0x28(%bp) /* FAT start sector(lo) */ - movw %di, 0x2a(%bp) /* FAT start sector(hi) */ - - //xchgw %ax, %dx /* let AX = 0 */ - movb 0x10(%bp), %al /* number of FATs */ - /* cbw */ - mulw 0x16(%bp) /* sectors per FAT */ - /* DX:AX = total number of FAT sectors */ - /* DX = 0 since no too many FAT sectors */ - addw %ax, %si - adcw %dx, %di /* DI:SI = root directory start sector */ - movw %si, 0x2c(%bp) /* root directory starting sector(lo) */ - movw %di, 0x2e(%bp) /* root directory starting sector(hi) */ - - /* Calculate how many sectors the root directory occupies */ - - movw 0x0b(%bp), %bx /* bytes per sector */ - movb $5, %cl /* divide BX by 32 */ - shrw %cl, %bx /* BX = directory entries per sector */ - - movw 0x11(%bp), %ax /* max number of root dir entries */ - addw %bx, %ax - decw %ax - /* xorw %dx, %dx */ /* assuming DX = 0 */ - divw %bx /* AX = sectors per root directory */ - cwd /* DX = 0 */ - - movw %ax, 0x26(%bp) /* number of sectors the root dir occupies */ - - addw %ax, %si /* DI:SI = first data sector */ - adcw %dx, %di /* assuming DX = 0 */ - - movw %si, 0x30(%bp) /* data starting sector(lo) */ - movw %di, 0x32(%bp) /* data starting sector(hi) */ - - . = . - (. - 1b)/63 - -#endif - - -#ifdef USE_TOTAL_CLUSTERS - movw 0x13(%bp), %cx /* total sectors(small) */ - jcxz 1f - movw %cx, 0x20(%bp) /* total sectors(large)(lo) */ - movw %dx, 0x22(%bp) /* total sectors(large)(hi), assuming DX = 0 */ -1: - movw 0x20(%bp), %ax /* total sectors(large) */ - movw 0x22(%bp), %bx - addw 0x1c(%bp), %ax /* number of hidden sectors */ - adcw 0x1e(%bp), %bx - subw %si, %ax /* data starting sector */ - sbbw %di, %bx /* BX:AX = total sectors in the data area */ - movb 0x0d(%bp), %dl /* sectors per cluster(DH=0) */ - xchgw %bx, %dx /* DX:AX = total sectors in the data area */ - /* BX = sectors per cluster */ - divw %bx /* AX = total clusters in the data area */ - movw %ax, 0x34(%bp) /* total clusters in the data area */ -#else - movw $0xffff, 0x36(%bp) /* bytes per FAT( > 0x1800 means FAT16) */ - movw 0x16(%bp), %ax /* sectors per FAT */ - mulw 0x0b(%bp) /* bytes per sector */ - jc 1f - movw %ax, 0x36(%bp) -1: -#endif - /* Searches for the file in the root directory - * - * Returns: - * AX = first cluster of file - */ - - /* First, read the whole root directory into the temporary buffer */ - - movw 0x2c(%bp), %ax /* root directory starting sector(lo) */ - movw 0x2e(%bp), %dx /* root directory starting sector(hi) */ - movw 0x26(%bp), %cx /* number of sectors the root dir occupies */ - lesw (loadseg_off_12_16 - Entry_12_16)(%bp), %bx - /* ES:BX = loadseg:0 */ - -// pushw %es - call readDisk_12_16 /* CX=0, AX,DX,ES changed */ -// popw %es - - lesw (loadseg_off_12_16 - Entry_12_16)(%bp), %di - /* ES:DI = loadseg:0 */ - - - /* Search for kernel file name, and find start cluster */ - - /* BX=0, CX=0 */ - -// pushw %cx -// popw %di - -1: - movw $(filename_12_16 - Entry_12_16 + 0x7c00), %si /* filename */ - - movb $11, %cl /* length of kernel filename */ - - pushw %di - repz cmpsb - popw %di - - jz 1f - - addw $0x20, %di /* next entry */ - jz 2f /* or jc 2f, exceeding 64K */ - - /* if the entry begins in 0, this also ends the dir. */ - - cmpb %ch, %es:(%di) /* CH=0 */ - jnz 1b -2: - movw $(msg_BootError_12_16 - Entry_12_16 + 0x7c00), %si - jmp boot_error_12_16 /* fail if not found */ - -#ifndef ALTERNATIVE_KERNEL -loadseg_off_12_16: .word 0 -loadseg_seg_12_16: .word LOADSEG_12_16 -#endif - -1: - -/****************************************************************************/ - - /* BX=0, CX=0 */ - - ###################################################################### - # Reads the FAT chain and stores it in a temporary buffer in the - # first 64KB. The FAT chain is stored an array of 16-bit cluster - # numbers, ending with 0. - # - # The file must fit in conventional memory, so it can't be larger - # than 640KB. The sector size must be at least 512 bytes, so the - # FAT chain can't be larger than around 3KB. - ###################################################################### - - /********************************************************************/ - /* First, load the complete FAT into memory. The FAT can't be */ - /* larger than 128KB, so it should fit in the temporary buffer. */ - /********************************************************************/ - - pushw %es:0x1a(%di) /* save first cluster number of file */ - -// lesw (loadseg_off_12_16 - Entry_12_16)(%bp), %bx -// /* ES:BX = loadseg:0 */ - movw 0x16(%bp), %cx /* sectors per FAT */ - movw 0x28(%bp), %ax /* FAT start sector(lo) */ - movw 0x2a(%bp), %dx /* FAT start sector(hi) */ - - pushw %es /* ES=0x2000 */ - call readDisk_12_16 /* CX=0, AX,DX,ES changed */ - popw %ds /* DS=0x2000 */ - - popw %ax /* restore first cluster number of file */ - - /********************************************************************/ - /* Then, extract the clusters of the file from the FAT */ - /********************************************************************/ - - /* Set ES:DI to the temporary storage for the FAT chain */ - - pushw %ds /* ES=0x2000 */ - - pushw %ss - popw %es - movw $FATBUF, %di - - /* BX=0, CX=0 */ -2: - stosw /* store cluster number */ - movw %ax, %si /* SI = cluster number */ - - ////////////////////////////////////////////////////////////// - // - // FAT16 can occupy 128KB, so the segment must be adjusted - // - ////////////////////////////////////////////////////////////// - - popw %dx /* DX=0x2000, segment for FAT16 */ - pushw %dx - addw %si, %si /* multiply cluster number by two */ - jnc 1f - addb $0x10, %dh /* overflow. Add 0x1000 to segment value */ -1: - -#ifdef USE_TOTAL_CLUSTERS - cmpw $0x0ff7, 0x34(%bp) /* total clusters in the data area */ -#else - cmpw $0x1801, 0x36(%bp) /* bytes per FAT */ -#endif - jnb 3f - - /******** FAT12 ********/ - - addw %ax, %si /* multiply cluster number by 3 ... */ - shrw $1, %si /* ... and divide by 2 */ - lodsw - - /* If the cluster number was even, the cluster value is now in - * bits 0-11 of AX. If the cluster number was odd, the cluster - * value is in bits 4-15, and must be shifted right 4 bits. If - * the number was odd, CF was set in the last shift instruction. - */ - - jnc 1f - movb $4, %cl /* CL=4 */ - shrw %cl, %ax -1: - andb $0x0f, %ah /* mask off the highest 4 bits */ - cmpw $0x0ff7, %ax /* check for EOF */ - jmp 4f - -3: - /******** FAT16 ********/ - - movw %dx, %ds /* DS:SI points to next cluster */ - lodsw /* AX = next cluster */ - - cmpw $0xfff7, %ax /* check for EOF */ -4: - jbe 2b /* continue if not EOF */ - - /* Mark end of FAT chain with 0, so we have a single - * EOF marker for both FAT12 and FAT16 systems. - */ - - xorw %ax, %ax - stosw - -/****************************************************************************/ - - /* Load the file into memory, one cluster at a time */ - - popw %es /* ES=0x2000 */ -// lesw (loadseg_off_12_16 - Entry_12_16)(%bp), %bx -// /* ES:BX = loadseg:0 */ - pushw %ss - popw %ds /* DS=SS */ - movw $FATBUF, %si /* set DS:SI to the FAT chain */ - -1: - /* CH=0 */ - - lodsw /* AX = next cluster to read */ - subw $2, %ax /* cluster numbers start with 2 */ - jc 1f /* the cluster should be 0 for EOC */ - - movb 0x0d(%bp), %cl /* CH=0, CX=sectors per cluster */ - mulw %cx - addw 0x30(%bp), %ax /* data starting sector(lo) */ - adcw 0x32(%bp), %dx /* data starting sector(hi) */ - /* DX:AX = first sector to read */ - - call readDisk_12_16 /* CX=0, AX,DX,ES changed */ - - jmp 1b /* read next cluster */ - -1: - /* EOC encountered - done */ -#ifdef BOOTGRUB - movw 0x24(%bp), %dx /* boot_drive and boot_partition */ -#else - movb 0x24(%bp), %bl /* FreeDOS kernel uses BL, not DL, for drive */ -#endif - pushw %dx /* for loading grub.exe */ - ljmp *(loadseg_off_12_16 - Entry_12_16)(%bp) /* boot it! */ - -/****************************************************************************/ - -/* Read a number of sectors into memory. - * - * Call with: DS=SS - * DX:AX = 32-bit DOS sector number - * CX = number of sectors to read - * ES:BX = destination buffer - * - * Returns: CX=0 - * ES increased, BX untouched - * ES:BX points one byte after the last byte read. - * DX:AX = next sector number after read - * All other registers preserved - */ - -readDisk_12_16: -2: - pushfw - pushaw - xorw %cx, %cx - pushw %cx /* hi word of hi dword */ - pushw %cx /* lo word of hi dword */ - pushw %dx /* hi word of lo dword */ - pushw %ax /* lo word of lo dword */ - pushw %es /* buffer segment */ - pushw %bx /* buffer offset */ - incw %cx - pushw %cx /* 1 sector to read */ - movb $16, %cl - pushw %cx /* size of this parameter block */ - - xchgw %ax, %cx /* save AX to CX */ - - /* - * translate sector number to BIOS parameters - * - * LBA = sector-1 offset in track - * + head * sectPerTrack offset in cylinder - * + cyl * sectPerTrack * nHeads offset in platter - * - */ -#if 1 - pushw %bx - - pushw %dx - movw 0x18(%bp), %ax /* sectors per track */ - movw %ax, %bx - mulw 0x1a(%bp) /* nHeads */ - /* DX=0, AX=sectors per cylinder */ - xchgw %ax, %cx /* restore AX from CX, and save AX to CX */ - /* CX=nHeads * sectPerTrack <= 256*63 */ - /* AX=LBA lo word */ - popw %dx /* DX:AX=LBA */ - -#else - - pushw %bx - movw 0x18(%bp), %ax /* sectors per track */ - movw %ax, %bx - mulb 0x1a(%bp) /* nHeads, but maybe a word value 0x100 */ - jnz 1f - movb %bl, %ah /* nHeads=0x100, so AX=sectPerTrack*0x100 */ -1: - xchgw %ax, %cx /* restore AX from CX, and save AX to CX */ - /* DX:AX = LBA, CX = nHeads * sectPerTrack <= 256*63 */ -#endif - - divw %cx /* AX = cyl, DX = sector-1 + head * sectPerTrack */ - xchgw %ax, %dx /* DX = cyl, AX = sector-1 + head * sectPerTrack */ - divb %bl /* sectors per track */ - /* DX = cyl, AL = head, AH = sector-1 */ -#if 1 - xchgb %al, %ah /* DX = cyl, AH = head, AL = sector-1 */ - incw %ax /* DX = cyl, AH = head, AL = sector */ - xchgw %ax, %dx /* AX = cyl, DH = head, DL = sector */ - xchgw %ax, %cx /* CX = cyl, DH = head, DL = sector */ - xchgb %cl, %ch /* set cyl number low 8 bits in CH */ - rorb $1, %cl /* move cyl high bits into bits 7-6 */ - rorb $1, %cl /* (assumes top = 0) */ - orb %dl, %cl /* merge sector into cylinder */ -#else - movw %dx, %cx /* CX = cyl, AL = head, AH = sector-1 */ - - /* - * the following manipulations are necessary in order to properly place - * parameters into registers. - * CH = cylinder number low 8 bits - * CL<7-6> = cylinder high two bits - * CL<5-0> = sector - */ - movb %al, %dh /* save head into DH for BIOS */ - xchgb %cl, %ch /* set cyl number low 8 bits in CH */ - rorb $1, %cl /* move cyl high bits into bits 7-6 */ - rorb $1, %cl /* (assumes top = 0) */ - incb %ah /* AH = sector number */ - orb %ah, %cl /* merge sector into cylinder */ -#endif - popw %bx - - movw $0x0201, %ax /* read 1 sector */ -ebios_12_16: /* ebios_12_16 - 1 points to 0x02 that can be changed to 0x42 */ - - movw %sp, %si /* DS:SI points to disk address packet */ - movb 0x24(%bp), %dl /* drive number */ - - pushw %es - pushw %ds - int $0x13 - popw %ds - -jc_code_begin: - jc disk_error_12_16 /* caller could change it to NOPs */ -jc_code_end: - - /* increment ES */ - popw %bx /* old ES on stack */ - leaw 0x20(%bx), %bx /* LEA does not touch flags */ - movw %bx, %es - - popaw /* remove parameter block from stack */ - popaw - popfw /* restore IF, DF */ - incw %ax /* next sector */ - jnz 1f - incw %dx -1: - loop 2b - - ret - -// . = . - (. - readDisk_12_16)/99 - -msg_DiskReadError_12_16: - - .ascii "disk error\0" - -msg_BootError_12_16: - - .ascii "No " - -filename_12_16: - -#ifdef BOOTGRUB - .ascii "GRUB EXE\0" -#else - .ascii "KERNEL SYS\0" -#endif - -#ifdef ALTERNATIVE_KERNEL -filename_end_12_16: - - . = Entry_12_16 + 0x1e8 - -loadseg_off_12_16: .word 0 -loadseg_seg_12_16: .word LOADSEG_12_16 - - . = Entry_12_16 + 0x1ec - -boot_image_ofs_12_16: - - .word (filename_12_16 - Entry_12_16)+(filename_end_12_16 - filename_12_16 - 1)*2048 -#endif - - . = Entry_12_16 + 0x1ee - -disk_error_12_16: - - movw $(msg_DiskReadError_12_16 - Entry_12_16 + 0x7c00), %si - -boot_error_12_16: - -/* prints string DS:SI (modifies AX BX SI) */ - -//print_12_16: -1: - lodsb (%si), %al /* get token */ - //xorw %bx, %bx /* video page 0 */ - movb $0x0e, %ah /* print it */ - int $0x10 /* via TTY mode */ - cmpb $0, %al /* end of string? */ - jne 1b /* until done */ - - /* The caller will change this to - * ljmp $0x9400, $(try_next_partition - _start1) - */ - -1: jmp 1b - - . = Entry_12_16 + 0x1fc - - .word 0, 0xAA55 /* Win9x uses all 4 bytes as magic value here */ - - . = Entry_12_16 + 0x200 - - . = _start1 + 0x800 - -#----------------------------------------------------------------------------- -# GRLDR structure for sector 2-3 ends here -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# GRLDR structure for sector 4 begins here -#----------------------------------------------------------------------------- - - - . = _start + 0x800 - - .arch i486, nojumps - -#define DEBUG call debug_print -#undef DEBUG - -Entry_ext2: - - jmp 1f - - . = Entry_ext2 + 0x02 - - /* The default mode is CHS. This is for maximum compatiblity with - * small-sized disks, e.g., floppies. - * - * Valid values are 0x02 for CHS mode, or 0x42 for LBA mode. - * - * If the BIOS int13 supports LBA, this byte can be safely set to 0x42. - * - * Some USB BIOSes might have bugs when using CHS mode, so the format - * program should set this byte to 0x42. It seems that (generally) all - * USB BIOSes have LBA support. - * - * If the format program does not know whether the BIOS has LBA - * support, it may operate this way: - * - * if (partition_start + total_sectors_in_partition) exceeds the CHS - * addressing ability(especially when it is greater than 1024*256*63), - * the caller should set this byte to 0x42, otherwise, set to 0x02. - */ - - .byte 0x02 /* for CHS. Another possible value is 0x42 for LBA */ - - . = Entry_ext2 + 0x03 - -#if 0 - - .ascii "ext2 grldr" - -#else - -msg_DiskReadError_ext2: - - .ascii "I/O error\0" - -#endif - - . = Entry_ext2 + 0x0d - - /* sectors per block. Valid values are 2, 4, 8, 16, 32. */ - - .byte 2 - - . = Entry_ext2 + 0x0e - - /* bytes per block. - * Valid values are 0x400, 0x800, 0x1000, 0x2000, 0x4000. - */ - - .word 1024 /* bytes per block, at most 16K */ - - . = Entry_ext2 + 0x10 - - /* pointers in pointers-per-block blocks, that is, number of blocks - * covered by a double-indirect block. - * Valid values are 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000. - */ - - .long 0x10000 /* number of blocks covered by double-indirect block */ - /* low word=0 */ - - . = Entry_ext2 + 0x14 - - /* pointers per block, that is, number of blocks covered by an indirect - * block. Valid values are 0x100, 0x200, 0x400, 0x800, 0x1000. - */ - - .long 0x100 /* high word=0, low byte=0 */ - - . = Entry_ext2 + 0x18 - - /* this is default for 1.44M floppy, the caller should set it to - * a correct value */ - - .word 18 /* sectors per track */ - - . = Entry_ext2 + 0x1a - - /* this is default for 1.44M floppy, the caller should set it to - * a correct value */ - - .word 2 /* number of heads */ - - . = Entry_ext2 + 0x1c - - /* this is default for 1.44M floppy, the caller should set it to - * a correct value */ - - .long 0 /* hidden sectors */ - - . = Entry_ext2 + 0x20 - - /* total sectors in the filesystem(or in the partition). - * This value is informative. The code does not use it. - */ - - /* this is default for 1.44M floppy, the caller should set it to - * a correct value */ - - .long 2880 - - . = Entry_ext2 + 0x24 - - /* This byte is ignored for read. The program will write DL onto - * this byte. The caller should set drive number in DL. - * We assume all BIOSes pass correct drive number in DL. - * That is to say, buggy BIOSes are not supported!! - */ - - .byte 0 /* drive number */ - - . = Entry_ext2 + 0x25 - - /* this is default for floppies, the caller should set it to - * a correct value for hard-drive partitions */ - - .byte 0xff /* partition number, 0xff for whole drive */ - - . = Entry_ext2 + 0x26 - - .word 0x80 /* inode size */ - - . = Entry_ext2 + 0x28 - - /* this is default for 1.44M floppy, the caller should set it to - * a correct value */ - - .long 2048 /* s_inodes_per_group */ - - . = Entry_ext2 + 0x2c - - /* block number for group descriptors = s_first_data_block + 1. - * Valid values are 2 for 1024-byte blocks, and 1 for otherwise. - */ - - /* this is default for 1.44M floppy, the caller should set it to - * a correct value */ - - .long 2 /* block number for group descriptors */ - - . = Entry_ext2 + 0x30 -1: - cld /* 0xFC */ - - xorw %ax, %ax /* 0x31, 0xC0; CF=0, ZF=1 */ - - /* this byte `nop' will be changed to `cwd' by bootlace for floppy */ - nop /* 0x90=nop, 0x99=cwd */ - /* cwd will set DL=0 forcibly for floppy A: */ - - movw %ax, %ss /* constant SS=0 */ - movw $0x7c00, %sp - - movw %sp, %bp /* constant BP=0x7c00 */ - - pushw %ax /* 0x0000 at 0000:7bfe */ - movw $0x1000, %bx - pushw %bx /* 0x1000 at 0000:7bfc */ - pushw %ax /* 0x0000 at 0000:7bfa */ - /* SP=0x7bfa */ - - /* the 6 bytes in the stack are used by read_block(): - * 0000 ---- -2(%bp) - * 1000 ---- -4(%bp) - * 0000 ---- -6(%bp) - * Don't touch them! - */ - - movb %dl, 0x24(%bp) /* BIOS passes drive number in DL */ - - pushw %ss - movb $0x41, %ah - movw $0x55AA, %bx - int $0x13 - popw %ds /* constant DS=0 */ - jc 1f #; No EBIOS - - //testb $1, %cl - //jz 1f #; No EBIOS -#if 0 - /* gcc-4.0.1 does not generate 2-byte code. */ - rcrb $1, %cl #; also can be rorb $1, %cl -#else - .byte 0xD0, 0xD9 #; ror cl: D0 C9 -#endif - jnc 1f #; No EBIOS - - movb $0x42, (ebios_ext2 - 1 - Entry_ext2 + 0x7c00) -1: - xorl %eax, %eax /* CF=0, ZF=1 */ - -#if 0 - /* the INC touches ZF flag, so use MOV instead */ - - incw %ax - incw %ax /* EAX=2=inode number for root dir */ -#else - - /* MOV keeps all flags untouched, so it is better than INC */ - - movb $2, %al /* EAX=2=inode number for root dir */ -#endif - - /* CF=0, ZF=1 because MOV and PUSH do not touch Flags */ - - /* read root dir to 0000:1000, and grldr to 1000:0000 */ - -4: - /* EAX holds the inode number: for root dir or grldr */ - - /* These 3 PUSHes is intended to place 1000:0000 onto the stack for - * grldr. For root dir, the stack is not used since CF is cleared. - * Although there is no corresponding POPs, this is safe enough - * because the program comes here only twice: the first is for - * the root dir, and the second is for grldr. - * - * For root dir, CF=0 and ZF=1. For grldr, CF=1. - */ - - pushw %di /* 0x1000, see "jz 4b" below. */ - pushw %ss /* 0x0000 */ - pushfw - - /* SP=0x7bf4 for root dir, or 0x7bee for grldr */ - - decl %eax /* EAX=(inode - 1) */ - - /* inode numbers are far less than 0x7fffffff, so it is safe to - * initialise EDX with CDQ */ - - cdq /* let EDX=0 */ - - divl 0x28(%bp) /* s_inodes_per_group */ - /* EAX=group number */ - pushl %edx /* EDX=inode number in the group */ - - /* group numbers are far less than 0x7fffffff, so it is safe to - * initialise EDX with CDQ */ - - cdq /* let EDX=0 */ - shll $5, %eax /* EAX=relative displacement of the group descriptor */ - divl 0x0e(%bp) /* bytes per block */ - /* EAX=relative block number for the group descriptor */ - /* DX=displacement in the block */ - /* EDX high=0 */ - - pushw %dx /* we don't care about EDX high word, because it is 0 */ - - addl 0x2c(%bp), %eax /* EAX=absolute block number for the group descriptor */ - /* CF=0, ZF=0 */ - - call read_block /* 0000:1000 points to the block data containing the group descriptor */ - /* ES changed and > 0, BX=0x1000 */ - /* ECX=EDX=0 */ - /* CF=0, ZF=0 */ - - popw %si /* DS:[BX+SI] points to the group descriptor */ - /* DS:[BX+SI+8] points to the starting block number of the group inode table */ - - popl %eax /* inode number in the group */ -// shll $7, %eax /* inode struct size = 0x80 */ -// /* EAX=relative displacement of the inode struct */ -// /* EDX=0 */ - movw 0x26(%bp), %dx /* EDX=inode size */ - mull %edx /* EDX:EAX=relative displacement of the inode struct */ - - divl 0x0e(%bp) /* bytes per block */ - /* EAX=relative block number for the inode struct */ - pushw %dx /* DX=displacement of the inode struct in the block */ - /* EDX high=0 */ - - addl 8(%bx, %si), %eax /* EAX=absolute block number for the inode struct */ - /* CF=0, ZF=0 */ - - call read_block /* 0000:1000 points to the block data containing the inode struct */ - /* ES changed and > 0, BX=0x1000 */ - /* ECX=EDX=0 */ - /* CF=0, ZF=0 */ - - popw %si /* DS:[BX+SI] points to the inode struct */ - - addw %bx, %si /* DS:SI points to the inode struct */ - - /* Move the inode struct to a known safe area(0000:0fa8 - 0000:0fff), - * that is, 0x58 bytes immediately before 0000:1000. We care about only - * the beginning 0x58 bytes of the 0x80-byte inode struct, the last - * 0x28 bytes are ignored. The area from 0xfa8+0x28 to 0xfa8+0x57 - * stores 12 direct block pointers. - * - * - * At address Initial value Stores what? - * ========== ============= ====================================== - * 0xfa8+0x04 (const) the size of the file in bytes - * - * 0xfa8+0x08 total blocks blocks left to read - * - * 0xfa8+0x0c 0 serial number of the block to read - * - */ - - pushw %ss - popw %es /* ES=0 */ - - leaw -0x58(%bx), %di /* BX=0x1000, so DI=0x0fa8 */ - //movw $0x0fa8, %di - movb $0x2c, %cl /* 0x2c words = 0x58 bytes */ - - repz movsw /* now ECX=0, BX=0x1000=DI */ - - movl %ecx, (0x0c - 0x58)(%di) /* block serial number of the file */ - /* ECX=0 means first block */ - /* DI=0x1000 */ - - movl (0x04 - 0x58)(%di), %eax /* i_size, the file size */ - decl %eax - - divl 0x0e(%bp) /* bytes per block */ - /* EDX=various */ - incl %eax - movl %eax, (0x08 - 0x58)(%di) /* total blocks for file data */ - - /* - * 0000:1000 trebly indirect block - * 0000:8000 indirect block - * 0000:c000 double indirect block - * 1000:0000 the file data - */ - - /* now DS:SI points to indirect block number */ - - lodsl /* indirect block number */ - testl %eax, %eax - jz 1f - - //pushw %ss - //popw %es /* ES=0 */ - movb $0x80, %bh /* ES:BX=0000:8000 */ -#if 0 - stc - call read_block -#else - call read_block_c -#endif - /* ES changed and > 0, BX=0x8000 */ - /* ECX=EDX=0 */ - /* ZF=0, CF=0 */ - - /* now DS:SI points to double indirect block number */ - - lodsl /* double indirect block number */ - testl %eax, %eax - jz 1f - -#if 0 - pushw %ss - popw %es /* ES=0 */ - movb $0xc0, %bh /* ES:BX=0000:c000 */ - stc - call read_block -#else - movb $0xc0, %bh /* ES:BX=0000:c000 */ - call read_block_c -#endif - /* ES changed and > 0, BX=0xc000 */ - /* ECX=EDX=0 */ - /* ZF=0, CF=0 */ - - /* now DS:SI points to trebly indirect block number */ - - lodsl /* trebly indirect block number */ - testl %eax, %eax /* CF=0, TEST always clears CF */ - jz 1f - /* ZF=0 */ - //pushw %ss - //popw %es /* ES=0 */ - //movb $0x10, %bh /* ES:BX=0000:1000 */ - //stc - call read_block /* 0000:1000 points to the block data */ - /* ES changed and > 0, BX=0x1000 */ - /* ECX=EDX=0 */ - /* ZF=0, CF=0 */ - - /* the block at 0000:1000, which contains the indirect block numbers, - * is just overwritten by the trebly indirect block */ - -1: - /* get absolute block number by block serial number */ - - movl (0x0c - 0x58)(%di), %ebx /* block serial number of the file */ - subl $12, %ebx - jc 3f /* direct block: block serial number < 12 */ - - pushw %bx - subl 0x14(%bp), %ebx - popw %ax - jnc 2f - - /* indirect block: 12 <= block serial number < 12 + 0x14(%bp) */ - - //addw 0x14(%bp), %bx - addb $(0x70 / 4), %ah - //xchgw %ax, %bx - jmp 8f - -2: - pushl %ebx - subl 0x10(%bp), %ebx - jc 7f /* EBX on the stack is < 0x10(%bp). double indirect block: */ - /* 12 + 0x14(%bp) <= block serial number < 12 + 0x14(%bp) + 0x10(%bp) */ - - /* trebly indirect block: block serial number >= 12 + 0x14(%bp) + 0x10(%bp) */ - - popl %eax /* discard the stack */ - xchgl %eax, %ebx /* move EBX to EAX */ - /* EDX=0 */ - divl 0x10(%bp) - /* EAX=indirect block number, < 0x14(%bp) */ - /* EDX=block number, < 0x10(%bp) */ - - pushl %edx /* EDX < 0x10(%bp) */ - testl %edx, %edx - jnz 7f - - /* EDX=0, so we need to load the double indirect block */ - - shlw $2, %ax - xchgw %ax, %bx - - /* get the double indirect block number from the trebly indirect - * block data */ - - movl (%bx, %di), %eax - -//6: - movw $0xc000, %bx /* ES:BX=0000:c000 */ - - //pushw %ss - //popw %es /* ES=0 */ - //stc - call read_block_c /* 0000:c000 points to the block data */ - /* ES changed and > 0, BX=0xc000 */ - /* ECX=EDX=0 */ - /* CF=0, ZF=0 */ -7: - popl %eax /* EAX < 0x10(%bp) */ - cdq /* let EDX=0 (notice the above jc 7f and jnz 7f) */ - divl 0x14(%bp) - /* EAX=indirect block number, < 0x14(%bp) */ - /* EDX=block number, < 0x14(%bp) */ - - pushw %dx /* EDX < 0x14(%bp) */ - testw %dx, %dx - jnz 7f - - /* if DX=0, we need to load the indirect block */ - - //addb $(0xb0 / 4), %ah - shlw $2, %ax - xchgw %ax, %bx - - /* get the indirect block number from the double indirect block data */ - - movl 0xb000(%bx, %di), %eax - //movl (%bx, %di), %eax -//5: - movw $0x8000, %bx /* ES:BX=0000:8000 */ - - //pushw %ss - //popw %es /* ES=0 */ - //stc - call read_block_c /* 0000:8000 points to the block data */ - /* ES changed and > 0, BX=0x8000 */ - /* ECX=EDX=0 */ - /* CF=0, ZF=0 */ -7: - popw %ax /* AX < 0x14(%bp) */ -8: - xchgw %ax, %bx -3: - shlw $2, %bx - movl (%bx, %di), %eax - - /* got it! EAX=absolute block number */ - - /* read block data to 1000:0000. For root dir, read each block to - * 1000:0000(overwrite the previous read). For grldr, read blocks - * one by one to the area starting at 1000:0000. - */ - - popfw - popw %bx - popw %es - pushfw - - /* CF=0 and ZF=1 for reading root dir, CF=1 for reading grldr */ - - call read_block /* 1000:0000 points to the block data */ - /* ES changed and > 0x1000, BX=0 */ - /* ECX=EDX=0 */ - /* CF=0, ZF=0 */ - - popfw - pushw %es - pushw %bx - pushfw - - jc 3f /* CF=1, we are reading grldr */ - - /* We have just read a block of the root dir to 1000:0000. - * So we check all dir entries in the block to see if anyone - * matches grldr. - */ - - xorw %si, %si - pushw %ss - popw %es /* ES=0 */ - -2: - pushw %ds /* DS=0 */ - movw %di, %ds /* DS=0x1000 */ - movw $(filename_ext2 - Entry_ext2 + 0x7c00), %di - - pushw %si - lodsl /* This is possible inode number for grldr */ - pushl %eax /* This is possible inode number for grldr */ - lodsw - xchgw %ax, %dx /* rec_len */ - lodsw /* AL=name_len, should be 5 for grldr */ - /* AH=file_type(1 for regular file) */ -#if 0 - cmpw $0x0105, %ax - jnz 5f - movb %al, %cl /* CH is already 0 */ - repz cmpsb -#else - decb %ah - //jnz 5f - xchgw %ax, %cx /* CX=name_len */ - repz cmpsb - jnz 5f - xchgw %ax, %cx /* movb $0, %al */ - scasb -#endif -5: - popl %eax /* This is possible inode number for grldr */ - popw %si - - /* DS=0x1000, EAX=inode number */ - - movw %ds, %di /* DI=0x1000 */ - popw %ds /* DS=0 */ - - stc /* indicates the new inode is for grldr */ - - jz 4b /* grldr is found with EAX=inode number */ - - addw %dx, %si - cmpw 0x0e(%bp), %si /* bytes per block */ - jb 2b - - /* file not found in this block, continue */ - - /* We are lucky that CF=0, which indicates we are dealing with - * the root dir. - */ - -3: - - /* CF=1 for grldr, CF=0 for root dir. */ - - incl (0x0c - 0x58)(%di) - decl (0x08 - 0x58)(%di) - jnz 1b - -#if 0 - /* The above 2 instructions INC and DEC do not touch CF, so we - * can omit this POP-PUSH pair. - */ - - popfw - pushfw -#endif - - movw $(msg_No_grldr_ext2 - Entry_ext2 + 0x7c00), %si - - jnc boot_error_ext2 /* grldr not found in the root dir */ - - /* All grldr blocks have been loaded to memory starting at 1000:0000, - * Before the boot, we pass boot_drive and boot_partition to grldr. - */ - - /* ES>0x1000, BX=0, ECX=EDX=0, DI=0x1000, SS=0, SI>0x7c00, DS=0 - * BP=0x7c00, SP<=0x7c00 - */ - - movw 0x24(%bp), %dx - - /* boot it now! */ - - pushw %dx /* for loading grub.exe */ - pushw %di /* 0x1000 */ - pushw %ss /* 0x0000 */ - lret - -read_block_c: - - pushw %ss - popw %es /* ES=0 */ - stc - -/* read_block - read a block - * input: CF - indicator for overlap or consecution - * EAX = block number - * ES:BX - buffer - * - * output: if CF is cleared on input, ES:BX is initialized to 0000:1000 - * ES:BX - buffer filled with data - * ES, EAX - Changed - * ECX = 0 - * EDX = 0 - * ZF = 0 - * CF = 0 - */ - -read_block: - - jc 1f - - .byte 0xC4, 0x5E, 0xFC /* lesw -4(%bp), %bx */ - /* ES:BX=0000:1000 */ - jnz 1f - - //at this time, the gcc cannot generate 3 byte code - .byte 0xC4, 0x5E, 0xFA /* lesw -6(%bp), %bx */ - /* ES:BX=1000:0000 */ - //. = . - (. - read_block) / 6 -1: - movzbl 0x0d(%bp), %ecx /* CX=sectors per block */ - /* ECX high=0 */ - . = . - (. - 1b) / 6 - mull %ecx /* EAX=relative sector number */ - /* EDX=0 */ - . = . - (. - 1b) / 9 - addl 0x1c(%bp), %eax /* EAX=absolute sector number */ - -#if 1 - /* pass through, saving 4 bytes(call and ret) */ -#else - call readDisk_ext2 - ret -#endif - -/* Read sectors from disk, using LBA or CHS - * input: EAX = 32-bit LBA sector number - * CX = number of sectors to read - * ECX high word = 0 - * ES:BX = destination buffer - * - * output: No return on error - * BX not changed - * ES = ES + 0x20 * CX - * EAX = EAX + CX - * ZF = 0 - * CF = 0 - */ - -readDisk_ext2: -2: - pushal - //xorl %edx, %edx /* EDX:EAX = LBA */ - pushl %edx /* hi 32bit of sector number */ - pushl %eax /* lo 32bit of sector number */ - pushw %es /* buffer segment */ - pushw %bx /* buffer offset */ - pushw $1 /* 1 sector to read */ - pushw $16 /* size of this parameter block */ - - //xorl %ecx, %ecx - pushl 0x18(%bp) /* lo:sectors per track, hi:number of heads */ - popw %cx /* ECX = sectors per track */ - divl %ecx /* residue is in EDX */ - /* quotient is in EAX */ - /* EDX high=0, DH=0 */ - incw %dx /* DL=sector number */ - popw %cx /* ECX = number of heads */ - pushw %dx /* push sector number into stack */ - xorw %dx, %dx /* EDX:EAX = cylinder * TotalHeads + head */ - divl %ecx /* residue is in EDX, head number */ - /* quotient is in EAX, cylinder number */ - /* EDX high=0, EAX high=0 */ - - - xchgb %dl, %dh /* head number should be in DH */ - /* DL = 0 */ - popw %cx /* pop sector number from stack */ - xchgb %al, %ch /* lo 8bit cylinder should be in CH */ - /* AL = 0 */ - shlb $6, %ah /* hi 2bit cylinder ... */ - orb %ah, %cl /* ... should be in CL */ - - incw %ax /* AL=1, read 1 sector */ - - /* Instead of 0x0e, the LBA indicator at 2(%bp) is - * - * 0x42 for LBA - * - * and - * - * 0x02 for CHS - */ -#if 0 - movb $0x42, %ah - /* ebios_ext2 - 1 points to 0x42 that can be changed to 0x02 */ -#else - movb $0x02, %ah - /* ebios_ext2 - 1 points to 0x02 that can be changed to 0x42 */ -#endif -ebios_ext2: - - //andb 2(%bp), %ah - - movw %sp, %si /* DS:SI points to disk address packet */ - movb 0x24(%bp), %dl /* drive number */ - pushw %es - pushw %ds - int $0x13 - popw %ds - popw %bx - jc disk_error_ext2 - leaw 0x20(%bx), %bx - movw %bx, %es - popaw /* remove parameter block from stack */ - popal - incl %eax /* next sector, here ZF=0 */ - loop 2b - ret - - //. = . - (. - readDisk_ext2)/74 - -//msg_DiskReadError_ext2: -// -// .ascii "disk error\0" - -msg_No_grldr_ext2: - - .ascii "No " - -filename_ext2: - .ascii "grub.exe\0" - - . = Entry_ext2 + 0x1ee - -filename_end_ext2: - - .word (filename_ext2 - Entry_ext2)+(filename_end_ext2 - filename_ext2 - 1)*2048 - - . = Entry_ext2 + 0x1f0 - -disk_error_ext2: - - movw $(msg_DiskReadError_ext2 - Entry_ext2 + 0x7c00), %si - -boot_error_ext2: - -/* prints string DS:SI (modifies AX BX SI) */ - -//print_ext2: -1: - lodsb (%si), %al /* get token */ - //xorw %bx, %bx /* video page 0 */ - movb $0x0e, %ah /* print it */ - int $0x10 /* via TTY mode */ - cmpb $0, %al /* end of string? */ - jne 1b /* until done */ -#if 1 - - /* The caller will change this to - * ljmp $0x9400, $(try_next_partition - _start1) - */ - -1: jmp 1b - -#else - /* boot failed, try to hand over the control to supervisor */ - ldsw (1f + 3 - Entry_ext2)(%bp), %si - lodsl - cmpl $0x9400b8fa, %eax -1: jnz 1b /* no supervisor, hang up. */ - ljmp $0x9400, $(try_next_partition - _start1) - - //. = . - (. - disk_error_ext2) / 30 -#endif - - . = Entry_ext2 + 0x1fe - - .word 0xAA55 - -#ifdef DEBUG - - . = Entry_ext2 + 0x201 - -debug_print: - - pushfl - pushal - movl %eax, %ebp - call 2f -#if 0 - popal - pushal - movl %ebx, %ebp - call 2f - popal - pushal - movl %ecx, %ebp - call 2f - popal - pushal - movl %edx, %ebp - call 2f - popal - pushal - movl %esi, %ebp - call 2f - popal - pushal - movl %edi, %ebp - call 2f - popal - popfl - pushfl - pushal - pushfl - popl %ebp /* flags */ - call 2f - movw %ds, %bp - shll $16, %ebp - movw %es, %bp - call 2f - movw $0x0e0d, %ax /* print CR */ - int $0x10 /* via TTY mode */ - movw $0x0e0a, %ax /* print LF */ - int $0x10 /* via TTY mode */ -#endif - popal - popfl - ret -2: - movw $7, %cx -1: - xorw %bx, %bx /* video page 0 */ - movl %ebp, %eax - shrl %cl, %eax - shrl %cl, %eax - shrl %cl, %eax - shrl %cl, %eax - andb $0x0f, %al - addb $0x30, %al - movb $0x0e, %ah /* print char in AL */ - int $0x10 /* via TTY mode */ - - decw %cx - testw %cx, %cx - jns 1b - - movw $0x0e20, %ax /* print space */ - int $0x10 /* via TTY mode */ - ret -#endif - -#----------------------------------------------------------------------------- -# GRLDR structure for sector 4 ends here -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# GRLDR structure for sector 5-8 begins here -#----------------------------------------------------------------------------- - - . = _start1 + 0xA00 - -#define INSIDE_GRLDR - -//#include "ntfsbs.S" -//-----------------begin of "ntfsbs.S"----------------------- -/* - * GRUB Utilities -- Utilities for GRUB Legacy, GRUB2 and GRUB for DOS - * Copyright (C) 2007 Bean (bean123@126.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* NTFS boot sector for loading GRLDR , written by bean - * - * This file can be compiled as standalone boot sector, or it can be embeded in - * GRLDR.MBR at 0xA00 , right after the ext2 boot sector - * - * To compile the standalone ntfsbs.bin: - * gcc -c -o ntfsbs.o ntfsbs.S - * gcc -nostdlib -Wl,-N -Wl,-Ttext -Wl,7C00 -o ntfsbs_exec ntfsbs.o - * objcopy -O binary ntfsbs_exec ntfsbs.bin - * - * To install the standalone ntfsbs.bin: - * grubinst --restore=ntfsbs.bin DEVICE_OR_FILE - * - * Where DEVICE_OR_FILE specify a NTFS partition - * - * Limitations: - * 1. Don't support >1K MFT record size, >4K INDEX record size - * 2. Don't support encrypted file - * 3. Don't support >4K non-resident attribute list and $BITMAP - * - */ - -#ifndef INSIDE_GRLDR - - .text - - .code16 -#endif - -#define AT_STANDARD_INFORMATION 0x10 -#define AT_ATTRIBUTE_LIST 0x20 -#define AT_FILENAME 0x30 -#define AT_OBJECT_ID 0x40 -#define AT_SECURITY_DESCRIPTOR 0x50 -#define AT_VOLUME_NAME 0x60 -#define AT_VOLUME_INFORMATION 0x70 -#define AT_DATA 0x80 -#define AT_INDEX_ROOT 0x90 -#define AT_INDEX_ALLOCATION 0xA0 -#define AT_BITMAP 0xB0 -#define AT_SYMLINK 0xC0 -#define AT_EA_INFORMATION 0xD0 -#define AT_EA 0xE0 - -#define MAX_MFT_SIZE 1 // 1<<(1+9) = 1024 -#define MAX_IDX_SIZE 3 // 1<<(3+9) = 4096 - -#define LOADSEG_NT 0x2000 - -#define MMFT_BASE 0x2000 -#define MMFT_EMFT (MMFT_BASE + 1024) -#define MMFT_EBUF (MMFT_BASE + 2048) - -#define CMFT_BASE (MMFT_BASE + 6144) -#define CMFT_EMFT (CMFT_BASE + 1024) -#define CMFT_EBUF (CMFT_BASE + 2048) - -#define INDX_BASE (CMFT_BASE + 6144) - -#define SBUF_BASE (INDX_BASE + 4096) - -#define NTFS_Large_Structure_Error_Code 1 -#define NTFS_Corrupt_Error_Code 2 -#define NTFS_Run_Overflow_Error_Code 3 -#define NTFS_No_Data_Error_Code 4 -#define NTFS_Decompress_Error_Code 5 - -#define NT_FG_COMP 1 -#define NT_FG_MMFT 2 -#define NT_FG_ALST 4 -#define NT_FG_GPOS 8 - -#define nt_boot_drive -2(%bp) -#define nt_blocksize -4(%bp) -#define nt_spc -5(%bp) -#define nt_mft_size -6(%bp) -#define nt_idx_size -7(%bp) -#define nt_mft_start -12(%bp) -#define nt_remain_len -16(%bp) -//#define nt_file_count -18(%bp) - -#define nt_flag (%di) -#define nt_attr_cur 2(%di) -#define nt_attr_nxt 4(%di) -#define nt_attr_end 6(%di) -#define nt_curr_vcn 8(%di) -#define nt_curr_lcn 0x10(%di) -#define nt_attr_ofs 0x14(%di) -#define nt_target_vcn 0x18(%di) -#define nt_read_count 0x1C(%di) -#define nt_vcn_offset 0x20(%di) - -#define nt_emft_buf 1024(%di) -#define nt_edat_buf 2048(%di) - - .arch i586 - -Entry_nt: - jmp 1f - - . = Entry_nt + 0x02 - - .byte 0x90 /* for CHS. Another possible value is 0x0e for LBA */ - - .ascii "NTFS " - - .word 0 /* 0B - Bytes per sector */ - .byte 0 /* 0D - Sectors per cluster */ - .word 0 /* 0E - reserved sectors, unused */ - .byte 0 /* 10 - number of FATs, unused */ - .word 0 /* 11 - Max dir entries for FAT12/FAT16, unused */ - .word 0 /* 13 - total sectors for FAT12/FAT16, unused */ - .byte 0xF8 /* 15 - Media descriptor */ - .word 0 /* 16 - sectors per FAT for FAT12/FAT16, unused */ - .word 255 /* 18 - Sectors per track */ - .word 63 /* 1A - Number of heads */ -nt_part_ofs: - .long 0 /* 1C - hidden sectors */ - .long 0 /* 20 - total sectors for FAT32, unused */ - .long 0x800080 - /* 24 - Usually 80 00 80 00, A value of 80 00 00 00 has - * been seen on a USB thumb drive which is formatted - * with NTFS under Windows XP. Note this is removable - * media and is not partitioned, the drive as a whole - * is NTFS formatted. - */ - .long 0,0 /* 28 - Number of sectors in the volume */ - .long 0,0 /* 30 - LCN of VCN 0 of the $MFT */ - .long 0,0 /* 38 - LCN of VCN 0 of the $MFTMirr */ - .long 0 /* 40 - Clusters per MFT Record */ - .long 4 /* 44 - Clusters per Index Record */ - .long 0,0 /* 48 - Volume serial number */ - .long 0 /* 50 - Checksum, usually 0 */ - -1: - - . = Entry_nt + 0x54 - - cli - cld - - . = Entry_nt + 0x56 - - /* the byte at offset 0x57 stores the real partition number for read. - * the format program or the caller should set it to a correct value. - * For floppies, it should be 0xff, which stands for whole drive. - */ - - movb $0xff, %dh /* boot partition number */ - - xorw %ax, %ax - movw $0x7c00, %bp - - movw %ax, %ss /* stack and BP-relative moves up, too */ - leaw -0x20(%bp), %sp - sti - - movw %dx, nt_boot_drive - - pushw %ax /* AX=0 */ - - /* Test if your BIOS support LBA mode */ - movb $0x41, %ah - movw $0x55AA, %bx - int $0x13 - - popw %ds /* DS=0 */ - - jc 1f /* No EBIOS */ - cmpw $0xAA55, %bx - jne 1f /* No EBIOS */ - testb $1, %cl - jz 1f /* No EBIOS */ - /* EBIOS supported */ - movb $0x42, (ebios_nt - 1 - Entry_nt)(%bp) -1: - - pushw %ss /* SS=0 */ - popw %es /* ES=0 */ - - cmpl $0x42555247, (nt_sector_mark - Entry_nt)(%bp) - jz 1f // Must be called from GRLDR.MBR - - movw $0x7E00, %bx - movl (nt_part_ofs - Entry_nt)(%bp), %eax - incl %eax - call readDisk_nt // Load the second sector from disk - call readDisk_nt // Load the third sector from disk - call readDisk_nt -1: - - xorl %eax, %eax - movw 0xb(%bp), %ax // Bytes per sector (blocksize) - movw %ax, nt_blocksize - - call convert_to_power_2 - movb %cl, %bl - movb 0xd(%bp), %al // Sectors per cluster - call convert_to_power_2 - movb %cl, %ch - addb %bl, %ch - subb $9, %ch // 1< (start + 0x1000 + 0x82))) - - . = . - ((0x1000 + 0x81) / (. - start)) - - /* print ASCIZ string DS:SI (modifies AX BX SI) */ -1: - xorw %bx, %bx /* video page 0 */ - movb $0x0e, %ah /* print char in AL */ - int $0x10 /* via TTY mode */ - -prtstr: - - lodsb /* get token */ - cmpb $0, %al /* end of string? */ - jne 1b - ret - -a20_control_begin_string: - .ascii "\r\nkernel grub.exe: Trying to turn on A20 gate ...\r\n\0$" - -a20_control_ok_string: - .ascii "\r\nkernel grub.exe: A20 gate turned on OK!\r\n\0$" - -a20_control_fail_string: - .ascii "\r\nkernel grub.exe: A20 gate not responding!\r\n\0$" - -#include "a20.inc" - -//# Read the cmos clock. Return the seconds in al -//gettime: -// pushw %cx -// movb $0x02, %ah -// int $0x1a -// movb %dh, %al # %dh contains the seconds -// andb $0x0f, %al -// movb %dh, %ah -// movb $0x04, %cl -// shrb %cl, %ah -// aad -// popw %cx -// ret - -# Descriptor tables -# -# NOTE: The intel manual says gdt should be sixteen bytes aligned for -# efficiency reasons. However, there are machines which are known not -# to boot with misaligned GDTs, so alter this at your peril! If you alter -# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two -# empty GDT entries (one for NULL and one reserved). -# -# NOTE: On some CPUs, the GDT must be 8 byte aligned. This is -# true for the Voyager Quad CPU card which will not boot without -# This directive. 16 byte aligment is recommended by intel. -# - -/* this gdt is only used by linux code. it will be reused/overwritten by - * DOS code to place temp boot sector of the floppy. The boot sector will - * also overwrite some code after real_helper_start. - */ - - .align 16 -gdt: - .fill 2 /* GDT_ENTRY_BOOT_CS */,8,0 - - .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) - .word 0 # base address = 0 - .word 0x9A00 # code read/exec - .word 0x00CF # granularity = 4096, 386 - # (+5th nibble of limit) - - .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) - .word 0 # base address = 0 - .word 0x9200 # data read/write - .word 0x00CF # granularity = 4096, 386 - # (+5th nibble of limit) -gdt_end: - .align 4 - - .word 0 # alignment byte -idt_48: - .word 0 # idt limit = 0 - .word 0, 0 # idt base = 0L - - .word 0 # alignment byte -gdt_48: - .word gdt_end - gdt - 1 # gdt limit - .word 0, 0 # gdt base (filled in later) - -# Include video setup & detection code - -#;#include "video.S" - -# After this point, there is some free space which is used by the video mode -# handling code to store the temporary mode table (not used by the kernel). - -modelist: - -real_helper_start: - - /* helper function begins here - * before the call: - * CF=1 : indicates an invalid or corrupt entry - * CF=0 : indicates a valid entry - * - * on return: - * CF=1 : means "below", try next entry - * CF=0,ZF=1 : means "equal", helper did nothing, so we need - * a further try to boot via NT bootsector - * CF=0,ZF=0 : means "above", helper succeeded, boot it now - */ - - sti - - /* DS=SS=0x9400 */ - pushw %cs - popw %ds - - pushw $FS_BOOT - popw %es - - /* ES=FS_BOOT */ - - /* Format of partition information blocks. - * - * Offset Length in bytes Field - * 00h 1 Set to 80h if this partition is active. - * 01h 1 Partition's starting head. - * 02h 2 Partition's starting sector and track. - * 04h(SI) 1 Partition's ID number. - * 05h 1 Partition's ending head. - * 06h 2 Partition's ending sector and track. - * 08h 4 Starting LBA. - * 0Ch 4 Partition's length in sectors. - */ - - pushw %ds /* DS=0x9400 */ - pushw %es /* ES=FS_BOOT */ - pushal - pushfw -#if 0 - popfw - popal - popw %es - popw %ds - - pushw %ds /* DS=0x9400 */ - pushw %es /* ES=FS_BOOT */ - pushal - pushfw -#endif - - //cmpb $0x0e, 0x00 /* EBIOS previously checked OK? */ - //jbe 1f /* yes, skip the check */ - movb $0x02, 0x00 /* initialise this byte to 0x02 */ - movb $0x41, %ah /* EBIOS check existence */ - movw $0x55aa, %bx -// int $0x13 - call int13 - jc 1f /* No EBIOS */ - cmpw $0xaa55, %bx - jnz 1f /* No EBIOS */ - testb $1, %cl - jz 1f /* No EBIOS */ - movb $0x42, 0x00 /* LBA supported, save 0x42 to 9400:0000 */ -1: - popfw - popal - popw %es - popw %ds - - pushw %ds /* DS=0x9400 */ - pushw %es /* ES=FS_BOOT */ - pushal - pushfw - - pushaw - cmpw $0x1c2, %si - jne 1f - - /* initialize partition number and partition entries end */ - movw $0xffff, 0x1bc /* hd partition number */ - movw $0x01fe, 0x1ba /* partition entries end */ -1: - pushw %dx - -// pushw %ds -// pushw %es -// call geometry_tune -//geometry_tune: -// -// # on call: -// # CS=DS=SS -// # ES=FS_BOOT -// # -// # on return: -// # CL max sector number -// # DH max head number -// # DS changed -// # ES changed -// # AX changed -// # BX changed -// # CX changed -// # byte at CS:[08] updated on success(Smax) -// # byte at CS:[09] updated on success(Hmax) -// # - - - testb %dl, %dl /* floppy? */ - js 3f /* no, continue with hard drive */ - /* floppy */ - xorl %ebx, %ebx - movb %es:0x18(%bx), %al /* sectors per track */ - andb $0x3F, %al - stc - jz 1f - movb %es:0x1a(%bx), %ah /* number of heads in 0x1a(%bp) */ - decb %ah - movw %ax, 0x08 - jmp 4f -3: - /* hard drive */ - cmpw $0x1c2, %si /* first run on this hard drive? */ - jne 2f /* no, avoid tuning again. */ - movw $0xffff, 0x08 -2: - cmpw $0x1f2, %si /* is it a primary partition? */ - ja 2f /* no, it is an extended partition */ - movl 4(%si), %eax - movl %eax, 8(%si) /* parent part_start saved here */ - xorl %eax, %eax - movl %eax, 4(%si) /* current part_start(0) saved here */ -2: - //movl -4(%si), %eax - //cmpl $0xfffffe00, %eax /* check the starting CHS */ - //jb 1f /* use normal CHS mode */ - - pushaw /* <------ at least DL,SI need to be saved */ - cmpw $0xFFFF, 0x08 /* geometry determined? */ - jne 3f /* yes, skip */ - - movw $0xFE3F, 0x08 /* use a default of H=255, S=63 */ - - movb $8, %ah /* read drive parameters changes DX,ES,DI,BX */ - - /* should not use "call int13", because "int13" will restore DX, - * and the DH returned by "int $0x13" thus be destroyed. - */ - pushw %ds - pushw %es - int $0x13 - popw %es - popw %ds - jc 3f /* failed */ - andb $63, %cl /* sectors per track */ - jz 3f /* failed */ - - movb %dh, %ch /* DH=Hmax */ - movw %cx, 0x08 /* CL=Smax, CH=Hmax */ - -3: - popaw /* <------ at least DL,SI need to be restored */ - - /* check the partition's starting LBA */ - movl 4(%si), %ebx - addl 8(%si), %ebx /* EBX=start_LBA */ - - testl %ebx, %ebx - stc - je 1f -3: - cmpb $0x42, 0x00 /* EBIOS present? */ - je 3f /* yes, skip the CHS mode int13 fix */ -4: - /******************************************************************/ - /* read the boot sectors once again using CHS translated from LBA */ - /******************************************************************/ - - //addl $32, %ebx /* read sector 32 past the boot sector */ - - movw $0, %bp - movw 0x08, %ax - movw %ax, %dx - movb $0, %dh - movw %dx, 0x18 /* sectors per track in 0x18(%bp) */ - movb %ah, %dl - incw %dx - movw %dx, 0x1a /* number of heads in 0x1a(%bp) */ - - popw %ax /* AX=orig DX which holds drive number DL */ - pushw %ax - - movb %al, 0x24 /* drive number in 0x24(%bp) */ - - pushw (jc_code_begin - _start1) /* save original code */ - - /* modify jc_code_begin in readDisk_12_16 */ - movw $(0xEB | ((jc_code_end - jc_code_begin - 2) << 8)), (jc_code_begin - _start1) - - pushw %es - pushl %ebx - - pushl %ebx /* LBA */ - xorw %bx, %bx /* buffer in ES:BX=FS_BOOT:0 */ -// movw $4, %cx /* number of sectors to read in CX */ - movw $33, %cx /* number of sectors to read in CX */ -// testb %al, %al -// js 2f /* hard drive */ -// movw $1, %cx /* read 1 sector of sector 32 */ -// movw $0x4000, %bx -//2: - popw %ax - popw %dx /* DX:AX=LBA */ - - call readDisk_12_16 /* CX=0, AX,DX,ES changed */ - - popl %ebx - popw %es - - popw (jc_code_begin - _start1) /* restore original code */ - - /*******************************************************/ - /* load partition boot track to FS_BOOT using LBA mode */ - /*******************************************************/ - - //cmpb $0x42, 0x00 /* EBIOS present? */ - //jne 1f /* no, skip the LBA mode int13 call */ - jmp 1f -3: - popw %ax /* AX=orig DX which holds drive number DL */ - pushw %ax - xorw %dx, %dx - pushw %dx /* DX=0, higher 4 bytes of starting LBA */ - pushw %dx -// pushl %edx /* EDX=0, higher 4 bytes of starting LBA */ - pushl %ebx /* lower 4 bytes of starting LBA */ - pushw %es /* ES=FS_BOOT */ - pushw %dx /* DX=0, ES:0 is the buffer */ - //pushl $0x003f0010 /* transfer 63 sectors */ - pushw $0x3f /* transfer 63 sectors */ - pushw $0x10 /* size of disk address packet */ - xchgw %ax, %dx /* restore drive number DL from AL */ - movb $0x42, %ah /* extended read */ - movw %sp, %si /* DS:SI points to disk address packet */ -// int $0x13 /* ignore the read failure */ - call int13 - popaw /* adjust the stack */ -1: - popw %dx - popaw -// jc 1f -// popfw -// clc -// pushfw /* push new flags with CF=0 */ -//1: - popw %ax /* discard flags */ -// pushfw /* setup new flags */ - -// popfw - popal - popw %es - popw %ds - - pushw %ds /* DS=0x9400 */ - pushw %es /* ES=FS_BOOT */ - pushal - pushfw - - pushw %si - - pushfw - pushw %es -//--------------------------------------------------------- - /* print "Try (hd0,n): " or "Try (fd0): "*/ - pushw %ds - popw %es /* ES=DS=CS=0x9400 */ - - cld /* for stosb */ - xorw %ax, %ax - testb %dl, %dl - jns 1f /* floppy */ - /* hard drive */ -#if 0 - movw %si, %ax - subw $0x1c2, %ax - shrw $4, %ax - cmpw $0x1fe, %si /* is in MBR? */ - jb 1f /* yes */ - /* no, it is an entry in an extended partition */ - movb $0xFC, (add_sub_si + 2 - _start1) /* addw $-4, %si */ - incw 0x1bc /* logical partition number */ - movb 0x1bc, %al -#else - incw 0x1bc /* logical partition number */ - movw 0x1bc, %ax - cmpb $4, %al - jb 1f - movb $0xFC, (add_sub_si + 2 - _start1) /* addw $-4, %si */ -#endif -1: - /* AL=partition number, AH=0 */ - pushw %ax - - movw $(partition_message - _start1 + 7), %di /* drive type */ - movb %dl, %al - shrb $7, %al /* drive type: floppy=0, harddrive=1 */ - shlb $1, %al - addw $0x6466, %ax /* "fd" or "hd" */ - stosw - movb %dl, %al - andb $0x7f, %al /* drive number */ - aam /* convert binary to decimal, AH=high, AL=low */ - testb %ah, %ah - jz 1f - addb $0x30, %ah - movb %ah, (%di) - incw %di -1: - addb $0x30, %al - stosb - - popw %ax - - testb %dl, %dl - jns 2f /* floppy */ - /* this is a hard drive, the partition number is in AL */ - movb $0x2c, (%di) /* "," */ - incw %di - aam /* convert binary to decimal, AH=high, AL=low */ - testb %ah, %ah - jz 1f - addb $0x30, %ah - movb %ah, (%di) - incw %di -1: - addb $0x30, %al - stosb -2: - movl $0x00203a29, (%di) /* "): \0" */ - - movw $(partition_message - _start1), %si - call print_message /* CS:SI points to message string */ -//--------------------------------------------------------- - popw %es - popfw - //stc - jc invalid_or_null /* invalid or null entry */ - - xorw %si, %si - pushw %es - popw %ds - - /* DS=ES=FS_BOOT */ - - /* First, check for ext2 filesystem */ - - cmpw $0xEF53, 0x438 /* Magic signature */ - jnz 1f - xorl %eax, %eax - cmpl %eax, 0x400 /* s_inodes_count */ - jz 1f - cmpl %eax, 0x404 /* s_blocks_count */ - jz 1f -// cmpw %ax, 0x458 /* s_inode_size, usually 0x80 */ -// jz 1f - cmpl %eax, 0x420 /* s_blocks_per_group */ - jz 1f - cmpl %eax, 0x428 /* s_inodes_per_group */ - jz 1f - movl 0x414, %eax /* s_first_data_block */ - movw %ax, %bx /* BX=1 for 1K block, 0 otherwise */ - shrl $1, %eax /* must be 0 */ - jnz 1f - movl 0x418, %ecx /* s_log_block_size */ - cmpl $4, %ecx /* max size of block is 16K */ - ja 1f - negw %cx /* CF=0 for 1K block, CF=1 otherwise */ - adcw %ax, %bx /* EAX=0 */ - decw %bx - jnz 1f - - /* BX = 0 */ - /* EAX= 0 */ - - movw $0x80, %ax /* EXT2_GOOD_OLD_INODE_SIZE */ - movw %ax, %cs:0x826 /* inode size */ - movl 0x44C, %ecx /* ECX=s_rev_level */ - jecxz 3f /* EXT2_GOOD_OLD_REV */ - movw 0x458, %ax /* AX=s_inode_size */ - testw %ax, %ax - jz 1f /* invalid inode size */ - pushw %ax - pushw %dx - movb 0x418, %cl /* s_log_block_size */ - addb $10, %cl - xorw %dx, %dx /* DX=0 */ - incw %dx /* DX=1 */ - shlw %cl, %dx /* DX=block size in bytes */ - xchgw %ax, %cx /* CX=s_inode_size */ - xchgw %ax, %dx /* AX=block size in bytes */ - xorw %dx, %dx /* DX:AX=block size in bytes */ - divw %cx /* quo=AX, rem=DX */ - testw %dx, %dx - popw %dx - popw %ax - jnz 1f /* invalid inode size */ - movw %ax, %cs:0x826 /* inode size */ -3: - /* BX = 0 */ - - /* super block is sane */ - - //pushw %cs - //popw %ds - ///* DS=SS=0x9400 */ - ///* ES=FS_BOOT */ - cld - movw $0x800, %si - xorw %di, %di - movw $0x0200, %cx /* yes, we need 2 sectors if enable debug */ - - repz cs movsw /* CS segment override prefix(=0x2E) */ - - /* modify the boot partition number */ - - /* the boot partition number is at offset 0x25 for ext2 */ - - testb %dl, %dl - jns 3f /* no modification for floppy */ - movw $0x25, %di - movw %cs:0x1bc, %ax /* partition number */ - stosb -3: - /* fix for ext2 partition: hidden_sectors, offset 0x1c */ - popw %si /* DI points to old entry in MBR */ - pushw %si - xorl %eax, %eax /* let hidden_sectors=0 for floppy */ - testb %dl, %dl - jns 3f /* floppy */ - movl %cs:4(%si), %eax - addl %cs:8(%si), %eax -3: - /* BX = 0 */ - - movl %eax, %es:0x1c(%bx) /* adjust hidden_sectors for EXT2 */ - - /* fix for ext2 partition: EBIOS indicator, offset 0x02 */ - - movb %cs:0x00(%bx), %al - movb %al, %es:0x02(%bx) - - /* fix for ext2 partition: sectors per block, offset 0x0d */ - /* fix for ext2 partition: bytes per block, offset 0x0e */ - /* fix for ext2 partition: dwords per block(dpb), offset 0x14 */ - /* fix for ext2 partition: square of dpb, offset 0x10 */ - - movb %es:0x418, %cl /* s_log_block_size */ - //incw %cx - movl $2, %eax - shlw %cl, %ax - movb %al, %es:0x0d(%bx) - shlw $9, %ax /* block size is word wide */ - movw %ax, %es:0x0e(%bx) - shrw $2, %ax - movl %eax, %es:0x14(%bx) - addb $8, %cl - shll %cl, %eax - movl %eax, %es:0x10(%bx) - - - /* fix for ext2 partition: sectors per track, offset 0x18 */ - /* fix for ext2 partition: number of heads, offset 0x1a */ - movw %cs:0x08(%bx), %ax /* BX=0 */ - cmpw $0xFFFF, %ax - jz 3f - movb %al, %es:0x18(%bx) - shrw $8, %ax - incw %ax - movw %ax, %es:0x1a(%bx) -3: - -#if 0 - testb %dl, %dl - jns 3f /* floppy */ - popw %di /* DI points to old entry in MBR */ - pushw %di - movw %cs:1(%di), %ax - andb $63, %ah - movb %ah, %es:0x18 - xorb %ah, %ah - incw %ax - movw %ax, %es:0x1a -3: -#endif - - /* fix for ext2 partition: s_inodes_per_group, offset 0x28 */ - movl %es:0x428, %eax /* s_inodes_per_group */ - movl %eax, %es:0x28(%bx) - - /* fix for ext2 partition: block number for group descriptors, offset 0x2c */ - /* At which block the group descriptors begin? */ - movl %es:0x414, %eax /* s_first_data_block */ - incw %ax - movl %eax, %es:0x2c(%bx) - - /* fix for ext2 partition: on error go back to supervisor, offset 0x01fc */ - movw $0x01fc, %si - movw %si, %di - lodsw - cmpw $0xFEEB, %ax /* EB FE is jmp back to itself(infinite loop) */ - jnz 3f - decw %ax /* AL=0xEA, ljmp */ - stosb - //movw $(try_next_partition - _start1), %ax - movw $MONITOR, %ax - stosw - //movw %cs, %ax /* AX=0x9400 */ - xorw %ax, %ax - stosw /* the last byte 0x00 is in the next sector! */ -// addw $0x0f, %di -// movw $(restore_GRLDR_CS - _start1), %si -// movw $((gdt_end - restore_GRLDR_CS) / 4), %cx -// .byte 0x2e /* %cs: prefix */ -// repz movsl -3: - - movw $(EXT2_message - _start1), %si - call print_message /* CS:SI points to message string */ - - clc - jmp move_entries_and_return - -1: - #; It is not EXT2. Check for FAT12/16/32/NTFS. - - /* DS=ES=FS_BOOT, SI=0 */ - testb %dl, %dl - js 3f - movb $0xff, %cs:0x1bc /* partition number for floppy */ - movl 0x401C, %eax - cmpl $0x20, %eax - jne 3f - - xorw %bx, %bx /* partition number */ - movw $0x1C6, %di - movw $4, %cx -8: - cld - scasl - jne 2f - incw %si - movb %bl, %cs:0x1bc /* partition number */ -2: - addw $12, %di - incw %bx - loop 8b - - decw %si - jnz 3f - movb $0, %al - movw $0x0B, %di - movw $(0x5A - 0x0B), %cx - cld - repz scasb - jnz 3f - movw $0x400B, %si - movw $0x0B, %di - movw $(0x5A - 0x0B), %cx - //movw $0x4000, %si - //movw $0x0000, %di - //movw $0x0100, %cx - cld - repz movsw - xchgb %al, 0x1C - addw %ax, 0x0E -3: - xorw %si, %si - cmpw $0x200, 0x0b(%si) /* bytes per sector */ - jne 1f /* not a normal BPB */ - movb 0x0d(%si), %al /* sectors per cluster */ - testb %al, %al - jz 1f /* invalid if = 0 */ - movb %al, %cl - movw $128, %ax - divb %cl /* quo=AL, rem=AH */ - testb %ah, %ah - jnz 1f /* invalid if not 2^n */ - movw 0x18(%si), %ax /* sectors per track */ - testw %ax, %ax - jz 1f /* invalid if = 0 */ - cmpw $63, %ax - ja 1f /* invalid if > 63 */ - movw 0x1a(%si), %ax /* number of heads */ - decw %ax /* Max head number, should be a byte */ - testb %ah, %ah /* should be 0 */ - jnz 1f /* invalid if number of heads > 256 */ - cmpb $0xf0, 0x15(%si) /* media descriptor */ - jb 1f - - cmpb $0x42, %cs:0x00 /* EBIOS present? */ - jne 3f - //movb $0x41, %ah /* EBIOS check existence */ - //movw $0x55aa, %bx - //int $0x13 - //jc 3f /* No EBIOS */ - //cmpw $0xaa55, %bx - //jnz 3f /* No EBIOS */ - //testb $1, %cl - //jz 3f /* No EBIOS */ - movb $0x0e, 0x02(%si) /* force LBA */ -3: - cld - movw $0x0600, %bx /* FAT12/FAT16 */ - movw $0x003c, %cx /* FAT12/FAT16 */ - - movb 0x10(%si), %al /* number of FATs(NTFS:0, FAT:1,2) */ - cmpb $2, %al - ja 1f /* abnormal FAT */ - movw 0x11(%si), %ax /* max root entries */ - testw %ax, %ax - jnz 2f /* FAT12/FAT16 */ - - /* FAT32 or NTFS */ - movw 0x13(%si), %ax /* total sectors(small) */ - testw %ax, %ax - jnz 1f /* invalid FAT32 BPB */ - movw 0x16(%si), %ax /* sectors per FAT(small) */ - testw %ax, %ax - jnz 1f /* invalid FAT32 BPB */ - movb 0x10(%si), %al /* number of FATs(NTFS:0, FAT:1,2) */ - testb %al, %al - jz 8f - - /* FAT32 */ - movl 0x20(%si), %eax /* FAT32 total sectors */ - testl %eax, %eax - jz 1f - movl 0x24(%si), %eax /* FAT32 sectors per FAT */ - testl %eax, %eax - jz 1f - movw $0x0400, %bx /* FAT32 */ - movw $0x0058, %cx /* FAT32 */ - movw $(FAT32_message - _start1), %si /* SI changed!! */ - jmp 7f -8: - /* NTFS */ - movl 0x20(%si), %eax /* FAT32 total sectors */ - testl %eax, %eax - jnz 1f - //movw 0x11(%si), %ax /* max root entries */ - //testw %ax, %ax - //jnz 1f - movw 0x0e(%si), %ax /* reserved sectors */ - testw %ax, %ax - jnz 1f - - /* fix for ntfs partition: sectors per track, offset 0x18 */ - /* fix for ntfs partition: number of heads, offset 0x1a */ - movw %cs:0x08(%si), %ax /* SI=0 */ - cmpw $0xFFFF, %ax - jz 3f - movb %al, 0x18(%si) /* DS=ES */ - shrw $8, %ax - incw %ax - movw %ax, 0x1a(%si) -3: - /* BUG fix for extended NTFS partition */ - popw %si /* SI points to old entry in MBR */ - pushw %si - xorl %eax, %eax /* let hidden_sectors=0 for floppy */ - testb %dl, %dl - jns 3f /* floppy */ - movl %cs:4(%si), %eax - addl %cs:8(%si), %eax -3: - movl %eax, 0x1c /* adjust hidden_sectors for NTFS */ - - movb %dl, 0x24 /* adjust drive number for NTFS */ - -#if 1 - // Load NTFS using internal boot sector at 0xA00 - - movw $(NTFS5_message - _start1), %si - call print_message /* CS:SI points to message string */ - - movw $0xA00, %bx - movw $0x52, %cx - - pushw %cs - popw %ds - - /* DS=SS=0x9400 */ - /* ES=FS_BOOT */ - - movw %bx, %si - xorw %di, %di - lodsw - stosw - addw %cx, %si - addw %cx, %di - movw $0x800, %cx - subw %di, %cx - - repz movsb - - /* modify the boot partition number */ - movb %es:1, %al - addb $5, %al /* AL is less than 0x80 */ - cbw /* AH=0 */ - xchgw %ax, %di /* move AX to DI */ -// movb $0xff, %al /* partition=whole drive for floppy */ -// testb %dl, %dl -// jns 3f /* no modification for floppy */ - movb 0x1bc, %al /* partition number */ -//3: - stosb - - /* fix for NTFS partition: on error go back to supervisor, offset 0x01fa */ - - movw $0x01fa, %di - movw %es:(%di), %ax - cmpw $0xFEEB, %ax /* EB FE is jmp back to itself(infinite loop) */ - jnz 3f - decw %ax /* AL=0xEA, ljmp */ - stosb - //movw $(try_next_partition - _start1), %ax - movw $MONITOR, %ax - stosw - - //movw %cs, %ax /* AX=0x9400 */ - xorw %ax, %ax - stosw /* DI=0x01ff */ -3: - clc - jmp move_entries_and_return - -#else - - /* modify the boot partition number */ - movb $0xB6, %al /* 0xB6="MOV DH,imm8" */ - movb %cs:0x1bc, %ah - testb %dl, %dl - js 3f - movb $0xff, %ah /* partition number for floppy is whole drive */ -3: - /* before the call: - * AH= partition number - * AL= 0xB6 ; 0xB6 is opcode of "MOV DH,imm8" - * DL= drive number - * - * on return: CF=0 if there is NTFS boot record; - * CF=1 otherwise. - * CF of flags_orig on the stack will set if CF=1 - */ - - call modify_NTFS_boot_record - //jnc move_entries_and_return - //movw $(NTFS5_message - _start1), %si - ////jmp 4f - //call print_message /* CS:SI points to message string */ - //stc - jmp move_entries_and_return - -#endif - -2: - /* FAT12/FAT16 */ - xorw %si, %si - movb 0x10(%si), %al /* number of FATs(NTFS:0, FAT:1,2) */ - testb %al, %al - jz 1f - movw 0x16(%si), %ax /* sectors per FAT(small) */ - testw %ax, %ax - jz 1f - movw $(FAT16_message - _start1), %si - cmpw $12, %ax - ja 7f - movw $(FAT12_message - _start1), %si -7: - pushw %bx - pushw %cx - call print_message /* CS:SI points to message string */ - popw %cx - popw %bx - - /* fix for fat 12/16/32: sectors per track, offset 0x18 */ - /* fix for fat 12/16/32: number of heads, offset 0x1a */ - xorw %si, %si - movw %cs:0x08(%si), %ax /* SI=0 */ - cmpw $0xFFFF, %ax - jz 3f - movb %al, 0x18(%si) /* DS=ES */ - shrw $8, %ax - incw %ax - movw %ax, 0x1a(%si) -3: - /* BUG fix for extended FAT12/16/32 partition */ - popw %di /* DI points to old entry in MBR */ - pushw %di - xorl %eax, %eax /* let hidden_sectors=0 for floppy */ - testb %dl, %dl - jns 3f /* floppy */ - movl %cs:4(%di), %eax - addl %cs:8(%di), %eax -3: - movl %eax, 0x1c /* adjust hidden_sectors for FAT */ - - pushw %cs - popw %ds - /* DS=SS=0x9400 */ - /* ES=FS_BOOT */ - movw %bx, %si - xorw %di, %di - lodsw - stosw - addw %cx, %si - addw %cx, %di - movw $0x0200, %cx - subw %di, %cx - repz movsb - /* modify the boot partition number */ - movb %es:1, %al - addb $5, %al /* AL is less than 0x80 */ - cbw /* AH=0 */ - xchgw %ax, %di /* move AX to DI */ -// movb $0xff, %al /* partition=whole drive for floppy */ -// testb %dl, %dl -// jns 3f /* no modification for floppy */ - movb 0x1bc, %al /* partition number */ -//3: - stosb - - /* fix for FAT12/16/32 partition: on error go back to supervisor, offset 0x01fa */ - //pushw %es - //popw %ds - movw $0x01fa, %di - //movw %di, %si - //lodsw - movw %es:(%di), %ax - cmpw $0xFEEB, %ax /* EB FE is jmp back to itself(infinite loop) */ - jnz 3f - decw %ax /* AL=0xEA, ljmp */ - stosb - //movw $(try_next_partition - _start1), %ax - movw $MONITOR, %ax - stosw - //movw %cs, %ax /* AX=0x9400 */ - xorw %ax, %ax - stosw /* DI=0x01ff */ -3: - - clc - jmp move_entries_and_return -1: - #; It is not FAT12/16/32/NTFS. Check for extended partition. - - /* DS=ES=FS_BOOT */ - - pushw %cs - popw %es - - /* ES=SS=0x9400 */ - /* DS=FS_BOOT */ - - popw %si - pushw %si - cmpb $0x05, %es:(%si) /* extended */ - je 1f - cmpb $0x0f, %es:(%si) /* Win95 extended (LBA) */ - je 1f - cmpb $0x15, %es:(%si) /* hidden extended */ - je 1f - cmpb $0x1f, %es:(%si) /* hidden win95 extended (LBA) */ - je 1f - cmpb $0x85, %es:(%si) /* Linux extended */ - je 1f - movw $(non_MS_message - _start1), %si -4: - call print_message /* CS:SI points to message string */ - stc - jmp move_entries_and_return -1: - /* extended partition entry */ - cmpw $0x1fe, %si - jb 1f - decw %es:0x1bc /* count the partitions in extended zone */ -1: - movw $(extended_message - _start1), %si - call print_message /* CS:SI points to message string */ - movw $0x1be, %si - movw $4, %cx -5: - //xorl %eax, %eax - //cmpl %eax, (%si) - //jnz 2f - movl (%si), %eax - cmpw 2(%si), %ax /* Is EAX high word equal to AX? */ - jnz 2f - cmpb %al, %ah /* Is AL=AH? */ - jnz 2f - - /* now all 4 bytes in EAX are equal to each other. */ - cmpl %eax, 4(%si) - jnz 2f - cmpl %eax, 8(%si) - jnz 2f - cmpl %eax, 12(%si) - jz 3f /* entry with 16 dups of a byte means empty entry */ -2: - movb (%si), %al - shlb $1, %al - jnz 1f - //jnz 3f /* invalid entry is treated as empty entry */ - movb 2(%si), %al - and $63, %al /* starting sector number */ - jz 1f - //jz 3f /* invalid entry is treated as empty entry */ - movb 6(%si), %al - and $63, %al /* ending sector number */ - jz 1f - //jz 3f /* invalid entry is treated as empty entry */ - movl 8(%si), %eax /* starting LBA */ - testl %eax, %eax - jz 1f - //jz 3f /* invalid entry is treated as empty entry */ - movl 12(%si), %eax /* total number of sectors in partition */ - testl %eax, %eax - jz 1f -3: - addw $16, %si - loop 5b - cmpw $0xaa55, (%si) - jnz 1f - - movw $0x1be, %si - movw $4, %cx - popw %bx /* the old SI points to extended partition ID in MBR */ - pushw %bx -5: -#if 1 - //xorl %eax, %eax - //cmpl %eax, (%si) - //jnz 2f - movl (%si), %eax - cmpw 2(%si), %ax /* Is EAX high word equal to AX? */ - jnz 2f - cmpb %al, %ah /* Is AL=AH? */ - jnz 2f - - /* now all 4 bytes in EAX are equal to each other. */ - cmpl %eax, 4(%si) - jnz 2f - cmpl %eax, 8(%si) - jnz 2f - cmpl %eax, 12(%si) - jz 3f /* entry with 16 dups of a byte means empty entry */ -2: - /* now it is an acceptable entry */ - movw %es:0x1ba, %di /* partition entries end */ - /* ensure our stack not to be overwritten by the partition entries */ - cmpw $0x83f0, %di - ja 3f /* try next */ - /* ensure our code not to be overwritten by the partition entries */ - cmpw $0x3fe, %di - jne 6f - /* more entries stores at 0x9be00-0x9c3ff */ - movw $0x7e00, %di - movw %di, %es:0x1ba -6: - addw $16, %es:0x1ba /* increment partition entries end */ - - lodsl - stosl - lodsl - stosl - - xchgw %ax, %dx /* save AL(the partition ID)to DL */ - - lodsl - xchgl %eax, %edx /* restore AL from DL(the partition ID), */ - /* and save EAX to EDX */ - cmpb $0x05, %al - je 6f - cmpb $0x0f, %al - je 6f - cmpb $0x15, %al - je 6f - cmpb $0x1f, %al - je 6f - cmpb $0x85, %al - je 6f - /* normal partition, copied to 0x941fe-0x943fb */ - addl %es:4(%bx), %edx /* current partition start */ -6: - /* extended partition, copied to 0x941fe-0x943fb */ - xchgl %eax, %edx /* restore or update EAX from EDX */ - stosl - lodsl /* adjust SI only */ - movl %es:8(%bx), %eax /* parent partition start ... */ - stosl /* ... stored here */ - jmp 2f -3: - addw $16, %si -#endif - //. = 5b + 0x7c -2: - loop 5b - - /* extended partition is not a normal one, so set carry to try next */ - stc - jmp move_entries_and_return - -invalid_or_null: -1: - movw $(invalid_message - _start1), %si - call print_message /* CS:SI points to message string */ - stc - -move_entries_and_return: - popw %si - pushfw - pushw %cs - popw %ds - pushw %cs - popw %es - pushw %si - cmpw $0x202, %si - jne 1f - /* move entries backward 1 entry */ - movw $0x1fe, %di - movw $0x20e, %si - movw $0xf8, %cx /* 0x1f0 bytes = 0xf8 words */ - cld /* move upward */ - repz movsw - movw $0x3ee, %di - movw $0x7e00, %si - movw $0x8, %cx /* 0x10 bytes = 0x8 words */ - cld /* move upward */ - repz movsw - movw $0x7e00, %di - movw $0x7e10, %si - movw $0x2f8, %cx /* 0x5f0 bytes = 0x2f8 words */ - cld /* move upward */ - repz movsw - cmpw $0x7e10, 0x1ba - jne 2f - movw $0x40e, 0x1ba -2: - subw $0x10, 0x1ba - -1: - popw %si - movw $0x1fe, %ax - movw $(add_sub_si + 5 - _start1), %di - movw %ax, (%di) /* 0x1fe */ - cmpw $0x31b2, %si /* floppy? */ - je 4f /* yes */ - incw (%di) /* 0x1ff */ - cmpw %ax, 0x1ba /* AX=0x1fe */ - jne 1f - decw (%di) /* 0x1fe */ - //cmpw $0x31b2, %si /* floppy? */ - //je 4f // 1f /* yes */ - cmpw $0x1f2, %si - ja 2f /* logical partition */ - jb 1f /* primary partition 0, 1, 2 */ - /* primary partition 3 */ - cmpw $0x0003, 0x1bc /* are there any logical partitions? */ - ja 1f /* yes */ -2: -//inc_hard_drive: - - /* all partitions on the drive have been checked, try next drive. - * - * the current stack is: - * - * SP + 38 : DS - * SP + 36 : ES - * SP + 32 : EAX - * SP + 28 : ECX - * SP + 24 : EDX - * SP + 20 : EBX - * SP + 16 : ESP_temp - * SP + 12 : EBP - * SP + 8 : ESI - * SP + 4 : EDI - * SP + 2 : flags_orig - * SP : flags - * - */ - - /* get total hard drives */ - xorw %ax, %ax - movw %ax, %ds - movb 0x475, %dh - pushw %cs - popw %ds -// cmpb $16, %dh -// jnb 2f -// movb $16, %dh -//2: - orb $0x80, %dh /* CF=0, DH=Max harddrive number + 1 */ - //xchgw %ax, %cx /* CL=Max harddrive number + 1, CH=0 */ - movw %sp, %bp - movb 24(%bp), %dl /* BIOS drive number is in DL */ -2: - jnc 3f - call print_message /* CS:SI points to message string */ - movw $(drive_number_string - _start1), %si - movb %dl, %al - andb $0x7f, %al - aam /* AH=high decimal, AL=low decimal */ - addw $0x3030, %ax - xchgb %al, %ah - movw %ax, 32(%si) - call print_message /* CS:SI points to message string */ -3: - incw %dx /* !!!! Next drive !!!! */ - cmpb %dh, %dl - jnb 2f /* all drives checked, try floppy finally */ - - pushw %bx - movb $8, %ah /* read drive parameters changes DX,ES,DI,BX */ - call int13 - jc 3f /* try next hard drive */ - andb $63, %cl /* CL=sectors per track, CF cleared */ - stc - jz 3f /* try next hard drive */ - popw %bx - movb %dl, %ch /* DL saved at BP high byte in the stack */ - pushw %cx /* push new BX onto stack */ - movw $0x201, %ax /* read 1 sector */ - movw $0x7e00, %bx /* read MBR to 9400:7e00 */ - movw $1, %cx - xorb %dh, %dh - call int13 - sti -3: - popw %bx /* BL=sectors per track, BH=DL */ - - movw $(Error_while_reading_string - _start1), %si - jc 2b /* read failure, try next hard drive */ - - /* on seccessful return, should be: ah=0 for OK, al=1 for 1 sector */ - //decw %ax /* some BIOSes return incorrect AL */ - testb %ah, %ah - stc - jnz 2b - - /* The new partition table might be empty or invalid. - * Move the new partition table onto the old one while checking - */ - - //movb %dl, %bh /* DL saved at BP high byte in the stack */ - - movw $0x7fbe, %si - movw $0x01be, %di - -3: - cmpw $0x1fe, %di - jnb 3f - - xorl %ecx, %ecx - - lodsl - stosl - orl %eax, %ecx - lodsl - stosl - orl %eax, %ecx - lodsl - stosl - orl %eax, %ecx - lodsl - stosl - orl %eax, %ecx - jecxz 3b /* null entry, check next */ - - //lodsw - //stosw - movb -16(%si), %al - shlb $1, %al - stc - xchgw %ax, %si /* save SI to AX */ - movw $(partition_boot_indicator_string - _start1), %si - jnz 2b - xchgw %ax, %si /* restore SI from AX */ - //lodsw - //stosw - movb -14(%si), %al - andb $63, %al - stc - xchgw %ax, %si /* save SI to AX */ - movw $(partition_sectors_per_track_string - _start1), %si - jz 2b - xchgw %ax, %si /* restore SI from AX */ - //lodsw - //stosw - //lodsw - //stosw - movb -10(%si), %al - andb $63, %al - stc - xchgw %ax, %si /* save SI to AX */ - movw $(partition_sectors_per_track_string - _start1), %si - jz 2b - xchgw %ax, %si /* restore SI from AX */ - //lodsl - //stosl - movl -8(%si), %eax - testl %eax, %eax - stc - xchgw %ax, %si /* save SI to AX */ - movw $(partition_start_sector_string - _start1), %si - jz 2b - xchgw %ax, %si /* restore SI from AX */ - - //lodsl - //stosl - movl -4(%si), %eax - testl %eax, %eax - stc - xchgw %ax, %si /* save SI to AX */ - movw $(partition_end_sector_string - _start1), %si - jz 2b - xchgw %ax, %si /* restore SI from AX */ - - jmp 3b -3: - cmpw $0xAA55, (%si) - stc - xchgw %ax, %si /* save SI to AX */ - movw $(no_boot_signature_string - _start1), %si - jnz 2b - xchgw %ax, %si /* restore SI from AX */ - //lodsw - //stosw /* store boot signature */ - - /* Now the partition table is OK */ - - movw %bx, 12(%bp) /* adjust BP in the stack */ - - movw $0x1b2, 8(%bp) /* adjust SI in the stack */ - - /* temp change the code: call self_modify_once - * - * "call self_modify_once" at add_sub_si is: - * - * .byte 0xE8 - * .word (self_modify_once - add_sub_si - 3) - * - */ - movb $0xE8, (add_sub_si - _start1) - movw $(self_modify_once - add_sub_si - 3), (add_sub_si + 1 - _start1) - - /* initialize partition number and partition entries end */ - movw $0xffff, 0x1bc /* hd partition number */ - movw $0x01fe, 0x1ba /* partition entries end */ - - jmp 1f -2: - /* get here if all drives have been checked */ -#if 0 - movw $0x202, 8(%bp) /* adjust SI in the stack */ - - /* restore the original code: addw $-4, %si */ - movw $0xC683, (add_sub_si - _start1) /* 0x83, 0xC6 */ - movb $0xFC, (add_sub_si + 2 - _start1) /* 0xFC */ -#endif -4: - //-------------------------------------------------------------------- - /* change the code: jmp Error_modify - * - * "jmp Error_modify" at Error_or_prev_MBR: - * - * .byte 0xE9 - * .word (Error_modify - Error_or_prev_MBR - 3) - * - */ - movb $0xE9, (Error_or_prev_MBR - _start1) - movw $(Error_modify - Error_or_prev_MBR - 3), (Error_or_prev_MBR + 1 - _start1) - //-------------------------------------------------------------------- - -// //-------------------------------------------------------------------- -// /* floppy search disabled ? */ -//#if 0 -// testb $1, 0x02 /* test bit0 of the third byte */ -// jz 1f /* zero means floppy search enabled */ -// /* 0x1fd or below means disable floppy search */ -// decw (add_sub_si + 5 - _start1) -//#else -// movb 0x02, %al -// andb $0x01, %al -// subb %al, (add_sub_si + 5 - _start1) -//#endif -// //-------------------------------------------------------------------- - -1: -#if 0 - popfw - lahf /* Load Flags into AH Register. */ - /* AH = SF:ZF:xx:AF:xx:PF:xx:CF */ - /* CF will be moved to ZF */ - movb %ah, %al - andb $1, %al /* CF=0 */ - shlb $6, %al /* move CF to ZF */ - popfw - lahf /* Load Flags into AH Register. */ - /* AH = SF:ZF:xx:AF:xx:PF:xx:CF */ - andb $0xbf, %ah /* 0xbf= binary 1011 1111. It clears ZF */ - orb %al, %ah -#else - popw %ax /* AX=Flags */ - popfw /* Flags_orig */ - lahf /* Load Flags_orig into AH Register. */ - /* AH = SF:ZF:xx:AF:xx:PF:xx:CF */ - shlb $2, %ah - rorw $2, %ax /* move CF of Flags to ZF of Flags_orig */ -#endif - - sahf /* update flags */ - /* current CF is the CF of Flags_orig */ - /* current ZF is the CF of Flags */ - /* CF=1 means failed in loading bootsector */ - popal - popw %es - popw %ds - ret - -self_modify_once: - /* when we get here, SI should be 0x1b2, and BP high holds DL */ - addw $12, %si /* 0x83, 0xC6, 0x0C */ - movw %bp, %ax - movb %ah, %dl - - /* note: DS=0x9400 */ - - /* restore the original code: addw $12, %si */ - movw $0xC683, (add_sub_si - _start1) /* 0x83, 0xC6 */ - movb $0x0C, (add_sub_si + 2 - _start1) /* 0x0C */ - ret - -Error_modify: - -//boot_prev_mbr: - - /* prepare to boot the previous MBR */ - - /* at this moment DS=0x9400, ES=$FS_BOOT or ES=0x9400 */ -// xorw %ax, %ax /* AX=0, for the segment of 0000:7c00 */ -// movw %ax, %es /* ES=0x0000 */ -// movw %ax, %ds /* DS=0x0000 */ -// sti - /* no previous MBR, print "Error" */ - ///* Note the 0000:7C00 is on the stack */ - //popw %ax /* AX=0x0000 */ - //popw %ax /* AX=0x7C00 */ - - movw $(message_string_helper - _start1), %si - call print_message /* CS:SI points to message string */ - movw $(nt_boot_image - _start1), %si - call print_message /* CS:SI points to message string */ - movw $(ctrl_alt_del_string - _start1), %si - call print_message /* CS:SI points to message string */ -1: - sti - hlt - jmp 1b /* hang */ - -move_helper: - - /* called only once and only when the boot loader loaded this code */ - pushw %si - pushw %bx - pushl %eax - - movw $0x0003, %ax /* set display mode: 80*25 color text */ - int $0x10 - - movw $0x200, %si /* move from the 2nd sector */ - movw %si, %di - movw $0x3E00, %cx /* move 0x3E=62 sectors */ - cld - repz movsw - - popl %eax - popw %bx - popw %si - ret - -Error_while_reading_string: - .ascii "\r\nError while reading MBR of \0" - -drive_number_string: - .ascii " in partition table of drive (hd0 ) \0" - -partition_boot_indicator_string: -// .ascii "\r\nInvalid boot indicator\0" - -partition_sectors_per_track_string: -// .ascii "\r\nInvalid sectors_per_track\0" - -partition_start_sector_string: -// .ascii "\r\nInvalid start_sector\0" - -partition_end_sector_string: -// .ascii "\r\nInvalid end_sector\0" - -no_boot_signature_string: -// .ascii "\r\nNo boot signature\0" - .ascii "\r\nError\0" - -Cannot_find_GRLDR_string: -message_string_helper: - .ascii "\r\nCannot find \0" -ctrl_alt_del_string: - .ascii " in all drives. Press Ctrl+Alt+Del to restart.\0" - -partition_message: - .ascii "\r\nTry (hd0,0 ) : \0" - -EXT2_message: - .ascii "EXT2: \0" - -NTFS5_message: - .ascii "NTFS5: \0" -FAT32_message: - .ascii "FAT32: \0" -FAT16_message: - .ascii "FAT16: \0" -FAT12_message: - .ascii "FAT12: \0" -non_MS_message: - .ascii "non-MS: skip \0" -extended_message: - .ascii "Extended: \0" -invalid_message: - .ascii "invalid or null \0" - - ###################################################################### - # External modifiers may setup a long integer at offset 0x1FFC as the - # unique disk signature. The same signature value must be also placed - # into the disk_serial_number_structure in the first sector(the MBR - # sector). You can easily locate the structure through the pointer at - # offset 0x1FF8. - # - # For GRUB.EXE the default disk serial number is the grub signature - # ("GrUb"). Generally you needn't change it, though you are - # allowed to change it through an external modifier. - ###################################################################### - - . = _start1 + 0x1FF8 - - /* point to disk serial number in the first sector, i.e., the MBR - * sector. The program never access this pointer. It can be used by - * an external program to easily locate the disk serial number at MBR. - */ - - .word disk_serial_number_structure - _start1 + 5 - - . = _start1 + 0x1FFA - - /* version word of grldr.mbr, the address is (grldr_signature - 2) */ - - .word 4 - -grldr_signature: - .byte 0x47, 0x72, 0x55, 0x62 /* signature for helper */ - -/* stolen from linux-2.6.13.1/arch/i386/boot/compressed/head.S */ - -/* - * linux/boot/head.S - * - * Copyright (C) 1991, 1992, 1993 Linus Torvalds - */ - -/* - * head.S contains the 32-bit startup code. - * - * NOTE!!! Startup happens at absolute address 0x00001000, which is also where - * the page directory will exist. The startup code will be overwritten by - * the page directory. [According to comments etc elsewhere on a compressed - * kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC] - * - * Page 0 is deliberately kept safe, since System Management Mode code in - * laptops may need to access the BIOS data stored there. This is also - * useful for future device drivers that either access the BIOS via VM86 - * mode. - */ - -/* - * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 - */ - -//#include -//#include - - . = _start + 0x2000 - - .code32 - - .align 0x200 - - .globl startup_32 - - -//#define debug_putchar(x) movw $(x | ((x << 12) & 0xF000) | (((x << 8) & 0x0F00) ^ 0xC00)), (0xB8140 + (((x - 0x30) % 80) * 2)) -#define debug_putchar(x) - -startup_32: - cld - cli - movl $(0x18 /* __BOOT_DS */), %eax - movl %eax, %ds - movl %eax, %es - movl %eax, %fs - movl %eax, %gs - movl %eax, %ss - - debug_putchar('0') -// movw $0x0C30, 0xB80A0 - - /* we use space near the end of real mode IDT for temp stack */ - movl $0x400, %esp - - xorl %eax,%eax -/* - * Initialize eflags. Some BIOS's leave bits like NT set. This would - * confuse the debugger if this code is traced. - * XXX - best to initialize before switching to protected mode. - */ - //pushl $0 - pushl %eax # EAX=0 - popfl # cli, cld by the way - -1: incl %eax # check that A20 really IS enabled - movl %eax,0x000000 # loop forever if it isn't - cmpl %eax,0x100000 - je 1b - - debug_putchar('1') -// movw $0x1D31, (0xB80A0 + (1 * 2)) - - call 1f # just calculate the EIP register -1: - popl %ebp # EBP=linear address of 1b, i.e., current EIP - subl $(1b - startup_32), %ebp # EBP=linear address of startup_32 - -#if 0 - # debug, move conventional mem to 0x1000000 - - pushw %cs - pushw %ds - pushw %es - pushw %ss - pushw %fs - pushw %gs - pushal - movl $0x1000000, %edi - xorl %esi, %esi - movl $0x400000, %ecx - cld - rep movsl - popal - popw %gs - popw %fs - popw %ss - popw %es - popw %ds - popw %cx -#endif - - /* memory layout: - * - * 0x0600-0x07FF this sector is not used - * 0x0800-0x0DFF 3 sectors for command line - * 0x0E00-0x0FFF the current sector will be copied here - * 0x1000-0x8000 the rest sectors - * - * Note: The first page(4KB) is not used by Linux, so it is a safe - * place to store our code and data. - */ - - cld # can be omitted(already done by popfl) - - /* save initrd address and size on stack before moving memory */ - - pushl 0x21C(%esi) # initrd size - pushl 0x218(%esi) # initrd base address - - //pushl %esi # points to boot_params - - /* move 3 sectors of commandline onto 0x00000800-0x00000DFF */ - - movl $0x00000800, %edi - movl 0x228(%esi), %esi # 0x228 is offset for cmd_line_ptr - movl $0x00000180, %ecx # move 3 sectors - repz movsl - - debug_putchar('2') - -// popl %esi -// pushl %esi -// -// /* move 2-sector real mode variables onto 0x00000A00-0x00000DFF */ -// -// movl $0x00000A00, %edi -// movl $0x00000100, %ecx # move 2 sectors -// repz movsl -// -// debug_putchar('3') - - /* move 1 sector of the init code here to a safe place 0x00000E00 */ - - movl $0x00000E00, %edi - movl %ebp, %esi # EBP=linear address of startup_32 - movl $0x00000080, %ecx # move 1 sector - repz movsl - - debug_putchar('4') - - /* jump to new code in the sector starting at 0x00000E00 */ - - /* just to learn various jumps */ -#if 1 - # this way we needn't touch CS register -#if 1 - # and this way we needn't touch the stack -#if 0 - # and this even won't touch any registers - # but unfortunately we don't know the - # relative displacement - // jmp (1f - 0x????????) -#else - # but this way we need to touch a register - movl $(1f - startup_32 + 0x00000E00), %eax - jmp *%eax # Oh, don't use `jmp *(%eax)' by mistake! - # Should use register indirect addressing, - # not memory indirect addressing. -#endif -#else - # and, this way we need the stack - movl $(1f - startup_32 + 0x00000E00), %eax - pushl %eax - ret -#endif - -#else - # jump to new code. __BOOT_CS is this segment, and still 32 bit - - ljmp $(__BOOT_CS), $(1f - startup_32 + 0x00000E00) -#endif - -1: - - debug_putchar('5') - - /* We are executed in low memory rang 0x0E00 to 0x0FFF, and now - * it is safe to copy the rest code to 0x00001000 - */ - - movl $((_dos_start - startup_32 - 0x200) / 4), %ecx - repz movsl - - debug_putchar('6') - - /* default boot device: DH=partition number, DL=drive number */ - movl $0x80, %edx - - /* At last, move pre_stage2 to 0x00008200 */ - - movl $0x00008200, %edi - movl $0x00020000, %ecx # move 0x80000 bytes(512KB) - movl %ebp, %esi # EBP=linear address of startup_32 - addl $(pre_stage2_start - startup_32), %esi - # ESI points to pre_stage2_start - cmpl $0xFFFFFFFF, 0x80(%esi) - je 1f - movb 0x80(%esi), %dl # DL=default drive number - movb 0x0A(%esi), %dh # DH=default partition number -1: - cmpl $0x00008200, %esi - jb 1f - - cld - repz movsl - jmp 2f - -1: - addl $0x7fffc, %edi - addl $0x7fffc, %esi - - std # downward - # remember to clear it later! - - rep movsl # EDI=0x00008200 - - cld # now clear it so we are safe -2: - debug_putchar('7') - - //popl %esi # points to boot_params - -//---------------------------------------------------------------------------- - // it is time to evaluate rd_base and rd_size now. - // rd_base is a long long integer at 0x82D0. - // rd_size is a long long integer at 0x82D8. - popl %ecx # initrd base address - popl %eax # initrd size - jecxz 1f - movl %ecx, 0x82D0 # rd_base lo 32-bit - movl %eax, 0x82D8 # rd_size lo 32-bit - xorl %ecx, %ecx # ECX=0 - movl %ecx, 0x82D4 # clear rd_base hi 32-bit - movl %ecx, 0x82DC # clear rd_size hi 32-bit -1: - // bit 1 of the byte at 0x8211 indicates booting as a Linux kernel. - orb $0x02, 0x8211 -//---------------------------------------------------------------------------- - # resolve the commandline arguments and move preset_menu to 0x00000800 - - # commandline has been copied to the sector starting at 0x00000800 - - /* ECX = 0 */ - - movl $0x00000600, %ecx # find the option in 3 sectors - //movb $2, %ch # ECX=0x200 - movl $0x00000800, %esi # starting at physical address 0x800 - - /* look for a non-blank char */ - - cld -3: - lodsb - cmpb $0, %al - je 4f # end string, failure - cmpb $0x20, %al - je 2f - cmpb $0x09, %al - jne 1f -2: - loop 3b # load next byte, ECX decreased - jmp 4f #; all are blanks, failure -1: - decl %esi # found, let ESI point to it -// incl %ecx - - /* This is a leading non-blank char. Check if it matches the option. - * option_config_file points to constant string "--config-file=" - */ - - movl $(option_config_file - startup_32 + 0xE00), %edi - - pushl %ecx - - movl $(option_config_file_end - option_config_file), %ecx - movl %esi, %eax # save ESI - cld - repz cmpsb #; ESI, EDI both changed - - popl %ecx - - je 1f # success - - /* No match. Then look for a blank char. */ - movl %eax, %esi # restore ESI - incl %esi # let ESI points to the char next to - # the leading non-blank char. - - decl %ecx - - cld -3: - lodsb - cmpb $0, %al - je 4f # end string, failure - cmpb $0x20, %al - je 2b # Blank found, try again - cmpb $0x09, %al - je 2b # Blank found, try again - loop 3b - -4: - /* failure: the option "--config-file" was not found. */ - - debug_putchar('8') - - stc - jmp normal_config_file - -1: - debug_putchar('9') - - /* success: the option "--config-file" was found. */ - - xorl %ebx, %ebx - cmpb $0x22, (%esi) /* 0x22 is the double quote char */ - jne 1f - incl %esi - incl %ebx /* EBX=1 means a leading double quote exists */ -1: - cmpb $0x28, (%esi) /* 0x28 is "(" */ - je normal_config_file # CF=0 - cmpb $0x2F, (%esi) /* 0x2F is "/" */ - je normal_config_file # CF=0 - - # locate the end of the commandline preset_menu - - movl $0x00000Dff, %ecx # end of the 3 sectors - subl %esi, %ecx # length of menu - - movl $0x00000800, %edi - - testl %ebx, %ebx # quoted? - jz 1f # no - - /* change the double quote to NULL */ - - pushl %edi - pushl %ecx - - movl %esi, %edi # EDI points to source menu string - movb $0x22, %al # locate the double quote - cld - repnz scasb - jnz 4f # not found, continue - decl %edi # EDI points to the double quote - movb $0, (%edi) # change to 0 in source string -4: - popl %ecx - popl %edi - - /* Move the command-line menu to 0x800, and change semi-colon - * to LF by the way. - */ -1: - cld - lodsb - cmpb $0x3B, %al /* semi-colon */ - jne 3f - movb $0x0A, %al /* change to LF */ -3: - stosb - cmpb $0, %al - je 4f - loop 1b -4: - - # the config_file should be disabled - - movb $0, (default_config_file - startup_32 + 0xE00) - - jmp 4f - -normal_config_file: - - # clear preset_menu value at 0x820C to 0 - movl $0, 0x0000820C - - jc 4f /* no `--config-file=' option specified. */ - - /* ESI points to the first byte of the filename. if it is not `(', - * then don't touch the boot device. - */ - - xorl %eax, %eax - movl %esi, %edi /* save ESI */ - cmpb $0x28, (%esi) /* 0x28 is "(" */ - jne 1f - lodsb - lodsb - cmpb $0x30, %al /* 0x30 is "0" */ - jb 4f /* invalid config file */ - cmpb $0x39, %al /* 0x39 is "9" */ - jbe 2f /* BIOS drive number */ - cmpb $0x66, %al /* 0x66 is "f" */ - je 3f - movb $0x80, %ah /* for hard drive */ - cmpb $0x68, %al /* 0x68 is "h" */ - je 3f - lodsb - cmpb $0x64, %al /* 0x64 is "d" */ - je 1f - jmp 4f /* invalid config file */ -3: - /* hard drive or floppy */ - lodsb - cmpb $0x64, %al /* 0x64 is "d" */ - jne 4f /* invalid config file */ - - lodsb - cmpb $0x30, %al /* 0x30 is "0" */ - jb 4f /* invalid config file */ - cmpb $0x39, %al /* 0x39 is "9" */ - ja 4f /* invalid config file */ - -2: - movl $0x7f, %ebx /* Max drive number */ - call parse_number /* parse drive number */ - jc 4f - xchgl %eax, %ebx /* save drive number to EAX */ - /* BH=0 for floppy, and 0x80 for hard drive */ - orb %bh, %al /* adjust hard drive number */ - movb $0xff, %bl /* partition number for floppy */ - testb %bh, %bh /* floppy, skip the partition number parsing. */ - jz 5f - movl $0x7f, %ebx /* Max partition number */ - call parse_number /* parse partition number */ - jc 4f -5: - /* partition number is in BL */ - xchgl %eax, %edx /* save drive number to DL */ - movb %bl, %dh /* save partition number to DH */ - - /* From now on, remember not to change DX until launching GRUB */ - -1: - # move the specified config-file to default_config_file - - movl %edi, %esi /* restore ESI */ - movl $0x4d, %ecx - movl $(default_config_file - startup_32 + 0xE00), %edi - //cld - repz movsb -4: - debug_putchar('A') - -//---------------------------------------------------------------------------- - - //cld - cli - movl $(head_idt_48 - startup_32 + 0xE00), %esi - # ESI=linear address of idt_48 - lidt (%esi) # load idt at idt_48 with limit=0x3ff, base=0 - - movl $(head_gdt - startup_32 + 0xE00), %eax - # EAX=linear address of gdt - movl $(head_gdt_48 - startup_32 + 0xE00), %esi - # ESI=linear address of gdt_48 - movl %eax, 2(%esi) # let gdt_base = linear address of gdt - lgdt (%esi) # load gdt at gdt_48 - - # switch to 16bit protected mode code segment - - ljmp $0x10 /*(__BOOT_CS)*/ , $(to_realmode - startup_32 + 0xE00) - -//---------------------------------------------------------------------------- -parse_number: - - /* input: ESI points to the number - * EBX upper limit of the number - * output: EBX the value of the number - * ESI points to the next byte after the delimiter - * EBP changed - * CF=1 failure - * CF=0 success - */ - - pushl %edx - pushl %eax - pushl %ebx /* upper limit */ - cld - movl $16, %ebp /* initialize EBP for hex */ - //movl %edi, %esi - movl $0xffffffff, %edx - xorl %ebx, %ebx - lodsw - cmpw $0x5830, %ax /* 0X */ - je 2f - cmpw $0x7830, %ax /* 0x */ - je 2f - - /* decimal */ - decl %esi - decl %esi - movl $10, %ebp -2: - xorl %eax, %eax - lodsb - cmpb $0, %al - je 4f /* CF=0 */ - cmpb $0x2C, %al /* 0x2C= `,' ends the drive number. */ - je 4f /* CF=0 */ - cmpb $0x29, %al /* 0x29= `)' ends partition number. */ - je 4f /* CF=0 */ - cmpb $0x30, %al - jb 3f - cmpb $0x39, %al - jbe 1f - cmpl $16, %ebp /* Is hex? */ - jb 3f /* no, failure */ - orb $0x20, %al - cmpb $0x61, %al - jb 3f - cmpb $0x66, %al - ja 3f - subb $0x27, %al -1: - subb $0x30, %al - pushl %eax - movl %ebx, %eax - mull %ebp - movl %eax, %ebx - popl %eax - jc 3f - addl %eax, %ebx - jc 3f - popl %eax - pushl %eax /* upper limit */ - cmpl %eax, %ebx - ja 3f - jmp 2b - -4: - testl %edx, %edx /* CF=0 */ - jz 1f /* return success */ -3: - /* return failure */ - stc -1: - popl %eax /* upper limit */ - popl %eax - popl %edx - ret - -//---------------------------------------------------------------------------- -option_config_file: - .ascii "--config-file=" -option_config_file_end: - -# Descriptor tables -# -# NOTE: The intel manual says gdt should be sixteen bytes aligned for -# efficiency reasons. However, there are machines which are known not -# to boot with misaligned GDTs, so alter this at your peril! If you alter -# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two -# empty GDT entries (one for NULL and one reserved). -# -# NOTE: On some CPUs, the GDT must be 8 byte aligned. This is -# true for the Voyager Quad CPU card which will not boot without -# This directive. 16 byte aligment is recommended by intel. -# - .align 16 -head_gdt: -// .fill GDT_ENTRY_BOOT_CS,8,0 - - # GDT entry 0(NULL entry) - .word 0 # alignment byte -head_gdt_48: - .word head_gdt_end - head_gdt - 1 # gdt limit - .word 0, 0 # gdt base (filled in later) - - # GDT entry 1(not used) - .word 0 # alignment byte -head_idt_48: - .word 0x3ff # idt limit = 0x3ff - .word 0, 0 # idt base = 0L - - # GDT entry 2(__BOOT_CS) - .word 0xFFFF # limit 64Kb - (0x10000 = 64Kb) - .word 0 # base address = 0 - .word 0x9A00 # code read/exec - .word 0x0000 # granularity = 1, 386 - # (+5th nibble of limit) - - # GDT entry 3(__BOOT_DS) - .word 0xFFFF # limit 64Kb - (0x10000 = 64Kb) - .word 0 # base address = 0 - .word 0x9200 # data read/write - .word 0x0000 # granularity = 1, 386 - # (+5th nibble of limit) -head_gdt_end: - - /* Here comes the initial stack pointer of DOS executable. - * Note that grub as a dos EXE would call init_pic below, so the - * stack should be here to avoid overwriting the code in init_pic. - */ - - /* Also note that the stack pointer should be dword aligned */ - - .align 4 - -dos_stack: - - .code16 - - # real mode startup code for pre_stage2 - # load all segment registers - -to_realmode: - cli - movw $(0x18 /* __BOOT_DS */), %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - movw %ax, %ss - movl %cr0, %eax - andl $0x00000011, %eax /* turn off paging */ -// orl $0x60000000, %eax /* cache disabled! */ - xorl %ebx, %ebx - movl %ebx, %cr3 /* reload page dir to asure paging off */ - movl %eax, %cr0 -// movl %cr0, %ebx -// andl $0x60000000, %ebx /* test if wbinvd is supported */ -// jz 1f -// wbinvd -//1: - andb $0x10, %al /* mask off the PE bit */ - movl %eax, %cr0 - - /* far jump to load the real mode CS */ - ljmp $0, $(1f - startup_32 + 0xE00) -1: - /* Now we are in real mode */ - xorw %ax, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - movw %ax, %ss - movl $0x400, %esp /* clear high word of ESP */ - xorl %ebp, %ebp - - pushw %dx /* boot drive and partition number */ - - call init_pic - - popw %dx /* boot drive and partition number */ - - # old code, should be deleted later - // /* ensure this is in the sector starting at 0000:0A00 */ - // - // . = . - ((0xA00 - 1)/ (. - startup_32 + 0x800)) - // - // /* It is right time to move the menu sector at 0x600 onto 0x800 */ - // movw $0x600, %si - // movw $0x800, %di - // movw $0x080, %cx /* move 1 sector */ - // cld - // repz movsl - - /* put the config file name */ - - movw $0x0010, %cx /* set max length of grub version string */ - movw $0x8212, %di /* version string */ - xorw %ax, %ax /* AL=0. Locate the end of version string */ - - /* pre_stage2_start+0xA holds the boot partition number. The default - * partition number is 0(and default drive number is 0x80 in DL) - */ - #;movb %dh, -8(%di) /* 0x820A, the boot partition number */ - orb $2, -13(%di) /* 0x8205, disable keyboard intervention */ - - cld - repnz scasb /* find the location of the default config file name */ - jcxz 1f /* failed, will not use the default config file name */ - - movw $0x4e, %cx /* max length of config file name */ - movw $(default_config_file - startup_32 + 0xE00), %si - cld - repz movsb /* move file name to the config-file field of stage2 */ -1: - //sti - -// movw $0x0003, %ax /* set display mode: 80*25 color text */ -// int $0x10 - -// movw $(launch_pre_stage2 - startup_32 + 0xE00), %si -// call print_message1 - - xorw %ax, %ax - movw %ax, %ss - movw $0x2000, %sp - //movb $0x80, %dl /* default boot_drive is (hd0) */ - - //sti - ljmp $0, $0x8200 //jmp pre_stage2_start - -init_pic: - -#if 0 /* enabled 2008-05-23, comment out 2009-10-06 */ - /* this is needed for booting via win98 */ - - xorw %ax, %ax - - /* init DMA, stolen from bochs(rombios.c) */ - - #; first reset the DMA controllers - outb %al, $0x0D #; disable DMA-1 - outb %al, $0xDA #; disable DMA-2 - movl $2, %ecx # delay at least 2 microseconds - call iodelay - - #; then initialize the DMA controllers - movb $0xC0, %al #; cascade mode of channel 4 enabled - outb %al, $0xD6 #; DMA-2 mode register - movb $0x00, %al #; unmask channel 4 - outb %al, $0xD4 #; DMA-2 mask register - movl $2, %ecx # delay at least 2 microseconds - call iodelay -#endif - - /* initialize PIC. */ - - //outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ - //outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */ - -#if 0 /* marked off 2007-10-07, enabled 2008-05-23, disabled 2010-03-13 */ - - /* these commands are only valid after init of 8259, so comment out. - * - tinybit 2010-03-13 - */ - - /* send clear_mask command to slave and master */ - movb $0x48, %al - call send_command_to_slave_and_master - - /* send EOI command to slave and master */ - movb $0x20, %al - call send_command_to_slave_and_master - - /* set IRQ15 and IRQ7 to least privilege */ - movb $0xC7, %al - call send_command_to_slave_and_master -#endif - - -#if 1 /* off 2007-10-07, on 2008-05-23, off 2010-03-13, on 2010-10-08 */ - - /* WinPE requires this. Confirmed by in8ape at - * http://www.boot-land.net/forums/index.php?showtopic=12620 - */ - - ######################################################################################## - ## make sure any possible coprocessor is properly reset.. - ######################################################################################## - - xorw %ax, %ax - movw $0xF0, %dx # write a byte of 0 to port F0 will clear the busy bit of math coprocessor - call outb_and_delay - - movw $0xF1, %dx # write a byte of 0 to port F1 will reset coprocessor and switch it to real mode - call outb_and_delay -#endif - - ######################################################################################## - ## Now we mask all interrupts - ######################################################################################## - - movb $0xFF, %al # mask all interrupts for now - movw $0xA1, %dx - call outb_and_delay - - movb $0xFB, %al # mask all irq's but irq2 which is cascaded - movw $0x21, %dx - call outb_and_delay - - /* - * outb_p - this has to work on a wide range of PC hardware. - */ - - cli - - //outb_p(0x11, PIC_MASTER_CMD); /* ICW1: select 8259A-1 init */ - - /* init 8259a-1 */ - - # bit 7,6,5 used only in MCS-80/85 mode. - # A7-A5 of interrupt vector address - # bit 7=0 unused - # bit 6=0 unused - # bit 5=0 unused - # bit 4=1 start init - # bit 3=0 edge trig(PC,XT,AT) - # bit 3=1 level trig(MCA) - # bit 2=0 call address interval(0=interval of 8, 1=interval of 4) - # bit 1=0 cascade mode(AT+ with 2 controlers) - # bit 1=1 single mode(PC/XT with 1 controler) - # bit 0=0 no ICW4 needed - # bit 0=1 ICW4 needed - - # If bit 0=0 then all functions selected in ICW4 are set to zero - # (Non-Buffered mode, no Auto-EOI, MCS-80/85 system) - - movb $0x11, %al - movw $0x20, %dx # 8259-1 command port - call outb_and_delay - - /* the 2nd command byte sent to port 0x21 */ - - # in MCS-80/85 mode, bit 7-0 is for interrupt vector address bit 15-8. - # in 8086/8088 mode, bit 7-3 is for interrupt vector address bit 7-3. - # interrupt vector address bit 2-0 is cleared. - # in 8086/8088 mode, bit 2-0 is not used. - - //outb_p(0x20 + 0, PIC_MASTER_IMR); /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */ - movb $0x08, %al # interrupt number 0x08 - 0x0F - movw $0x21, %dx - call outb_and_delay - - /* the 3rd command byte sent to port 0x21 */ - - # bit 7=0 no slave connected to IRQ 7 - # bit 6=0 no slave connected to IRQ 6 - # bit 5=0 no slave connected to IRQ 5 - # bit 4=0 no slave connected to IRQ 4 - # bit 3=0 no slave connected to IRQ 3 - # bit 2=0 no slave connected to IRQ 2(PC/XT) - # bit 2=1 slave connected to IRQ 2(AT+) - # bit 1=0 no slave connected to IRQ 1 - # bit 0=0 no slave connected to IRQ 0 - - //outb_p(1U << PIC_CASCADE_IR, PIC_MASTER_IMR); /* 8259A-1 (the master) has a slave on IR2 */ - movb $0x04, %al - movw $0x21, %dx - call outb_and_delay - - /* the 4th command byte sent to port 0x21 */ - - # bit 7=0 unused - # bit 6=0 unused - # bit 5=0 unused - # bit 4=0 not special fully nested mode - # bit 4=1 special fully nested mode - # bit 3=0 non-buffered mode(AT+), bit 2=unused - # bit 3=1 buffered mode(PC/XT), bit 2=0(slave)bit 2=1(master) - # bit 1=0 normal EOI - # bit 1=1 Auto EOI(no system support it) - # bit 0=1 8086/8088 mode - # bit 0=0 MCS-80/85 mode - - /* Yes, the normal EOI should be used for real mode OS. */ - - movb $0x01, %al - movw $0x21, %dx - call outb_and_delay - - /* cancel special mask mode */ - movb $0x4A, %al - movw $0x20, %dx - call outb_and_delay - - /* init 8259a-2 */ - - //outb_p(0x11, PIC_SLAVE_CMD); /* ICW1: select 8259A-2 init */ - movb $0x11, %al - movw $0xA0, %dx - call outb_and_delay - - //outb_p(0x20 + 8, PIC_SLAVE_IMR); /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */ - movb $0x70, %al # interrupt number 0x70 - 0x77 - movw $0xA1, %dx - call outb_and_delay - - /* the 3rd command byte sent to port 0xA1 */ - - # bit 7=0 unused - # bit 6=0 unused - # bit 5=0 unused - # bit 4=0 unused - # bit 3=0 unused - # bit 2,1,0 slave controler ID, should be 2 for IRQ 2 - # bit 2=0 - # bit 1=1 - # bit 0=0 - - //outb_p(PIC_CASCADE_IR, PIC_SLAVE_IMR); /* 8259A-2 is a slave on master's IR2 */ - movb $0x02, %al - movw $0xA1, %dx - call outb_and_delay - - //outb_p(SLAVE_ICW4_DEFAULT, PIC_SLAVE_IMR); /* (slave's support for AEOI in flat mode is to be investigated) */ - movb $0x01, %al - movw $0xA1, %dx - call outb_and_delay - - /* cancel special mask mode */ - movb $0x4A, %al - movw $0xA0, %dx - call outb_and_delay - - /* set IRQ15 and IRQ7 to least privilege */ - movb $0xC7, %al - call send_command_to_slave_and_master - - //udelay(100); /* wait for 8259A to initialize */ - movl $100, %ecx # delay at least 100 microseconds - call iodelay - - //outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */ - //outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */ - - cli - - movb $0x00, %al # enable all IRQs - movw $0x21, %dx - call outb_and_delay - - movb $0x00, %al # enable all the cascaded IRQs - movw $0xA1, %dx - call outb_and_delay - - //udelay(100); /* wait for 8259A to initialize */ - movl $100, %ecx # delay at least 100 microseconds - call iodelay - - /* end initialize PIC. */ - - /* FIXME: init edge-level-control-registers(IO ports 0x4D0, 0x4D1) for EISA */ -#if 0 /* disabled 2011-09-16. */ - - /* This must be disabled, because with this code ASUS eee PC 1215B - * boots extremely slow and fails to access SATA hard drive. - * With this book, value at port 0x4D0 is 0x80, and 0x4D1 holds 0x0C. - * - tinybit, 2011-09-16 - */ - - /* added 2010-03-13, disabled 2010-10-07, enabled 2010-10-09 */ - - /* WinPE (on a HP model) requires this. Confirmed by in8ape at - * http://www.boot-land.net/forums/index.php?showtopic=12620 - * Without this code, WinPE boots extremely slow(expend sevral hours). - */ - - /* EISA 8259-1 */ - - # bit 7=0 IRQ 7 edge trig - # bit 6=0 IRQ 6 edge trig - # bit 5=0 IRQ 5 edge trig - # bit 4=0 IRQ 4 edge trig - # bit 3=0 IRQ 3 edge trig - # bit 2=x IRQ 2 (do not change) - # bit 1=x IRQ 1 (do not change) - # bit 0=x IRQ 0 (do not change) - - movw $0x4D0, %dx - inb %dx, %al - andb $0x07, %al # clear bit 3-7 in case not cleared - call outb_and_delay - - /* EISA 8259-2 */ - - # bit 7=0 IRQ 15 edge trig - # bit 6=0 IRQ 14 edge trig - # bit 5=x IRQ 13 (do not change) - # bit 4=0 IRQ 12 edge trig - # bit 3=0 IRQ 11 edge trig - # bit 2=0 IRQ 10 edge trig - # bit 1=0 IRQ 9 edge trig - # bit 0=x IRQ 8 (do not change) - - movw $0x4D1, %dx - inb %dx, %al - andb $0x21, %al # clear bit 1-4, 6-7 in case not cleared - call outb_and_delay -#endif - - /* init system timer 0 (stolen from bochs rombios.c) */ -#if 1 /* enabled 2008-05-23, disabled 2010-03-13, enabled 2010-10-11 */ - - /* this is needed for booting via win98 */ - - /* WinPE (on a HP model) requires this. Confirmed by in8ape at - * http://www.boot-land.net/forums/index.php?showtopic=12620 - * Without this code, the HP hangs halfway through the Windows - * progress bar "Windows is loading files...". - */ - - /* EISA 8259-1 */ - - //movb $0x34, %al # system timer 0, 16-bit binary count, mode 2 - movb $0x36, %al # system timer 0, 16-bit binary count, mode 3 - # system timer 0 should be in mode 3 - - movw $0x43, %dx - call outb_and_delay - - movb $0x00, %al # maximum count of 0000H = 18.2Hz - movw $0x40, %dx - call outb_and_delay # write lo byte 00 - call outb_and_delay # write hi byte 00 -#endif - - /* init system timer 2 */ - inb $0x61, %al - andb $0xFE, %al - movw $0x61, %dx - call outb_and_delay - - /* enable keyboard */ - movb $0xAE, %al - movw $0x64, %dx - call outb_and_delay - -#if 0 /* marked off 2008-05-23 */ - /* disable NMI */ - orb $0x80, %al - outb %al, $0x70 - movl $2, %ecx # delay at least 2 microseconds - call iodelay -#endif - - /* init PCI (stolen from bochs rombios.c) */ - -#if 0 - call pcibios_init_iomem_bases - call pcibios_init_irqs -#endif - -#if 0 - /* this is needed for booting via win98 */ - - /* EISA 8259-1 */ - movw $0x4D0, %dx - inb %dx, %al - movw $0x21, %dx # mask off level-triggerred IRQs - call outb_and_delay - - /* EISA 8259-2 */ - movw $0x4D1, %dx - inb %dx, %al - movw $0xA1, %dx # mask off level-triggerred IRQs - call outb_and_delay -#endif - -#if 1 /* marked off 2007-10-07, enabled 2008-05-23, disabled 2010-03-13 */ - /* enabled 2010-10-04 and improved with loop */ - movl $100, %ecx -1: - movb $0x20, %al #; send EOI to 8259A-2 - movw $0xA0, %dx - //call outb_and_delay - - //movb $0x20, %al #; send EOI to 8259A-1 - movw $0x20, %dx - //call outb_and_delay - loop 1b -#endif - -#if 0 - movw $0x461, %dx - inb %dx, %al - andb $0xF0, %al - call outb_and_delay -#endif - -#if 0 - movb $0x0C, %al - outb %al, $0xA1 - xorw %cx, %cx -1: loop 1b - - movb $0x08, %al - outb %al, $0x21 - xorw %cx, %cx -1: loop 1b -#endif - -#if 0 - /* reset mouse */ - movw $0xC201, %ax - int $0x15 - - /* disable mouse */ - movw $0xC200, %ax - xorw %bx, %bx /* BH=0 means disable */ - int $0x15 - - /* set mouse handler address */ - movw $0xC207, %ax - xorw %bx, %bx /* ES:BX=0000:0000 to cancel the handler */ - int $0x15 - - /* disable monitor clock (Watch-Dog) */ - movw $0xC300, %ax - int $0x15 -#endif - - ret - - -#if 0 - .align 16 - -pci_routing_table_structure: - .byte 0x24, 0x50, 0x49, 0x52 #; "$PIR" signature - .byte 0, 1 #; version - .word 32 + (6 * 16) #; table size - .byte 0 #; PCI interrupt router bus - .byte 0x08 #; PCI interrupt router DevFunc - .word 0x0000 #; PCI exclusive IRQs - .word 0x8086 #; compatible PCI interrupt router vendor ID - .word 0x7000 #; compatible PCI interrupt router device ID - .word 0,0 #; Miniport data - .byte 0,0,0,0,0,0,0,0,0,0,0 #; reserved - .byte 0x07 #; checksum - #; first slot entry PCI-to-ISA (embedded) - .byte 0 #; pci bus number - .byte 0x08 #; pci device number (bit 7-3) - .byte 0x60 #; link value INTA#: pointer into PCI2ISA config space - .word 0xdef8 #; IRQ bitmap INTA# - .byte 0x61 #; link value INTB# - .word 0xdef8 #; IRQ bitmap INTB# - .byte 0x62 #; link value INTC# - .word 0xdef8 #; IRQ bitmap INTC# - .byte 0x63 #; link value INTD# - .word 0xdef8 #; IRQ bitmap INTD# - .byte 0 #; physical slot (0 = embedded) - .byte 0 #; reserved - #; second slot entry: 1st PCI slot - .byte 0 #; pci bus number - .byte 0x10 #; pci device number (bit 7-3) - .byte 0x61 #; link value INTA# - .word 0xdef8 #; IRQ bitmap INTA# - .byte 0x62 #; link value INTB# - .word 0xdef8 #; IRQ bitmap INTB# - .byte 0x63 #; link value INTC# - .word 0xdef8 #; IRQ bitmap INTC# - .byte 0x60 #; link value INTD# - .word 0xdef8 #; IRQ bitmap INTD# - .byte 1 #; physical slot (0 = embedded) - .byte 0 #; reserved - #; third slot entry: 2nd PCI slot - .byte 0 #; pci bus number - .byte 0x18 #; pci device number (bit 7-3) - .byte 0x62 #; link value INTA# - .word 0xdef8 #; IRQ bitmap INTA# - .byte 0x63 #; link value INTB# - .word 0xdef8 #; IRQ bitmap INTB# - .byte 0x60 #; link value INTC# - .word 0xdef8 #; IRQ bitmap INTC# - .byte 0x61 #; link value INTD# - .word 0xdef8 #; IRQ bitmap INTD# - .byte 2 #; physical slot (0 = embedded) - .byte 0 #; reserved - #; 4th slot entry: 3rd PCI slot - .byte 0 #; pci bus number - .byte 0x20 #; pci device number (bit 7-3) - .byte 0x63 #; link value INTA# - .word 0xdef8 #; IRQ bitmap INTA# - .byte 0x60 #; link value INTB# - .word 0xdef8 #; IRQ bitmap INTB# - .byte 0x61 #; link value INTC# - .word 0xdef8 #; IRQ bitmap INTC# - .byte 0x62 #; link value INTD# - .word 0xdef8 #; IRQ bitmap INTD# - .byte 3 #; physical slot (0 = embedded) - .byte 0 #; reserved - #; 5th slot entry: 4rd PCI slot - .byte 0 #; pci bus number - .byte 0x28 #; pci device number (bit 7-3) - .byte 0x60 #; link value INTA# - .word 0xdef8 #; IRQ bitmap INTA# - .byte 0x61 #; link value INTB# - .word 0xdef8 #; IRQ bitmap INTB# - .byte 0x62 #; link value INTC# - .word 0xdef8 #; IRQ bitmap INTC# - .byte 0x63 #; link value INTD# - .word 0xdef8 #; IRQ bitmap INTD# - .byte 4 #; physical slot (0 = embedded) - .byte 0 #; reserved - #; 6th slot entry: 5rd PCI slot - .byte 0 #; pci bus number - .byte 0x30 #; pci device number (bit 7-3) - .byte 0x61 #; link value INTA# - .word 0xdef8 #; IRQ bitmap INTA# - .byte 0x62 #; link value INTB# - .word 0xdef8 #; IRQ bitmap INTB# - .byte 0x63 #; link value INTC# - .word 0xdef8 #; IRQ bitmap INTC# - .byte 0x60 #; link value INTD# - .word 0xdef8 #; IRQ bitmap INTD# - .byte 5 #; physical slot (0 = embedded) - .byte 0 #; reserved -#endif - -pci_irq_list: - .byte 11, 10, 9, 5 - -pcibios_init_sel_reg: - - # input: - # BX hi 16 bit of address - # DL lo 8 bit of address - # output: - # register was selected - # DX 0x0cf8 - - pushl %eax - movl $0x800000, %eax - movw %bx, %ax - shll $8, %eax - andb $0xfc, %dl - orb %dl, %al - movw $0x0cf8, %dx - outl %eax, %dx - popl %eax - ret - -pcibios_init_iomem_bases: - pushw %bp - movw %sp, %bp - movl $0xe0000000, %eax #; base for memory init - pushl %eax - movw $0xc000, %ax #; base for i/o init - pushw %ax - movw $0x0010, %ax #; start at base address #0 - pushw %ax - movw $0x0008, %bx #; hi 16-bit - -pci_init_io_loop1: - movb $0x00, %dl #; lo 8-bit - call pcibios_init_sel_reg - movw $0x0cfc, %dx - inw %dx, %ax - cmpw $0xffff, %ax - jz next_pci_dev - movb $0x04, %dl #; disable i/o and memory space access - call pcibios_init_sel_reg - movw $0x0cfc, %dx - inb %dx, %al - andb $0xfc, %al - outb %al, %dx - -pci_init_io_loop2: - movb -8(%bp), %dl - call pcibios_init_sel_reg - movw $0x0cfc, %dx - inl %dx, %eax - testb $0x01, %al - jnz init_io_base - movl %eax, %ecx - movl $0xffffffff, %eax - outl %eax, %dx - inl %dx, %eax - cmpl %ecx, %eax - je next_pci_base - xorl $0xffffffff, %eax - movl %eax, %ecx - movl -4(%bp), %eax - outl %eax, %dx - addl %ecx, %eax #; calculate next free mem base - addl $0x01000000, %eax - andl $0xff000000, %eax - movl %eax, -4(%bp) - jmp next_pci_base - -init_io_base: - movw %ax, %cx - movw $0xffff, %ax - outw %ax, %dx - inw %dx, %ax - cmpw %cx, %ax - je next_pci_base - xorw $0xfffe, %ax - movw %ax, %cx - movw -6(%bp), %ax - outw %ax, %dx - addw %cx, %ax #; calculate next free i/o base - addw $0x0100, %ax - andw $0xff00, %ax - movw %ax, -6(%bp) - -next_pci_base: - movb -8(%bp), %al - addb $0x04, %al - cmpb $0x28, %al - je enable_iomem_space - movb %al, -8(%bp) - jmp pci_init_io_loop2 - -enable_iomem_space: - movb $0x04, %dl #; enable i/o and memory space access if available - call pcibios_init_sel_reg - movw $0x0cfc, %dx - inb %dx, %al - orb $0x07, %al - outb %al, %dx - -next_pci_dev: - movb $0x10, -8(%bp) - incw %bx - cmpw $0x0100, %bx - jne pci_init_io_loop1 - movw %bp, %sp - popw %bp - ret - -pcibios_init_set_elcr: - pushw %ax - pushw %cx - movw $0x04d0, %dx - testb $0x08, %al - jz is_master_pic - incw %dx - andb $0x07, %al - -is_master_pic: - movb %al, %cl - movb $0x01, %bl - shlb %cl, %bl - inb %dx, %al - orb %bl, %al - outb %al, %dx - popw %cx - popw %ax - ret - -pcibios_init_irqs: - pushw %ds - pushw %bp - - movw $0xf000, %ax - movw %ax, %ds # DS=0xF000 - - movw $0x04d0, %dx #; reset ELCR1 + ELCR2 - movb $0x00, %al - outb %al, %dx - incw %dx - outb %al, %dx - - /* find pci_routing_table_structure in ROM range F0000-FFFF0 */ - - cld - xorw %si, %si -1: - lodsl - addw $12, %si #; points to next paragraph - jc pci_init_end #; PCI IRQ Routing Table not found - cmpl $0x52495024, %eax #; "$PIR" signature - jnz 1b #; try next paragraph - - /* table size must be larger than 32 and must be a multiple of 16 */ - movw -10(%si), %ax - cmpw $32, %ax - jb 1b #; try next paragraph - testb $0x0F, %al - jnz 1b #; try next paragraph - - /* sum of all bytes in the PCI IRQ Routing Table should be 0 */ - - pushw %si - movw %ax, %cx #; table size - subw $16, %si #; points to table - xorw %ax, %ax -2: - lodsb - addb %al, %ah - loop 2b - testb %ah, %ah - popw %si - jnz 1b #; try next paragraph - - subw $16, %si #; points to table - movb 8(%si), %bh - movb 9(%si), %bl - movb $0x00, %dl - call pcibios_init_sel_reg - movw $0x0cfc, %dx - inl %dx, %eax - - cmpl 12(%si), %eax #; check irq router - jne pci_init_end - - movb 34(%si), %dl - call pcibios_init_sel_reg - - pushw %bx #; save irq router bus + devfunc - - movw $0x0cfc, %dx - movw $0x8080, %ax - outw %ax, %dx #; reset PIRQ route control - incw %dx - incw %dx - outw %ax, %dx - movw 6(%si), %ax - subw $0x20, %ax - shrw $4, %ax - movw %ax, %cx - addw $0x20, %si #; set pointer to 1st entry - - movw %sp, %bp - - /* calculate pointer value pci_irq_list relative to CS segment */ - call 1f -1: - popw %ax /* AX=instruction pointer of 1b */ - - subw $(1b - pci_irq_list), %ax /* AX=instruction pointer of pci_irq_list */ - pushw %ax #; save pointer to stack - - xorw %ax, %ax - pushw %ax #; push 0 - -pci_init_irq_loop1: - movb (%si), %bh - movb 1(%si), %bl - -pci_init_irq_loop2: - movb $0x00, %dl - call pcibios_init_sel_reg - movw $0x0cfc, %dx - inw %dx, %ax - cmpw $0xffff, %ax - jnz pci_test_int_pin - testb $0x07, %bl - jz next_pir_entry - jmp next_pci_func - -pci_test_int_pin: - movb $0x3c, %dl - call pcibios_init_sel_reg - movw $0x0cfd, %dx - inb %dx, %al - andb $0x07, %al - jz next_pci_func - decb %al #; determine pirq reg - movb $0x03, %dl - //mulb %dl, %al - mulb %dl - addb $0x02, %al - xorb %ah, %ah - movw %ax, %bx - movb (%bx, %si), %al - movb %al, %dl - movw (%bp), %bx - call pcibios_init_sel_reg - movw $0x0cfc, %dx - andb $0x03, %al - addb %al, %dl - inb %dx, %al - cmpb $0x80, %al - jb pirq_found - - movw -2(%bp), %bx #; pci_irq_list pointer - movb %cs:(%bx), %al - outb %al, %dx - incw %bx - movw %bx, -2(%bp) #; points to next irq - call pcibios_init_set_elcr - -pirq_found: - movb (%si), %bh - movb 1(%si), %bl - addb -3(%bp), %bl #; pci function number - movb $0x3c, %dl - call pcibios_init_sel_reg - movw $0x0cfc, %dx - outb %al, %dx - -next_pci_func: - incb -3(%bp) - incb %bl - testb $0x07, %bl - jnz pci_init_irq_loop2 - -next_pir_entry: - addw $0x10, %si - movb $0x00, -3(%bp) - loop pci_init_irq_loop1 - movw %bp, %sp - popw %bx - -pci_init_end: - popw %bp - popw %ds - ret - - - - -send_command_to_slave_and_master: - movw $0xA0, %dx - call outb_and_delay - movw $0x20, %dx - call outb_and_delay - ret - - -outb_and_delay: - outb %al, %dx - movl $2, %ecx # delay at least 2 microseconds - call iodelay - ret - -iodelay: - /* input: ECX - microseconds to delay */ - - /* On a 4GHz CPU, we needs roughly 4G/1000000=4000 clocks - * for a microsecond. - */ - - shll $14, %ecx /* 2**14=4096*4, 4 times of a microsecond */ -1: - addr32 loop 1b - ret - -// /* prints string DS:SI (modifies AX BX SI) */ -//3: -// //xorw %bx, %bx /* video page 0 */ -// movb $0x0e, %ah /* print char in AL */ -// int $0x10 /* via TTY mode */ -// -//print_message1: -// -// lodsb (%si), %al /* get token */ -// cmpb $0, %al /* end of string? */ -// jne 3b -// ret -// -// -//launch_pre_stage2: -// .ascii "\r\n\r\nLaunching GRUB...\r\n" -// -// .byte 0 /* mark the end of ascii zero string */ - -default_config_file: - .ascii "/menu.lst" -default_config_file_end: - - .byte 0 /* mark the end of ascii zero string */ - - . = default_config_file + 0x4d - - .byte 0 /* mark the end of ascii zero string */ - - // . = _start + 0x2400 - - .align 0x200 - -#----------------------------------------------------------------------------- -# Linux kernel structure ends here -#----------------------------------------------------------------------------- - -////////////////////////////////////////////////////////////////////////////// - -#----------------------------------------------------------------------------- -# DOS EXE code begins here -# -# Segment base of CS and SS is START: CS:0000=SS:0000=START=(PSP+0x2E0) -# Segment base of DS and ES is PSP : DS:0000=ES:0000=PSP=(START-0x2E0) -# -#----------------------------------------------------------------------------- - -//dos_stack: -_dos_start: - - /* Code from startup_32 to _dos_start will be copied to 0x0E00-0x8000 - * when grub.exe is used as a linux kernel. So check the length here - */ - - . = . - ((_dos_start - startup_32) / (0x8000 - 0x0E00 + 1)) - - /* first, move command line to CS:0081 */ - - //cli /* marked off 2008-08-04 */ - - cld /* move upward */ - movw $0x80, %si - movw %cs, %ax - movw %ax, %es - movw %si, %di - movw %si, %cx /* move 0x80 bytes */ - repz movsb - - movw %ax, %ds - - /* non-zero indicates EXE rather than device driver */ - movb $1, 0x80 - movb $0x00, 0xff /* end it with NULL */ - -_dos_start1: - /* At here DS=ES=CS=SS */ - - sti /* added 2008-08-04, and marked off cli */ - //cli /* disable interrupt for usb keyboard hack */ - - /* XXX: Maybe we should better mask off all IRQs - * and disable NMI here - */ - -//---------------------------------------------------------------------------- - /* change all TABs to spaces, and the first CR/LF char to NULL */ - - cld /* load upward */ - movw $0x0081, %si /* get command line */ - movw $0x1000, %cx /* max length of command line */ -1: - lodsb - cmpb $0x00, %al /* NULL */ - je 1f - cmpb $0x0D, %al /* CR */ - je 1f - cmpb $0x0A, %al /* LF */ - je 1f - cmpb $0x09, %al /* TAB */ - jne 2f - movb $0x20, -1(%si) /* change TAB to SPACE */ - jmp 3f -2: - cmpb $0x20, %al /* another non-printable char below SPACE? */ - jb invalid_option /* yes, invalid */ -3: - loop 1b -1: - decw %si /* SI points to the ending NULL */ - movb $0x00, (%si) /* change CR/LF to NULL */ - - -//---------------------------------------------------------------------------- - /* change the leading slash and chars upto "--" to spaces */ - - cld /* scan upward */ - movw $0x0081, %di /* get command line */ - movw %si, %cx - subw %di, %cx /* length of command line */ - movb $0x20, %al /* the space bar */ - repz scasb /* skip spaces */ - jz 3f /* the line contains only spaces */ - - /* scas always increment/decrement DI, so DI > 0x81 */ - - decw %di /* points to the first non-space char */ - incw %cx - - cmpb $0x2f, (%di) /* check if the leading char is a slash */ - je 2f - cmpb $0x00, (%di) /* check if the leading char is NULL */ - je 3f - cmpw $0x2d2d, (%di) /* check if the leading pair is "--" */ - je 1f /* yes, continue */ - jmp invalid_option -2: - /* yes, it is a possible switch inserted by Microsoft for the - * SHELL=GRUB.EXE line in CONFIG.SYS, so we wipe it out... - */ - - stosb /* change the leading slash to space... */ - - /* ... and change all the rest chars to spaces, up to the pair "--" */ -2: - cmpb $0x20, (%di) /* check if the next char is printable */ - jb 3f /* this is NULL, and command line is empty */ - cmpw $0x2d2d, (%di) /* check if the next pair is "--" */ - je 1f /* yes, continue */ - stosb /* change the char to space bar */ - loop 2b - /* no "--" is found */ -3: -use_default_config_file: - - /* no option specified */ - - /* first, try .\menu.lst */ - - /* SI points to filename */ - movw $ABS_PSP(default_config_file_dos1), %si - call open_dos_file - jnc 3f /* success */ - - /* second, try \menu.lst */ - - /* SI points to filename */ - movw $ABS_PSP(default_config_file_dos2), %si - call open_dos_file - jnc 3f /* success */ - - /* last, use default config file */ - - movw $ABS_PSP(default_config_file_dos), %si - movw $(default_config_file_dos_end - default_config_file_dos), %cx - jmp put_config_file_name -3: - jmp raw_commands_embedded - ///* setup saved_entry_no, etc. */ - //jmp done_options -1: -//---------------------------------------------------------------------------- - /* when we get here, DI points to the leading "--" */ - - pushw %si - pushw %di - pushw %si - pushw %di - /* find options --bypass, --time-out=T, --hot-key=K, --duce, --chs-no-tune, --keep-pxe */ -4: - popw %di - popw %si - pushw %si - pushw %di - cld - movw %si, %cx - subw %di, %cx /* length of command line */ - movb $0x2d, %al /* "-" */ -1: - repnz scasb - testw %cx, %cx - jnz 2f - /* not found */ - movb ABS_PSP(options_doing), %al - orb %al, ABS_PSP(options_done) - popw %ax /* discard old DI */ - popw %ax /* discard old SI */ - popw %di /* restore original DI */ - popw %si /* restore original SI */ - pushw %si /* push SI back to stack */ - pushw %di /* push DI back to stack */ - pushw %si /* push SI again */ - pushw %di /* push DI again */ - jmp 3f -2: - cmpb $0x2d, (%di) /* the second "-" */ - jne 1b - decw %di - incw %cx - popw %dx - pushw %dx - cmpw %dx, %di - jbe 3f - incw %di - decw %cx - incw %di - decw %cx - cmpb $0x20, -3(%di) - jne 1b - decw %di - incw %cx - decw %di - incw %cx - - //pushw %di -3: -////////////////////////////////////////////////////////////////////////////// - testb $1, ABS_PSP(options_done) - jne 5f - - movl $1, ABS_PSP(options_doing) - /* compare with "--bypass" */ - cld /* compare upward */ - movw $ABS_PSP(option_bypass_dos), %si - movw %di, %dx /* DI is our option string, save to DX */ - movw $(option_bypass_dos_end - option_bypass_dos), %cx - /* length of the string */ - repz cmpsb - jz 2f /* yes, exactly */ - - movw $ABS_PSP(option_bypass1_dos), %si - movw %dx, %di /* restore DI from DX */ - movw $(option_bypass1_dos_end - option_bypass1_dos), %cx - /* length of the string */ - repz cmpsb - jnz 3f -2: - /* found "--bypass" */ - cmpb $0x20, (%di) - je 2f - cmpb $0, (%di) - jne 3f - //orb $1, ABS_PSP(options_done) -2: - cmpl $0, ABS_PSP(bypass) - jne invalid_option /* specify --bypass twice */ - movl $1, ABS_PSP(bypass) - /* wipe off "--bypass" */ - movw $(option_bypass_dos_end - option_bypass_dos), %cx - subw %cx, %di - movb $0x22, %al /* double-quote */ - stosb - decw %cx - movb $0x20, %al /* SPACE */ - repz stosb -3: - popw %ax /* discard old DI */ - pushw %di /* push new DI */ - //testb $1, ABS_PSP(options_done) - //jz 4b - jmp 4b - - //popw %di - //pushw %di -5: -////////////////////////////////////////////////////////////////////////////// - testb $2, ABS_PSP(options_done) - jne 5f - - movl $2, ABS_PSP(options_doing) - /* compare with "--time-out=" */ - cld /* compare upward */ - movw $ABS_PSP(option_time_out_dos), %si - movw %di, %dx /* DI is our option string, save to DX */ - movw $(option_time_out_dos_end - option_time_out_dos), %cx - /* length of the string */ - repz cmpsb - jz 2f /* yes, exactly */ - - movw $ABS_PSP(option_time_out1_dos), %si - movw %dx, %di /* restore DI from DX */ - movw $(option_time_out1_dos_end - option_time_out1_dos), %cx - /* length of the string */ - repz cmpsb - jnz 3f -2: - /* found "--time-out=" */ - movl $0x000000ff, %ebx /* upper limit of time-out */ - movw %di, %si - call parse_number_dos - jc invalid_option /* invalid time-out value */ - decw %si - movw %si, %cx - subw %di, %cx - movw %si, %di - lodsb - cmpb $0x20, %al - je 2f - cmpb $0, %al - jne invalid_option /* invalid time-out value */ - //orb $2, ABS_PSP(options_done) -2: - cmpl $0x80000000, ABS_PSP(time_out) - jne invalid_option /* specify time-out twice */ - movl %ebx, ABS_PSP(time_out) - /* wipe off "--time-out=T" */ - addw $(option_time_out_dos_end - option_time_out_dos), %cx - subw %cx, %di - movb $0x22, %al /* double-quote */ - stosb - decw %cx - movb $0x20, %al /* SPACE */ - repz stosb -3: - popw %ax /* discard old DI */ - pushw %di /* push new DI */ - //testb $2, ABS_PSP(options_done) - //jz 4b - jmp 4b - - //popw %di - //pushw %di - -5: -////////////////////////////////////////////////////////////////////////////// - testb $4, ABS_PSP(options_done) - jne 5f - - movl $4, ABS_PSP(options_doing) - /* compare with "--hot-key=" */ - cld /* compare upward */ - movw $ABS_PSP(option_hot_key_dos), %si - movw %di, %dx /* DI is our option string, save to DX */ - movw $(option_hot_key_dos_end - option_hot_key_dos), %cx - /* length of the string */ - repz cmpsb - jz 2f /* yes, exactly */ - - movw $ABS_PSP(option_hot_key1_dos), %si - movw %dx, %di /* restore DI from DX */ - movw $(option_hot_key1_dos_end - option_hot_key1_dos), %cx - /* length of the string */ - repz cmpsb - jnz 3f -2: - /* found "--hot-key=" */ - movl $0x0000ffff, %ebx /* upper limit of hot-key */ - movw %di, %si - call parse_number_dos - jc invalid_option /* invalid hot-key value */ - decw %si - movw %si, %cx - subw %di, %cx - movw %si, %di - lodsb - cmpb $0x20, %al - je 2f - cmpb $0, %al - jne invalid_option /* invalid hot-key value */ - //orb $4, ABS_PSP(options_done) -2: - cmpl $0xffff3920, ABS_PSP(hot_key) - jne invalid_option /* specify hot-key twice */ - movl %ebx, ABS_PSP(hot_key) - /* wipe off "--hot-key=K" */ - addw $(option_hot_key_dos_end - option_hot_key_dos), %cx - subw %cx, %di - movb $0x22, %al /* double-quote */ - stosb - decw %cx - movb $0x20, %al /* SPACE */ - repz stosb -3: - popw %ax /* discard old DI */ - pushw %di /* push new DI */ - //testb $4, ABS_PSP(options_done) - //jz 4b - jmp 4b - - //popw %di -5: -////////////////////////////////////////////////////////////////////////////// - testb $8, ABS_PSP(options_done) - jne 5f - - movl $8, ABS_PSP(options_doing) - /* compare with "--duce" */ - cld /* compare upward */ - movw $ABS_PSP(option_duce_dos), %si - movw %di, %dx /* DI is our option string, save to DX */ - movw $(option_duce_dos_end - option_duce_dos), %cx - /* length of the string */ - repz cmpsb - jz 2f /* yes, exactly */ - - movw $ABS_PSP(option_duce1_dos), %si - movw %dx, %di /* restore DI from DX */ - movw $(option_duce1_dos_end - option_duce1_dos), %cx - /* length of the string */ - repz cmpsb - jnz 3f -2: - /* found "--duce" */ - cmpb $0x20, (%di) - je 2f - cmpb $0, (%di) - jne 3f - //orb $1, ABS_PSP(options_done) -2: - cmpl $0, ABS_PSP(duce) - jne invalid_option /* specify --duce twice */ - movl $1, ABS_PSP(duce) - /* wipe off "--duce" */ - movw $(option_duce_dos_end - option_duce_dos), %cx - subw %cx, %di - movb $0x22, %al /* double-quote */ - stosb - decw %cx - movb $0x20, %al /* SPACE */ - repz stosb -3: - popw %ax /* discard old DI */ - pushw %di /* push new DI */ - //testb $1, ABS_PSP(options_done) - //jz 4b - jmp 4b - - //popw %di - //pushw %di -5: -////////////////////////////////////////////////////////////////////////////// - testb $0x10, ABS_PSP(options_done) - jne 5f - - movl $0x10, ABS_PSP(options_doing) - /* compare with "--chs-no-tune" */ - cld /* compare upward */ - movw $ABS_PSP(option_chs_no_tune_dos), %si - movw %di, %dx /* DI is our option string, save to DX */ - movw $(option_chs_no_tune_dos_end - option_chs_no_tune_dos), %cx - /* length of the string */ - repz cmpsb - jz 2f /* yes, exactly */ - - movw $ABS_PSP(option_chs_no_tune1_dos), %si - movw %dx, %di /* restore DI from DX */ - movw $(option_chs_no_tune1_dos_end - option_chs_no_tune1_dos), %cx - /* length of the string */ - repz cmpsb - jnz 3f -2: - /* found "--chs-no-tune" */ - cmpb $0x20, (%di) - je 2f - cmpb $0, (%di) - jne 3f - //orb $1, ABS_PSP(options_done) -2: - cmpl $0, ABS_PSP(chs_no_tune) - jne invalid_option /* specify --chs-no-tune twice */ - movl $1, ABS_PSP(chs_no_tune) - /* wipe off "--chs-no-tune" */ - movw $(option_chs_no_tune_dos_end - option_chs_no_tune_dos), %cx - subw %cx, %di - movb $0x22, %al /* double-quote */ - stosb - decw %cx - movb $0x20, %al /* SPACE */ - repz stosb -3: - popw %ax /* discard old DI */ - pushw %di /* push new DI */ - //testb $1, ABS_PSP(options_done) - //jz 4b - jmp 4b - - //popw %di - //pushw %di -5: -////////////////////////////////////////////////////////////////////////////// - testb $0x20, ABS_PSP(options_done) - jne 5f - - movl $0x20, ABS_PSP(options_doing) - /* compare with "--keep-pxe" */ - cld /* compare upward */ - movw $ABS_PSP(option_keep_pxe_dos), %si - movw %di, %dx /* DI is our option string, save to DX */ - movw $(option_keep_pxe_dos_end - option_keep_pxe_dos), %cx - /* length of the string */ - repz cmpsb - jz 2f /* yes, exactly */ - - movw $ABS_PSP(option_keep_pxe1_dos), %si - movw %dx, %di /* restore DI from DX */ - movw $(option_keep_pxe1_dos_end - option_keep_pxe1_dos), %cx - /* length of the string */ - repz cmpsb - jnz 3f -2: - /* found "--keep-pxe" */ - cmpb $0x20, (%di) - je 2f - cmpb $0, (%di) - jne 3f - //orb $1, ABS_PSP(options_done) -2: - cmpl $0, ABS_PSP(keep_pxe) - jne invalid_option /* specify --keep-pxe twice */ - movl $1, ABS_PSP(keep_pxe) - /* wipe off "--keep-pxe" */ - movw $(option_keep_pxe_dos_end - option_keep_pxe_dos), %cx - subw %cx, %di - movb $0x22, %al /* double-quote */ - stosb - decw %cx - movb $0x20, %al /* SPACE */ - repz stosb -3: - popw %ax /* discard old DI */ - pushw %di /* push new DI */ - //testb $1, ABS_PSP(options_done) - //jz 4b - jmp 4b - - //popw %di - //pushw %di -5: -////////////////////////////////////////////////////////////////////////////// - -// testb $2, ABS_PSP(options_done) -// jne 5f -// -// jmp 4b -// -//1: - popw %di - popw %si - popw %di - popw %si - -//--------------------------------------------------------------------------- - /* if specified --bypass, then time-out default to 5 */ - - movl ABS_PSP(bypass), %ecx /* --bypass specified? */ - jecxz 1f /* no, continue */ - cmpl $0x80000000, ABS_PSP(time_out) - jne 1f - movl $5, ABS_PSP(time_out) -1: -//--------------------------------------------------------------------------- - /* if time-out is not 0, print message */ - movw ABS_PSP(time_out), %cx - jcxz 1f - - movw $ABS_PSP(press_space_bar_string), %dx - cmpw $0x3920, ABS_PSP(hot_key) - je 2f - movw $ABS_PSP(press_hot_key_string), %dx -2: - movb $0x09, %ah /* display a dollar terminated string */ - int $0x21 /* call DOS */ - movw $ABS_PSP(press_any_key_string), %dx - movb $0x09, %ah /* display a dollar terminated string */ - int $0x21 /* call DOS */ -1: -//--------------------------------------------------------------------------- - /* find option "--config-file=" */ - - cld - movw %di, %si /* SI points to the leading "--" */ - /* but may be changed to double-quote */ -1: - lodsb - cmpb $0x22, %al /* the double quote char */ - //je 1b - jne 2f - movb $0x20, -1(%si) - jmp 1b -2: - cmpb $0x20, %al /* SPACE */ - je 1b - cmpb $0, %al - je use_default_config_file - decw %si - cmpw $0x2d2d, (%si) /* "--" */ - jne invalid_option - - movw %si, %di /* DI points to the leading "--" */ - - /* compare with "--config-file=" */ - - cld /* compare upward */ - movw $ABS_PSP(option_config_file_dos), %si - movw %si, %bx /* SI is const string "--config-file=" */ - movw %di, %dx /* DI is our option string, save to DX */ - movw $(option_config_file_dos_end - option_config_file_dos), %cx - /* length of the string */ - repz cmpsb - jz 1f /* yes, exactly */ - - /* translate all upper case to lower case, and try again */ - - movw $0x1000, %cx - movw %dx, %si /* about to translate our option string */ - movw %dx, %di -2: - lodsb - cmpb $0x00, %al - je 2f - cmpb $0x41, %al /* below 'A'? */ - jb 3f /* yes, no change. */ - cmpb $0x5a, %al /* above 'Z'? */ - ja 3f /* yes, no change. */ - orb $0x20, %al /* change to lower */ -3: - stosb - loop 2b -2: - - /* compare again */ - - cld /* compare upward */ - movw $(option_config_file_dos_end - option_config_file_dos), %cx - movw %bx, %si /* SI is const string "--config-file=" */ - movw %dx, %di /* DI is our option string, restore from DX */ - repz cmpsb /* compare for the second time */ - jnz invalid_option -1: - - /* the option "--config-file=" exists for sure */ - - cld /* scan upward */ - movw %di, %si /* points to the config file name */ - movw $0x1000, %cx - movb $0x00, %al /* find the end of command line */ - repnz scasb - jnz invalid_option /* no ending NULL */ - - movw %di, %cx /* points to end of config file name */ - subw %si, %cx - decw %cx /* length of config file name */ - jz invalid_option /* FILENAME is empty */ - - /* SI points to filename string with length CX */ - - /* the leading "(" or "/" indicates a normal config filename */ - movb (%si), %al - cmpb $0x28, %al /* "(" */ - jz 2f - cmpb $0x2F, %al /* "/" */ - jnz 1f -2: - /* we change the ending space-slash to NULL only for normal config - * filename. - */ - - pushw %cx /* save CX(=length) important! */ - - /* find the space-slash pair and change the space to NULL */ - cld /* scan upward */ - xorw %dx, %dx /* 0 for outside the double-quotes */ - movw %si, %di /* scan the filename */ - //movw $0x1000, %cx /* max length of command line */ - movb $0x20, %al /* the space bar character */ -2: - repnz scasb /* find the space char */ - jnz 2f /* not found, continue */ - cmpb $0x2f, (%di) /* is it the " /" pair */ - jnz 2b /* no, search the rest of the command line */ - decw %di - movb $0x00, %al /* mark the end of command line */ - stosb /* change the space to NULL */ -2: - popw %cx /* restore CX, which is non-zero. */ - jmp put_config_file_name -1: - /* The filename specifies an embedded command-line menu. */ - - movw %cx, %bx - incw %cx - - cld - //movw $0x1000, %cx - movw $0x81, %di - xorw %ax, %ax - - /* change semi-colon to LF. change double-quote to 0 if it is followed - * by SPACE or NULL, otherwise delete the double-quote char and - * continue. - */ - -3: - lodsb -4: - cmpb $0x3B, %al /* semi-colon */ - jnz 2f - movb $0x0A, %al /* change to LF */ -2: - cmpb $0x22, %al /* the double quote */ - jnz 2f - jcxz 4f - lodsb - decw %cx - cmpw %bx, %cx /* is the double quote leading? */ - jae 4b /* yes, discard the double quote */ - cmpb $0x20, %al /* is the next char a space? */ - jz 4f /* yes, end */ - cmpb $0x00, %al /* is the next char a NULL */ - jnz 4b /* no, discard the double quote */ -4: - movb $0x00, %al /* change to NULL */ -2: - stosb - cmpb $0x00, %al - jz 1f - jcxz 4b - loop 3b -1: - - /* DI points to the char after the ending NULL */ - - movw $0x81, %si /* SI points to filename */ - movw %di, %cx /* points to end of filename */ - subw %si, %cx - decw %cx /* CX=length of the filename */ - jz invalid_option /* FILENAME is empty */ - - /* the leading "(" or "/" indicates a normal config filename */ - movb (%si), %al - cmpb $0x28, %al /* "(" */ - jz put_config_file_name - cmpb $0x2F, %al /* "/" */ - jz put_config_file_name - - /* invalidate the config file in pre_stage2 */ - -raw_commands_embedded: - - /* CX=0 means raw commands are embedded. */ - xorw %cx, %cx /* copy 0 bytes to config-file field */ - //jmp 6f - -put_config_file_name: - cld - - movl %esi, %edx /* save ESI to EDX */ - - movl ABS_PSP(duce), %eax /* --duce specified? */ - - movw $ABS_PSP(pre_stage2_start+0x12), %di /* version string */ - - shlb $2, %al /* bit2=DUCE */ - movb ABS_PSP(chs_no_tune), %ah - shlb $3, %ah /* bit3=chs-no-tune */ - orb %ah, %al - movb ABS_PSP(keep_pxe), %ah - decb %ah - negb %ah /* AH=disable pxe */ - orb %ah, %al /* bit0=disable pxe */ - orb %al, -13(%di) - - xorl %eax, %eax /* 0 means the end of the string */ - - /* pre_stage2_start+0xA holds the boot partition number. We use - * default partition number 0(and default drive number 0x80 in DL) - */ - #;movb %al, -8(%di) /* the boot partition number */ - - /* pre_stage2_start+0xB holds our temp boot_drive */ - movb $0x80, -7(%di) /* temp storage for boot_drive */ - - pushal - /* get boot drive, AX = 3305h, Return: DL = boot drive (1=A:,...) */ - xorw %dx, %dx /* set DL to a known value */ - movw $0x3305, %ax - int $0x21 - cmpb $1, %dl # drive A: -//;; je 1f - jne 3f - /* drive A: */ - /* read boot sector */ - movw $0x201, %ax - movw $ABS_START(gdt), %bx # temp use this sector - movw $1, %cx - movw $0, %dx - pushw %ds - pushw %es - pushaw - stc - int $0x13 - popaw - popw %es - popw %ds - jc 2f # failed - movw $ABS_PSP(pre_stage2_start+0x138), %di # dos_drive_geometry - movw 0x18(%bx),%cx # sectors per track - jcxz 2f # failed - cmpw $63, %cx - ja 2f # failed - movw 0x1a(%bx),%ax # heads - decw %ax - js 2f # failed - testb %ah, %ah - jnz 2f # failed - xchgb %al, %ah # AL=0(floppy drive), AH=Hmax - //cld # already done priviously - stosw - xchgw %ax, %cx # movw %cx, %ax - stosw - /* DI now points to dos_part_start */ - //movl 0x1C(%bx),%eax # hidden sectors - xorl %eax, %eax # hidden sectors should be 0 for floppy!! - stosl - jmp 2f /* done */ -3: - cmpb $3, %dl # drive C: - jne 2f # failed -//;;1: - /* boot drive is valid */ - pushw %dx # drive number(1=A:,...) - movw $0x440D, %ax # IOCTL - generic block device request - movb %dl, %bl # drive (0=default, 1=A:, etc) - movw $0x0860, %cx # get disk parameters - movw $ABS_START(dos_stack), %dx # temp use this space - pushw %dx - int $0x21 - popw %bx # point to parameter block - popw %dx # drive number(1=A:,...) - jc 2f # failed - movw $ABS_PSP(pre_stage2_start+0x138), %di # dos_drive_geometry - movw 0x14(%bx),%cx # sectors per track - jcxz 2f # failed - cmpw $63, %cx - ja 2f # failed - movw 0x16(%bx),%ax # heads - decw %ax - js 2f # failed - testb %ah, %ah - jnz 2f # failed - addb $0x7E, %dl # DL=0x7F(A:) or 0x81(C:) - andb $0x80, %dl # DL=0(A:) or 0x80(C:) - movb %al, %ah - movb %dl, %al - //cld # already done priviously - stosw - xchgw %ax, %cx # movw %cx, %ax - stosw - /* DI now points to dos_part_start */ - movl 0x18(%bx),%eax # hidden sectors - stosl -2: - popal - - jcxz 6f /* CX=0 means raw commands are embedded. */ - - /* pre_stage2_start+0xC holds the address of preset_menu. - * we are using the config-file, and we do not change the default - * preset_menu, so let it be 0. */ - movl %eax, -6(%di) - - /* ESI points to the first byte of the filename. if it is not `(', - * then don't touch the boot device. - */ - - cmpb $0x28, (%si) /* 0x28 is "(" */ - jne 6f - - xorw %ax, %ax /* clear AH */ - - lodsb /* AL="(" */ - lodsb - - /* the drive number in hex or decimal form */ - - cmpb $0x30, %al /* 0x30 is "0" */ - jb invalid_option /* invalid config file */ - cmpb $0x39, %al /* 0x39 is "9" */ - jbe 2f /* BIOS drive number */ - - /* the drive number in (fd?) or (hd?) form */ - - cmpb $0x66, %al /* 0x66 is "f" */ - je 3f - movb $0x80, %ah /* for hard drive */ - cmpb $0x68, %al /* 0x68 is "h" */ - je 3f - lodsb - cmpb $0x64, %al /* 0x64 is "d" */ - je 6f /* might be cd/nd/md/rd, do nothing */ - jmp invalid_option /* invalid config file */ -3: - /* hard drive or floppy */ - lodsb - cmpb $0x64, %al /* 0x64 is "d" */ - jne invalid_option /* invalid config file */ - - lodsb - cmpb $0x30, %al /* 0x30 is "0" */ - jb invalid_option /* invalid config file */ - cmpb $0x39, %al /* 0x39 is "9" */ - ja invalid_option /* invalid config file */ - -2: - decw %si /* SI points to hexa or decimal number */ - movl $0x7f, %ebx /* Max drive number */ - call parse_number_dos /* parse drive number */ - jc invalid_option /* invalid config file */ - cld - decw %si /* SI points to delimiter "," or ")" */ - lodsb - cmpb $0x2C, %al /* "," */ - je 2f - cmpb $0x29, %al /* ")" */ - jne invalid_option /* invalid config file */ -2: - xchgl %eax, %ebx /* save drive number to EAX */ - /* BH=0 for floppy, and 0x80 for hard drive */ - orb %bh, %al /* adjust hard drive number */ - movb $0xff, %bl /* partition number for floppy */ - testb %bh, %bh /* floppy, skip the partition number parsing */ - jz 2f - movl $0x7f, %ebx /* Max partition number */ - call parse_number_dos /* parse partition number */ - jc invalid_option /* invalid config file */ -2: - - /* BL=boot partition number, AL=boot_drive number */ - - movb %al, %bh /* BH=boot_drive number */ - - decw %si /* SI should point to ")" */ - lodsb - - cmpb $0x29, %al /* ")" */ - jne invalid_option /* invalid config file */ - - movw %bx, -8(%di) /* setup boot_drive and boot_partition number */ - -//---------------------------------------------------------------------------- -6: - movl %edx, %esi /* restore ESI from EDX */ - xorb %al, %al - pushw %cx /* CX=0 means raw commands are embedded. */ - movw $0x0010, %cx /* set max length of grub version string */ - cld - repnz scasb /* DI changed */ - popw %cx /* CX=0 means raw commands are embedded. */ - - movw %cx, %ax - addw %di, %ax - cmpw $ABS_PSP(pre_stage2_start+0x6f), %ax - /* check for possible buffer overflow */ - jnb file_name_too_long - pushw %cx /* CX=0 for embedded menu, and ... */ - cld - repz movsb /* now it is safe, perform the move */ - popw %cx /* ... CX=non-zero for normal file */ - xorb %al, %al /* write an end-of-string mark ... */ - movb %al, (%di) /* ... to the new config file name */ - - testw %cx, %cx /* CX=0 means raw commands are embedded. */ - jnz 1f /* normal grub-file, continue */ - - /* CX=0, and SI points to beginning of the string. */ - - /* If "#@" is leading, it leads a DOS filename for menu. - * Based on John Cobb (Queen Mary, University of London): - * http://sysdocs.stu.qmul.ac.uk/sysdocs/Comment/Code_Snippets/Grub_For_DOS_Extra/paramfile.s - */ - - cmpw $0x4023, (%si) /* "#@" */ - jne 2f /* normal embedded menu, continue */ - - lodsw /* addw $2, %si; see cld above */ - -dos_filename: - - /* SI points to filename */ - call open_dos_file - jc invalid_option /* failure */ - jmp 1f /* done, continue. */ - -2: - /* check if it is DOS-style */ - cld - movw %si, %di - movw $0x1000, %cx - movb $0x20, %al - repz scasb - //jcxz 1f /* don't check a long menu for dos filename */ - testw %cx, %cx - jz 1f /* don't check a long menu for dos filename */ - decw %di /* DI points to the first non-space char */ - movw %di, %si - movw $70, %cx - xorb %al, %al - repnz scasb - //jcxz 1f /* don't check a long menu for dos filename */ - testw %cx, %cx - jz 1f /* don't check a long menu for dos filename */ - movw %di, %bx - subw %si, %bx - decw %bx /* length */ - movw (%si), %ax - cmpb $0x3A, %ah /* : */ - jne 2f - cmpb $0x41, %al /* A */ - jb 2f - cmpb $0x7A, %al /* z */ - ja 2f - cmpb $0x5A, %al /* Z */ - jbe dos_filename //invalid_option - cmpb $0x61, %al /* a */ - jae dos_filename //invalid_option -2: - cmpb $0x5C, %al /* \ */ - je dos_filename //invalid_option - //cmpb $0x2F, %al /* / */ - //je invalid_option - - /* if there is a LF, this is not of a DOS filename. */ - - movw %si, %di - //incw %di - movw %bx, %cx - //decw %cx - movb $0x0A, %al - repnz scasb - jz 1f - - /* if there is a back slash, this is of a DOS filename. */ - - movw %si, %di - //incw %di - movw %bx, %cx - //decw %cx - movb $0x5C, %al - repnz scasb - jz dos_filename //invalid_option - - /* now no LFs, no back slahses. So this can only be a filename without - * leading dir part. If there is a space in the file name, then it is - * not treated as a DOS filename. - */ - - movw %si, %di - //incw %di - movw %bx, %cx - //decw %cx - movb $0x20, %al - repnz scasb - jz 1f - - //movw %si, %di - //incw %di - //movw %bx, %cx - //decw %cx - //movb $0x2F, %al - //repnz scasb - //jz invalid_option - - /* now no spaces. If there is a dot in the file name, then it is - * treated as a DOS filename. - */ - - movw %si, %di - movw %bx, %cx - movb $0x2E, %al /* . */ - repnz scasb - jz dos_filename //invalid_option - - movw %si, %di - movw %bx, %cx - movb $0x2D, %al /* - */ - repnz scasb - jz dos_filename //invalid_option - - //movw %si, %di - //movw %bx, %cx - //movb $0x5F, %al /* _ */ - //repnz scasb - //jz invalid_option - - movw %si, %di - movw %bx, %cx - movb $0x7E, %al /* ~ */ - repnz scasb - jz dos_filename //invalid_option - - movw %si, %di - movw %bx, %cx - movb $0x21, %al /* ! */ - repnz scasb - jz dos_filename //invalid_option - - movw %si, %di - movw %bx, %cx - movb $0x2A, %al /* * */ - repnz scasb - jz dos_filename //invalid_option - - movw %si, %di - movw %bx, %cx - movb $0x3F, %al /* ? */ - repnz scasb - jz dos_filename //invalid_option - -1: -done_options: - - smsw %ax /* the old 286 code, save MSW to AX */ - testb $0x01, %al /* is it in protected mode? */ - jnz protected_mode /* continue to check vm86 mode */ - jmp backup_low_memory_and_HMA /* in real mode, continue */ - -invalid_option: - movw $ABS_PSP(usage_string), %dx - movb $0x09, %ah /* display a dollar terminated string */ - int $0x21 /* call DOS */ - - /* hexdump the PSP commandline area */ - movb $0x0e, %ah /* display char */ - movw $7, %bx /* white */ - movb $8, %dh /* 8 sections (1 section = 16 bytes) */ - movw $0x0080, %si /* offset in PSP */ -4: - movw $0x10, %cx /* display 16 bytes per line */ - /* display leading string like "0080: " */ - movb $0x30, %al /* display "0" */ - int $0x10 - int $0x10 /* twice */ - movw %si, %ax /* AH modified */ - shrb $4, %al /* higher 4 bits of SI */ - cmpb $9, %al - jbe 2f - addb $7, %al -2: - addb $0x30, %al /* 0x30 is '0' */ - movb $0x0e, %ah /* display char */ - int $0x10 - movb $0x30, %al /* display "0" */ - int $0x10 - movb $0x3a, %al /* display ":" */ - int $0x10 - movb $0x20, %al /* display 3 space chars */ - int $0x10 - int $0x10 - int $0x10 - - /* display hex values */ -1: - lodsb - movb %al, %dl /* save lower 4 bits of AL to DL */ - shrb $4, %al /* higher 4 bits */ - cmpb $9, %al - jbe 2f - addb $7, %al -2: - addb $0x30, %al /* 0x30 is '0' */ - movb $0x0e, %ah /* display char */ - //movw $7, %bx /* white */ - int $0x10 - movb %dl, %al /* restore AL from DL */ - andb $0x0f, %al - cmpb $9, %al - jbe 2f - addb $7, %al -2: - addb $0x30, %al /* 0x30 is '0' */ - //movb $0x0e, %ah /* display char */ - //movw $7, %bx /* white */ - int $0x10 - movb $0x20, %al /* display a space char */ - int $0x10 - loop 1b - - int $0x10 /* display 2 space chars */ - int $0x10 - - /* display ascii values */ - - movw $0x10, %cx - subw %cx, %si -1: - lodsb - //cmpb $0x80, %al /* is it big char? */ - //jb 2f /* no, continue */ - cmpb $7, %al /* is it BELL char? */ - je 2f /* no, continue */ - cmpb $8, %al /* is it BACKSPACE char? */ - je 2f /* no, continue */ - cmpb $0x0a, %al /* is it LF char? */ - je 2f /* no, continue */ - cmpb $0x0d, %al /* is it CR char? */ - jne 3f /* no, continue */ -2: - movb $0x2e, %al /* display a dot */ -3: - int $0x10 - loop 1b - - movb $0x0d, %al /* display CR char */ - int $0x10 - movb $0x0a, %al /* display LF char */ - int $0x10 - - decb %dh - jnz 4b - - jmp exit_no_message - -open_dos_file: - - /* SI points to filename */ - - /* skip any possible leading blanks in the filename. */ - movw %si, %di - movw $0x1000, %cx - movb $0x20, %al /* space */ - cld - repz scasb - jz 4f //invalid_option /* filename cannot be only spaces */ - decw %di /* DI points to the first non-space char */ - - //AH = 3Dh //OPEN EXISTING FILE - //AL = access and sharing modes - //DS:DX -> ASCIZ filename - //CL = attribute mask of files to look for (server call only) - - //Return: - //CF clear if successful - //AX = file handle - //CF set on error - //AX = error code (01h,02h,03h,04h,05h,0Ch,56h) - - movzwl %di, %edx - movw $0x3d00, %ax /* open file for reading */ - int $0x21 /* call DOS */ - jnc 3f - - /* open failure */ - - pushl %edx - movl $ABS_PSP(failed_open_file_string), %edx - movb $0x09, %ah - int $0x21 - popl %edx - - /* locate the end of filename */ - movw %dx, %di - movw $0x1000, %cx - movb $0, %al /* NULL */ - cld - repnz scasb - decw %di /* DI points to the ending NULL */ - pushw %di - movb $0x24, %al /* '$' */ - stosb /* change the NULL to '$' */ - - movb $0x09, %ah /* display a dollar terminated string */ - int $0x21 /* call DOS */ - popw %di - movb $0, %al - stosb /* change `$' back to NULL */ - jmp 4f //invalid_option /* jump if failed to open */ -failed_open_file_string: - .ascii "\r\nUnable to open DOS file: $" -3: - - //READ FROM FILE OR DEVICE - - //AH = 3Fh - //BX = file handle - //CX = number of bytes to read - //DS:DX -> buffer for data - - //Return: - //CF clear if successful - //AX = number of bytes actually read (0 if at EOF before call) - //CF set on error - //AX = error code (05h,06h) - - movw %ax, %bx - pushw %bx - movb $0x3f, %ah - movw $0x1000, %cx - movl $0x81, %edx - int $0x21 - popw %bx - jnc 3f - - /* read failure */ - - movl $ABS_PSP(failed_read_file_string), %edx - movb $0x09, %ah /* display a dollar terminated string */ - int $0x21 /* call DOS */ - jmp 4f //invalid_option /* jump if failed to read */ -failed_read_file_string: - .ascii "\r\nUnable to read DOS file.$" -3: - //CLOSE FILE - - //AH = 3Eh - //BX = file handle - // - //Return: - //CF clear if successful - // AX destroyed - //CF set on error - // AX = error code (06h) - - pushw %ax //number of bytes actually read (0 if at EOF before call) - - movb $0x3e, %ah // close file (BX = file handle) - int $0x21 - - popw %bx //number of bytes actually read (0 if at EOF before call) - - movb $0, 0x81(%bx) /* end in NULL */ - clc - ret -4: - stc - ret - -message_exit: - movb $0x09, %ah /* display a dollar terminated string */ - int $0x21 /* call DOS */ -exit_no_message: - movw $0x4C01, %ax /* exit EXE with error number 01 */ -terminate_program: - cmpb $0, %cs:0x80 /* Are we running as EXE or device driver? */ - jne 1f /* It is EXE. So we call DOS to exit. */ - - /* We are running as a device driver. */ - - /* Calculate the CS */ - movw %cs, %bx /* points to START. */ - subw $((start -nxtdev) >> 4), %bx - pushw %bx /* points to device driver start */ - movw $(device_driver_exit - nxtdev), %bx - pushw %bx - lret - -1: - int $0x21 /* call DOS */ - -program_hangs: /* should not get here, just in case int21/AH=4Ch would fail */ - jmp program_hangs - -#----------------------------------------------------------------------------- -# DOS device driver Interrupt routine begins here -#----------------------------------------------------------------------------- - -ReqHeader: -RhOffs: .word 0 #Saved offset of request header -RhSeg: .word 0 #Saved segment of request header - -#The following command table is initialised to the exit routines to -# use when the command is not implemented. In this skeleton, only Init -# is implemented. Change the pointers as you add routines. -#Normally, at least the following routines are required: -# For character device drivers: 0,4,5,6,7,8,9,0ah,0bh -# For block devices : 0,1,2,4,8,9 - -//cmdtab: .word Init - nxtdev # 0 Initialisation command -// .word Exit_Done - nxtdev # 1 Media_check -// .word Exit_Done - nxtdev # 2 Build BPB -// .word Exit_UC - nxtdev # 3 IOCtl in -// .word Exit_Done - nxtdev # 4 Input -// .word Exit_Busy - nxtdev # 5 Non-destructive input -// .word Exit_Done - nxtdev # 6 Input status -// .word Exit_Done - nxtdev # 7 Input flush -// .word Exit_Done - nxtdev # 8 Output -// .word Exit_Done - nxtdev # 9 Output with verify -// .word Exit_Done - nxtdev #0Ah Output status -// .word Exit_Done - nxtdev #0Bh Output flush -// .word Exit_UC - nxtdev #0Ch IOCtl out -// .word Exit_Done - nxtdev #0Dh Device open (3.0+) -// .word Exit_Done - nxtdev #0Eh Device close (3.0+) -// .word Exit_UC - nxtdev #0Fh Removable media (3.0+) -// .word Exit_UC - nxtdev #10h Output till busy (3.0+) -// .word Exit_UC - nxtdev #11h (Unused) -// .word Exit_UC - nxtdev #12h (Unused) -// .word Exit_UC - nxtdev #13h Generic IOCTL (3.2:B, 3.3+:B/C) -// .word Exit_UC - nxtdev #14h (Unused) -// .word Exit_UC - nxtdev #15h (Unused) -// .word Exit_UC - nxtdev #16h (Unused) -// .word Exit_UC - nxtdev #17h Get logical device (3.2+) -// .word Exit_UC - nxtdev #18h Set logical device (3.2+) -// .word Exit_UC - nxtdev #19h IOCTL query (5.0+) - -interrupt: - pushfw - cli - cld - pushaw - pushw %ds #Save segment registers - pushw %es - - movw %cs, %ax #Make DS point to us - movw %ax, %ds - - lesw ReqHeader - nxtdev, %bx #Get ptr to request header in ES:BX - movb %es:2(%bx), %al #Get command - - testb %al, %al - jz Init - orw $0x8103, %es:3(%bx) #Set ERROR, DONE and UNKNOWN COMMAND -exit: - popw %es #Restore segment registers - popw %ds - popaw - popfw - lret #Return to caller - -Init: - -#if 1 - /* DS=CS */ - lesw ReqHeader - nxtdev, %bx #Get ptr to request header in ES:BX - ldsw %es:18(%bx), %si #Get pointer to commandline in DS:SI - - movw $0x0080, %di #Command line will be moved to here - #as if it is in a PSP - movw %cs, %ax - addw $((start - nxtdev) >> 4), %ax - movw %ax, %es - - cld - xorw %ax, %ax - stosb #store 0 at offset 0x0080, this is an - #indicator for device driver than EXE - - /* DS:SI points to driver name */ - movw $0xfff, %cx /* move at most 4095 bytes */ - - /* first, skip all blank characters. */ - -1: - lodsb - cmpb $0x20, %al /* 0x20 is space bar */ - je 1b - cmpb $0x09, %al /* 0x09 is TAB */ - je 1b - decw %si - - /* secondly, skip the name of the driver. */ - -1: - lodsb - cmpb $0x20, %al /* 0x20 is space bar */ - ja 1b - - /* finally, copy the rest of the command line. */ - -1: - cmpb $0x0A, %al /* 0x0A is LF */ - jne 2f - movb $0x0D, %al /* 0x0D is CR */ -2: - cmpb $0x0D, %al /* 0x0D is CR */ - je 3f - - cmpb $0x09, %al /* 0x09 is the TAB key. */ - jne 2f - movb $0x20, %al -2: - stosb - lodsb - loop 1b -3: - movb $0x00, %al /* Ends in a NULL */ - stosb /* the last char stored is NULL */ - -#endif - - movw %cs, %ax - movw %ax, %ds - lesw ReqHeader - nxtdev, %bx #Get ptr to request header back - - orw $0x810C, %es:3(%bx) #Set ERROR and DONE bits - # and OTHER ERROR code - movb $0, %es:13(%bx) #Clear UNITS byte for CHAR device - andw $0x7FFF, attr - nxtdev #Clear CHAR bit in device attrib eord - - xorw %ax, %ax - xchgw %ax, %es:14(%bx) #Set zero break address - - /* MS-DOS will initialize the break address as XXXX:0000. */ - - testw %ax, %ax #Is it MS-DOS 5.0+ ? - movw %cs, %ax - xchgw %ax, %es:16(%bx) #Set break address segment - jnz 1f #no, do not check the end address. - - /* yes, check the memory available for this device driver. */ - - movw %cs, %bx #the driver start segment - cmpw %bx, %ax #Is the end address too low? - jbe 1f #yes, do not check the end address. - cmpw $0xe000, %ax #Is the end address too high? - jae 1f #yes, do not check the end address. - - /* check if we have 64K room available at the end of the driver image. - * This 64K space will be used for backup the HMA. Exit here if no - * enough memory. And 12K room for VCPI page_info, and additional - * 1K room for restoring EBDA from (nearly)bottom to (nearly)top of - * the conventional memory. - */ - - movw %cs, %bx #the driver start segment - - addw $((exe_sectors * 0x20) + 0x1000 + 0x0300 + 0x0040), %bx - #0x1000 paragraphs = 64K (HMA_backup) - #0x0300 paragraphs = 12K (page_info) - #0x0040 paragraphs = 1K (EBDA) - - jc 2f #load too high, failure - cmpw %bx, %ax - jnb 1f #check passed, continue -2: - /* print error message. */ - movb $3, %ah #Read cursor position - xorb %bh, %bh # for video page 0 - int $0x10 #(BIOS) (Returned in dx) - movw $0x1301, %ax #Write string in teletype mode - movb $3, %bl # with attribute cyan - movw $(nomem_end - nomem), %cx # length of string - movw $(nomem - nxtdev), %bp # start of string - pushw %cs # in es:bp - popw %es - int $0x10 #(BIOS) - - jmp exit -1: - //jmp 2b - -#if 1 - - /* Because our stack will be changed, we must backup all registers. */ - - movw %cs, %ax - //movw %ax, %ds # DS=CS - - addw $((start - nxtdev) >> 4), %ax - movw %ax, %es /* ES:0000 now points to START */ - - cld - - xorw %di, %di - stosl /* EAX */ - movl %ebx, %eax - stosl /* EBX */ - movl %ecx, %eax - stosl /* ECX */ - movl %edx, %eax - stosl /* EDX */ - movl %edi, %eax - stosl /* EDI */ - movl %esp, %eax - stosl /* ESP */ - movl %ebp, %eax - stosl /* EBP */ - movw %ss, %ax - stosw /* SS */ - movw %fs, %ax - stosw /* FS */ - movw %gs, %ax - stosw /* GS */ - - pushfl - popl %eax - stosl /* EFLAGS */ - - movl %esi, %eax - stosl /* ESI */ - - /* modify the stack */ - cli - movw %es, %ax /* ES:0000 now points to START */ - movw %ax, %ds - movw %ax, %ss - movw $ABS_START(dos_stack), %sp - - /* far jump to _dos_start1. */ - - /* Note: DS=ES=CS tells _dos_start we are from device driver. */ - - pushw %es - pushw $ABS_START(_dos_start1) - lret - - /* if need be, we could come back here from _dos_start1. */ - -device_driver_exit: - - cli - cld - movw %cs, %ax - movw %ax, %ds - movw $(start - nxtdev), %si - lodsl /* EAX */ - lodsl /* EBX */ - xchgl %eax, %ebx - lodsl /* ECX */ - xchgl %eax, %ecx - lodsl /* EDX */ - xchgl %eax, %edx - lodsl /* EDI */ - xchgl %eax, %edi - lodsl /* ESP */ - xchgl %eax, %esp - lodsl /* EBP */ - xchgl %eax, %ebp - lodsw /* SS */ - movw %ax, %ss - lodsw /* FS */ - movw %ax, %fs - lodsw /* GS */ - movw %ax, %gs - - /* SS:SP has been restored, so it is safe to use stack. */ - - lodsl /* EFLAGS */ - pushl %eax - popfl - - /* direction flag here is UPWARD as we saved it before. */ - - /* Another note: the direction flag does not matter, because - * this is the last LODS instruction executed before we exit. - */ - - lodsl /* ESI */ - xchgl %eax, %esi - - jmp exit - -#endif - -nomem: - .ascii "\r\nError: No enough memory to run GRUB.EXE with the DEVICE command in CONFIG.SYS\r\n" -nomem_end: - -#----------------------------------------------------------------------------- -# DOS device driver Interrupt routine ends here -#----------------------------------------------------------------------------- - -//---------------------------------------------------------------------------- -file_name_too_long: - - .code16 - - movw $ABS_PSP(fatal_string), %dx - jmp message_exit - -//---------------------------------------------------------------------------- -parse_number_dos: - - .code16 - - /* input: ESI points to the number - * EBX upper limit of the number - * output: EBX the value of the number - * ESI points to the next byte after the delimiter - * EBP changed - * CF=1 failure - * CF=0 success - */ - - pushl %edx - pushl %eax - pushl %ebx /* upper limit */ - cld - movl $16, %ebp /* initialize EBP for hex */ - //movl %edi, %esi - movl $0xffffffff, %edx - xorl %ebx, %ebx - lodsw - cmpw $0x5830, %ax /* 0X */ - je 2f - cmpw $0x7830, %ax /* 0x */ - je 2f - - /* decimal */ - decl %esi - decl %esi - movl $10, %ebp -2: - xorl %eax, %eax - lodsb - cmpb $0, %al - je 4f /* CF=0 */ - cmpb $0x2C, %al /* 0x2C= `,' ends the drive number. */ - je 4f /* CF=0 */ - cmpb $0x29, %al /* 0x29= `)' ends partition number. */ - je 4f /* CF=0 */ - cmpb $0x20, %al /* 0x20= ` ' */ - je 4f /* CF=0 */ - cmpb $0x30, %al - jb 3f - cmpb $0x39, %al - jbe 1f - cmpl $16, %ebp /* Is hex? */ - jb 3f /* no, failure */ - orb $0x20, %al - cmpb $0x61, %al - jb 3f - cmpb $0x66, %al - ja 3f - subb $0x27, %al -1: - subb $0x30, %al - pushl %eax - movl %ebx, %eax - mull %ebp - movl %eax, %ebx - popl %eax - jc 3f - addl %eax, %ebx - jc 3f - popl %eax - pushl %eax /* upper limit */ - cmpl %eax, %ebx - ja 3f - jmp 2b - -4: - testl %edx, %edx /* CF=0 */ - jz 1f /* return success */ -3: - /* return failure */ - stc -1: - popl %eax /* upper limit */ - popl %eax - popl %edx - ret - -protected_mode: - pushfw - popw %ax - testb $0x30, %ah /* IOPL */ - jz 1f - - /* IOPL is not 0 */ - andb $0xcf, %ah /* let IOPL = 0 */ - pushw %ax - popfw - pushfw - popw %ax - testb $0x30, %ah /* is IOPL still 0? */ - jz 2f /* CPL is 0 */ - jmp 3f -1: - /* IOPL is 0 */ - orb $0x30, %ah /* let IOPL != 0 */ - pushw %ax - popfw - pushfw - popw %ax - testb $0x30, %ah /* is IOPL still 0? */ - jnz 2f /* CPL is 0 */ - jmp 3f -2: - /* ring 0 of 16-bit protected mode will get here */ - andb $0xcf, %ah /* let IOPL = 0 */ - pushw %ax - popfw - jmp backup_low_memory_and_HMA /* CPL = 0, Continue */ -3: - /* vm86 mode(emm386/Windows DOS Box/LINUX DOSEMU) will get here */ - /* CPL != 0 */ - -#ifndef BAD_BIOS - /* before probing int, we initialize umb_array while in VM86 mode. */ - - movw %cs, %ax - movw %ax, %es - cld - movw $ABS_START(umb_array), %di - movw $8, %cx - - /* find the first umb in the range from C000:0000 to F000:0000 */ - - /* the first umb should begin at a 4K boundary */ - - movw $0xBF00, %ax /* will begin at 0xBF00 + 0x100 = 0xC000 */ - movw %ax, %ds - -1: - movw %ds, %ax - addw $0x100, %ax - cmpw $0xF000, %ax - jnb 1f - movw %ax, %ds - - cmpb $0x4D, 0 /* 0x4D='M' */ - jne 1b - cmpl $0x20424D55, 8 /* 'UMB ' - 'UMB' and a space */ - jne 1b - cmpl $0x20202020, 12 /* ' ' - 4 spaces */ - jne 1b - - /* found. DS:0000 points to the first umb. */ -4: - movw %ds, %ax - stosw /* start segment */ - xchgw %ax, %bx /* save AX to BX */ - movw 3, %ax - incw %ax - stosw /* length in paragraphs */ - addw %ax, %bx /* the next umb */ - - jcxz 1f - decw %cx - jz 1f - - movw %bx, %ds - -2: - jcxz 1f - cmpb $0x4D, 0 /* 0x4D='M' */ - je 5f - cmpb $0x5A, 0 /* 0x5A='Z' */ - jne 1f - xorw %cx, %cx /* CX=0 indicates 'no more block'. */ -5: - cmpl $0x20202020, 12 /* ' ' - 4 spaces */ - jne 1f - - cmpl $0x20424D55, 8 /* 'UMB ' - 'UMB' and a space */ - je 3f - - /* 'SM' or others */ - - movw %ds, %ax - addw 3, %ax - incw %ax - movw %ax, %ds - jmp 2b -3: - /* UMB */ - - movw %ds, %ax - cmpw %ax, %bx - jne 4b /* add a new item */ - - /* use the old item and increase its length */ - movw 3, %ax - incw %ax - addw %ax, %es:-2(%di) - addw %ax, %bx - movw %bx, %ds - jmp 2b - -1: -#endif - - /* Note for people who are tracing/debugging this program: - * - * PROBE_INT will take over int01, so probably you don't want - * to trace into PROBE_INT. - */ - - call probe_int - - jc failed_probe_int - - movw %cs, %ax - movw %ax, %ds - movw %ax, %es - - /* Note for people who are tracing/debugging this program: - * - * The following code will switch from VM86 mode to protected mode, - * and then to real mode. Your debugger will hang in a mode switch. - * So stop tracing now. - */ - -/* Use VCPI to switch to protected mode, and then switch to real mode - * and run grub. After returning from grub, switch to protected mode, and - * finally use VCPI again to switch back to vm86 mode. - */ - -/* stolen from http://my.execpc.com/~geezer/os/slfb.asm */ -#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -#; Simulated Linear Frame Buffer -#; Christopher Giese -#; http://www.execpc.com/~geezer/os/ -#; -#; Updated March 6, 2001: can now return to V86 mode when done -#; -#; Some stuff (actually, pmode VESA BIOS bank switching) fixed by -#; Alexei A. Frounze -#; http://alexfru.chat.ru -#; -#; You can do anything with this code but blame us for it. -#; -#; To run this code, you need a PC with a 32-bit processor (386SX or better) -#; and DOS. This code has been tested with the following SVGA video boards: -#; -#; bank-switch function -#; buss chipset used by this code -#; ---- ------- -------------------- -#; 16-bit ISA Cirrus 5422 Cirrus -#; 32-bit PCI S3 86c765 (Trio 64V+) S3 -#; 32-bit PCI (?) STB Nitro (?) S3 -#; -#; To assemble this code, you need NASM (http://www.web-sites.co.uk/nasm/) -#; nasm -f bin -o slfb.com slfb.asm -#; -#; bugs/to do: -#; - test with other systems -#; -#; Here is an interesting link: -#; http://marc.theaimsgroup.com/?m=88102879813311&w=2 -#; Also, look at the "vflat" files in the source code to the -#; SciTech MGL graphics library -#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - movl $1, ABS_PSP(emm386_running) - -#; save CS value for return to real mode - movw %cs, ABS_PSP(real_mode_cs) - -#; our pmode code will use the stack DOS gave us, but we have -#; to zero the top 16 bits of the stack pointer (ESP) - movzwl %sp, %esp - -#; get the virtual-to-physical conversion value. Though we turn on paging, -#; this code runs in memory that is identity-mapped (i.e. no page-based -#; address translation). We do, however, use segment-based address -#; translation, to give things the same addresses in both real and pmode. - xorl %ebx, %ebx - movw %cs, %bx - shll $4, %ebx - -#; set base addresses of the 16- and 32-bit code segment descriptors - movl %ebx, %eax - movw %ax, ABS_PSP(gdt2 + 2) #; 32-bit code segment - movw %ax, ABS_PSP(gdt4 + 2) #; 16-bit code segment - shrl $16, %eax - movb %al, ABS_PSP(gdt2 + 4) #; 32-bit code segment - movb %al, ABS_PSP(gdt4 + 4) #; 16-bit code segment - movb %ah, ABS_PSP(gdt2 + 7) #; 32-bit code segment; AH=0 - #; movb %ah, ABS_PSP(gdt4 + 7) #; 16-bit code segment - -#; now do the same with the data/stack segment descriptors - movl %ebx, %eax - movw %ax, ABS_PSP(gdt3 + 2) #; 32-bit data segment - movw %ax, ABS_PSP(gdt5 + 2) #; 16-bit data segment - shrl $16, %eax - movb %al, ABS_PSP(gdt3 + 4) #; 32-bit data segment - movb %al, ABS_PSP(gdt5 + 4) #; 16-bit data segment - movb %ah, ABS_PSP(gdt3 + 7) #; 32-bit data segment; AH=0 - #; movb %ah, ABS_PSP(gdt5 + 7) #; 16-bit data segment - -#; point the TSS descriptor to the LINEAR/PHYSICAL address of 'tss' - movl $ABS_PSP(tss), %eax - addl %ebx, %eax - movw %ax, ABS_PSP(gdt6 + 2) #; 32-bit TSS selector - shrl $16, %eax - movb %al, ABS_PSP(gdt6 + 4) #; 32-bit TSS selector - movb %ah, ABS_PSP(gdt6 + 7) #; 32-bit TSS selector - -# we don't use protected mode idt during the mode switch - -#; point 'gdt_ptr' to LINEAR/PHYSICAL address of the GDT; -#; 'idt_ptr' to LINEAR/PHYSICAL addr of the IDT - addl %ebx, ABS_PSP(gdt_ptr + 2) - addl %ebx, ABS_PSP(idt_ptr + 2) - -#; DOS doesn't load .COM or .EXE files on a page (4K) boundary, so -#; we must now find a page boundary for the page directory/tables. - movw %es, %ax - addw $(HMA_backup), %ax - movw %ax, %es - -#; page_info immediately follows 64K space at HMA_backup - - xorl %esi, %esi -#if 1 - movw %es, %si - addw $(HMA_backup+0x1000), %si #; SI=segment of page_info - shll $4, %esi #; ESI = LINEAR/PHYSICAL addr of page_info -#else - movw $ABS_PSP(page_info), %si #; SI = offset of page_info - addl %ebx, %esi #; ESI = LINEAR/PHYSICAL addr of page_info -#endif - addl $4095, %esi #; round to 4K boundary - - andl $0xFFFFF000, %esi #; ESI = LINEAR/PHYSICAL addr of page dir - movl %esi, %edi -#if 0 - subl %ebx, %edi #; DI = offset of page dir; EDI <= 0xffff -#else - shrl $4, %edi #; DI=segment of page dir - movw %di, %es #; ES:0000 points to page dir - xorw %di, %di -#endif - -#; save page dir address for later use by VCPI - movl %esi, ABS_PSP(vcpi_cr3) - -#; EAX = LINEAR/PHYSICAL address of "kernel" page table -#; (4K above the page directory) - movl %esi, %eax - addl $4096, %eax -#; create entry in page dir for "kernel" page table - orb $7, %al #; Ring 3, writable, present -#if 0 - movl %eax, (%di) -#else - movl %eax, %es:(%di) #; EDI=0 -#endif - -#; advance DI from page directory to "kernel" page table - addl $4096, %edi #; EDI=4096 - -#; using the "kernel" page table, identity-map -#; (virtual == physical) the bottom 4M of RAM -#; With VCPI, we can skip this step, and simply take over EMM386's -#; conventional memory page table using INT 67h AX=DE01h - cld - movw $1024, %cx - movl $7, %eax #; Ring 3, writable, present -1: - stosl - addl $4096, %eax #; next page - loop 1b - -#; move DI back to "kernel" page table, in case we want to change it - subl $4096, %edi #; EDI=4096 - -# Windows is running? - pushl %ebx - pushw %es - pushl %edi - movw $0x1600, %ax - int $0x2F - popl %edi - popw %es - popl %ebx - - //cmpb $0, %al - //je check_vcpi # not Windows DOS Box - //cmpb $0x80, %al - //je check_vcpi # not Windows DOS Box - shlb $1, %al - jz check_vcpi # not Windows DOS Box - - movl $1, ABS_PSP(windows_running) - -check_dpmi: - - /* print the warning */ - - movw $ABS_PSP(warning_win_msg), %dx - movb $0x09, %ah /* display a dollar terminated string */ - int $0x21 /* call DOS */ - - movw $ABS_PSP(press_space_bar_string), %dx - cmpw $0x3920, ABS_PSP(hot_key) - je 2f - movw $ABS_PSP(press_hot_key_string), %dx -2: - movb $0x09, %ah /* display a dollar terminated string */ - int $0x21 /* call DOS */ - movw $ABS_PSP(press_any_key_string), %dx - movb $0x09, %ah /* display a dollar terminated string */ - int $0x21 /* call DOS */ - - movw $5, ABS_PSP(time_out) /* non-zero timeout hangs Windows */ - - sti /* for sleep_5_seconds to work. */ - - call sleep_5_seconds - //xorw %ax, %ax - - cli /* the clock is not used any more */ - - movw $ABS_PSP(cancel_msg), %dx - jne message_exit /* not the hot-key, exit to DOS */ - /* hot-key pressed, continue */ - - //// movw $0, ABS_PSP(time_out) /* clear time_out before we continue to run under Windows. */ - - cmpl $0, ABS_PSP(bypass) /* default is bypass GRUB? */ - jne message_exit /* yes, exit to DOS now. */ - /* no, continue to run grub under windows. */ - - /* now bypass is 0. */ - -#if 0 - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jmp message_exit #; Cant_Enter_PMode -#endif - #; check dpmi -#; -#; Get the entry point address and save it -#; - movw $0x1687, %ax #; DOS Protected-Mode Interface - INSTALLATION CHECK - int $0x2F #; Return: - #; AX = 0000h if installed BX = flags - #; - #; bit 0: 32-bit programs supported - #; CL = processor type (02h=80286, 03h=80386, 04h=80486) - #; DH = DPMI major version - #; DL = two-digit DPMI minor version (binary) - #; SI = number of paragraphs of DOS extender private data - #; ES:DI -> DPMI mode-switch entry point. - #; AX nonzero if not installed - - - testw %ax, %ax - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jnz message_exit #; Cant_Enter_PMode - movw %es, ABS_PSP(PMode_Entry_Seg) - movw %di, ABS_PSP(PMode_Entry_Off) - -#; -#; Allocate memory for use by DOS extender if necessary -#; NOTE: This code assumes that the program has already -#; shrunk its memory block so that the DOS -#; memory allocation call will work -#; - testw %si, %si - jz Enter_PMode_Now - movw %si, %bx - movb $0x48, %ah - int $0x21 - jc message_exit #; Cant_Enter_PMode - movw %ax, %es - -#; -#; Enter protected mode as a 16-bit program -#; -Enter_PMode_Now: -#; After using Int 2Fh function 1687h, to obtain the protected mode -#; entry point, the DPMI client must call the entry point address as -#; described in this section. - -#;To Call - -#; AX = Flags -#; Bit 0 = 1 if program is a 32-bit application -#; ES = Real mode segment of DPMI host data area. This -#; must be the size of the data area returned in SI -#; from the previous function. ES will be ignored if -#; the required data size is zero. -#; Call the address returned in ES:DI by the previous -#; function - -#;Returns - -#; If function was successful: -#; Carry flag is clear. -#; Program is now executing in protected mode. -#; CS = 16-bit selector with base of real mode CS and a -#; 64K limit -#; SS = Selector with base of real mode SS and a 64K limit -#; DS = Selector with base of real mode DS and a 64K limit -#; ES = Selector to program's PSP with a 100h byte limit -#; FS and GS = 0 (if running on an 80386 or 80486) -#; If the program is a 32-bit application the high word of -#; ESP will be 0 -#; All other registers are preserved - -#; If function was not successful: -#; Carry flag is set. -#; Program is executing in real mode - - xorw %ax, %ax - //movw %ax, %ds #; DS=0 - lcall %cs:*ABS_PSP(PMode_Entry_Off) - jc message_exit #; Cant_Enter_PMode - -#; -#; The program is running in protected mode now! - -ring_check: - -#; 5. clear the PE bit - movl %cr0, %eax - andb $0xFE, %al - movl %eax, %cr0 - - pushfw - popw %ax - testb $0x30, %ah /* IOPL */ - jz 4f - - /* IOPL is not 0 */ - andb $0xcf, %ah /* let IOPL = 0 */ - pushw %ax - popfw - pushfw - popw %ax - testb $0x30, %ah /* is IOPL still 0? */ - jz 2f /* CPL is 0 */ - jmp 3f -4: - /* IOPL is 0 */ - orb $0x30, %ah /* let IOPL != 0 */ - pushw %ax - popfw - pushfw - popw %ax - testb $0x30, %ah /* is IOPL still 0? */ - jnz 2f /* CPL is 0 */ - jmp 3f -2: - /* ring 0 of 16-bit protected mode will get here */ - andb $0xcf, %ah /* let IOPL = 0 */ - pushw %ax - popfw - jmp real2 /* CPL = 0, Continue */ -3: - /* CPL != 0 */ - - #; we must switch to ring 0 - - #; Allocate Descriptors - movw $0x0000, %ax #; function number - movw $1, %cx #; CX = Number of descriptors to allocate - int $0x31 #; call DPMI - #; return AX = Base selector - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit #; Cant_Enter_PMode - - movw %ax, ABS_PSP(selector_alloc) - - #; Get Descriptor - movw $0x000B, %ax #; function number - movw %ds, %bx #; selector number - #; ES:(E)DI = Pointer to an 8 byte buffer to receive copy of descriptor - movl $ABS_PSP(descriptor_buf), %edi - pushw %es - pushw %ds - popw %es - int $0x31 #; call DPMI - popw %es - #; DS:DI points to buffer - - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit #; Cant_Enter_PMode - - #; Set Descriptor - movw $0x000C, %ax #; function number - movw ABS_PSP(selector_alloc), %bx #; selector number - #; ES:(E)DI = Pointer to an 8 byte buffer that contains descriptor. - #; The type byte (byte 5) follows the same format and restrictions - #; as the access rights/type parameter (in CL) to Set Descriptor - #; Access Rights. The extended type byte (byte 6) follows the same - #; format and restrictions as the extended access rights/type parameter - #; (in CH) to Set Descriptor Access Rights, except the limit field may - #; have any value, except the low order 4 bits (marked "reserved") are - #; used to set the upper 4 bits of the descriptor's limit. - movl $ABS_PSP(descriptor_buf), %edi - pushw %es - pushw %ds - popw %es - int $0x31 #; call DPMI - popw %es - #; DS:DI points to buffer - - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit #; Cant_Enter_PMode - - movw ABS_PSP(selector_alloc), %cx - incw %cx - testw $7, %cx - jnz message_exit - -// . = . - (ABS_PSP(.) - 0x28F3) - - movw ABS_PSP(selector_alloc), %cx - movw %cx, %fs #; FS is the new selector - - #; get LDTR(it is a selector that points into GDT) - -// pushw %ds -// popw %fs #; fs base = 0, limit=64K - -// pushw %ss -// popw %ds - - #; Set Segment Base Address of fs to 0 - #; Sets the 32-bit linear base address field in the LDT descriptor - #; for the specified segment. - movw $0x0007, %ax #; function number - movw %fs, %bx #; selector number - #; CX:DX = 32-bit linear base address of segment - xorw %cx, %cx - xorw %dx, %dx - int $0x31 #; call DPMI - - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit #; Cant_Enter_PMode - - #; check if fs base == 0 - #; Get Segment Base Address - movw $0x0006, %ax #; function number - movw %fs, %bx #; selector number - int $0x31 #; call DPMI - #; return CX:DX = 32-bit linear base address of segment - - movw %dx, %ax - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit #; Cant_Enter_PMode - - testw %ax, %ax - jnz message_exit - - testw %cx, %cx - jnz message_exit - - #; adjust fs limit to 4G - #; AX = 0008h - #; BX = Selector - #; CX:DX = 32-bit segment limit - movw $0x0008, %ax #; function number - movw %fs, %bx #; selector number - movw $0xffff, %cx - movw $0xffff, %dx - int $0x31 #; call DPMI - - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit #; Cant_Enter_PMode -#if 1 - xorl %ecx, %ecx - movl %fs, %ecx - lsll %ecx, %eax - jnz message_exit - - movw $ABS_PSP(err_msg), %dx #; yup, it's 'Doze - - incl %eax - jnz message_exit - - sgdt ABS_PSP(gdtr) - -// movl ABS_PSP(gdtr + 2), %ebx #; GDT linear base address -// -// fs testl $0xFFFFFFFF, (%ebx) -// movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze -// jnz message_exit #; Cant_Enter_PMode -#endif -#if 0 - #; Get CS Base Address - movw $0x0006, %ax #; function number - movw %cs, %bx #; selector number - int $0x31 #; call DPMI - #; return CX:DX = 32-bit linear base address of segment - - movw %dx, %ax - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit #; Cant_Enter_PMode - - shll $16, %ecx - movw %ax, %cx #; ECX=linear base address of CS - - xorl %edx, %edx - movw ABS_PSP(real_mode_cs), %dx - shll $4, %edx - - cmpl %ecx, %edx - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jnz message_exit #; Cant_Enter_PMode -#endif - - #; Set Protected Mode Interrupt Vector - #; - - movw $0x0205, %ax #; function number - movb $0x00, %bl #; Interrupt number - - #; CX:(E)DX = Selector:Offset of exception handler - xorl %edx, %edx - xorl %ecx, %ecx -#if 0 - movw ABS_PSP(real_mode_cs), %cx - movw $ABS_PSP(int3_handler), %dx - shll $4, %ecx - addl %ecx, %edx #; EDX=linear address - movl $0x28, %ecx #; win9x selector with ring 0 -#else - movw %cs, %cx - movw $ABS_PSP(int3_handler), %dx -#endif - int $0x31 #; call DPMI - - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit #; Cant_Enter_PMode -// jnc message_exit #; Cant_Enter_PMode - - movw %cs, %cx - incw %cx - testw $7, %cx - jnz message_exit - - #; Allocate Descriptors - movw $0x0000, %ax #; function number - movw $1, %cx #; CX = Number of descriptors to allocate - int $0x31 #; call DPMI - #; return AX = Base selector - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit #; Cant_Enter_PMode - - movw %ax, ABS_PSP(selector_alloc) - - #; Get Descriptor - movw $0x000B, %ax #; function number - movw %cs, %bx #; selector number - #; ES:(E)DI = Pointer to an 8 byte buffer to receive copy of descriptor - movl $ABS_PSP(descriptor_buf), %edi - pushw %es - pushw %ds - popw %es - int $0x31 #; call DPMI - popw %es - #; DS:DI points to buffer - - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit #; Cant_Enter_PMode - -// andb $0x9F, 5(%di) #; Let DPL=0 - - #; Set Descriptor - movw $0x000C, %ax #; function number - movw ABS_PSP(selector_alloc), %bx #; selector number - #; ES:(E)DI = Pointer to an 8 byte buffer that contains descriptor. - #; The type byte (byte 5) follows the same format and restrictions - #; as the access rights/type parameter (in CL) to Set Descriptor - #; Access Rights. The extended type byte (byte 6) follows the same - #; format and restrictions as the extended access rights/type parameter - #; (in CH) to Set Descriptor Access Rights, except the limit field may - #; have any value, except the low order 4 bits (marked "reserved") are - #; used to set the upper 4 bits of the descriptor's limit. - movl $ABS_PSP(descriptor_buf), %edi - pushw %es - pushw %ds - popw %es - int $0x31 #; call DPMI - popw %es - #; DS:DI points to buffer - - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit #; Cant_Enter_PMode - - movw ABS_PSP(selector_alloc), %cx - incw %cx - testw $7, %cx - jnz message_exit - - #; get LDTR(it is a selector that points into GDT) - - sldt %bx -#if 0 - /* cannot get ldt base in this way because the function works only - * for BX=(a selector that points into LDT) - */ - - #; Get LDT Base Address - movw $0x0006, %ax #; function number -// movw %fs, %bx #; selector number - int $0x31 #; call DPMI - #; return CX:DX = 32-bit linear base address of LDT - -// movw $ABS_PSP(err_msg), %dx #; DEBUG DPMI -// cmpw $0x8022, %ax -// jz message_exit #; Cant_Enter_PMode -// movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze -// jmp message_exit - - movw %dx, %ax - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit -#else - movl ABS_PSP(gdtr + 2), %eax #; GDT linear base address - andl $0xFFF8, %ebx - addl %eax, %ebx #; EBX points to LDT descriptor - addr32 fs movl 2(%ebx), %eax #; lower 3 byte of LDT base - roll $8, %eax - andb $0x1F, %al - cmpb $0x02, %al - jne message_exit - - addr32 fs movb 7(%ebx), %al #; higher byte of LDT base - rorl $8, %eax #; EAX=linear address of LDT base - movl %eax, ABS_PSP(ldt_base) -#endif -// movw %cx, %bx -// shll $16, %ebx -// movw %ax, %bx #; EBX=LDT linear base address - - movl ABS_PSP(ldt_base), %ebx - xorl %ecx, %ecx - movw ABS_PSP(selector_alloc), %cx - andw $0xFFF8, %cx #; offset in LDT - addl %ecx, %ebx #; points to descriptor - - addr32 fs movb 5(%ebx), %al - xorb $0x60, %al - andb $0x60, %al - - jnz message_exit - - addr32 fs xorb $0x60, 5(%ebx) #; Let DPL=0 - -// movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze -// jz message_exit - - #; Set Protected Mode Interrupt Vector - #; - - movw $0x0205, %ax #; function number - movb $0x00, %bl #; Interrupt number - - #; CX:(E)DX = Selector:Offset of exception handler - xorl %edx, %edx - xorl %ecx, %ecx - - movw ABS_PSP(selector_alloc), %cx - andw $0xFFFC, %cx - movw $ABS_PSP(int3_handler), %dx - int $0x31 #; call DPMI - - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit #; Cant_Enter_PMode - - #; Physical Address Mapping - #; - - #; To Call - - #; AX = 0800h - #; BX:CX = Physical address of memory - #; SI:DI = Size of region to map in bytes - - #; Returns - - #; If function was successful: - #; Carry flag is clear. - #; BX:CX = Linear address that can be used to access the physical memory - - #; If function was not successful: - #; Carry flag is set. - - movw $0x0800, %ax - movw $0, %bx - movw $0, %cx - movw $0x000A, %si - movw $0, %di - - int $0x31 - - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit - - movw %cx, ABS_PSP(conventional_linear) - movw %bx, ABS_PSP(conventional_linear + 2) - - #; Allocate Memory Block - #; Allocates and commits a block of linear memory. - #; Call With - #; AX = 0501H - #; BX:CX = size of block (bytes, must be nonzero) - #; Returns - #; if function successful - #; Carry flag = clear - #; BX:CX = linear address of allocated memory block - #; SI:DI = memory block handle (used to resize and free block) - #; if function unsuccessful - #; Carry flag = set - #; AX = error code - #; 8012H linear memory unavailable - #; 8013H physical memory unavailable - #; 8014H backing store unavailable - #; 8016H handle unavailable - #; 8021H invalid value (BX:CX = 0) - movw $0x0501, %ax - movw $0x000A, %bx - movw $0, %cx - - int $0x31 - - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit - - movw %cx, ABS_PSP(conventional_backup) - movw %bx, ABS_PSP(conventional_backup + 2) - - #; Allocate Descriptors - movw $0x0000, %ax #; function number - movw $1, %cx #; CX = Number of descriptors to allocate - int $0x31 #; call DPMI - #; return AX = Base selector - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit #; Cant_Enter_PMode - - movw %ax, ABS_PSP(selector_alloc1) - - #; Get Descriptor - movw $0x000B, %ax #; function number - movw %cs, %bx #; selector number - #; ES:(E)DI = Pointer to an 8 byte buffer to receive copy of descriptor - movl $ABS_PSP(descriptor_buf), %edi - pushw %es - pushw %ds - popw %es - int $0x31 #; call DPMI -// . = . - (ABS_PSP(.) - 0x2AE6) - popw %es - #; DS:DI points to buffer - - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit #; Cant_Enter_PMode - - #; Set Descriptor - movw $0x000C, %ax #; function number - movw ABS_PSP(selector_alloc1), %bx #; selector number - #; ES:(E)DI = Pointer to an 8 byte buffer that contains descriptor. - #; The type byte (byte 5) follows the same format and restrictions - #; as the access rights/type parameter (in CL) to Set Descriptor - #; Access Rights. The extended type byte (byte 6) follows the same - #; format and restrictions as the extended access rights/type parameter - #; (in CH) to Set Descriptor Access Rights, except the limit field may - #; have any value, except the low order 4 bits (marked "reserved") are - #; used to set the upper 4 bits of the descriptor's limit. - movl $ABS_PSP(descriptor_buf), %edi - pushw %es - pushw %ds - popw %es - int $0x31 #; call DPMI - popw %es - #; DS:DI points to buffer - - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit #; Cant_Enter_PMode - - movw ABS_PSP(selector_alloc1), %cx - incw %cx - testw $7, %cx - jnz message_exit - - movw ABS_PSP(selector_alloc1), %cx - movw %cx, %gs #; GS is the new selector - - #; Set Segment Base Address of gs - #; Sets the 32-bit linear base address field in the LDT descriptor - #; for the specified segment. - movw $0x0007, %ax #; function number - movw %gs, %bx #; selector number - #; CX:DX = 32-bit linear base address of segment - //movw ABS_PSP(conventional_linear), %dx - //movw ABS_PSP(conventional_linear + 2), %cx - //xorw %cx, %cx - //xorw %dx, %dx - xorl %ecx, %ecx - xorl %edx, %edx - movw ABS_PSP(real_mode_cs), %cx - //shll $4, %ecx - //movw %cx, %dx - //shrl $16, %ecx - movw %cx, %dx - shrw $12, %cx - shlw $4, %dx - int $0x31 #; call DPMI - - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit #; Cant_Enter_PMode - - #; adjust gs limit to 64K - #; AX = 0008h - #; BX = Selector - #; CX:DX = 32-bit segment limit - movw $0x0008, %ax #; function number - movw %gs, %bx #; selector number - movw $0x0000, %cx - movw $0xFFFF, %dx - int $0x31 #; call DPMI - - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit #; Cant_Enter_PMode - - xorl %ecx, %ecx - movl %gs, %ecx - lsll %ecx, %eax - jnz message_exit - - cmpl $0x0000FFFF, %eax - jnz message_exit - - movl ABS_PSP(ldt_base), %ebx - xorl %ecx, %ecx - movw ABS_PSP(selector_alloc1), %cx - andw $0xFFF8, %cx #; offset in LDT - addl %ecx, %ebx #; points to descriptor - - addr32 fs movb 5(%ebx), %al - xorb $0x60, %al - andb $0x60, %al - - jnz message_exit - - addr32 fs xorb $0x60, 5(%ebx) #; Let DPL=0 - -#if 0 - #; Set Protected Mode Interrupt Vector - #; - - movw $0x0205, %ax #; function number - movb $0x00, %bl #; Interrupt number - - #; CX:(E)DX = Selector:Offset of exception handler - xorl %edx, %edx - xorl %ecx, %ecx - - movw ABS_PSP(selector_alloc1), %cx - andw $0xFFFC, %cx - movw ABS_PSP(real_mode_cs), %dx - shll $4, %edx - addl $ABS_PSP(int3_handler), %edx - int $0x31 #; call DPMI - - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit #; Cant_Enter_PMode -#endif - - -// movw %cs, %cx -// incw %cx -// testw $7, %cx -// jnz message_exit - -#if 0 - //pushl %edx - sidt ABS_PSP(idtr) - //popl %edx #; EDX=IDT base address - - movl ABS_PSP(idtr + 2), %edx - - addl $(0x00 * 8), %edx - pushw %ds - movw $0x30, %cx - movw %cx, %ds - addr32 orw $0xE000, 4(%edx) - popw %ds - #; EBX=original offset of int3 service routine - -#endif - - /* we can use int00 instead of int03 */ - - xorw %bx, %bx - xorw %dx, %dx - movw $1, %ax -#if 0 - divw %bx -#else - int $0x00 -#endif - - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jmp message_exit #; Cant_Enter_PMode - -/* DPMI DATA */ - -dpmi_old_cr0: - .long 0 - -dpmi_old_cr3: - .long 0 - -ldt_base: - .long 0 - -conventional_linear: - .long 0 - -conventional_backup: - .long 0 - -descriptor_buf: - .long 0 - .long 0 - -selector_alloc: - .word 0 -selector_alloc1: - .word 0 -gdtr: - .word 0 - .long 0 - -idtr: - .word 0 - .long 0 - -/* VCPI DATA */ - -#; Even if you don't use TSS-based task-switching, you need one -#; TSS to hold the user stack pointer. -tss: - .word 0, 0 #; back link - - .long 0 #; ESP0 - .word gdt3 - gdt0, 0 #; SS0, reserved - - .long 0 #; ESP1 - .word 0, 0 #; SS1, reserved - - .long 0 #; ESP2 - .word 0, 0 #; SS2, reserved - - .long 0 #; CR3 - .long 0, 0 #; EIP, EFLAGS - .long 0, 0, 0, 0 #; EAX, ECX, EDX, EBX - .long 0, 0, 0, 0 #; ESP, EBP, ESI, EDI - .word 0, 0 #; ES, reserved - .word 0, 0 #; CS, reserved - .word 0, 0 #; SS, reserved - .word 0, 0 #; DS, reserved - .word 0, 0 #; FS, reserved - .word 0, 0 #; GS, reserved - .word 0, 0 #; LDT, reserved - .word 0, 0 #; debug, IO perm. bitmap - - .align 16 -#; null descriptor -gdt0: - .word 0 #; limit 15:0 - .word 0 #; base 15:0 - .byte 0 #; base 23:16 - .byte 0 #; type - .byte 0 #; limit 19:16, flags - .byte 0 #; base 31:24 -#; LINEAR_SEL equ $-gdt -gdt1: - .word 0xFFFF - .word 0 - .byte 0 - .byte 0x92 #; present, ring 0, data, expand-up, writable - .byte 0xCF #; page-granular, 32-bit - .byte 0 -#; CODE_SEL equ $-gdt -gdt2: - .word 0xFFFF - .word 0 - .byte 0 - .byte 0x9A #; present, ring 0, code, non-conforming, readable - .byte 0xCF #; page-granular, 32-bit - .byte 0 -#; DATA_SEL equ $-gdt -gdt3: - .word 0xFFFF - .word 0 - .byte 0 - .byte 0x92 #; present, ring 0, data, expand-up, writable - .byte 0xCF #; page-granular, 32-bit - .byte 0 -#; CODE_SEL16 equ $-gdt -gdt4: - .word 0xFFFF - .word 0 - .byte 0 - .byte 0x9A #; present, ring 0, code, non-conforming, readable - .byte 0 #; byte-granular, 16-bit - .byte 0 -#; DATA_SEL16 equ $-gdt -gdt5: - .word 0xFFFF - .word 0 - .byte 0 - .byte 0x92 #; present, ring 0, data, expand-up, writable - .byte 0 #; byte-granular, 16-bit - .byte 0 -#; TSS_SEL equ $-gdt -gdt6: - .word 103 - .word 0 - .byte 0 - .byte 0x89 #; Ring 0 available 32-bit TSS - .byte 0 - .byte 0 -#; VCPI_SEL equ $-gdt -gdt7: - .long 0, 0 #; dummy descriptors used by VCPI - - .long 0, 0 - - .long 0, 0 -gdt10_end: - -idt: - .rept 32 - - .word 0 #; low 16 bits of ISR address - .word gdt2 - gdt0 #; 32-bit code segment selector - .byte 0 #; word count - .byte 0x8E #; access byte: Present, Ring 0, '386 intr gate - .word 0 #; high 16 bits of ISR - - .endr -idt_end: - -gdt_ptr: - .word gdt10_end - gdt0 - 1 #; GDT limit - .long ABS_PSP(gdt0) #; linear, physical address of GDT - -idt_ptr: - .word idt_end - idt - 1 #; IDT limit - .long ABS_PSP(idt) #; linear, physical address of IDT - -real_idt_ptr: - .word 0x3FF #; limit 1023 - .long 0 #; IDT (IVT, actually) at address 0 - -#;krnl_page_table: -#; dw 0 - -vcpi_entry: - .long 0 - .word gdt7 - gdt0 #; dummy descriptors used by VCPI - -vcpi_cr0: - .long 0 - -vcpi_control_block: -vcpi_cr3: - .long 0 -vcpi_gdtr: - .long ABS_PSP(gdt_ptr) -vcpi_idtr: - .long ABS_PSP(idt_ptr) -vcpi_ldtr: - .word 0 -vcpi_tr: - .word gdt6 - gdt0 #; 32-bit TSS selector -vcpi_eip: - .long ABS_PSP(from_vcpi) -vcpi_cs: - .word gdt2 - gdt0 #; 32-bit code segment selector - -//page_info: -// .space 4096 #; padding to 4K boundary -// .space 4096 #; page dir somewhere in here -// .space 4096 #; "kernel" page table for bottom 4 meg - -#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -#; DATA -#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -PMode_Entry_Off: - .word 0 -PMode_Entry_Seg: - .word 0 - -windows_running: - .long 0 - -emm386_running: - .long 0 - -error_message: - .long 0 - -err_msg: - .ascii "\r\nIt is in VM86 mode but without VCPI. Enable VCPI with EMM386 and try again.\r\n" - .ascii "\r\nThis problem will occur when GRUB.EXE runs at the Command Prompt of Windows\r\n" - .ascii "NT/2K/XP. If so, restart the computer with a bootable DOS floppy and try again.\r\n$" - -win_msg: - .ascii "\r\nDue to a DPMI failure, GRUB.EXE cannot run in a Windows DOS box.\r\n" - .ascii "\r\nRestart the computer in MS-DOS mode and try again.\r\n$" - -warning_win_msg: - .ascii "\r\nRunning GRUB.EXE from a Windows DOS box could hang the machine!\r\n" - .ascii "\r\nYou should better restart the computer in MS-DOS mode and run GRUB.EXE there.\r\n" - .ascii "\r\n !!Save your work before you choose to continue!!\r\n$" - -cancel_msg: - .ascii "\r\n\r\nCancelled.\r\n$" - -vcpi_err_msg: - .ascii "\r\nError getting VCPI server entry point.\r\n$" - -int3_handler: - - /* it is our handler, int3 or int0 */ - - /* it seems our handler is in 16-bit protected mode */ - - .code16 - - cli -// jmp 0f -// -// #; simply return if we are in real mode -// incl %ebx -// xorw %dx, %dx -// xorw %ax, %ax -// -// iret -// -//0: - - #;jmp ring_check - -#; 5. clear the PE bit - movl %cr0, %eax - andb $0xFE, %al - movl %eax, %cr0 - - pushfw - popw %ax - testb $0x30, %ah /* IOPL */ - jz 4f - - /* IOPL is not 0 */ - andb $0xcf, %ah /* let IOPL = 0 */ - pushw %ax - popfw - pushfw - popw %ax - testb $0x30, %ah /* is IOPL still 0? */ - jz 2f /* CPL is 0 */ - jmp 3f -4: - /* IOPL is 0 */ - orb $0x30, %ah /* let IOPL != 0 */ - pushw %ax - popfw - pushfw - popw %ax - testb $0x30, %ah /* is IOPL still 0? */ - jnz 2f /* CPL is 0 */ - jmp 3f -3: - -// . = . - (ABS_PSP(.) - 0x2A36) - - /* CPL != 0 */ -#if 0 - movw $1, %bx - movw $0, %ax - movw $0, %dx - iret -#endif - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jmp message_exit #; Cant_Enter_PMode -2: - /* ring 0 of 16-bit protected mode will get here */ - andb $0xcf, %ah /* let IOPL = 0 */ - pushw %ax - popfw - - /* we are in 16-bit protected mode with CPL=0 */ -#if 0 - /* for debug only */ - movl $ABS_PSP(int3_handler), %eax - xorl %ecx, %ecx - movw ABS_PSP(real_mode_cs), %cx - shll $4, %ecx - addl %ecx, %eax - - addr32 fs cmpw $0xEBFA, (%eax) - jne 0f -// jmp real2 /* CPL = 0, Continue */ - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze -0: - jmp message_exit #; Cant_Enter_PMode -#endif - - /* now switch from privileged protected mode to real mode */ - - #; save old dpmi cr0 and cr3 - - movl $ABS_PSP(dpmi_old_cr0), %edi - movl %cr0, %eax - movl %eax, (%di) - xorl %esi, %esi - movw ABS_PSP(real_mode_cs), %si - shll $4, %esi - addl %esi, %edi -// . = . - (ABS_PSP(.) - 0x2BBA) - addr32 fs movl %eax, (%edi) - - movl $ABS_PSP(dpmi_old_cr3), %edi - movl %cr3, %eax - movl %eax, (%di) - xorl %esi, %esi - movw ABS_PSP(real_mode_cs), %si - shll $4, %esi - addl %esi, %edi - addr32 fs movl %eax, (%edi) - - #; get physical base address of page dir - andl $0xFFFFF000, %eax - - movw %ax, %cx - shrl $16, %eax - movw %ax, %bx - - #; Physical Address Mapping - #; - - #; To Call - - #; AX = 0800h - #; BX:CX = Physical address of memory - #; SI:DI = Size of region to map in bytes - - #; Returns - - #; If function was successful: - #; Carry flag is clear. - #; BX:CX = Linear address that can be used to access the physical memory - - #; If function was not successful: - #; Carry flag is set. - - movw $0x0800, %ax - movw $0x0000, %si - movw $0x1000, %di - - int $0x31 - - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit - - movw %bx, %si - shll $16, %esi - movw %cx, %si #; ESI=linear base address of page dir - - #; load the first entry - cld -// . = . - (ABS_PSP(.) - 0x2BE8) - addr32 fs lodsl - - pushl %eax - - #; copy all page dir entries except the first one - movw %es, %ax - movw %fs, %bx - movw %bx, %es - movl $(1024 - 1), %ecx - movl ABS_PSP(vcpi_cr3), %edi - addl $4, %edi - cld - repz addr32 fs movsl - movw %ax, %es - - popl %eax - - #; get physical base address of the first page table - andl $0xFFFFF000, %eax - - movw %ax, %cx - shrl $16, %eax - movw %ax, %bx - - #; Physical Address Mapping - #; - - #; To Call - - #; AX = 0800h - #; BX:CX = Physical address of memory - #; SI:DI = Size of region to map in bytes - - #; Returns - - #; If function was successful: - #; Carry flag is clear. - #; BX:CX = Linear address that can be used to access the physical memory - - #; If function was not successful: - #; Carry flag is set. - - movw $0x0800, %ax - movw $0x0000, %si - movw $0x1000, %di - - int $0x31 - - movw $ABS_PSP(win_msg), %dx #; yup, it's 'Doze - jc message_exit - - movw %bx, %si - shll $16, %esi - movw %cx, %si #; ESI=linear base address of the first page table - - #; skip the leading 160 page table entries - addl $(160 * 4), %esi #; 160 = 640K / 4K - - #; copy the rest of the page table entries - movw %es, %ax - movw %fs, %bx - movw %bx, %es - movl $(1024 - 160), %ecx - movl ABS_PSP(vcpi_cr3), %edi - addl $(4096 + (160 * 4)), %edi - cld - repz addr32 fs movsl - movw %ax, %es - -#if 1 - #; move 640K linear conventional memory to physical 0 - - cld - movw %es, %ax - movw %fs, %bx - movw %bx, %es - movl ABS_PSP(conventional_backup), %edi - xorl %esi, %esi - movl $(0xA0000 / 4), %ecx - repz addr32 fs movsl - - movl ABS_PSP(conventional_linear), %edi - movl ABS_PSP(conventional_backup), %esi - movl $(0xA0000 / 4), %ecx - repz addr32 fs movsl - movw %ax, %es - -#else - #; move only the grub.exe image from linear to physical - - movw %es, %ax - movw %fs, %bx - movw %bx, %es - - movl $((ABS_PSP(STAGE2_SIZE + pre_stage2_start + 15 + 0x10000 + 0x03000) / 16) * 4), %ecx - #; 0x10000 = 64KB for HMA_backup - #; 0x03000 = 12KB for VCPI page_info - movl ABS_PSP(conventional_linear), %edi - xorl %esi, %esi - movw ABS_PSP(real_mode_cs), %si - shll $4, %esi - addl %esi, %edi - - cld - repz addr32 fs movsl - movw %ax, %es -#endif - - #; load cr3 - movl ABS_PSP(vcpi_cr3), %eax - movl %eax, %cr3 - - #; now the low 640K is identity-mapped - -#; back-to-real-mode sequence from 14.5 of 386INTEL.TXT -#; 1. TURN OFF PAGING -#; 1a. jump to code memory which is identity-mapped - - /* Load new GDT. All memory references should be limited in - * conventional memory, i.e., lower than physical address 640K. - */ - - lgdt ABS_PSP(gdt_ptr) - ljmp $(gdt4 - gdt0), $ABS_PSP(2f) #; 16-bit code segment -2: - -#; 1b. clear the PG bit - movl %cr0, %eax - andl $0x7FFFFFFF, %eax - movl %eax, %cr0 - -#; 1c. "Move zeros to CR3 to clear out the paging cache." - xorl %eax, %eax - movl %eax, %cr3 -#; 2. jump to 16-bit code segment - //ljmp $(gdt4 - gdt0), $ABS_PSP(real2) - // #; (gdt4 - gdt0) is 16-bit code segment selector - - #; we are already in 16-bit code segment - jmp real2 - - - .code16 - -#; Protected mode initialization code would go here. -#; Mark program's real mode memory as pageable, etc. -#; -#; . -#; . -#; . - -#; -#; Quit the program and return to real mode DOS -#; -#; mov ax, 4C00h -#; int 21h - -check_vcpi: - -#; if it's EMM386, we can use VCPI to switch to protected mode -#; Testing for VCPI like this makes Win95 pop up a dialog suggesting -#; "MS-DOS mode". This may or may not be a good thing. - movw $0xDE00, %ax - pushl %ebx #; save EBX; not interested in VCPI version - pushw %es - pushl %edi - int $0x67 - popl %edi - popw %es - popl %ebx - cmpb $0, %ah - movw $ABS_PSP(err_msg), %dx -#if 1 - jne message_exit # no VCPI; Windows NT/2K/XP -#else - jne check_dpmi # no VCPI; Windows NT/2K/XP - # DPMI for NT/2K/XP does not work :-( -#endif -#; get "kernel" page table and partial GDT from the VCPI server. -#; If we set up our own identity-mapped page table, this step is optional. -#; (we still need to do INT 67h AX=DE01h to get the pmode entry -#; point to the VCPI server -- so we can return to V86 mode later) - - #; ES:DI points to buffer for "kernel" page table - #; DS:SI points to buffer for 3 entries in GDT - - movw $ABS_PSP(gdt7), %si #; dummy descriptors used by VCPI - movw $0xDE01, %ax - pushl %ebx - //pushl %edi - int $0x67 - movl %ebx, ABS_PSP(vcpi_entry) - //popl %edi - popl %ebx - cmpb $0, %ah - movw $ABS_PSP(vcpi_err_msg), %dx - jne message_exit - -#; set up the VCPI control block for the switch to pmode - addl %ebx, ABS_PSP(vcpi_gdtr) - addl %ebx, ABS_PSP(vcpi_idtr) - -#; disable interrupts - cli - -#; OK, let's do it - movl $ABS_PSP(vcpi_control_block), %esi - addl %ebx, %esi - movw $0xDE0C, %ax -#; if all goes well, the interrupt will return at 'from_vcpi' - int $0x67 - -#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -#; MAIN 32-BIT PMODE CODE, here from VCPI -#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -from_vcpi: - - /* This is in 32-bit protected mode. CS=(gdt2 - gdt0) */ - - .code32 - -//1: jmp 1b - movw $(gdt3 - gdt0), %ax #; 32-bit data segment - movw %ax, %ss - movw %ax, %ds - movw $(gdt1 - gdt0), %ax #; 4GB, 32-bit data segment, base 0 - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - -#; call draw_lines - -#; save pmode registers - movl %cr0, %eax - movl %eax, ABS_PSP(vcpi_cr0) - #; movl %cr3, %eax - #; movl %eax, ABS_PSP(pmode_cr3) -#; save GDTR LDTR IDTR - #; (needn't do) - -#; back-to-real-mode sequence from 14.5 of 386INTEL.TXT -#; 1. TURN OFF PAGING -#; 1a. jump to code memory which is identity-mapped - #; (already done) -#; 1b. clear the PG bit - movl %cr0, %eax - andl $0x7FFFFFFF, %eax - movl %eax, %cr0 - -#; 1c. "Move zeros to CR3 to clear out the paging cache." - xorl %eax, %eax - movl %eax, %cr3 -#; 2. jump to 16-bit code segment (real2 is above, in the BITS 16 section) - ljmp $(gdt4 - gdt0), $ABS_PSP(real2) #; 16-bit code segment - -#; enter real mode -#; mov eax, cr0 -#; and eax, 7ffffffeh ; turn off paging -#; mov cr0, eax ; enter real mode -#; xor eax, eax -#; mov cr3, eax ; flush the TLB - -#; return to protected mode - -#; restore pmode registers - - -#; we jump here (in 16-bit pmode) when returning to real mode -#; Back-to-real-mode sequence from 14.5 of 386INTEL.TXT: -#; 3. load segment registers with values "appropriate to real mode" -real2: - - /* This is in 16-bit protected mode */ - - .code16 - -// . = . - (ABS_PSP(.) - 0x2A84) - - movw $(gdt5 - gdt0), %ax #; 16-bit data segment selector - movw %ax, %ss - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs -#; 4. disable interrupts - #; (already done) -#; 5. clear the PE bit - movl %cr0, %eax - andb $0xFE, %al - movl %eax, %cr0 - -#; 6. far jump to true real mode - -#if 0 - #; movw $ABS_PSP(real3), ABS_PSP(real_mode_ip) - ljmp *ABS_PSP(real_mode_ip) -#else - .byte 0xEA #; ljmp $CURR_CS, $ABS_PSP(real3) -#endif -real_mode_ip: - .word ABS_PSP(real3) -real_mode_cs: - .word 0 #; filled earlier with the current CS value - -#; 7. load an IDT that is compatible with real-mode IVT -real3: - - /* This is in real mode */ - - .code16 - - /* Note: DS is still of protected mode but working */ - - lidt ABS_PSP(real_idt_ptr) - -#; 9. restore real-mode segment registers - movw %cs, %ax - movw %ax, %ss - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - -#; we are in real mode, run grub as normal :-) -#; remember to restore our stack pointer for quit_address to work well - movw $ABS_START(dos_stack), %sp - - #; initialize EFLAGS - pushl $0 - popfl - -#if 1 - cmpl $0, ABS_START(windows_running) - je 1f - - /* this is needed for booting via win98 */ - - xorw %ax, %ax - - /* init DMA, stolen from bochs(rombios.c) */ - - #; first reset the DMA controllers - outb %al, $0x0D #; disable DMA-1 - outb %al, $0xDA #; disable DMA-2 - movl $2, %ecx # delay at least 2 microseconds - call iodelay - - #; then initialize the DMA controllers - movb $0xC0, %al #; cascade mode of channel 4 enabled - outb %al, $0xD6 #; DMA-2 mode register - movb $0x00, %al #; unmask channel 4 - outb %al, $0xD4 #; DMA-2 mask register - movl $2, %ecx # delay at least 2 microseconds - call iodelay -1: -#endif - - #; initialize PIC here - #; Note that the code for init_pic is shared. It can be called when - #; grub.exe is running both from dos and from kexec on linux. - call init_pic - -#if 0 - #; disable DMA - movb $0, %al - outb %al, $0x0D #; disable DMA-1 - outb %al, $0xDA #; disable DMA-2 - movl $2, %ecx # delay at least 2 microseconds - call iodelay - - #; system clock 0 set to mode 3 - movb $0x16, %al #; 8-bit command, mode 3, binary data - outb %al, $0x43 #; sent to mode control port - movl $2, %ecx # delay at least 2 microseconds - call iodelay - - movb $0, %al #; data 0 for 18.2Hz - outb %al, $0x40 #; save to clock 0 - movl $2, %ecx # delay at least 2 microseconds - call iodelay -#endif - -#if 1 - cmpl $0, ABS_START(windows_running) - je 1f - - /* this is needed for booting via win98 */ - - /* EISA 8259-1 */ - /* init system timer 0 (stolen from bochs rombios.c) */ -#if 0 - movb $0x34, %al # system timer 0, 16-bit binary count, mode 2 -#else - /* system timer 0 should be in mode 3 */ - movb $0x36, %al # system timer 0, 16-bit binary count, mode 3 -#endif - movw $0x43, %dx - call outb_and_delay - - movb $0x00, %al # maximum count of 0000H = 18.2Hz - movw $0x40, %dx - call outb_and_delay # write lo byte 00 - call outb_and_delay # write hi byte 00 - - /* disable NMI */ - orb $0x80, %al - outb %al, $0x70 - movl $2, %ecx # delay at least 2 microseconds - call iodelay -1: -#endif - -#if 1 - cmpl $0, ABS_START(windows_running) - je 1f - - /* this is needed for booting via win98 */ - - /* EISA 8259-1 */ - movw $0x4D0, %dx - inb %dx, %al - movw $0x21, %dx # mask off level-triggerred IRQs - call outb_and_delay - - /* EISA 8259-2 */ - movw $0x4D1, %dx - inb %dx, %al - movw $0xA1, %dx # mask off level-triggerred IRQs - call outb_and_delay -1: -#endif - -#if 0 - /* debug check for a working emm386 VCPI */ - jmp message_exit1 -#endif - - cmpl $0, ABS_START(windows_running) - jne restore_BIOS_environment # no backup 64K DOS memory - jmp backup_low_memory_and_HMA - - -//---------------------------------------------------------------------------- - .align 4 -options_doing: - .long 0 -options_done: - .long 0 - - .align 4 -option_bypass_dos: - .ascii "--bypass" -option_bypass_dos_end: - .align 4 -bypass: - .long 0 -option_bypass1_dos: - .ascii "--BYPASS" -option_bypass1_dos_end: - .align 4 -time_out: - .long 0x80000000 -option_time_out_dos: - .ascii "--time-out=" -option_time_out_dos_end: - .align 4 -option_time_out1_dos: - .ascii "--TIME-OUT=" -option_time_out1_dos_end: - .align 4 -hot_key: - .long 0xffff3920 -option_hot_key_dos: - .ascii "--hot-key=" -option_hot_key_dos_end: - .align 4 -option_hot_key1_dos: - .ascii "--HOT-KEY=" -option_hot_key1_dos_end: - .align 4 -option_duce_dos: - .ascii "--duce" -option_duce_dos_end: - .align 4 -duce: - .long 0 -option_duce1_dos: - .ascii "--DUCE" -option_duce1_dos_end: - .align 4 -option_chs_no_tune_dos: - .ascii "--chs-no-tune" -option_chs_no_tune_dos_end: - .align 4 -chs_no_tune: - .long 0 -option_chs_no_tune1_dos: - .ascii "--CHS-NO-TUNE" -option_chs_no_tune1_dos_end: - .align 4 -option_keep_pxe_dos: - .ascii "--keep-pxe" -option_keep_pxe_dos_end: - .align 4 -keep_pxe: - .long 0 -option_keep_pxe1_dos: - .ascii "--KEEP-PXE" -option_keep_pxe1_dos_end: - .align 4 -option_config_file_dos: - .ascii "--config-file=" -option_config_file_dos_end: -default_config_file_dos: - .ascii "/menu.lst" -default_config_file_dos_end: - - .byte 0 /* mark the end of ascii zero string */ - - /* bad DOS pathname delimiter! Don't use single back slash by mistake! */ - -default_config_file_dos2: - .ascii "\\menu.lst\0" /* use double back slashes */ - -default_config_file_dos1: - .ascii ".\\menu.lst\0" /* use double back slashes */ - -usage_string: /* DOS string terminator is dollar($), not the null char */ - .ascii "\r\nGRUB: Unrecognized or failed command line parameters. Usage:\r\n" - .ascii "\tGRUB [OPTIONS]\r\n" - .ascii "OPTIONS: --bypass, --time-out=T, --hot-key=K, --duce, --chs-no-tune,\r\n" - .ascii "OPTIONS: --keep-pxe, --config-file=\"FILE\"\r\n" - .ascii "The options are case-sensitive, you must use lower-case letters. Each\r\n" - .ascii "option can be specified only once at most.\r\n" - .ascii "FILE can be specified in GRUB or DOS style. If FILE is led by the pair '#@',\r\n" - .ascii "then a DOS filename follows.\r\n" - .ascii "FILE can also be some GRUB commands delimited by semi-colon, or the whole\r\n" - .ascii "content of a menu file(again semi-colon delimits each line of the menu file).\r\n" - .ascii "FILE can be double-quoted(this is recommended, especially for use as embedded\r\n" - .ascii "commands or menu). Hexdump of command-line buffer in PSP:\r\n$" - -fatal_string: - .ascii "\r\nFatal error: filename too long!\r\n$" - -dos_unsupport_string: -#ifdef BAD_BIOS - .ascii "\r\nSorry! Only MS-DOS 7+ and FreeDOS are supported.\r\n\r\nPrograms such as TSRs and device drivers may also change the BIOS interrupt\r\nvector table. Make sure those programs are not running, then try again.\r\n$" -#else - .ascii "\r\nFailure restore ROM INT 0xHH vector. Unsupported DOS, device driver, or TSR.\r\n$" -#endif - -failed_BDA_EBDA_string: - .ascii "\r\nFailure restore BDA/EBDA. Unsupported DOS, device driver, or TSR.\r\n$" - -#if 0 -A20_crash_string: - .ascii "\r\nGRUB.EXE: About to turn on A20. Report bug if crashing. CR0=0x$" -#endif - -//check_bootable_cdrom_string: -// .ascii "\r\nAbout to check bootable CDROM disk emulation...\r\n$" -//terminate_cdrom_emulation_string: -// .ascii "\r\nAbout to terminate CDROM disk emulation...\r\n$" -//check_bootable_cdrom_done_string: -// .ascii "\r\nBootable CDROM check is done\r\n$" - -press_space_bar_string: - .ascii "\r\nPress space bar$" - -press_hot_key_string: - .ascii "\r\nPress your hot-key$" - -press_any_key_string: - .ascii " to start GRUB, any other key to bypass GRUB ...$" - - .align 4 - -//mapped_int13_vector_BIOS: -// .word 0 /* hooked int13 segment */ -// .word 0 /* low mem in K before int13 hook */ -// .long 0 /* original BIOS int13 vector if non-zero */ -stage2_64K_pages: - .long (STAGE2_SIZE + 0x1010 + 0x200 + 0xffff) >> 16 -//boot_drive: -// .long 0x80 /* default boot drive is (hd0) */ -a20_status: - .long 0 - -sleep_5_seconds: - - .code16 - - /* sleep 5 seconds */ - - /* sleep forever if ABS_PSP(time_out) is 0xff */ - - /* calculate the timeout ticks */ - - pushw %es - pushw %ds - pushl %edx - - pushw %ds - popw %es - - movl $0xffffffff, %edx - movzbl ABS_PSP(time_out), %eax - cmpb $0xff, %al - je 1f - movl $18, %edx /* 18.2 ticks per second. We simply use 18. */ - mulw %dx /* EDX=0, EAX=ticks */ - xchgw %ax, %dx /* EAX=0, EDX=ticks */ -1: - xorw %ax, %ax - movw %ax, %ds /* DS=0 */ - movl 0x46c, %eax /* initial tick */ - movl %eax, %ecx /* ECX=initial tick */ - testl %edx, %edx - js 1f - addl %edx, %eax /* EAX=timeout tick */ - jmp 3f -1: - movl %edx, %eax /* EAX=0xffffffff */ -3: - movl 0x46c, %ebx /* EBX=current tick */ - cmpl %ecx, %ebx - jnb 2f - - /* current tick is less than initial tick, this means the ticks have - * overflowed to the next day, and EBX is rather small. */ - xorl %ecx, %ecx - movl %edx, %eax -2: - /* check if there is any key press. */ - pushl %eax - movb $1, %ah - int $0x16 - pushw %ax - pushfw - - movb $0x11, %ah - int $0x16 - jnz 1f - popfw - jnz 2f - - /* no, there is no key press. */ - - popw %ax - popl %eax - cmpl %eax, %ebx /* timeout? */ - jbe 3b /* no, continue to wait */ - - /* timeout reached, CF=0, no key pressed. */ - /* `above' for no key */ - popl %edx - popw %ds - popw %es - ret -1: - popfw -2: - /* yes, there is a key press. */ -#if 0 - /* clear the keyboard buffer */ - movb $1, %ah - int $0x16 - jz 1f /* no keys, end */ - movb $0, %ah - int $0x16 /* discard the key */ - jmp 1b -1: -#endif - - /* check if it is the desired key. */ - - /* DS=0, but ES=old DS on stack */ - - xorw %es:ABS_PSP(hot_key), %ax /* CF=0 */ - popw %ax - - je 1f - xorw %es:ABS_PSP(hot_key), %ax /* CF=0 */ - jne 2f /* not desired, return CF=0 */ - - /* remove the desired key from the keyboard buffer. */ - - pushfw - movb $0, %ah - int $0x16 /* discard the key */ - popfw - jmp 3f - -1: - /* remove the desired key from the keyboard buffer. */ - - pushfw - movb $0x10, %ah - int $0x16 /* discard the key */ - popfw -3: - stc /* CF=1, the desired key pressed */ -2: - cmc - - /* `equal' for hot key, `below' for other key */ - - popl %eax - popl %edx - popw %ds - popw %es - ret - -//check_a_range_of_ROM_vectors: -// cld -// lodsl -// cmpl $0xC0000000, %eax /* ROM vectors assumed to be above C000:0 */ -// jb 1f /* check failed, with carry */ -// loop check_a_range_of_ROM_vectors -// clc /* check passed, with no carry */ -//1: ret - -# Descriptor tables -# -# NOTE: The intel manual says gdt should be sixteen bytes aligned for -# efficiency reasons. However, there are machines which are known not -# to boot with misaligned GDTs, so alter this at your peril! If you alter -# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two -# empty GDT entries (one for NULL and one reserved). -# -# NOTE: On some CPUs, the GDT must be 8 byte aligned. This is -# true for the Voyager Quad CPU card which will not boot without -# This directive. 16 byte aligment is recommended by intel. -# - .align 16 -dos_gdt: - /* this is the default null entry in GDT */ - .word dos_gdt_end - dos_gdt - 1 # gdt limit - .long 0 # linear address of dos_gdt - .word 0 # pad 2 bytes - - .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) - .word 0 # base address = 0 - .word 0x9200 # data read/write - .word 0x00CF # granularity = 4096, 386 - # (+5th nibble of limit) -// /* real mode data segment base=0x200000 */ -// .word 0xFFFF, 0 -// .byte 0x20, 0x92, 0, 0 - - /* real mode data segment base=0 */ - .word 0xFFFF, 0 - .byte 0, 0x92, 0, 0 - -dos_gdt_end: - -quit_address: - - .code16 - - cli - cld - movw %cs, %ax - movw %ax, %ss - movw $(ABS_START(dos_stack) - 36), %sp - popal - popw %es - popw %ds - - /* restore High Memory Area */ - pushw %ds - pushw %es - movw %ds, %ax - addw $(HMA_backup + 1), %ax - movw %ax, %ds /* DS:0 is (CS + HMA_backup):0010 */ - xorw %si, %si - movw $0xFFFF, %di - movw %di, %es /* ES=0xFFFF */ - movw $0x0010, %di - movw $(0x4000-4), %cx /* move 64KB -16Bytes */ - repz movsl - popw %es - popw %ds - -message_exit1: - - .code16 - -#; if we had escaped from emm386, we should go back to pmode - cmpl $0, ABS_PSP(emm386_running) - jne 1f - - /* No emm386, normal exit to real-mode dos. */ - - movw $0x0003, %ax /* set display mode: 80*25 color text */ - int $0x10 - - movl ABS_PSP(error_message), %edx - testl %edx, %edx - jnz message_exit /* error */ - - movw $0x4c00, %ax /* exit with error number 00 */ - //int $0x21 /* call DOS */ - jmp terminate_program - -1: - /* emm386 was running and we need to restore its VM86 environment. */ - - /* print a debug message */ - movw $0x0e58, %ax /* print an 'X' */ - int $0x10 - -#; set vital registers: page directory base register(CR3) - movl ABS_PSP(vcpi_cr3), %eax - movl %eax, %cr3 -#; ...GDTR and IDTR - cli /* in case interrupt was enabled. */ - lgdt ABS_PSP(gdt_ptr) - lidt ABS_PSP(idt_ptr) -#; ...enable paging and pmode - movl ABS_PSP(vcpi_cr0), %eax - movl %eax, %cr0 -#; far jmp to 32-bit pmode code segment to return to vm86-mode DOS - ljmp $(gdt2 - gdt0), $ABS_PSP(1f) #; 32-bit code segment - -1: -############################################################################## - - /* This is in 32-bit protected mode. CS=(gdt2 - gdt0) */ - - /* Will switch to VM86 mode and go back to DOS in VM86 mode */ - - .code32 - - movw $(gdt3 - gdt0), %ax #; 32-bit data segment - movw %ax, %ds - movw %ax, %ss - movl $ABS_START(dos_stack), %esp - - movw $(gdt1 - gdt0), %ax #; 4GB, 32-bit data segment, base 0 - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - - #; movl ABS_PSP(vcpi_cr3), %eax - #; movl %eax, %cr3 - #; movl ABS_PSP(vcpi_cr0), %eax - #; movl %eax, %cr0 - -#if 0 - /* FreeDOS has not a working VCPI with EMM386 */ - jmp 1f -#endif - -#; return to V86 mode - movl $0xDE0C, %eax - -#; from E-67DE0C of Ralf Brown's list: -#; DS = segment selector mapping entire linear -#; address space obtained via AX=DE01h -#; I'm not sure what that means, but I peeked inside EMM386.EXE, -#; and it sets DS for me, so I don't have to. - - movzwl ABS_PSP(real_mode_cs), %ebx - movl %esp, %ebp - pushl %ebx #; GS - pushl %ebx #; FS - pushl %ebx #; DS - pushl %ebx #; ES - - pushl %ebx #; SS - pushl %ebp #; ESP - pushl $0x00023002 #; EFLAGS - - pushl %ebx #; CS - pushl $ABS_PSP(1f) #; EIP - - movw $(gdt7 - gdt0), %bx #; dummy descriptors used by VCPI - movw %bx, %ds - - lcall %cs:*ABS_PSP(vcpi_entry) - - /* will return to VM86 mode below */ - - #; should not reach this - - // in case VCPI returns failure, go to real mode and print a message. - //jmp from_vcpi - - /* end of 32-bit code segment of switch to vm86 mode */ -############################################################################## - -1: - /* This is in VM86 mode */ - - /* Will return to DOS in VM86 mode(terminate normally). */ - - .code16 - -#if 0 -#undef debug_putchar -#define debug_putchar(x) movw $(x | ((x << 12) & 0xF000) | (((x << 8) & 0x0F00) ^ 0xC00)), (0x140 + (((x - 0x30) % 80) * 2)) - - movw $0xB800, %ax - movw %ax, %ds - - debug_putchar ('2') - debug_putchar ('3') - debug_putchar ('4') - debug_putchar ('5') -#endif - movw %cs, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - movw %ax, %ss - movw $ABS_START(dos_stack), %sp - - movw $0x0003, %ax /* set display mode: 80*25 color text */ - int $0x10 - -#if 0 - /* print a debug message */ - movw $0x0e59, %ax /* print a 'Y' */ - int $0x10 -#endif - - movl ABS_PSP(error_message), %edx - testl %edx, %edx - jnz message_exit /* error */ - - movw $0x4c00, %ax /* exit with error number 00 */ - //int $0x21 /* call DOS */ - jmp terminate_program - -# The mode switch series completed -############################################################################## - -#if 0 -display_word: - - .code16 - - /* routine for display hex value of BP */ - pushaw - xorw %bx, %bx - movw %bp, %ax - shrw $12, %ax - cmpb $9, %al - jbe 1f - addb $7, %al -1: - addb $0x30, %al - movb $0x0e, %ah - int $0x10 - - movw %bp, %ax - shrw $8, %ax - andb $0x0f, %al - cmpb $9, %al - jbe 1f - addb $7, %al -1: - addb $0x30, %al - movb $0x0e, %ah - int $0x10 - - movw %bp, %ax - shrw $4, %ax - andb $0x0f, %al - cmpb $9, %al - jbe 1f - addb $7, %al -1: - addb $0x30, %al - movb $0x0e, %ah - int $0x10 - - movw %bp, %ax - andb $0x0f, %al - cmpb $9, %al - jbe 1f - addb $7, %al -1: - addb $0x30, %al - movb $0x0e, %ah - int $0x10 - popaw - ret -#endif - -backup_low_memory_and_HMA: - - .code16 - -#if 0 - movw $ABS_PSP(A20_crash_string), %dx - movb $0x09, %ah /* display a dollar terminated string */ - int $0x21 /* call DOS */ - - movl %cr0, %eax - - movw $0x4D1, %dx - inb %dx, %al - movb %al, %ah - movw $0x4D0, %dx - inb %dx, %al - movl %eax, %ebp - - shrl $16, %ebp - - call display_word - - movl %eax, %ebp - - call display_word -#endif - -//--------------------------------------------------------------------------- -#if 1 - /* if time-out is not 0, sleep */ - movw ABS_PSP(time_out), %cx - jcxz 2f - - sti /* for sleep_5_seconds to work. */ - - call sleep_5_seconds - - //cli /*2008-08-04*/ /* the clock is not used any more */ - - je 1f /* desired hot-key pressed */ - jb message_exit1 /* another key pressed */ - - /* timeout reached */ -2: - cmpl $0, ABS_PSP(bypass) /* default is bypass GRUB? */ - jne message_exit1 /* yes, exit to DOS */ - /* no, continue to run grub */ -1: -#endif -//--------------------------------------------------------------------------- -#if 0 - movl $0x04000000, %ecx -1: - addr32 loop 1b -#endif - - /* enable A20! */ - - /* oh! it seems we MUST cli, because DOS might enable/disable A20 - * when entering/leaving DOS interrupt service routine which is - * loaded in the High Memory Area. - * - * We should asure A20 keeps ON when we backup HMA! - */ - - - //cli /* marked off 2008-08-04 */ - - movw $0x00ff, %cx # try so many times on failure - movw $0x0101, %dx # with a20 debug on - - /* Note for people who are tracing/debugging this program: - * - * ENABLE_DISABLE_A20 is not likely what you want to trace into. - */ - -#if 1 - call enable_disable_a20 - movw $ABS_PSP(a20_control_fail_string), %dx - jnz message_exit /* enable a20 failed */ - //jz exit_no_message /* A20 disabled */ -#endif - -#if 0 /* marked off 2008-08-04 */ - //pushw ABS_PSP(time_out) - movw $1, ABS_PSP(time_out) /* sleep 1 second after A20 control */ - - sti /* for sleep_5_seconds to work. */ - - call sleep_5_seconds - - //cli /*2008-08-04*/ /* the clock is not used any more */ - //popw ABS_PSP(time_out) -#endif - -#if 0 - /* now A20 is on */ - decl ABS_PSP(a20_status) # let it be 0xFFFFFFFF -#else - /* save the current gateA20 status */ - xorl %eax, %eax - movl %eax, ABS_PSP(a20_status) - - /* check A20 status again to confirm */ - - call a20_test /* ZF=0 for A20 enabled, ZF=1 for disabled */ - movw $ABS_PSP(a20_control_fail_string), %dx -// jz 1f /* A20 disabled */ - jz message_exit /* enable a20 failed */ - - /* now A20 is on */ - decl %eax /* EAX=0xFFFFFFFF */ - movl %eax, ABS_PSP(a20_status) -1: -#endif - - - /* backup High Memory Area to HMA_backup */ - - pushw %ds - pushw %es - movw $0xFFFF, %ax - movw %ax, %ds /* DS=0xFFFF(i.e., HMA segment) */ - - /* HMA_backup is the destination address */ - movw %es, %ax - addw $(HMA_backup), %ax - movw %ax, %es - - movw $0x4000, %cx /* 0x4000 dwords= 64KB */ - xorw %si, %si - xorw %di, %di - cld - repz movsl - popw %es - popw %ds - - /* HMA backup is done, so it is safe now to sti. But this could - * cause A20 off, even keyboard off. So we don't sti until DOS - * has totally gone. - */ - //sti - - - /* save 640KB conventional memory(surely, including 64K at HMA_backup) - * to physical address 0x200000=2MB, so we could restore our DOS - * memory later. - */ - - /* fill gdt base first thing! */ - xorl %eax, %eax - movw %ds, %ax - shll $4, %eax - addl $ABS_PSP(dos_gdt), %eax - movl %eax, ABS_PSP(dos_gdt) + 2 - - /* DS=ES */ - - /* Save all registers on stack, which quit_address will use to - * restore registers after pre_stage2 calls quit. - */ - - pushw %ds - pushw %es - pushal - //movw %es, %bx # save old ES to BX - movl ABS_PSP(a20_status), %edx - - cli - lgdt ABS_PSP(dos_gdt) - - /* Note for people who are tracing/debugging this program: - * - * This will switch to protected mode! Don't single step it! - * - * Set break point at restore_BIOS_environment, and go! - */ - - movl %cr0, %eax - orb $1, %al - movl %eax, %cr0 - - /* Here the CPU is in protected mode. The real mode interrupt - * vector table won't work now. - * - * Note that the CS segment is still 16-bit because we have not - * reloaded CS with a 32-bit segment selector. - */ - - jmp 1f -1: - movw $8, %si # 4GB limit - movw %si, %es - movw %si, %ds - - xorl %ebp, %ebp - xorl %esi, %esi - movl $0x200000, %edi - movl $(0xA0000 / 4), %ecx # move 640K - - cld -1: - addr32 lodsl (%esi) - addl %eax, %ebp - addr32 stosl (%edi) - addr32 loop 1b - //decl %ecx - //jnz 1b - - movl $0x50554B42, %eax # "BKUP" - addl %eax, %ebp - addr32 stosl (%edi) - xchgl %eax, %edx - addl %eax, %ebp - addr32 stosl (%edi) - movw %cs, %ax - shll $16, %eax - movw $ABS_START(quit_address), %ax - addl %eax, %ebp - addr32 stosl (%edi) - - xchgl %eax, %ebp - negl %eax - addr32 stosl (%edi) - - movw $16, %si # get real mode 64K segment limit - movw %si, %es - movw %si, %ds - - movl %cr0, %eax - andb $0xfe, %al - movl %eax, %cr0 - - jmp 1f -1: - /* Here the CPU turns back to real mode. The real mode interrupt - * vector table should work now. - * - * Note that the CS segment is still 16-bit because we have not - * reloaded CS with a 32-bit segment selector. - */ - - //jmp 1b - //movw %bx, %es # restore ES from BX - //movw %bx, %ds # restore DS from BX - sti /* added 2008-08-04 */ - popal - popw %es - popw %ds - - -restore_BIOS_environment: - - /* Now we should be safely in real mode. But if emm386_running, - * the probe_int should have been called while in VM86 mode, - * and we shouldn't call it once more. - */ - - cmpl $0, ABS_PSP(emm386_running) - jne 1f - - /* Note for people who are tracing/debugging this program: - * - * PROBE_INT will take over int01, so probably you don't want - * to trace into PROBE_INT. - */ - - call probe_int - - jc failed_probe_int - -1: - - /* Note for people who are tracing/debugging this program: - * - * restore_BDA_EBDA will destroy the DOS memory structure, - * i.e., the MCB (Memory Control Block). - * - * If you trace into restore_BDA_EBDA now, DOS could hang - * when you quit the debugger. - */ - - call restore_BDA_EBDA - - jc failed_restore_BDA_EBDA - - /* Note for people who are tracing/debugging this program: - * - * Oh! Don't continue. The interrupt vector table will be changed! - * The DOS(especially with your debugger!) will disappear! - * It will be overwritten by the GRUB code and data of pre_stage2. - * After pre_stage2 gains control, the processor will switch to - * protected mode. - */ - - /* overwrite 1 sector of IVT with the new bios_interrupt_vector_table */ - movw %cs, %ax - movw %ax, %ds - movw $ABS_START(bios_interrupt_vector_table), %si - xorw %di, %di /* ES:DI=0000:0000 */ - movw %di, %es - movw $0x80, %cx - - cli - cld - repz movsl - sti /* added 2008-08-04 */ - -#if 0 /* marked out in 2008-05-07 */ - /* restore int 13 and int 15 for disk emulation */ - movl ABS_START(tmp_int13_vector), %eax - cmpl $0x5A000000, %eax // cmpl $0x9A000000, %eax - jb 1f - movw $0x4C, %di - stosl - - movl ABS_START(tmp_int15_vector), %eax - cmpl $0x5A000000, %eax // cmpl $0x9A000000, %eax - jb 1f - movw $0x54, %di - stosl -1: -#endif - jmp move_stage2_image - -failed_probe_int: - /* probe failure */ - movw %cs, %ax - movw %ax, %ds - movw %ax, %es -#ifndef BAD_BIOS - xchgw %ax, %cx # move CL to AL - xorb %ah, %ah - movb $16, %cl - divb %cl # quo=AL, rem=AH - orw $0x3030, %ax - - cmpb $0x39, %ah - jbe 1f - addb $7, %ah -1: - cmpb $0x39, %al - jbe 1f - addb $7, %al -1: - movw %ax, ABS_START(dos_unsupport_string) + 28 -#endif - movl $ABS_START(dos_unsupport_string), ABS_PSP(error_message) - jmp message_exit1 - - -#ifndef BAD_BIOS -compare_to_lowmem_size: - - pushw %ds - pushw %bx - pushl %ecx - xorw %bx, %bx - movw %bx, %ds /* DS=0 */ - movl %eax, %ecx - movw %ax, %bx - shrl $16, %ecx /* CX=segment */ - shrw $4, %bx - addw %bx, %cx - movw 0x413, %bx /* low mem size in KB */ - shlw $6, %bx /* low mem size in paragraphs */ - cmpw %bx, %cx - popl %ecx - popw %bx - popw %ds - ret - -/* begin guess_dos_versions */ -guess_dos_versions: - - /* OK, now begin to guess dos versions */ - - /* check MS-DOS 7.0+ */ - - xorw %ax, %ax - movw %ax, %ds /* DS=0 */ - - movw $0x0560, %si /* begins the int 08 vector */ - cld - lodsl /* int 08 - IRQ 0 - system timer */ - cmpl $0xC0000000, %eax - jb failed_check_msdos7plus - lodsl /* int 09 - IRQ 1 - keyboard data ready */ - cmpl $0xC0000000, %eax - jb failed_check_msdos7plus - //lodsl /* int 0A - IRQ 2 - LPT2(PC), vertical retrace interrupt */ - //lodsl /* int 0B - IRQ 3 - serial communications(COM2) */ - //lodsl /* int 0C - IRQ 4 - serial communications(COM1) */ - //lodsl /* int 0D - IRQ 5 - fixed disk(PC,XT), LPT2(AT), reserved(PS/2) */ - //lodsl /* int 0E - IRQ 6 - diskette controller */ - //lodsl /* int 0F - IRQ 7 - parallel printer */ -#if 0 - /* this area seems to be an internal MSDOS stack, so may be corrupted */ - movw $0x05dc, %si /* begins the int 70 vector */ - movw $0x0008, %cx /* 8 vectors to check, from int 70 to 77 */ - call check_a_range_of_ROM_vectors - jc failed_check_msdos7plus -#else - movw $0x05DC, %si /* int 70 - IRQ 8 - CMOS real-time clock */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f - movw $0x01C0, %si /* int 70 - IRQ 8 - CMOS real-time clock */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f - ldsw -4(%si), %si /* DS changed! */ - subw $4, %si - lodsl - cmpl $0xC0000000, %eax - jb failed_check_msdos7plus - xorw %ax, %ax - movw %ax, %ds /* DS = 0 */ -1: - movw $0x05E0, %si /* int 71 - IRQ 9 - redirected to int 0A by BIOS */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f - movw $0x01C4, %si /* int 71 - IRQ 9 - redirected to int 0A by BIOS */ - cld - lodsl - cmpl $0xC0000000, %eax - jb failed_check_msdos7plus -1: -// movw $0x05E4, %si /* int 72 - IRQ 10 - reserved */ -// cld -// lodsl -// cmpl $0xC0000000, %eax -// jnb 1f -// movw $0x01C8, %si /* int 72 - IRQ 10 - reserved */ -// cld -// lodsl -// cmpl $0xC0000000, %eax -// jnb 1f -// ldsw -4(%si), %si /* DS changed! */ -// lodsw -// cmpw $0x10EB, %ax -// jne failed_check_msdos7plus -// lodsl -// cmpl $0xC0000000, %eax -// jb failed_check_msdos7plus -// xorw %ax, %ax -// movw %ax, %ds /* DS = 0 */ -1: -// movw $0x05e8, %si /* int 73 - IRQ 11 - reserved */ -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jnb 1f -// movw $0x01cc, %si -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jnb 1f -// ldsw -4(%si), %si /* DS got changed */ -// lodsw -// cmpw $0x10eb, %ax -// jne failed_check_msdos7plus -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos7plus -// xorw %ax, %ax -// movw %ax, %ds /* let DS = 0 */ -1: -// movw $0x05ec, %si /* int 74 - IRQ 12 - pointing device(PS) */ -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jnb 1f -// movw $0x01d0, %si -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jnb 1f -// ldsw -4(%si), %si /* DS got changed */ -// lodsw -// cmpw $0x10eb, %ax -// jne failed_check_msdos7plus -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos7plus -// xorw %ax, %ax -// movw %ax, %ds /* let DS = 0 */ -1: - movw $0x05f0, %si /* int 75 - IRQ 13 - math coprocessor exception(AT+) */ - cld - lodsl - cmpl $0xc0000000, %eax - jnb 1f - movw $0x01d4, %si - cld - lodsl - cmpl $0xc0000000, %eax - jb failed_check_msdos7plus -1: -// movw $0x05f4, %si /* int 76 - IRQ 14 - hard disk controller - operation complete(AT+) */ -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jnb 1f -// movw $0x01d8, %si -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jnb 1f -// ldsw -4(%si), %si /* DS got changed */ -// lodsw -// cmpw $0x10eb, %ax -// jne failed_check_msdos7plus -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos7plus -// xorw %ax, %ax -// movw %ax, %ds /* let DS = 0 */ -1: -// movw $0x05f8, %si /* int 77 - IRQ 15 - reserved(AT, PS) - secondary IDE controller */ -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jnb 1f -// movw $0x01dc, %si -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jnb 1f -// ldsw -4(%si), %si /* DS got changed */ -// lodsw -// cmpw $0x10eb, %ax -// jne failed_check_msdos7plus -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos7plus -// xorw %ax, %ax -// movw %ax, %ds /* let DS = 0 */ -1: -#endif - cmpl $0, 0x5A4 /* int 19 vector(?) must be 0 */ - jnz failed_check_msdos7plus - - cmpl $0xC0000000, 0x5D4 /* int 4B - Virtual DMA Specification */ - jb failed_check_msdos7plus - - movw $0x800, %si /* another saved int 10 vector */ - cld - lodsb - cmpb $0x10, %al - jnz failed_check_msdos7plus - cld - lodsl - cmpl %eax, 0x580 /* saved int 10 vector */ - jnz failed_check_msdos7plus - - movw $0x805, %si /* another saved int 13 vector */ - cld - lodsb - cmpb $0x13, %al - jnz failed_check_msdos7plus - cld - lodsl - cmpl %eax, 0x58C /* saved int 13 vector */ - jnz failed_check_msdos7plus - - movw $0x80A, %si /* another saved int 15 vector */ - cld - lodsb - cmpb $0x15, %al - jnz failed_check_msdos7plus - cld - lodsl - cmpl %eax, 0x594 /* saved int 15 vector */ - jnz failed_check_msdos7plus - - movw $0x814, %si /* another saved int 1B vector */ - cld - lodsb - cmpb $0x1B, %al - jnz failed_check_msdos7plus - cld - lodsl - cmpl %eax, 0x5AC /* saved int 1B vector */ - jnz failed_check_msdos7plus - - movw $0x819, %si /* another saved int 4F vector */ - cld - lodsb - cmpb $0x4F, %al - jnz failed_check_msdos7plus - cld - lodsl - cmpl %eax, 0x5D8 /* saved int 4F vector */ - jnz failed_check_msdos7plus - - movw $0x81E, %si /* another saved int 08 vector */ - cld - lodsb - cmpb $0x08, %al - jnz failed_check_msdos7plus - cld - lodsl - cmpl %eax, 0x560 /* saved int 08 vector */ - jnz failed_check_msdos7plus - - movw $0x823, %si /* another saved int 0F vector */ - cld - lodsb - cmpb $0x0F, %al - jnz failed_check_msdos7plus - cld - lodsl - cmpl %eax, 0x57C /* saved int 0F vector */ - jnz failed_check_msdos7plus - - /* yes, it is MS-DOS 7.0+ */ - movl $0x4D530700, %cs:ABS_START(dos_version) /* 0x4D53 = MS */ - - xorw %ax, %ax - movw %ax, %ds /* DS=0 */ - movw $0x540, %si /* int 00 to 1F */ - movw %cs, %ax - movw %ax, %es /* ES=CS */ - movw $ABS_START(bios_interrupt_vector_table), %di - - /* Fix int1A remote boot problem. Reported by John Cobb (Queen Mary, University of London). */ - movw $0x0020, %cx /* int 00 to 1F */ - cld -1: - lodsl - cmpl $0xC0000000, %es:(%di) /* Is it already a ROM vector? */ - jnb 2f /* Yes. Keep it untouched. */ - /* if it points to beyond the low mem, we accept it. */ - cmpl $0x5A000000, %es:(%di) - jb 8f - pushw %ds - pushw %bx - pushw %cx - xorw %bx, %bx - movw %bx, %ds /* DS=0 */ - movw 0x413, %bx /* low mem size in KB */ - shlw $6, %bx /* low mem size in paragraphs */ - movw %es:(%di), %cx /* offset */ - shrw $4, %cx - addw %es:2(%di), %cx - cmpw %bx, %cx - popw %cx - popw %bx - popw %ds - jnb 2f -8: - stosl /* No. Store the new vector. */ - subw $4, %di -2: - addw $4, %di - loop 1b - - movw $0x5C0, %si /* int 40 to 43 */ - movw $ABS_START(bios_interrupt_vector_table + 0x100), %di - movw $0x0004, %cx /* int 40 to 43 */ - repz movsl - - lodsl /* int 46 */ - movw $ABS_START(bios_interrupt_vector_table + 0x118), %di - stosl - - lodsl /* int 4B, maybe changed by emm386 */ - movw $ABS_START(bios_interrupt_vector_table + 0x12C), %di - stosl - - lodsl /* int 4F */ - movw $ABS_START(bios_interrupt_vector_table + 0x13C), %di - stosl -#if 0 - /* the area 0x5dc-0x5ff seems to be an internal MSDOS stack, so may be corrupted */ - movw $0x01c0, %di /* int 70 to 77 */ - movw $0x0010, %cx /* 16 words to move */ - repz movsw -#else - movw $0x5DC, %si /* int 70 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 2f - movw $0x1C0, %si - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f /* need not change */ - call compare_to_lowmem_size - jnb 1f /* need not change */ - ldsw -4(%si), %si /* DS changed! */ - subw $4, %si - lodsl - xorw %si, %si - movw %si, %ds /* DS = 0 */ - //cmpl $0xC0000000, %eax - call compare_to_lowmem_size - jnb 2f - movl %cs:ABS_START(dummy_iret_vector), %eax -2: - movw $ABS_START(bios_interrupt_vector_table + 0x1C0), %di - stosl /* save new int 70 */ -1: - movw $0x1C4, %si /* int 71 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f /* need not change */ - call compare_to_lowmem_size - jnb 1f /* need not change */ - movw $0x5E0, %si /* int 71 */ - cld - lodsl - //cmpl $0xC0000000, %eax - call compare_to_lowmem_size - jb 1f - movw $ABS_START(bios_interrupt_vector_table + 0x1C4), %di - stosl /* save new int 71 */ -1: - movw $0x5E4, %si /* int 72 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 2f - movw $0x1C8, %si - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f /* need not change */ - call compare_to_lowmem_size - jnb 1f /* need not change */ - ldsw -4(%si), %si /* DS changed! */ - lodsw - lodsl - xorw %si, %si - movw %si, %ds /* DS = 0 */ - //cmpl $0xC0000000, %eax - call compare_to_lowmem_size - jnb 2f - movl %cs:ABS_START(dummy_iret_vector), %eax -2: - movw $ABS_START(bios_interrupt_vector_table + 0x1C8), %di - stosl /* save new int 72 */ -1: - movw $0x5E8, %si /* int 73 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 2f - movw $0x1CC, %si - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f /* need not change */ - call compare_to_lowmem_size - jnb 1f /* need not change */ - ldsw -4(%si), %si /* DS changed! */ - lodsw - lodsl - xorw %si, %si - movw %si, %ds /* DS = 0 */ - //cmpl $0xC0000000, %eax - call compare_to_lowmem_size - jnb 2f - movl %cs:ABS_START(dummy_iret_vector), %eax -2: - movw $ABS_START(bios_interrupt_vector_table + 0x1CC), %di - stosl /* save new int 73 */ -1: - movw $0x5EC, %si /* int 74 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 2f - movw $0x1D0, %si - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f /* need not change */ - call compare_to_lowmem_size - jnb 1f /* need not change */ - ldsw -4(%si), %si /* DS changed! */ - lodsw - lodsl - xorw %si, %si - movw %si, %ds /* DS = 0 */ - //cmpl $0xC0000000, %eax - call compare_to_lowmem_size - jnb 2f - movl %cs:ABS_START(dummy_iret_vector), %eax -2: - movw $ABS_START(bios_interrupt_vector_table + 0x1D0), %di - stosl /* save new int 74 */ -1: - movw $0x1D4, %si /* int 75 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f /* need not change */ - call compare_to_lowmem_size - jnb 1f /* need not change */ - movw $0x5F0, %si /* int 75 */ - cld - lodsl - //cmpl $0xC0000000, %eax - call compare_to_lowmem_size - jb 1f - movw $ABS_START(bios_interrupt_vector_table + 0x1D4), %di - stosl /* save new int 75 */ -1: - movw $0x5F4, %si /* int 76 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 2f - movw $0x1D8, %si - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f - call compare_to_lowmem_size - jnb 1f /* need not change */ - ldsw -4(%si), %si /* DS changed! */ - lodsw - lodsl - xorw %si, %si - movw %si, %ds /* DS = 0 */ - //cmpl $0xC0000000, %eax - call compare_to_lowmem_size - jnb 2f - movl %cs:ABS_START(dummy_iret_vector), %eax -2: - movw $ABS_START(bios_interrupt_vector_table + 0x1D8), %di - stosl /* save new int 76 */ -1: - movw $0x5F8, %si /* int 77 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 2f - movw $0x1DC, %si - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f - call compare_to_lowmem_size - jnb 1f /* need not change */ - ldsw -4(%si), %si /* DS changed! */ - lodsw - lodsl - xorw %si, %si - movw %si, %ds /* DS = 0 */ - //cmpl $0xC0000000, %eax - call compare_to_lowmem_size - jnb 2f - movl %cs:ABS_START(dummy_iret_vector), %eax -2: - movw $ABS_START(bios_interrupt_vector_table + 0x1DC), %di - stosl /* save new int 77 */ -1: -#endif - movw $0x810, %si /* another saved int 19 */ - lodsl - movw $ABS_START(bios_interrupt_vector_table + 0x0064), %di - stosl - - movw $0x170, %si /* int 5C */ - lodsl - cmpl $0xC0000000, %eax - jnb 1f - ldsw -4(%si), %si /* DS changed! */ - cld - lodsb - cmpb $0xEA, %al /* 0xEA=opcode for jmp far */ - jne 1f - lodsl - movw $ABS_START(bios_interrupt_vector_table + 0x170), %di - stosl /* save new int 5C */ -1: - xorw %si, %si /* CF=0 */ - movw %si, %ds /* DS = 0 */ - - //clc /* CF already cleared */ - ret - -failed_check_msdos7plus: -// /* check MS-DOS 5.0+ */ -// -// xorw %ax, %ax -// movw %ax, %ds -// -// movw $0x0800, %si -// cld -// lodsb -// cmpb $0x10, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x13, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0x98000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x15, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x19, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x1b, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// -// movw $0x0d41, %si -// cld -// lodsb -// cmpb $0x02, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x08, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x09, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x0a, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x0b, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x0c, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x0d, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x0e, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x70, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x72, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x73, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x74, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x76, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jnb 1f -// addw $0x000d, %ax -// movw %ax, %si -// shrl $0x10, %eax -// movw %ax, %ds -// lodsw -// movw %ax, %si -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// xorw %ax, %ax -// movw %ax, %ds -// movw $0x0d82, %si -//1: -// cld -// lodsb -// cmpb $0x77, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// -// call restore_BDA_EBDA -// -// cli -// xorw %ax, %ax -// movw %ax, %es -// movw %ax, %ds -// -// movw $0x0800, %si -// cld -// lodsb -// movw $0x0040, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x004c, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x0054, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x0064, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x006c, %di -// cld -// lodsl -// stosl -// -// movw $0x0d41, %si -// cld -// lodsb -// movw $0x0008, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x0020, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x0024, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x0028, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x002c, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x0030, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x0034, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x0038, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x01c0, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x01c8, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x01cc, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x01d0, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x01d8, %di -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jnb 1f -// addw $0x000d, %ax -// movw %ax, %si -// shrl $0x10, %eax -// movw %ax, %ds -// lodsw -// movw %ax, %si -// lodsl -//1: -// stosl -// xorw %ax, %ax -// movw %ax, %ds -// movw $0x0d82, %si -// cld -// lodsb -// movw $0x01dc, %di -// cld -// lodsl -// stosl -// -// jmp move_stage2_image -// -//check_msdos4minus: -// /* check MS-DOS 4.0- */ -// -// xorw %ax, %ax -// movw %ax, %ds -// -// movw %bx, %si /* int 19 */ -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb 1f -// cld -// lodsb -// cmpb $0x01, %al /* the byte 01 followed by int 02, ... */ -// jnz 1f -// -// /* int 02,08-0e,70,72-74,76-77 */ -// movw $0x000e, %cx /* 14 vectors to check */ -// call check_a_range_of_ROM_vectors -// jc 1f -// -// pushw %bx -// call restore_BDA_EBDA -// popw %bx -// -// cli -// cld -// xorw %ax, %ax -// movw %ax, %es -// movw %ax, %ds -// movw %bx, %si /* int 19 */ -// movw $0x0064, %di -// lodsl -// stosl -// lodsb /* the byte "01" */ -// movw $0x0008, %di /* int 02 */ -// lodsl -// stosl -// movw $0x0020, %di /* int 08 to 0f */ -// movw $0x000e, %cx /* 14 words to move */ -// repz movsw -// movw $0x01c0, %di /* int 70 */ -// lodsl -// stosl -// movw $0x01c8, %di /* int 72 */ -// lodsl -// stosl -// lodsl /* int 73 */ -// stosl -// lodsl /* int 74 */ -// stosl -// movw $0x01d8, %di /* int 76 */ -// lodsl -// stosl -// lodsl /* int 77 */ -// stosl -// -// clc -// ret -//1: -// stc /* failed_check_msdos4minus */ -// ret -// -//failed_check_msdos5plus: -// /* check for MS-DOS 4.01 */ -// -// movw $0x240e, %bx -// call check_msdos4minus -// jc failed_check_msdos4 -// -// jmp move_stage2_image -// -//failed_check_msdos4: -// /* check for MS-DOS 3.30 */ -// -// movw $0x2172, %bx -// call check_msdos4minus -// jc failed_check_msdos3 -// -// jmp move_stage2_image -// -//failed_check_msdos3: - - /* check FreeDOS (build 2029+) */ - - /* - * MS himem.sys takes over int 15, so check for the case. - */ - - xorw %ax, %ax - movw %ax, %es - movw %ax, %ds - movw $0x0054, %di - movl (%di), %eax /* int 15 vector in table */ - cmpl $0xC0000000, %eax /* is it a valid BIOS vector? */ - jnb 1f /* yes, do nothing */ - movw $0x3086, %si /* no, take one from himem */ - movl (%si), %eax - cmpl $0xC0000000, %eax /* is it a system BIOS vector? */ - jb failed_check_freedos /* no, do not continue */ -1: /* yes, continue */ - xorw %ax, %ax - movw %ax, %ds - movw $0x0020, %si /* DS:SI points to int 08 */ - lodsl - movl %eax, %ebx - movl %eax, %edx - movw $7, %cx -1: - lodsl - addw $6, %bx - jc failed_check_freedos - cmpl %eax, %ebx - jnz failed_check_freedos - loop 1b - - movw $0x1C0, %si /* DS:SI points to int 70 */ - movw $8, %cx -1: - lodsl - addw $6, %bx - jc failed_check_freedos - cmpl %eax, %ebx - jnz failed_check_freedos - loop 1b - - movw %dx, %si - shrl $16, %edx - movw %dx, %ds /* DS:SI points to int 08 routine */ - - movw $16, %cx - xorw %bx, %bx - xorw %dx, %dx -1: - lodsw - cmpw $0xBB53, %ax /* 0x53="pushw %bx",0xBB="movw $(...), %bx" */ - jnz failed_check_freedos - lodsw - cmpw %ax, %bx - jnz failed_check_freedos - addw $4, %bx - cmpw $1, %cx - jz 2f - lodsb - cmpb $0xEB, %al /* 0xEB="jmp ..." */ - jnz failed_check_freedos - lodsb - orw %dx, %dx - jnz 3f - movw %si, %dx - xorb %ah, %ah - addw %ax, %dx - jc failed_check_freedos - jmp 2f -3: - xorb %ah, %ah - addw %si, %ax - jc failed_check_freedos - cmpw %ax, %dx - jnz failed_check_freedos -2: - loop 1b - - addw $0x0025, %si - lodsb - cmpb $0x9C, %al /* 0x9C="pushfw" */ - jnz failed_check_freedos - lodsw - cmpw $0x9FFF, %ax /* 0x9FFF="call far [bx+????]" */ - jnz failed_check_freedos - lodsw - /*xorl %esi, %esi*/ - movw %ax, %si /* DS:SI begins old int 08-0F,70-77 vectors */ - movw %ds, %ax - orb %ah, %ah - jnz failed_check_freedos - shlw $4, %ax - addw %ax, %si /* 0000:SI begins the above int08-77vectors */ - jc failed_check_freedos - - - xorw %ax, %ax - movw %ax, %ds - /*movw $0x08a4, %si*/ /* int 08-0f,70-77 begins here */ - movw %si, %di /* save SI into DI */ - cld - lodsl /* int 08 */ - cmpl $0xC0000000, %eax /* is it a valid BIOS vector? */ - jb failed_check_freedos - lodsl /* int 09 */ - cmpl $0xC0000000, %eax /* is it a valid BIOS vector? */ - jb failed_check_freedos - lodsl /* int 0A */ - lodsl /* int 0B */ - lodsl /* int 0C */ - lodsl /* int 0D */ - lodsl /* int 0E */ - lodsl /* int 0F */ - lodsl /* int 70 */ - cmpl $0xC0000000, %eax /* is it a valid BIOS vector? */ - jb failed_check_freedos - lodsl /* int 71 */ - cmpl $0xC0000000, %eax /* is it a valid BIOS vector? */ - jb failed_check_freedos - lodsl /* int 72 */ - lodsl /* int 73 */ - lodsl /* int 74 */ - lodsl /* int 75 */ - cmpl $0xC0000000, %eax /* is it a valid BIOS vector? */ - jb failed_check_freedos - lodsl /* int 76 */ - lodsl /* int 77 */ - - /* yes, it is FreeMS */ - movl $0x46720000, %cs:ABS_START(dos_version) /* 0x4672 = Fr */ - - movw %di, %si /* restore SI from DI */ - xorw %ax, %ax - movw %ax, %ds /* DS=0 */ - /*movw $0x08a4, %si*/ - movw %cs, %ax - movw %ax, %es /* ES=CS */ - movw $ABS_START(bios_interrupt_vector_table + 0x20), %di - movw $0x0008, %cx /* int 08 to 0F */ - cld - repz movsl - movw $ABS_START(bios_interrupt_vector_table + 0x1C0), %di - movw $0x0008, %cx /* int 70 to 77 */ - cld - repz movsl - - /* - * MS himem.sys takes over int 15, so try to restore it - */ - - movw $0x0054, %di - movl (%di), %eax /* int 15 vector in table */ - cmpl $0xC0000000, %eax /* is it a valid BIOS vector? */ - jnb 1f /* yes, do nothing */ - movw $0x3086, %si /* no, take one from himem */ - movl (%si), %eax - cmpl $0xC0000000, %eax /* is it a system BIOS vector? */ - jb 1f /* no, do nothing */ - addw $ABS_START(bios_interrupt_vector_table), %di - stosl /* yes, write it to the table */ -1: - clc - ret - -failed_check_freedos: - - /* check DOSbox */ - - xorw %ax, %ax - movw %ax, %ds - movw $0x0020, %si /* int 08-1f */ - movw $0x0018, %cx /* 24 vectors to check */ - call check_a_range_of_ROM_vectors - jc failed_check_dosbox - - /* yes, it is DOSbox */ - movl $0xD05B5800, %cs:ABS_START(dos_version) - - //clc - ret - -check_a_range_of_ROM_vectors: -1: - cld - lodsl - cmpl $0xC0000000, %eax /* ROM vectors assumed to be above C000:0 */ - jb 1f /* check failed, with carry */ - loop 1b - /* check passed, with no carry */ -1: - ret - -failed_check_dosbox: - - ret - -/* end guess_dos_versions */ -#endif - -dos_version: - - .long 0 - -probe_int: - -#ifdef BAD_BIOS - - /* copy 1 sector of IVT to bios_interrupt_vector_table */ - movw %cs, %ax - movw %ax, %es /* ES=CS */ - movw $ABS_START(bios_interrupt_vector_table), %di - xorw %si, %si /* SI=0 */ - movw %si, %ds /* DS=0 */ - movw $0x80, %cx -2: - cld - lodsl - cmpl $0, %es:(%di) - jne 1f - stosl - subw $4, %di -1: - addw $4, %di - loop 2b - - /* OK, now begin to guess dos versions */ - - /* check MS-DOS 7.0+ */ - - xorw %ax, %ax - movw %ax, %ds /* DS=0 */ - - movw $0x0560, %si /* begins the int 08 vector */ - cld - lodsl /* int 08 - IRQ 0 - system timer */ - cmpl $0xC0000000, %eax - jb failed_check_msdos7plus - lodsl /* int 09 - IRQ 1 - keyboard data ready */ - cmpl $0xC0000000, %eax - jb failed_check_msdos7plus - //lodsl /* int 0A - IRQ 2 - LPT2(PC), vertical retrace interrupt */ - //lodsl /* int 0B - IRQ 3 - serial communications(COM2) */ - //lodsl /* int 0C - IRQ 4 - serial communications(COM1) */ - //lodsl /* int 0D - IRQ 5 - fixed disk(PC,XT), LPT2(AT), reserved(PS/2) */ - //lodsl /* int 0E - IRQ 6 - diskette controller */ - //lodsl /* int 0F - IRQ 7 - parallel printer */ -#if 0 - /* this area seems to be an internal MSDOS stack, so may be corrupted */ - movw $0x05dc, %si /* begins the int 70 vector */ - movw $0x0008, %cx /* 8 vectors to check, from int 70 to 77 */ - call check_a_range_of_ROM_vectors - jc failed_check_msdos7plus -#else - movw $0x05DC, %si /* int 70 - IRQ 8 - CMOS real-time clock */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f - movw $0x01C0, %si /* int 70 - IRQ 8 - CMOS real-time clock */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f - ldsw -4(%si), %si /* DS changed! */ - subw $4, %si - lodsl - cmpl $0xC0000000, %eax - jb failed_check_msdos7plus - xorw %ax, %ax - movw %ax, %ds /* DS = 0 */ -1: - movw $0x05E0, %si /* int 71 - IRQ 9 - redirected to int 0A by BIOS */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f - movw $0x01C4, %si /* int 71 - IRQ 9 - redirected to int 0A by BIOS */ - cld - lodsl - cmpl $0xC0000000, %eax - jb failed_check_msdos7plus -1: -// movw $0x05E4, %si /* int 72 - IRQ 10 - reserved */ -// cld -// lodsl -// cmpl $0xC0000000, %eax -// jnb 1f -// movw $0x01C8, %si /* int 72 - IRQ 10 - reserved */ -// cld -// lodsl -// cmpl $0xC0000000, %eax -// jnb 1f -// ldsw -4(%si), %si /* DS changed! */ -// lodsw -// cmpw $0x10EB, %ax -// jne failed_check_msdos7plus -// lodsl -// cmpl $0xC0000000, %eax -// jb failed_check_msdos7plus -// xorw %ax, %ax -// movw %ax, %ds /* DS = 0 */ -1: -// movw $0x05e8, %si /* int 73 - IRQ 11 - reserved */ -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jnb 1f -// movw $0x01cc, %si -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jnb 1f -// ldsw -4(%si), %si /* DS got changed */ -// lodsw -// cmpw $0x10eb, %ax -// jne failed_check_msdos7plus -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos7plus -// xorw %ax, %ax -// movw %ax, %ds /* let DS = 0 */ -1: -// movw $0x05ec, %si /* int 74 - IRQ 12 - pointing device(PS) */ -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jnb 1f -// movw $0x01d0, %si -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jnb 1f -// ldsw -4(%si), %si /* DS got changed */ -// lodsw -// cmpw $0x10eb, %ax -// jne failed_check_msdos7plus -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos7plus -// xorw %ax, %ax -// movw %ax, %ds /* let DS = 0 */ -1: - movw $0x05f0, %si /* int 75 - IRQ 13 - math coprocessor exception(AT+) */ - cld - lodsl - cmpl $0xc0000000, %eax - jnb 1f - movw $0x01d4, %si - cld - lodsl - cmpl $0xc0000000, %eax - jb failed_check_msdos7plus -1: -// movw $0x05f4, %si /* int 76 - IRQ 14 - hard disk controller - operation complete(AT+) */ -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jnb 1f -// movw $0x01d8, %si -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jnb 1f -// ldsw -4(%si), %si /* DS got changed */ -// lodsw -// cmpw $0x10eb, %ax -// jne failed_check_msdos7plus -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos7plus -// xorw %ax, %ax -// movw %ax, %ds /* let DS = 0 */ -1: -// movw $0x05f8, %si /* int 77 - IRQ 15 - reserved(AT, PS) - secondary IDE controller */ -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jnb 1f -// movw $0x01dc, %si -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jnb 1f -// ldsw -4(%si), %si /* DS got changed */ -// lodsw -// cmpw $0x10eb, %ax -// jne failed_check_msdos7plus -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos7plus -// xorw %ax, %ax -// movw %ax, %ds /* let DS = 0 */ -1: -#endif - cmpl $0, 0x5A4 /* int 19 vector(?) must be 0 */ - jnz failed_check_msdos7plus - - cmpl $0xC0000000, 0x5D4 /* int 4B - Virtual DMA Specification */ - jb failed_check_msdos7plus - - movw $0x800, %si /* another saved int 10 vector */ - cld - lodsb - cmpb $0x10, %al - jnz failed_check_msdos7plus - cld - lodsl - cmpl %eax, 0x580 /* saved int 10 vector */ - jnz failed_check_msdos7plus - - movw $0x805, %si /* another saved int 13 vector */ - cld - lodsb - cmpb $0x13, %al - jnz failed_check_msdos7plus - cld - lodsl - cmpl %eax, 0x58C /* saved int 13 vector */ - jnz failed_check_msdos7plus - - movw $0x80A, %si /* another saved int 15 vector */ - cld - lodsb - cmpb $0x15, %al - jnz failed_check_msdos7plus - cld - lodsl - cmpl %eax, 0x594 /* saved int 15 vector */ - jnz failed_check_msdos7plus - - movw $0x814, %si /* another saved int 1B vector */ - cld - lodsb - cmpb $0x1B, %al - jnz failed_check_msdos7plus - cld - lodsl - cmpl %eax, 0x5AC /* saved int 1B vector */ - jnz failed_check_msdos7plus - - movw $0x819, %si /* another saved int 4F vector */ - cld - lodsb - cmpb $0x4F, %al - jnz failed_check_msdos7plus - cld - lodsl - cmpl %eax, 0x5D8 /* saved int 4F vector */ - jnz failed_check_msdos7plus - - movw $0x81E, %si /* another saved int 08 vector */ - cld - lodsb - cmpb $0x08, %al - jnz failed_check_msdos7plus - cld - lodsl - cmpl %eax, 0x560 /* saved int 08 vector */ - jnz failed_check_msdos7plus - - movw $0x823, %si /* another saved int 0F vector */ - cld - lodsb - cmpb $0x0F, %al - jnz failed_check_msdos7plus - cld - lodsl - cmpl %eax, 0x57C /* saved int 0F vector */ - jnz failed_check_msdos7plus - - /* yes, it is MS-DOS 7.0+ */ - - xorw %ax, %ax - movw %ax, %ds /* DS=0 */ - movw $0x540, %si /* int 00 to 1F */ - movw %cs, %ax - movw %ax, %es /* ES=CS */ - movw $ABS_START(bios_interrupt_vector_table), %di - - /* Fix int1A remote boot problem. Reported by John Cobb (Queen Mary, University of London). */ - movw $0x0020, %cx /* int 00 to 1F */ - cld -1: - lodsl - cmpl $0xC0000000, %es:(%di) /* Is it already a ROM vector? */ - jnb 2f /* Yes. Keep it untouched. */ - /* if it points to beyond the low mem, we accept it. */ - cmpl $0x5A000000, %es:(%di) - jb 8f - pushw %ds - pushw %bx - pushw %cx - xorw %bx, %bx - movw %bx, %ds /* DS=0 */ - movw 0x413, %bx /* low mem size in KB */ - shlw $6, %bx /* low mem size in paragraphs */ - movw %es:(%di), %cx /* offset */ - shrw $4, %cx - addw %es:2(%di), %cx - cmpw %bx, %cx - popw %cx - popw %bx - popw %ds - jnb 2f -8: - stosl /* No. Store the new vector. */ - subw $4, %di -2: - addw $4, %di - loop 1b - - movw $0x5C0, %si /* int 40 to 43 */ - movw $ABS_START(bios_interrupt_vector_table + 0x100), %di - movw $0x0004, %cx /* int 40 to 43 */ - repz movsl - - lodsl /* int 46 */ - movw $ABS_START(bios_interrupt_vector_table + 0x118), %di - stosl - - lodsl /* int 4B, maybe changed by emm386 */ - movw $ABS_START(bios_interrupt_vector_table + 0x12C), %di - stosl - - lodsl /* int 4F */ - movw $ABS_START(bios_interrupt_vector_table + 0x13C), %di - stosl -#if 0 - /* the area 0x5dc-0x5ff seems to be an internal MSDOS stack, so may be corrupted */ - movw $0x01c0, %di /* int 70 to 77 */ - movw $0x0010, %cx /* 16 words to move */ - repz movsw -#else - movw $0x5DC, %si /* int 70 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 2f - movw $0x1C0, %si /* int 70 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f /* need not change */ - ldsw -4(%si), %si /* DS changed! */ - subw $4, %si - lodsl - xorw %si, %si - movw %si, %ds /* DS = 0 */ - cmpl $0xC0000000, %eax - jb 1f -2: - movw $ABS_START(bios_interrupt_vector_table + 0x1C0), %di - stosl /* save new int 70 */ -1: - movw $0x1C4, %si /* int 71 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f /* need not change */ - movw $0x5E0, %si /* int 71 */ - cld - lodsl - cmpl $0xC0000000, %eax - jb 1f - movw $ABS_START(bios_interrupt_vector_table + 0x1C4), %di - stosl /* save new int 71 */ -1: - movw $0x5E4, %si /* int 72 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 2f - movw $0x1C8, %si /* int 72 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f /* need not change */ - ldsw -4(%si), %si /* DS changed! */ - lodsw - lodsl - xorw %si, %si - movw %si, %ds /* DS = 0 */ - cmpl $0xC0000000, %eax - jb 1f -2: - movw $ABS_START(bios_interrupt_vector_table + 0x1C8), %di - stosl /* save new int 72 */ -1: - movw $0x5E8, %si /* int 73 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 2f - movw $0x1CC, %si /* int 73 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f /* need not change */ - ldsw -4(%si), %si /* DS changed! */ - lodsw - lodsl - xorw %si, %si - movw %si, %ds /* DS = 0 */ - cmpl $0xC0000000, %eax - jb 1f -2: - movw $ABS_START(bios_interrupt_vector_table + 0x1CC), %di - stosl /* save new int 73 */ -1: - movw $0x5EC, %si /* int 74 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 2f - movw $0x1D0, %si /* int 74 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f /* need not change */ - ldsw -4(%si), %si /* DS changed! */ - lodsw - lodsl - xorw %si, %si - movw %si, %ds /* DS = 0 */ - cmpl $0xC0000000, %eax - jb 1f -2: - movw $ABS_START(bios_interrupt_vector_table + 0x1D0), %di - stosl /* save new int 74 */ -1: - movw $0x1D4, %si /* int 75 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f /* need not change */ - movw $0x5F0, %si /* int 75 */ - cld - lodsl - cmpl $0xC0000000, %eax - jb 1f - movw $ABS_START(bios_interrupt_vector_table + 0x1D4), %di - stosl /* save new int 75 */ -1: - movw $0x5F4, %si /* int 76 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 2f - movw $0x1D8, %si /* int 76 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f - ldsw -4(%si), %si /* DS changed! */ - lodsw - lodsl - xorw %si, %si - movw %si, %ds /* DS = 0 */ - cmpl $0xC0000000, %eax - jb 1f -2: - movw $ABS_START(bios_interrupt_vector_table + 0x1D8), %di - stosl /* save new int 76 */ -1: - movw $0x5F8, %si /* int 77 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 2f - movw $0x1DC, %si /* int 77 */ - cld - lodsl - cmpl $0xC0000000, %eax - jnb 1f - ldsw -4(%si), %si /* DS changed! */ - lodsw - lodsl - xorw %si, %si - movw %si, %ds /* DS = 0 */ - cmpl $0xC0000000, %eax - jb 1f -2: - movw $ABS_START(bios_interrupt_vector_table + 0x1DC), %di - stosl /* save new int 77 */ -1: -#endif - movw $0x810, %si /* another saved int 19 */ - lodsl - movw $ABS_START(bios_interrupt_vector_table + 0x0064), %di - stosl - - movw $0x170, %si /* int 5C */ - lodsl - cmpl $0xC0000000, %eax - jnb 1f - ldsw -4(%si), %si /* DS changed! */ - cld - lodsb - cmpb $0xEA, %al /* 0xEA=opcode for jmp far */ - jne 1f - lodsl - movw $ABS_START(bios_interrupt_vector_table + 0x170), %di - stosl /* save new int 5C */ -1: - xorw %si, %si /* CF=0 */ - movw %si, %ds /* DS = 0 */ - - //clc /* CF already cleared */ - ret - -failed_check_msdos7plus: -// /* check MS-DOS 5.0+ */ -// -// xorw %ax, %ax -// movw %ax, %ds -// -// movw $0x0800, %si -// cld -// lodsb -// cmpb $0x10, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x13, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0x98000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x15, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x19, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x1b, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// -// movw $0x0d41, %si -// cld -// lodsb -// cmpb $0x02, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x08, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x09, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x0a, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x0b, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x0c, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x0d, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x0e, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x70, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x72, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x73, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x74, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// cld -// lodsb -// cmpb $0x76, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jnb 1f -// addw $0x000d, %ax -// movw %ax, %si -// shrl $0x10, %eax -// movw %ax, %ds -// lodsw -// movw %ax, %si -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// xorw %ax, %ax -// movw %ax, %ds -// movw $0x0d82, %si -//1: -// cld -// lodsb -// cmpb $0x77, %al -// jnz failed_check_msdos5plus -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb failed_check_msdos5plus -// -// call restore_BDA_EBDA -// -// cli -// xorw %ax, %ax -// movw %ax, %es -// movw %ax, %ds -// -// movw $0x0800, %si -// cld -// lodsb -// movw $0x0040, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x004c, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x0054, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x0064, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x006c, %di -// cld -// lodsl -// stosl -// -// movw $0x0d41, %si -// cld -// lodsb -// movw $0x0008, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x0020, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x0024, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x0028, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x002c, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x0030, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x0034, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x0038, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x01c0, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x01c8, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x01cc, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x01d0, %di -// cld -// lodsl -// stosl -// cld -// lodsb -// movw $0x01d8, %di -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jnb 1f -// addw $0x000d, %ax -// movw %ax, %si -// shrl $0x10, %eax -// movw %ax, %ds -// lodsw -// movw %ax, %si -// lodsl -//1: -// stosl -// xorw %ax, %ax -// movw %ax, %ds -// movw $0x0d82, %si -// cld -// lodsb -// movw $0x01dc, %di -// cld -// lodsl -// stosl -// -// jmp move_stage2_image -// -//check_msdos4minus: -// /* check MS-DOS 4.0- */ -// -// xorw %ax, %ax -// movw %ax, %ds -// -// movw %bx, %si /* int 19 */ -// cld -// lodsl -// cmpl $0xc0000000, %eax -// jb 1f -// cld -// lodsb -// cmpb $0x01, %al /* the byte 01 followed by int 02, ... */ -// jnz 1f -// -// /* int 02,08-0e,70,72-74,76-77 */ -// movw $0x000e, %cx /* 14 vectors to check */ -// call check_a_range_of_ROM_vectors -// jc 1f -// -// pushw %bx -// call restore_BDA_EBDA -// popw %bx -// -// cli -// cld -// xorw %ax, %ax -// movw %ax, %es -// movw %ax, %ds -// movw %bx, %si /* int 19 */ -// movw $0x0064, %di -// lodsl -// stosl -// lodsb /* the byte "01" */ -// movw $0x0008, %di /* int 02 */ -// lodsl -// stosl -// movw $0x0020, %di /* int 08 to 0f */ -// movw $0x000e, %cx /* 14 words to move */ -// repz movsw -// movw $0x01c0, %di /* int 70 */ -// lodsl -// stosl -// movw $0x01c8, %di /* int 72 */ -// lodsl -// stosl -// lodsl /* int 73 */ -// stosl -// lodsl /* int 74 */ -// stosl -// movw $0x01d8, %di /* int 76 */ -// lodsl -// stosl -// lodsl /* int 77 */ -// stosl -// -// clc -// ret -//1: -// stc /* failed_check_msdos4minus */ -// ret -// -//failed_check_msdos5plus: -// /* check for MS-DOS 4.01 */ -// -// movw $0x240e, %bx -// call check_msdos4minus -// jc failed_check_msdos4 -// -// jmp move_stage2_image -// -//failed_check_msdos4: -// /* check for MS-DOS 3.30 */ -// -// movw $0x2172, %bx -// call check_msdos4minus -// jc failed_check_msdos3 -// -// jmp move_stage2_image -// -//failed_check_msdos3: - - /* check FreeDOS (build 2029+) */ - - /* - * MS himem.sys takes over int 15, so check for the case. - */ - - xorw %ax, %ax - movw %ax, %es - movw %ax, %ds - movw $0x0054, %di - movl (%di), %eax /* int 15 vector in table */ - cmpl $0xC0000000, %eax /* is it a valid BIOS vector? */ - jnb 1f /* yes, do nothing */ - movw $0x3086, %si /* no, take one from himem */ - movl (%si), %eax - cmpl $0xC0000000, %eax /* is it a system BIOS vector? */ - jb failed_check_freedos /* no, do not continue */ -1: /* yes, continue */ - xorw %ax, %ax - movw %ax, %ds - movw $0x0020, %si /* DS:SI points to int 08 */ - lodsl - movl %eax, %ebx - movl %eax, %edx - movw $7, %cx -1: - lodsl - addw $6, %bx - jc failed_check_freedos - cmpl %eax, %ebx - jnz failed_check_freedos - loop 1b - - movw $0x1C0, %si /* DS:SI points to int 70 */ - movw $8, %cx -1: - lodsl - addw $6, %bx - jc failed_check_freedos - cmpl %eax, %ebx - jnz failed_check_freedos - loop 1b - - movw %dx, %si - shrl $16, %edx - movw %dx, %ds /* DS:SI points to int 08 routine */ - - movw $16, %cx - xorw %bx, %bx - xorw %dx, %dx -1: - lodsw - cmpw $0xBB53, %ax /* 0x53="pushw %bx",0xBB="movw $(...), %bx" */ - jnz failed_check_freedos - lodsw - cmpw %ax, %bx - jnz failed_check_freedos - addw $4, %bx - cmpw $1, %cx - jz 2f - lodsb - cmpb $0xEB, %al /* 0xEB="jmp ..." */ - jnz failed_check_freedos - lodsb - orw %dx, %dx - jnz 3f - movw %si, %dx - xorb %ah, %ah - addw %ax, %dx - jc failed_check_freedos - jmp 2f -3: - xorb %ah, %ah - addw %si, %ax - jc failed_check_freedos - cmpw %ax, %dx - jnz failed_check_freedos -2: - loop 1b - - addw $0x0025, %si - lodsb - cmpb $0x9C, %al /* 0x9C="pushfw" */ - jnz failed_check_freedos - lodsw - cmpw $0x9FFF, %ax /* 0x9FFF="call far [bx+????]" */ - jnz failed_check_freedos - lodsw - /*xorl %esi, %esi*/ - movw %ax, %si /* DS:SI begins old int 08-0F,70-77 vectors */ - movw %ds, %ax - orb %ah, %ah - jnz failed_check_freedos - shlw $4, %ax - addw %ax, %si /* 0000:SI begins the above int08-77vectors */ - jc failed_check_freedos - - - xorw %ax, %ax - movw %ax, %ds - /*movw $0x08a4, %si*/ /* int 08-0f,70-77 begins here */ - movw %si, %di /* save SI into DI */ - cld - lodsl /* int 08 */ - cmpl $0xC0000000, %eax /* is it a valid BIOS vector? */ - jb failed_check_freedos - lodsl /* int 09 */ - cmpl $0xC0000000, %eax /* is it a valid BIOS vector? */ - jb failed_check_freedos - lodsl /* int 0A */ - lodsl /* int 0B */ - lodsl /* int 0C */ - lodsl /* int 0D */ - lodsl /* int 0E */ - lodsl /* int 0F */ - lodsl /* int 70 */ - cmpl $0xC0000000, %eax /* is it a valid BIOS vector? */ - jb failed_check_freedos - lodsl /* int 71 */ - cmpl $0xC0000000, %eax /* is it a valid BIOS vector? */ - jb failed_check_freedos - lodsl /* int 72 */ - lodsl /* int 73 */ - lodsl /* int 74 */ - lodsl /* int 75 */ - cmpl $0xC0000000, %eax /* is it a valid BIOS vector? */ - jb failed_check_freedos - lodsl /* int 76 */ - lodsl /* int 77 */ - - /* yes, it is FreeMS */ - - movw %di, %si /* restore SI from DI */ - xorw %ax, %ax - movw %ax, %ds /* DS=0 */ - /*movw $0x08a4, %si*/ - movw %cs, %ax - movw %ax, %es /* ES=CS */ - movw $ABS_START(bios_interrupt_vector_table + 0x20), %di - movw $0x0008, %cx /* int 08 to 0F */ - cld - repz movsl - movw $ABS_START(bios_interrupt_vector_table + 0x1C0), %di - movw $0x0008, %cx /* int 70 to 77 */ - cld - repz movsl - - /* - * MS himem.sys takes over int 15, so try to restore it - */ - - movw $0x0054, %di - movl (%di), %eax /* int 15 vector in table */ - cmpl $0xC0000000, %eax /* is it a valid BIOS vector? */ - jnb 1f /* yes, do nothing */ - movw $0x3086, %si /* no, take one from himem */ - movl (%si), %eax - cmpl $0xC0000000, %eax /* is it a system BIOS vector? */ - jb 1f /* no, do nothing */ - addw $ABS_START(bios_interrupt_vector_table), %di - stosl /* yes, write it to the table */ -1: - clc - ret - -failed_check_freedos: - - /* check DOSbox */ - - xorw %ax, %ax - movw %ax, %ds - movw $0x0020, %si /* int 08-1f */ - movw $0x0018, %cx /* 24 vectors to check */ - call check_a_range_of_ROM_vectors - //jc failed_check_dosbox - - /* yes, it is DOSbox */ - - //clc - ret - -check_a_range_of_ROM_vectors: -1: - cld - lodsl - cmpl $0xC0000000, %eax /* ROM vectors assumed to be above C000:0 */ - jb 1f /* check failed, with carry */ - loop 1b - /* check passed, with no carry */ -1: - ret - -//failed_check_dosbox: -// movw %cs, %ax -// movw %ax, %ds -// movw %ax, %es -// movl $ABS_START(dos_unsupport_string), ABS_PSP(error_message) -// jmp message_exit1 - -#else /* ! BAD_BIOS */ - /* Note for people who are tracing/debugging this program: - * PROBE_INT will take over int01, so probably you don't want - * to trace into PROBE_INT. - * - * int 00 - 07, 10 will be replaced and restored in RESTORE_VECTOR. - */ - - /* probe critical interrupt vectors established by ROM BIOS. */ - - /* find a dummy default vector that simply do an `iret' */ - - /* first, search the Interrupt Vector Table for a dummy vector */ - xorw %ax, %ax - movw %ax, %ds /* DS=0 */ - movw %ax, %si - movw $256, %cx -1: - cld - lodsl - cmpl $0xC0000000, %eax - jb 2f /* failure, try next vector */ - - movw %ax, %di - shrl $16, %eax - movw %ax, %es - cmpb $0xCF, %es:(%di) /* 0xCF=IRET */ - je 3f -2: - loop 1b - - /* not found, try a further probe in ROM segment F000:0000 */ - - movw $0xF000, %ax - movw %ax, %es /* ES=0xF000 */ - movw $0xFFFF, %cx - movb $0xCF, %al /* 0xCF=IRET */ - movw $0xFFFF, %di /* top-down */ - std - repnz scasb - cld - movw $0xFFFE, %cx - stc - jnz 9f - incw %di - -3: - /* found, ES:DI points to IRET */ - movw %di, %cs:ABS_START(dummy_iret_vector) - movw %es, %cs:ABS_START(dummy_iret_vector + 2) - - /* copy 1 sector of IVT to bios_interrupt_vector_table */ - movw %cs, %ax - movw %ax, %es /* ES=CS */ - movw $ABS_START(bios_interrupt_vector_table), %di - xorw %si, %si /* DS:SI=0000:0000 */ - movw $0x80, %cx -2: - cld - lodsl - cmpl $0, %es:(%di) - jne 1f - stosl - subw $4, %di -1: - addw $4, %di - loop 2b - - call guess_dos_versions - -// cmpl $0x4D530700, %cs:ABS_START(dos_version) /* 0x4D53 = MS */ -// jne 1f -// -// jmp 2f -//1: -// cmpl $0x46720000, %cs:ABS_START(dos_version) /* 0x4672 = Fr */ -// jne 2f -// -//2: - movw %cs, %ax - movw %ax, %es /* ES=CS */ - xorw %ax, %ax - movw %ax, %ds /* DS=0 */ - - /* save the current int 00 - 1F vectors */ - xorw %si, %si /* DS:SI=0000:0000 */ - movw $ABS_START(orig_int_00_1F_vectors), %di - movw $32, %cx - repz movsl - - movw %cs, %ax - movw %ax, %ds /* DS=ES=CS */ - - /* Print a message before it could hang. */ - movw $ABS_START(probe_int_hang_string), %si - call prtstr - -// /* check the int 13 vector high word */ -// cmpw $0xC000, ABS_START(bios_interrupt_vector_table) + 0x4E -// jb 2f -// -// cmpw $0xF000, ABS_START(bios_interrupt_vector_table) + 0x4E -// jna 3f /* int 13 points to ROM */ -//2: -// /* int 13 service routine was not in ROM */ -// /* clear tmp_int13_vector and tmp_int15_vector */ -//// xorl %eax, %eax /* marked out in 2008-05-07 */ -//// movl %eax, ABS_START(tmp_int13_vector) -//// movl %eax, ABS_START(tmp_int15_vector) -//3: -// /* check the int 15 vector high word */ -// cmpw $0xC000, ABS_START(bios_interrupt_vector_table) + 0x56 -// jb 2f -// -// cmpw $0xF000, ABS_START(bios_interrupt_vector_table) + 0x56 -// jna 3f /* int 15 points to ROM */ -//2: -// /* int 15 service routine was not in ROM */ -// /* clear tmp_int15_vector */ -//// xorl %eax, %eax /* marked out in 2008-05-07 */ -//// movl %eax, ABS_START(tmp_int15_vector) -//3: - - movw $ABS_START(bios_interrupt_vector_table), %si - movw %si, %di - xorw %cx, %cx -1: - //cmpw $0x15, %cx - //je 2f - call print_cl - - cld - lodsl - testl %eax, %eax /* zero vector? */ - jz 2f /* yes. won't touch */ - cmpl $0xF000FFFF, %eax /* modified by protected-mode OS? */ - ja 8f /* yes. */ - cmpl $0xC0000000, %eax /* ROM vector? */ - jb 8f /* no. */ - - /* it is in the ROM range. */ - /* if in real mode, then it is ROM vector. */ - - pushw %ax - smsw %ax - testb $1, %al - popw %ax - jz 2f /* Real mode, ROM vector, won't touch. */ - - /* Now we are in VM86 mode. */ - - /* if it points to an ARPL, we suppose it is running in Windows 9x */ - - pushw %ds - pushw %si - ldsw -4(%si), %si - cmpb $0x63, (%si) /* 0x63=arpl */ - popw %si - popw %ds - jne 5f - - /* We are running in Windows 9x */ - - /* We know MS-DOS will backup int 13 and int 4B in memory areas - * starting at 0000:0800 and 0000:0540 - */ - - /* if it is not MS-DOS, let it fail. */ - pushw %ds - pushw %ax - xorw %ax, %ax - movw %ax, %ds - movw 0x803, %ax /* int 10 segment */ - cmpw $0xC000, %ax - jb 6f - movw 0x808, %ax /* int 13 segment */ - cmpw $0xC000, %ax - jb 6f - movw 0x80D, %ax /* int 15 segment */ - cmpw $0xC000, %ax - jb 6f - movw 0x812, %ax /* int 19 segment */ - cmpw $0xC000, %ax - jb 6f - movw 0x817, %ax /* int 1B segment */ - cmpw $0xC000, %ax - jb 6f - movw 0x81C, %ax /* int 4F segment */ - cmpw $0xC000, %ax - jb 6f - movw 0x821, %ax /* int 08 segment */ - cmpw $0xC000, %ax - jb 6f - movw 0x826, %ax /* int 0F segment */ - cmpw $0xC000, %ax - jb 6f - movw 0x82B, %ax /* int 16 segment */ - cmpw $0xC000, %ax - jb 6f - movb 0x800, %al /* should be 0x10 */ - cmpb $0x10, %al - jne 6f - movb 0x805, %al /* should be 0x13 */ - cmpb $0x13, %al - jne 6f - movb 0x80A, %al /* should be 0x15 */ - cmpb $0x15, %al - jne 6f - movb 0x80F, %al /* should be 0x19 */ - cmpb $0x19, %al - jne 6f - movb 0x814, %al /* should be 0x1B */ - cmpb $0x1B, %al - jne 6f - movb 0x819, %al /* should be 0x4F */ - cmpb $0x4F, %al - jne 6f - movb 0x81E, %al /* should be 0x08 */ - cmpb $0x08, %al - jne 6f - movb 0x823, %al /* should be 0x0F */ - cmpb $0x0F, %al - jne 6f - movb 0x828, %al /* should be 0x16 */ - cmpb $0x16, %al - jne 6f - movl 0x5D6, %eax /* int 4B segment */ - cmpw $0xC000, %ax - jb 6f - movl 0x5D8, %eax /* int 4F */ - cmpl 0x81A, %eax /* int 4F */ - //jne 6f -6: - popw %ax - popw %ds - jne 9f /* it is not MS-DOS. Failure. */ - - cmpw $ABS_START(bios_interrupt_vector_table) + 0x4C, %di /* int 13 */ - jne 7f - movl 0x806, %eax - jmp 2f -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x12C, %di /* int 4B */ - jne 9f /* failure */ - movl 0x5D4, %eax - jmp 2f -5: - /* now in VM86 mode(EMM386). check if the ROM routine is writable. */ - - pushl %eax - pushw %ds - pushw %si - movw %ax, %si - shrl $16, %eax - movw %ax, %ds - movw (%si), %ax /* save original word at CS:IP to AX. */ - notw (%si) /* toggle each bit. */ - cmpw (%si), %ax /* is it changed? */ - notw (%si) /* toggle back. The NOT won't change flags. */ - popw %si - popw %ds - popl %eax - je 2f /* equal, so it is in ROM and won't touch. */ - -8: - /* if it points to an IRET, set it to dummy iret */ - pushw %ds - pushw %si - ldsw -4(%si), %si - cmpb $0xCF, (%si) /* 0xCF=iret */ - popw %si - popw %ds - je 3f - - /* if it points to beyond the low mem, we accept it. */ - cmpl $0xC0000000, %eax - jnb 8f - cmpl $0x5A000000, %eax - jb 8f - pushw %ds - pushw %bx - pushw %cx - xorw %bx, %bx - movw %bx, %ds /* DS=0 */ - movw 0x413, %bx /* low mem size in KB */ - shlw $6, %bx /* low mem size in paragraphs */ - pushl %eax /* the vector */ - popw %cx - popw %cx /* segment value of the vector */ - cmpw %bx, %cx - popw %cx - popw %bx - popw %ds - jnb 2f -8: - /* set int 00, 01, 03, 04, 07 to dummy */ - cmpw $ABS_START(bios_interrupt_vector_table) + 0x08, %di - jb 3f /* int 00, 01 */ - ja 8f - - /* int 02 External hardware - NON-MASKABLE INTERRUPT */ - - /* Desc: Generated by the CPU when the input to the NMI pin is asserted. */ - - /* Notes: Return address points to start of interrupted instruction on - * 80286+. On the 80286+, further NMIs are disabled until the next IRET - * instruction, but one additional NMI is remembered by the hardware - * and will be serviced after the IRET instruction reenables NMIs. - * Maskable interrupts may interrupt the NMI handler if interrupts are - * enabled. Although the Intel documentation states that this interrupt - * is typically used for power-failure procedures, it has many other - * uses on IBM-compatible machines: Memory parity error, Coprocessor - * interrupt, Keyboard interrupt, I/O channel check, Disk-controller - * power-on request, System suspend, Real-time clock, System watch-dog - * timer time-out interrupt, DMA timer time-out interrupt, Low battery, - * Module pulled. - */ - - #; jmp 4f /* qemu sets this to dummy. */ - call restore_vector - - /* if failure, we set it to dummy */ - jc 3f //jc 9f - - jmp 2f -8: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x0C, %di /* int 03 */ - je 3f - cmpw $ABS_START(bios_interrupt_vector_table) + 0x10, %di /* int 04 */ - je 3f - cmpw $ABS_START(bios_interrupt_vector_table) + 0x14, %di /* int 05 */ - jne 8f -// je 3f - - /* once again DELL places garbage string "LL FX09 " over int03-05 - * to prevent/block our probing mechanism. We have to cancel this probing. - */ - - ///* qemu sets this to dummy. */ - //call restore_vector - //jc 3f - //jmp 2f - jmp 3f /* set to dummy */ -8: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x18, %di /* int 06 */ - jne 8f -#if 1 - /* FreeDOS takes over int06, so we couldn't probe it. Set it to dummy. */ - jmp 3f -#else - #; jmp 6f /* qemu sets this to dummy. */ - call restore_vector - - /* if failure, we set it to dummy */ - jc 3f //jc 9f - - jmp 2f -#endif -8: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x1C, %di /* int 07 */ - je 3f - cmpw $ABS_START(bios_interrupt_vector_table) + 0x20, %di /* int 08-0f hardware IRQs */ - jb 7f - cmpw $ABS_START(bios_interrupt_vector_table) + 0x40, %di - jnb 7f - cmpl $0, %cs:ABS_START(dos_version) /* known DOS? */ - jne 2f /* do not probe */ - call restore_vector - jnc 2f - cmpw $ABS_START(bios_interrupt_vector_table) + 0x30, %di /* int 0C */ - je 3f /* set to dummy */ - cmpw $ABS_START(bios_interrupt_vector_table) + 0x34, %di /* int 0D */ - je 3f /* set to dummy */ - jmp 9f -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x1C0, %di /* int 70-77 hardware IRQs */ - jb 7f - cmpw $ABS_START(bios_interrupt_vector_table) + 0x1E0, %di - jnb 7f - cmpl $0, %cs:ABS_START(dos_version) /* known DOS? */ - jne 2f /* do not probe */ - call restore_vector - jc 9f - jmp 2f -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x40, %di /* int 10, VIDEO */ - jne 7f - - /* teletype output a space char */ - movw $0x0E20, %ax - xorw %bx, %bx - call restore_vector - jc 9f - jmp 2f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x44, %di /* int 11, GET EQUIPMENT LIST */ - jne 7f - call restore_vector - jc 9f - jmp 2f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x48, %di /* int 12, GET MEMORY SIZE */ - jne 7f - call restore_vector - jc 9f - jmp 2f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x4C, %di /* int 13, DISK */ - jne 7f - - /* If we track it by reading a sector, we could track into protected - * mode or into int15/ah=87h for a RAM disk. So we only check the - * status of the drives. - */ - - /* GET STATUS OF LAST OPERATION */ - - movb $0, %dl /* try each drive 00 - FF */ -8: - movb $1, %ah - call restore_vector - jnc 2f - - /* try next floppy */ - incb %dl /* INC won't touch CF */ - jnz 8b - - jmp 9f /* CF=1 */ - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x50, %di /* int 14, SERIAL */ - jne 7f - - /* GET PORT STATUS */ - movw $0x0300, %ax - movw $0, %dx /* port number */ - call restore_vector - jc 9f - jmp 2f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x54, %di /* int 15, SYSTEM service */ - jne 7f - - /* later PS/2s - GET A20 GATE STATUS */ - movw $0x2402, %ax - call restore_vector - jnc 2f - /* BIOS - JOYSTICK SUPPORT (XT after 1982/11/8, AT, XT286, PS) */ - movw $0x8400, %ax - movw $0x0000, %dx /* subfunction: read joystick switches */ - call restore_vector - jnc 2f - /* SYSTEM - GET CONFIGURATION (XT >1986/1/10, AT mdl 3x9, CONV, XT286, PS) */ - movw $0xC000, %ax - call restore_vector - jnc 2f - jmp 9f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x58, %di /* int 16, KEYBOARD */ - jne 7f - - /* GET KEYBOARD FUNCTIONALITY */ - movw $0x0900, %ax - call restore_vector - jnc 2f - - /* GET KEYBOARD ID */ - movw $0x0A00, %ax - call restore_vector - jnc 2f - jmp 9f /* CF=1 */ - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x5C, %di /* int 17, PRINTER */ - jne 7f - - /* GET STATUS */ - movw $0x0200, %ax - movw $0, %dx /* port number */ - call restore_vector - jnc 2f - jmp 9f /* CF=1 */ - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x60, %di /* int 18, BOOT FAILURE */ - jne 7f - - /* We should not try to call this interrupt! */ - jmp 3f /* simply set to dummy */ - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x64, %di /* int 19, SYSTEM - BOOTSTRAP LOADER */ - jne 7f - - /* We should not try to call this interrupt! */ - jmp 3f /* simply set to dummy */ - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x68, %di /* int 1A, TIME and PCI BIOS */ - jne 7f - - /* Tracking into TIMER could hang the system when accessing CMOS! */ - - /* PCI BIOS needs too much stack, so do not call it. */ - - /* Call it with unknown function. */ - movw $0xFFFF, %ax - call restore_vector - jnc 2f - jmp 9f /* CF=1 */ - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x6C, %di /* int 1B, KEYBOARD - CONTROL-BREAK HANDLER */ - jne 7f - - /* Tracking into int 1B could break GRUB.EXE and return to DOS! */ - - /* BIOS sets this to dummy iret */ - - jmp 3f /* simply set to dummy */ - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x70, %di /* int 1C, TIME - SYSTEM TIMER TICK */ - jne 7f - - /* BIOS sets this to dummy iret */ - - jmp 3f /* simply set to dummy */ - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x74, %di /* int 1D, SYSTEM DATA - VIDEO PARAMETER TABLES */ - jne 7f - - /* Notes: The default parameter table is located at F000h:F0A4h - * for 100% compatible BIOSes. Under PhysTechSoft's PTS ROM-DOS - * this table is fictitious. ---- Ralf Brown's Interrupt List - */ - - /* QEMU sets this to dummy iret. It is not proper. */ - - /* DOS should not change this vector. */ - - pushw %ax - smsw %ax - testb $1, %al - popw %ax - jz 8f /* running in real-mode */ - - /* running in VM86 mode */ - cmpl $0xC0000000, %eax - jnb 2f - -8: - stc - jmp 9f /* CF=1 */ - - //movl $0xF000F0A4, %eax - //jmp 2f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x78, %di /* int 1E, SYSTEM DATA - DISKETTE PARAMETERS */ - jne 7f - - /* Notes: The default parameter table is located at F000h:EFC7h - * for 100% compatible BIOSes. - */ - - /* QEMU sets this to F000h:EFDFh. It is not proper. */ - - /* We can get this vector by calling int13/ah=8h (GET DRIVE PARAMETERS). - */ - - /* original floppy parameter table */ - - #; Do not call int13 if it has not been restored. - - cmpl $0xC000, ABS_START(bios_interrupt_vector_table) + 0x4E - jb 2f - - cmpl $0xF000, ABS_START(bios_interrupt_vector_table) + 0x4E - ja 2f - - pushw %cx - pushw %ds - pushw %si - pushw %es - pushw %di - pushl %eax - - movb $8, %ah - movb $0, %dl - stc - #; int $0x13 - pushfw - lcall *ABS_START(bios_interrupt_vector_table) + 0x4C - jc 8f - orw %bx, %ax - orw %cx, %ax - jz 8f - movw %es, %ax - testw %ax, %ax - jz 8f - popl %eax - pushw %es - pushw %di -8: - popl %eax - popw %di - popw %es - popw %si - popw %ds - popw %cx - jmp 2f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x7C, %di /* int 1F, SYSTEM DATA - 8 x 8 GRAPHICS FONT */ - jne 7f - - /* This vector points at 1024 bytes of graphics data, 8 bytes for - * each character 80h-FFh. - */ - - /* Notes: Graphics data for characters 00h-7Fh stored at F000h:FA6Eh - * in 100% compatible BIOSes. Under PhysTechSoft's PTS ROM-DOS this - * table is fictitious. ---- Ralf Brown's Interrupt List - */ - - /* System VGA BIOS sets to 0:0, Video Card usually sets to C000:xxxx */ - - /* We can get this vector by calling int10/ax=1130h/bh=04h - * (GET FONT INFORMATION). - */ - - /* get original font */ - - #; Do not call int10 if it has not been restored. - - cmpl $0xC000, ABS_START(bios_interrupt_vector_table) + 0x42 - jb 2f - - cmpl $0xF000, ABS_START(bios_interrupt_vector_table) + 0x42 - ja 2f - - pushw %cx - pushw %ds - pushw %si - pushw %es - pushw %di - pushl %eax - - movw $0x1130, %ax - movb $4, %bh - #; int $0x10 - pushfw - lcall *ABS_START(bios_interrupt_vector_table) + 0x40 - movw %es, %ax - cmpw $0xC000, %ax - jb 8f - popl %eax - pushw %es - pushw %bp -8: - popl %eax - popw %di - popw %es - popw %si - popw %ds - popw %cx - jmp 2f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x100, %di /* int 40, original ROM BIOS DISKETTE HANDLER */ - jne 7f - - /* This is ROM BIOS diskette handler relocated by hard disk BIOS. */ - - /* GET STATUS OF LAST OPERATION */ - - movb $0, %dl -8: - movb $1, %ah - call restore_vector - jnc 2f - incb %dl - cmpb $2, %dl - jnz 8b - stc - jmp 9f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0xC0, %di /* int 30 */ - jne 7f - - /* It seems BIOS set this interrupt to dummy iret. */ - jmp 3f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x104, %di /* int 41, SYSTEM DATA - HARD DISK 0 */ - jne 7f - - /* SYSTEM DATA(NOT A VECTOR!) - HARD DISK 0 PARAMETER TABLE ADDRESS */ - - /* DOS should not change this vector. */ - - /* It is hard to retrieve this vector. Hopefully int13/ah=09h never be called. */ - jmp 2f -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x118, %di /* int 46, SYSTEM DATA - HARD DISK 1 */ - jne 7f - - /* SYSTEM DATA(NOT A VECTOR!) - HARD DISK 1 PARAMETER TABLE ADDRESS */ - - /* DOS should not change this vector. */ - - /* It is hard to retrieve this vector. Hopefully int13/ah=09h never be called. */ - jmp 2f -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x108, %di /* int 42, RELOCATED INT 10 VIDEO SERVICES */ - jne 7f - - /* Desc: Contains the address of the original INT 10 handler which - * an EGA+ video adapter replaces with its own on-board BIOS code. - */ - - /* DOS should not change this vector. */ - - pushw %ax - smsw %ax - testb $1, %al - popw %ax - jz 8f /* running in real-mode */ - - /* running in VM86 mode */ - cmpl $0xC0000000, %eax - jnb 2f - -8: - stc - jmp 9f - - /* The vector is generally not used any longer. */ - //jmp 2f -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x10C, %di /* int 43, VIDEO DATA - CHARACTER TABLE */ - jne 7f - - /* VIDEO DATA(NOT A VECTOR!) - Points at graphics data for characters - * 00h-7Fh of the current font in 8 x 8 dot modes, graphics data for - * all characters in 8 x 14 and 8 x 16 modes. - */ - - /* We can get this vector by calling int10/ax=1130h/bh=03h - * (GET FONT INFORMATION). - */ - - /* get original font */ - - #; Do not call int10 if it has not been restored. - - cmpl $0xC000, ABS_START(bios_interrupt_vector_table) + 0x42 - jb 2f - - cmpl $0xF000, ABS_START(bios_interrupt_vector_table) + 0x42 - ja 2f - - pushw %cx - pushw %ds - pushw %si - pushw %es - pushw %di - pushl %eax - - movw $0x1130, %ax - movb $3, %bh - #; int $0x10 - pushfw - lcall *ABS_START(bios_interrupt_vector_table) + 0x40 - movw %es, %ax - cmpw $0xC000, %ax - jb 8f - popl %eax - pushw %es - pushw %bp -8: - popl %eax - popw %di - popw %es - popw %si - popw %ds - popw %cx - jmp 2f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x110, %di /* int 44, undocumented */ - jne 7f - - /* VIDEO DATA - ROM BIOS CHARACTER FONT, CHARACTERS 00h-7Fh (PCjr) - * This vector points at graphics data for current character font. - * ---- Ralf Brown's Interrupt List - */ - - /* Ralf Brown's Interrupt List seems wrong for this interrupt. - * And it seems BIOS set this interrupt to dummy iret. - */ - - /* DOS should not change this vector. */ - - pushw %ax - smsw %ax - testb $1, %al - popw %ax - jz 8f /* running in real-mode */ - - /* running in VM86 mode */ - cmpl $0xC0000000, %eax - jnb 2f - -8: - stc - jmp 9f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x114, %di /* int 45, undocumented */ - jne 7f - - /* It seems BIOS set this interrupt to dummy iret. */ - - /* DOS should not change this vector. */ - - pushw %ax - smsw %ax - testb $1, %al - popw %ax - jz 8f /* running in real-mode */ - - /* running in VM86 mode */ - cmpl $0xC0000000, %eax - jnb 2f - -8: - //stc - //jmp 9f - /* video card 'kyro2' is reported to have destroyed this vector. - * tinybit 2011-11-21 - */ - jmp 2f - -7: - - cmpw $ABS_START(bios_interrupt_vector_table) + 0x11C, %di /* int 47, undocumented */ - jne 7f - - /* It seems BIOS set this interrupt to dummy iret. */ - - /* DOS should not change this vector. */ - - pushw %ax - smsw %ax - testb $1, %al - popw %ax - jz 8f /* running in real-mode */ - - /* running in VM86 mode */ - cmpl $0xC0000000, %eax - jnb 2f - -8: - stc - jmp 9f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x120, %di /* int 48, undocumented keyboard */ - jne 7f - - /* It seems BIOS set this interrupt to dummy iret. */ - - /* DOS should not change this vector. */ - - pushw %ax - smsw %ax - testb $1, %al - popw %ax - jz 8f /* running in real-mode */ - - /* running in VM86 mode */ - cmpl $0xC0000000, %eax - jnb 2f - -8: - stc - jmp 9f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x124, %di /* int 49, undocumented */ - jne 7f - - /* SYSTEM DATA - NON-KEYBOARD SCAN-CODE TRANSLATION TABLE (PCjr) - * ---- Ralf Brown's Interrupt List - */ - - /* Ralf Brown's Interrupt List seems wrong for this interrupt. - * And it seems BIOS set this interrupt to dummy iret. - */ - - /* DOS should not change this vector. */ - - pushw %ax - smsw %ax - testb $1, %al - popw %ax - jz 8f /* running in real-mode */ - - /* running in VM86 mode */ - cmpl $0xC0000000, %eax - jnb 2f - -8: - stc - jmp 9f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x128, %di /* int 4A, SYSTEM - USER ALARM HANDLER */ - jne 7f - - /* Desc: This interrupt is invoked by the BIOS when a real-time - * clock alarm occurs. An application may use it to perform an - * action at a predetermined time. - * - * Note: This interrupt is called from within a hardware - * interrupt handler, so all usual precautions against - * reentering DOS must be taken. - * ---- Ralf Brown's Interrupt List - */ - - /* It seems BIOS set this interrupt to dummy iret. */ - - /* DOS should not change this vector. */ - - pushw %ax - smsw %ax - testb $1, %al - popw %ax - jz 8f /* running in real-mode */ - - /* running in VM86 mode */ - cmpl $0xC0000000, %eax - jnb 2f - -8: - stc - jmp 9f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x12C, %di /* int 4B, Virtual DMA Specification (VDS) */ - jne 7f - - #;/* It seems BIOS set this interrupt to dummy iret. */ - #;jmp 3f - - /* Virtual DMA Specification (VDS) - GET VERSION */ - /* Int 4B/AX=8102h/DX=0000h */ - - //movw $0x8102, %ax - movw $0xFFFF, %ax /* use an unknown function call */ - movw $0, %dx - call restore_vector - jc 9f - jmp 2f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x130, %di /* int 4C, undocumented */ - jne 7f - - #;/* It seems BIOS set this interrupt to dummy iret. */ - #;jmp 3f - - movw $0xFFFF, %ax /* use an unknown function call */ - call restore_vector - //jc 9f - jc 3f /* set to dummy on failure */ - jmp 2f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x134, %di /* int 4D, undocumented */ - jne 7f - - #;/* It seems BIOS set this interrupt to dummy iret. */ - #;jmp 3f - - movw $0xFFFF, %ax /* use an unknown function call */ - call restore_vector - //jc 9f - jc 3f /* set to dummy on failure */ - jmp 2f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x138, %di /* int 4E, undocumented */ - jne 7f - - #;/* It seems BIOS set this interrupt to dummy iret. */ - #;jmp 3f - - movw $0xFFFF, %ax /* use an unknown function call */ - call restore_vector - //jc 9f - jc 3f /* set to dummy on failure */ - jmp 2f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x13C, %di /* int 4F, undocumented */ - jne 7f - - #;/* It seems BIOS set this interrupt to dummy iret. */ - #;jmp 3f - - movw $0xFFFF, %ax /* use an unknown function call */ - call restore_vector - //jc 9f - jc 3f /* set to dummy on failure */ - jmp 2f - -7: -#if 0 - cmpw $ABS_START(bios_interrupt_vector_table) + 0x170, %di /* int 5C, NetBIOS INTERFACE */ - jne 7f - - /* Windows revectored this interrupt. */ - - /* It seems BIOS set this interrupt to dummy iret. */ - jmp 3f - -7: -#endif - cmpw $ABS_START(bios_interrupt_vector_table) + 0x140, %di /* int 50 - 5F */ - jb 7f - cmpw $ABS_START(bios_interrupt_vector_table) + 0x180, %di - jnb 7f - -#if 0 - #;/* It seems BIOS set this interrupt to dummy iret. */ - #;jmp 3f - - movw $0xFFFF, %ax /* use an unknown function call */ - call restore_vector - jc 9f - jmp 2f -#else - /* Windows revectored INT 5C(NetBIOS Interface). */ - /* It seems DOS does not change this vector. */ - - /* It seems BIOS set this interrupt to dummy iret. */ - /* It hangs on Haier MX510-28 after : ... 55 56! 57! 58 59 - * so we simply set it to dummy */ - jmp 3f -#endif - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x180, %di /* int 60 - 67 */ - jb 7f - cmpw $ABS_START(bios_interrupt_vector_table) + 0x1A0, %di - jnb 7f - - /* It seems BIOS set this interrupt to 0:0. */ - xorl %eax, %eax - jmp 2f - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x1B4, %di /* int 6D, VIDEO BIOS ENTRY POINT */ - jne 7f - - /* DOS should not change this vector. */ - - pushw %ax - smsw %ax - testb $1, %al - popw %ax - jz 8f /* running in real-mode */ - - /* running in VM86 mode */ - cmpl $0xC0000000, %eax - jnb 2f - -8: -#if 0 - stc - jmp 9f -#else - /* Ignore the error and simply set to dummy */ - jmp 3f -#endif - -7: - cmpw $ABS_START(bios_interrupt_vector_table) + 0x1A0, %di /* int 68 - 6F */ - jb 7f - cmpw $ABS_START(bios_interrupt_vector_table) + 0x1C0, %di - jnb 7f - -#if 0 - #;/* It seems BIOS set this interrupt to dummy iret. */ - #;jmp 3f - - movw $0xFFFF, %ax /* use an unknown function call */ - call restore_vector - jc 3f //jc 9f - jmp 2f -#else - /* It seems DOS does not change this vector. */ - - /* It seems BIOS set int 6D to C000:xxxx and set others to dummy. */ - /* For safety we simply set it to dummy */ - jmp 3f -#endif - -7: - - cmpw $ABS_START(bios_interrupt_vector_table) + 0x1E0, %di /* int 78 - 7F */ - jb 7f - cmpw $ABS_START(bios_interrupt_vector_table) + 0x200, %di - jnb 7f - - /* It seems BIOS set this interrupt to 0:0. */ - xorl %eax, %eax - jmp 2f - -7: - /* other vectors won't touch */ - jmp 2f - -#; 6: -#; /* int 06, bad code interrupt. */ -#; /* qemu sets this to dummy, so can we. */ - -#; 5: -#; /* int 05 */ -#; /* qemu sets this to dummy, so can we. */ - -#; 4: -#; /* int 02 */ -#; /* qemu sets this to dummy, so can we. */ - -3: - /* dummy iret vector */ - movl ABS_START(dummy_iret_vector), %eax -2: - stosl - jmp 2f -9: - testb %ch, %ch /* save the first failed vector ... */ - jnz 3f - movb %cl, %ch /* ... in CH */ -3: - addw $4, %di - - /* print an "!" for failure */ - - pushw %ds - pushw %es - pushal - - xorw %bx, %bx - movw $0x0e21, %ax /* 0x21 = "!" */ - int $0x10 - - popal - popw %es - popw %ds - - -2: - incb %cl - cmpb $0x80, %cl - jb 1b - - movb %ch, %cl - negb %ch /* CF=1 if CH is non-zero */ - - ret - -probe_int_hang_string: - .ascii "\r\nProbing ROM INT vectors. If hang, unload a device driver or TSR and try again.\r\n\0" - -restore_vector: - #; input: - #; DI points to vector in bios_interrupt_vector_table - #; output: - #; CF=0 success, EAX=the restored ROM vector - #; CF=1 failure, EAX destroyed. - - /* Note for people who are tracing/debugging this program: - * This is where int 00 - 07, 10 will be replaced and restored. - * Take care! - */ - - /* replace int1 and int2 handler */ - pushw %ax - pushw %es - pushw %di - xorw %ax, %ax - movw %ax, ABS_START(tmp_vector + 2) /* clear the segment value */ - movw %ax, %es /* ES=0 */ - movw $4, %di /* ES:DI=0000:0004 */ - movw $ABS_START(int1_handler), %ax - cld - stosw /* setup new int1 handler offset */ - movw %cs, %ax - stosw /* setup new int1 handler segment */ - movw $ABS_START(int2_handler), %ax - stosw /* setup new int2 handler offset */ - movw %cs, %ax - stosw /* setup new int2 handler segment */ - popw %di - popw %es - popw %ax - - ///* clear tmp_vector */ - //movl $0, ABS_START(tmp_vector) #; DS=CS - movw %di, ABS_START(tmp_vector) /* offset set to DI */ - - #;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - /* setup our fault recovery handler */ - - pushw %es - pushw %di - pushl %eax - - xorw %di, %di - movw %di, %es /* ES:DI=0000:0000 */ - - /* set EAX=CS:fault_recovery_handler */ - pushw %cs - pushw $ABS_START(fault_recovery_handler) - popl %eax - - /* Catch CPU exceptions 0, 3, 4, 5, 6, 7 - * 0 Divide - * 1 Debug - handled by int1_handler - * 2 NMI - * 3 Break point - * 4 Overflow - * 5 Bound - * 6 Invalid Instruction - * 7 no coprocessor - */ - - cld - stosl /* setup int 00 */ - addw $8, %di /* skip int 01 and int 02 */ - stosl /* setup int 03 */ - stosl /* setup int 04 */ - stosl /* setup int 05 */ - stosl /* setup int 06 */ - stosl /* setup int 07 */ - addw $(4 * 8), %di /* skip int 08 - 0F */ - stosl /* setup int 10 */ - - popl %eax - popw %di - popw %es - - /* backup old registers. */ - - movw %ds, %cs:ABS_START(original_registers) - movw %es, %cs:ABS_START(original_registers) + 4 - movw %ss, %cs:ABS_START(original_registers) + 8 - movl %esp, %cs:ABS_START(original_registers) + 12 - movl %eax, %cs:ABS_START(original_registers) + 16 - movl %ebx, %cs:ABS_START(original_registers) + 20 - movl %ecx, %cs:ABS_START(original_registers) + 24 - movl %edx, %cs:ABS_START(original_registers) + 28 - movl %esi, %cs:ABS_START(original_registers) + 32 - movl %edi, %cs:ABS_START(original_registers) + 36 - movl %ebp, %cs:ABS_START(original_registers) + 40 - #;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - pushw %ds - pushw %es - pushaw - - /* additional PUSHF/POPF are required because some BIOS INT service - * routines will end with `ret 02' instead of `iret'. - * The `ret 02' does not clear TF, while `iret' does. - * With additional PUSHF/POPF, the TF can be safely cleared. - */ - - cli /* added 2010-05-25 */ - pushfw /* additional PUSHF */ - //cli /* added 2008-08-04, commented out 2010-05-25 */ - pushfw /* PUSHF here together with LCALL below form an INT */ - - /* set the TF flag */ - pushw %ax - pushfw - popw %ax - orw $0x100, %ax - pushw %ax - popfw - popw %ax - - lcall *(%di) /* PUSHF above together with LCALL here form an INT */ - - //sti /* added 2008-08-04, commented out 2010-05-25 */ - popfw /* additional POPF */ - - /* TF is cleared here automatically */ - - popaw - popw %es - popw %ds - -restore_int_00_1F: - - cli - - pushl $0 - popfl #; CLD, CLI, Clear TF and many more... - - //sti /* added 2008-08-04, commented out 2010-05-25 */ - /* restore the original int 00 - 1F vectors */ - pushw %cs - popw %ds /* DS=CS */ - pushw %cs - popw %es /* ES=CS */ - - pushw %es - pushw %di - pushw %si - pushw %cx - movw $ABS_START(orig_int_00_1F_vectors), %si - xorw %di, %di - movw %di, %es /* ES:DI=0000:0000 */ - movw $32, %cx - - //cli /* added 2008-08-04, commented out 2010-05-25 */ - cld - repz movsl - sti /* added 2008-08-04 */ - - popw %cx - popw %si - popw %di - popw %es - - /* failure? */ - movl ABS_START(tmp_vector), %eax - cmpl $0x5A000000, %eax // cmpl $0xC0000000, %eax - - /* CF=1 for failure. EAX below 0xC0000000 is not a ROM vector. - * CF=0 for success. EAX is a ROM vector. - */ - - ret - -/* - * Check if the next instruction is in ROM, and if this is true, store the - * entry point to tmp_vector and terminate the tracking. - * - */ -int1_handler: - cli /* so that we won't take up too much stack. */ - pushw %bp - movw %sp, %bp - pushl %eax - - /* if we have got the vector, we clear TF flag to end the tracking. */ - cmpl $0x5A000000, %cs:ABS_START(tmp_vector) // cmpl $0xC0000000, %cs:ABS_START(tmp_vector) - jnb 4f - - movl 2(%bp), %eax /* CS:IP of the next instruction */ - cmpl $0xC0000000, %eax - jnb 2f - - /* if it points to beyond the low mem, we accept it. */ - cmpl $0x5A000000, %eax - jb 1f - pushw %ds - pushw %bx - pushw %cx - xorw %bx, %bx - movw %bx, %ds /* DS=0 */ - movw 0x413, %bx /* low mem size in KB */ - shlw $6, %bx /* low mem size in paragraphs */ - pushl %eax /* the vector */ - popw %cx - popw %cx /* segment value of the vector */ - cmpw %bx, %cx - popw %cx - popw %bx - popw %ds - jnb 5f - jmp 1f -2: - /* calculate linear address of CS:IP in EAX */ - - pushl %eax - pushl %ebx - movl %eax, %ebx - xorw %bx, %bx - shrl $12, %ebx - movzwl %ax, %eax - addl %eax, %ebx /* EBX=linear address */ - cmpl $0x100000, %ebx /* is it below 1M? */ - popl %ebx - popl %eax - jnb 1f /* not below, so it is not in ROM. */ - - /* it is in the ROM range. */ - /* if in real mode, then it is ROM vector. */ - - pushw %ax - smsw %ax - testb $1, %al - popw %ax - jz 5f /* in real mode, so it is ROM vector. */ - - /* now in VM86 mode. check if the ROM routine at CS:IP is writable. */ - - pushl %eax - pushw %ds - pushw %si - movw %ax, %si - shrl $16, %eax - movw %ax, %ds - movw (%si), %ax /* save original word at CS:IP to AX. */ - notw (%si) /* toggle each bit. */ - cmpw (%si), %ax /* is it changed? */ - notw (%si) /* toggle back. The NOT won't change flags. */ - popw %si - popw %ds - popl %eax - je 5f /* equal means read-only */ - - /* not equal, so it is writable. */ - call is_in_umb - jnc 1f /* yes, in umb. so it is not a ROM vector. */ -5: - /* This is the entry point in ROM */ - - /* It could hang when we call int 02 on some machines, so we end it. */ - /* It could hang when we call int 08 on some machines, so we end it. */ - /* It could hang when we call int 76 on some machines, so we end it. */ - /* It could hang when we call int 05 on some machines, so we end it. */ - /* It might cause OS boot failure when we call int 0F on some machines, so we end it. */ - - /* %cs:ABS_START(tmp_vector) stores DI which points to the current vector */ - - //pushl %eax - //movl %cs:ABS_START(tmp_vector), %eax - //popl %cs:ABS_START(tmp_vector) - xchgl %eax, %cs:ABS_START(tmp_vector) - - /* current stack - * BP +12: Flags for the iret - * BP + 8: return address for the iret - * BP + 6: Flags - * BP + 2: CS:IP of next instruction - * BP : old BP - * BP - 4: old EAX - */ - - -#if 1 - cmpl $ABS_START(bios_interrupt_vector_table) + 0x08, %eax - je fault_recovery_handler /* it is int 02, stop now */ - cmpl $ABS_START(bios_interrupt_vector_table) + 0x20, %eax - je fault_recovery_handler /* it is int 08, stop now */ - cmpl $ABS_START(bios_interrupt_vector_table) + 0x1D8, %eax - je fault_recovery_handler /* it is int 76, stop now */ - cmpl $ABS_START(bios_interrupt_vector_table) + 0x14, %eax - je fault_recovery_handler /* it is int 05, stop now */ - cmpl $ABS_START(bios_interrupt_vector_table) + 0x3C, %eax - je fault_recovery_handler /* it is int 0F, stop now */ - - /* not int 02, 08, 76, 05, 0F, continue */ -#else - - /* Don't track into ROM. Return now. */ - - /* clear the TF flag */ - andb $0xFE, 13(%bp) - - /* restore registers */ - popl %eax - popw %bp - - addw $6, %sp - - iret - //jmp fault_recovery_handler /* stop for INTs */ -#endif - -4: - -#if 1 - /* clear the TF flag */ - andb $0xFE, 7(%bp) - -// /* unhook int1 handler */ -// -// movl %cs:ABS_START(dummy_iret_vector), %eax -// pushw %ds -// pushw %si -// xorw %si, %si -// movw %si, %ds /* DS:SI=0000:0000 */ -// movl %eax, 4(%si) -// popw %si -// popw %ds - -#else - /* we can not go directly to fault_recovery_handler. */ - //pushl $0 /* Clear TF */ - //popfl - //jmp fault_recovery_handler - - /* clear the TF flag */ - andb $0xFE, 7(%bp) - -// /* unhook int1 handler */ -// -// movl %cs:ABS_START(dummy_iret_vector), %eax -// pushw %ds -// pushw %si -// xorw %si, %si -// movw %si, %ds /* DS:SI=0000:0000 */ -// movl %eax, 4(%si) -// popw %si -// popw %ds - - /* set the CF flag to indicate an error for the int call */ - orb $0x01, 12(%bp) /* Note: this should not be 6(%bp) */ - - /* set the return address to dummy iret */ - movl %cs:ABS_START(dummy_iret_vector), %eax - movl %eax, 2(%bp) - -#endif - -1: - /* restore registers */ - popl %eax - popw %bp - - iret - -is_in_umb: - - pushal - movw $ABS_START(umb_array), %si - movl %eax, %ebx - movzwl %ax, %eax - shrl $16, %ebx - shll $4, %ebx - addl %eax, %ebx - movw $8, %cx -1: - cld - cs lodsl /* start segment */ - testw %ax, %ax - jz 1f - movl %eax, %edx - movzwl %ax, %eax - shll $4, %eax - cmpl %eax, %ebx - jbe 1f - shrl $16, %edx - shll $4, %edx - addl %edx, %eax - cmpl %ebx, %eax - ja 2f /* found umb, CF=0 */ - loop 1b -1: - stc -2: - popal - ret - - .align 4 - -umb_array: - .word 0 /* 1, start segment */ - .word 0 /* 1, length in paragraphs */ - .word 0 /* 2, start segment */ - .word 0 /* 2, length in paragraphs */ - .word 0 /* 3, start segment */ - .word 0 /* 3, length in paragraphs */ - .word 0 /* 4, start segment */ - .word 0 /* 4, length in paragraphs */ - .word 0 /* 5, start segment */ - .word 0 /* 5, length in paragraphs */ - .word 0 /* 6, start segment */ - .word 0 /* 6, length in paragraphs */ - .word 0 /* 7, start segment */ - .word 0 /* 7, length in paragraphs */ - .word 0 /* 8, start segment */ - .word 0 /* 8, length in paragraphs */ - .word 0 /* end array with a null */ - .word 0 /* end array with a null */ - -#if 0 /* marked out in 2008-05-07 */ -tmp_int13_vector: - .word 0 - .word 0 - -tmp_int15_vector: - .word 0 - .word 0 -#endif - -tmp_vector: - .word 0 - .word 0 - -dummy_iret_vector: - .word 0 - .word 0 - -orig_int_00_1F_vectors: - .space 128 - -original_registers: - .space 48 - -fault_recovery_handler: - - /* restore old registers. */ - - /* stack validated first */ - - movw %cs:ABS_START(original_registers) + 8, %ss - movl %cs:ABS_START(original_registers) + 12, %esp - - /* stack is available, so we can push and pop. */ - - pushl $0 - popfl #; CLD, CLI, Clear TF and many more... - - //cli /* marked off 2008-08-04 */ - //sti /* added 2008-08-04, commented out 2010-05-25 */ - movw %cs:ABS_START(original_registers), %ds - movw %cs:ABS_START(original_registers) + 4, %es - //movw %cs:ABS_START(original_registers) + 8, %ss - //movl %cs:ABS_START(original_registers) + 12, %esp - movl %cs:ABS_START(original_registers) + 16, %eax - movl %cs:ABS_START(original_registers) + 20, %ebx - movl %cs:ABS_START(original_registers) + 24, %ecx - movl %cs:ABS_START(original_registers) + 28, %edx - movl %cs:ABS_START(original_registers) + 32, %esi - movl %cs:ABS_START(original_registers) + 36, %edi - movl %cs:ABS_START(original_registers) + 40, %ebp - - pushw $ABS_START(restore_int_00_1F) /* return address */ - ret - - /* never come here. */ - -int2_handler: - - /* do nothing for NMI */ - - iret - -print_cl: - pushw %ds - pushw %es - pushal - - xchgw %ax, %cx # move CL to AL - xorb %ah, %ah - movb $16, %cl - divb %cl # quo=AL, rem=AH - orw $0x3030, %ax - - cmpb $0x39, %ah - jbe 1f - addb $7, %ah -1: - cmpb $0x39, %al - jbe 1f - addb $7, %al -1: - movb %ah, %cl - - xorw %bx, %bx - - pushw %ax - movw $0x0e20, %ax - int $0x10 - popw %ax - - movb $0x0e, %ah - int $0x10 - - movb $0x0e, %ah - movb %cl, %al - int $0x10 - - popal - popw %es - popw %ds - ret -#endif /* ! BAD_BIOS */ - - .align 4 - - /* 1 sector for the first half of IVT */ -bios_interrupt_vector_table: - .space 0x200 - -restore_BDA_EBDA: - - /* MS-DOS 7+ moved the EBDA segment from higher address to lower - * address, so we need to move it back to the top of conventional - * memory. - */ - cli - cld - xorw %ax, %ax - movw %ax, %ds - movw $0x040e, %si /* points to EBDA segment */ - lodsw - orw %ax, %ax /* is EBDA segment? */ -#; jz invalid_EBDA /* no EBDA exists */ - jnz 1f - /* no EBDA, let EBDA be at A000:0000 */ - movw $0xA000, %ax -1: - - /* if MS-DOS changed EBDA, then AX should be small. */ - cmpw $0x4000, %ax - jb 1f - ret /* CF=0, success. */ -1: - - /* MS-DOS would only move EBDA if - * 1. EBDA is 1K. - * 2. Low mem size is 639K. - */ - - movw %ax, %cx /* CX=EBDA segment */ - movw $0x053C, %si /* points to conventional memory size in KB */ - lodsl - cmpl $0x9FC0027F, %eax - jne invalid_EBDA - movw $0x0413, %si /* points to conventional memory size in KB */ - lodsw - cmpw $0x0280, %ax /* 0x280 == 640 */ - //ja invalid_EBDA /* too much conventional memory */ - jne invalid_EBDA - - shlw $0x06, %ax - movw %ax, %dx /* conventional memory size in paragraphs */ - -// xorb %al, %al -// cmpw $0xA000, %cx -// jz 1f #; no EBDA exists -// -// movw %cx, %ds /* DOS currently used EBDA segment */ -// xorw %si, %si /* the first byte of the EBDA ... */ -// lodsb /* ...is the EBDA size in KB */ -// cmpb $0x80, %al /* EBDA size greater than 128K ? */ -// ja invalid_EBDA /* EBDA too large */ -// -// orb %al, %al /* EBDA size is 0 ? */ -// jz invalid_EBDA /* EBDA should not be 0 in length */ -//1: -// movw $0x0280, %bx -// subb %al, %bl /* BX is the calculated low mem in K */ -// shlw $0x06, %bx /* BX is the calculated EBDA segment */ -// cmpw %bx, %cx /* CX is currently used EBDA segment */ -// jb 1f /* MSDOS had moved EBDA to low, jump */ - movw $0x9FC0, %bx - movb $1, %al - jmp 1f - - /* BX should be equal to CX, so EBDA needn't be restored. - * - * DX holds the segment at low mem end, so DX should be less - * than or equal to BX. - */ - -#if 0 - /* restore vectors in the range from DX:0 to BX:0 */ - - movw %cs, %ax - movw %ax, %es - movw $ABS_START(mapped_int13_vector_BIOS), %di - movw %dx, %ax /* AX=currently used low mem in paragraghs */ - stosw /* the possible hooked int13 segment */ - - movw %bx, %ax /* AX is the calculated EBDA segment */ - shrw $6, %ax /* AX=calculated low mem in K */ - stosw /* the low mem in K before int13 hook */ - #; after int13 is unhooked, the low mem will - #; end at EBDA. so any int13 service routine - #; installed by another software(eg, memdisk) - #; will be forcibly dismissed!!!!!! - movw %di, %bp - movw %dx, %es /* currently used low mem in paragraghs */ - xorw %di, %di - - /* suppose ES:DI is our int13 handler, we check it. */ - - /* the original int13 vector must be stored in the first kilo bytes */ - - movw $0x0400, %cx - movb $0x9a, %al /* 0x9a == lcall */ -3: - repnz scasb - jcxz 2f /* our int13 code was not found. */ - cmpl $0x9a006e8b, %es:-4(%di) /* movw (%bp), %bp; lcall */ - jnz 3b - - /* our int13 found. */ - movw %di, %si - movw %bp, %di - movw %es, %ax - movw %ax, %ds /* DS=code segment of int13 service routine */ - #; DS:SI points to original BIOS int13 vector - movw %cs, %ax - movw %ax, %es #; ES:DI points to the location to save - lodsl - cmpl $0x80000000, %eax - jb 2f - stosl /* save the original BIOS int13 vector */ - -2: -#endif - ret - -1: - /* MS-DOS 7+ moved 1K EBDA from 9FC0:0000 to lower mem. In this case, - * there shouldn't be any int13 routine at the top of conventional - * memory. so we simply copy 1K of EBDA back to 9FC0:0000 and - * of course, adjust data at 0000:040e and 0000:0413 - */ - - /* Restore vectors in the range from DX:0 to A000:0 - * No vectors need to be restored because DX seems always be 0xA000 - */ - - /* AL = EBDA size in KB */ - /* BX = calculated EBDA segment = 0xA000 - EBDA_size_in_paragraphs */ - /* CX = currently used EBDA segment, and CX < BX */ - /* DX = conventional memory size in paragraphs, usually 0xA000 */ - -// /* if MS-DOS would have changed EBDA, then CX should be small. */ -// cmpw $0x4000, %cx -// jb 1f -// ret -//1: - movw %cx, %ds - movw %bx, %es /* ES is the calculated EBDA segment */ - shlw $9, %ax /* AX *= 512 */ - movw %ax, %cx /* EBDA size in words */ - decw %ax - shlw $1, %ax /* points to the last word in EBDA */ - movw %ax, %si /* DS holds the currently used EBDA segment */ - movw %ax, %di /* ES holds the calculated EBDA segment */ - std /* move higher word first */ - repz movsw /* move to BIOS EBDA */ - cld - xorw %ax, %ax - movw %ax, %es /* DI string operations use ES == 0 */ - movw %bx, %ax - movw $0x040e, %di - stosw /* restore the BDA pointer of EBDA segment */ - movw $0x0413, %di - shrw $6, %ax - stosw /* restore the BDA field of low mem size */ - clc - ret - -invalid_EBDA: - //xorw %ax, %ax /* AX == 0 means invalid EBDA segment */ - //movw %ax, %es /* DI string operations use ES == 0 */ - //movw $0x040e, %di /* let EBDA segment be invalid */ - //stosw /* store 0 to 0000:040e */ - //movw $0x0413, %di /* let lower memory size at 0x413 ... */ - //movw $0x0280, %ax /* ... be 640K (0x280 == 640) */ - //stosw /* store 640 to 0000:0413 */ - stc /* CF=1, failure. */ - ret - -failed_restore_BDA_EBDA: - - movw %cs, %ax - movw %ax, %ds - movw %ax, %es - movl $ABS_START(failed_BDA_EBDA_string), ABS_PSP(error_message) - jmp message_exit1 - -move_stage2_image: - -#if 1 - - /* The Chinese DOS display systems are in graphics mode and cause - * display problem after we enter GRUB environment, so we need to - * enter text mode. - */ - - movw $0x0003, %ax /* set display mode: 80*25 color text */ - int $0x10 - -#endif - - movw %cs, %ax - movw %ax, %ds /* DS=CS */ - xorw %ax, %ax - movw %ax, %es /* ES=0 */ - - /* move command-line menu from CS:0081 to 0000:0800 */ - movw $0x0081, %si /* DS=CS */ - movw $0x0800, %di /* ES=0 */ - movw $0x0400, %cx /* move 4KB */ - cld - repz movsl - stosb /* end in NULL */ - - /* the stack 0000:2000 is safe because this is where the dos kernel - * code was living, and dos cannot load grub.exe below 0000:2000. - */ - - cli /* added 2008-08-04 */ - xorw %ax, %ax - movw %ax, %ss - movw $0x2000, %sp - sti /* added 2008-08-04 */ - - movw $ABS_START(stage2_64K_pages), %si - movw (%si), %cx - - movw %cs, %ax - addw $(ABS_START(pre_stage2_start-0x200)/0x10), %ax - movw %ax, %bx /* save the final stage2 segment to BX */ - cmpw $0x0800, %ax - ja 2f /* move from higher at BX:0000 to lower at 0800:0000 */ - - /* move from lower at BX:0000 to higher at 0800:0000 */ -1: - xorw %ax, %ax - movb %cl, %ah - decb %ah - shlb $0x04, %ah - movw %bx, %dx - addw %ax, %dx - movw %dx, %ds - addb $0x08, %ah /* addw $0x0800, %ax */ - movw %ax, %es - movw $0xfffe, %si - movw %si, %di - movw %cx, %dx /* save %cx to %dx */ - movw $0x8000, %cx /* 0x8000 words == 64K bytes */ - - /* Can safely move the final sector, because this code is just before - * the final sector */ -#if 0 - cmpw $0x0001, %dx #; do not move the sector containing this code, - #; to ensure no overlap - ja 3f - decb %ch /* %cx == 0x7f00 */ -3: -#endif - //cli - std /* move begins at higher end */ - repz movsw - movw %dx, %cx /* restore %cx from %dx */ - loop 1b - - // launch_stage2_code is in the final sector, so it may be overwritten - //jmp launch_stage2_code - // - - ljmp $0x800, $ABS_FINAL(launch_stage2_code) - - //. = (DOSSTART_SIZE - 0x0200) - - . = . + (0x400 - (. % 0x200)) % 0x200 - -////////////////////////////////////////////////////////////////////////////// - - /* The final sector begins here! */ - -2: - /* move from higher at BX:0000 to lower at 0800:0000. - * Note: this could overwrite our code and stack, so we shouldn't - * use stack(remember to cli), and we should copy the final sector - * to a safe place(because the code will continue to execute after - * the moving). - */ - - /* first, copy the final sector to 07e0:0000. Use 07e0 other than 0800 - * to ensure no overlap. - */ - - /* Now we are at the final sector, and we are above 0800:0000. - * So it is safe to move ourselves onto the lower sector at 07e0:0000. - */ - - xorw %si, %si - xorw %di, %di - movw $0x07e0, %ax - movw %ax, %es - movw %bx, %ds - movw %cx, %dx /* save %cx to %dx */ - movw $0x0100, %cx /* move the sector containing this code */ - //cli /* marked off 2008-08-04 */ - cld - repz movsw - movw %dx, %cx /* restore %cx from %dx */ - - /* Now we should long jump to the new safe code that has just moved, - * because the further moving could overwrite the code here at the - * final sector. - */ - - ljmp $0x07e0, $ABS_FINAL(1f) - -1: - /* from here on, code must be in the FINAL sector */ - movw $0x0800, %ax - movw %ax, %es - movw %bx, %ds -1: - xorw %si, %si - xorw %di, %di - movw %cx, %dx /* save %cx to %dx */ - movw $0x8000, %cx /* 0x8000 words == 64K bytes */ - cld - repz movsw - movw %dx, %cx /* restore %cx from %dx */ - addw $0x1000, %ax /* move the next 64K-byte page */ - movw %ax, %es - addw $0x1000, %bx - movw %bx, %ds - loop 1b - -launch_stage2_code: - - cld - xorw %ax, %ax - movw %ax, %ds - movw %ax, %es - cli - movw %ax, %ss - movw $0x2000, %sp - sti /* added 2008-08-04 */ - xchgb %al, 0x820B # AL=boot_drive, and clear the byte at 0x820B - xchgw %ax, %dx # DL=boot_drive - xorl %ebp, %ebp - xorl %esi, %esi - - ljmp $0, $0x8200 - - . = 2b + 0x200 -#----------------------------------------------------------------------------- -# EXE code ends here -#----------------------------------------------------------------------------- - - // if not aligned 0x200, issue error - - . = . - (. % 0x200) - -pre_stage2_start: - - /* Main program of GNU GRUB(i.e., pre_stage2) immediately follows. */ - diff --git a/stage2/eltorito.asm b/stage2/eltorito.asm deleted file mode 100644 index 2ad209d4..00000000 --- a/stage2/eltorito.asm +++ /dev/null @@ -1,1267 +0,0 @@ - -;----------------------------------------------------------------------------- -; ElTorito.asm -; -; El Torito Bootable CD-ROM driver which does not reset the CD-ROM drive upon -; loading, but instead accesses the drive through BIOS system calls -; -; MIT License -; -; (c) 2000 by Gary Tong -; (c) 2001-2009 by Bart Lagerweij -; -; Permission is hereby granted, free of charge, to any person obtaining a copy -; of this software and associated documentation files (the "Software"), to deal -; in the Software without restriction, including without limitation the rights -; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -; copies of the Software, and to permit persons to whom the Software is -; furnished to do so, subject to the following conditions: -; -; The above copyright notice and this permission notice shall be included in -; all copies or substantial portions of the Software. -; -; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -; THE SOFTWARE. -; -;----------------------------------------------------------------------------- - -; Imported from syslinux-5.00 with ScanDrives fixed by Tinybit, 2013-01-12 - -; Ported to NASM by H. Peter Anvin. - -; To assemble and link, use these commands with NASM 2.x: -; nasm -Ox -f bin -o eltorito.sys eltorito.asm - -; To enable Trace markers uncomment the line below -; DEBUG_TRACERS=1 - -; To enable debug info uncomment the line below -; DEBUG=1 - -;----------------------------------------------------------------------------- -; Change log for eltorito.asm, by Bart Lagerweij -; -; Jun 25, 2009 - License source code under the MIT license -; -; Jun 6, 2002 - v1.2 -; Eltorito.sys does now also finds the correct driver number for the booted -; CD-Rom on a Dell PC with very buggy BIOS. It does not clear the carry flag -; after a succesfull call to int13/ax=4b01h call. Other PC's also using Phoenix -; BIOS version 1.10 A14, or alike maybe also benefit from this "workaround". -; -; Mar 9, 2002 -; - All read requests are now retried 5 times. -; - Bug fix, had... -; cmp ax, 3FFFh ;Too large? -; ja ReadLBad ;If yes -; seperated from... -; mov ax,es:[bx+18] ;Get number of sectors to read -; mov word ptr [SpecPkt+2],ax -; so, it was checking "wild" ax values... -; - Some cleanup and small changes -; - The tracers give trouble when using SHCD.. -; - Reverted proc ReadL back to Rev. 0.15BETA -; -; Mar 5, 2002 -; - Bug fix, when changing CD media some machines would "hang" in the -; PriVolDesc routine. -; - Added printing of TRACER characters to trace the bug above. -; - Major cleanup and now using ASCIIZ strings. -; -; May 9, 2001 -; - Fixed a "pad devicename with spaces" bug, this only happened when a device -; name was used with less than 8 characters, for example, "MSCD000" became -; "MSCD000(". -; - Bug fix, when eltorito.sys was called with invalid command line parameters, -; garbage was printed and sometimes followed by "system halted" that has been -; there since the very first version of eltorito.sys. I know that because I -; had the bug back then. When loading eltorito.sys using a device loader, -; for example "device.com eltorito.sys /test:123" garbage was printed instead -; of "No device name found." "driver not installed". -; - Changed the error message to include a "usage" string. -; -; May 8, 2001 -; - If diskemu.bin is loaded, eltorito.sys uses the drivenumber from diskemu. -; A call is made to "diskemu/Get status" (INT13/AX=5400) and the drivenumber -; is returned in CL. This should fix boot problems on Dell PCs (YES!). -; When diskemu.bin is not loaded, eltorito still loops all drive numbers -; using eltorito calls. -; - Removed "press Escape..." -; - When the Alt-key is pressed (and holded) more info is printed and -; eltorito.sys halts. -;----------------------------------------------------------------------------- - -%ifdef DEBUG_TRACERS - %macro TRACER 1 - call debug_tracer - db %1 - %endmacro -%else - %macro TRACER 1 - %endmacro -%endif ; DEBUG_TRACERS - -%define Ver '1.5' -%define CR 0DH, 0Ah -RPolyH equ 0EDB8h -RPolyL equ 08320h - - section .text align=16 - org 0 - -;============================================================================= - -Cdrom: - -NextDriver dd -1 ;-+ -Attributes dw 0C800h ; | -Pointers dw Strategy ; | - dw Commands ; | MSCDEX requires this -DeviceName db 'ELTORITO' ; | data in these locations - dw 0 ; | -DriveLetter db 0 ; | -NumUnitsSupp db 1 ;-+ - -DriverName db 'El-Torito CD-ROM Device Driver',0 - align 4, db 0 -ReqHdrLoc dd 0 -XferAddr dd 0 -Checksum dd -1 -DriveNumber db 0 -ReadBytes db 0 ;0 --> 2048 bytes/sector - ;1 --> 1024 bytes/sector - ;2 --> 512 bytes/sector - -Routines dw Init ;Init ;0 - dw Unsupported ;MediaCheck ;1 - dw Unsupported ;BuildBPB ;2 - dw IoctlInput ;IoctlInput ;3 - dw Unsupported ;Input ;4 - dw Unsupported ;NonDesInput ;5 - dw Unsupported ;InputStatus ;6 - dw Unsupported ;InputFlush ;7 - dw Unsupported ;Output ;8 - dw Unsupported ;OutputVerify ;9 - dw Unsupported ;OutputStatus ;10 - dw Unsupported ;OutputFlush ;11 - dw IoctlOutput ;IoctlOutput ;12 - dw DoNothing ;DeviceOpen ;13 - dw DoNothing ;DeviceClose ;14 - dw ReadL ;ReadL ;128 - -IoctlICtrl dw Raddr ;Raddr ;0 - dw Unsupported ;LocHead ;1 - dw Unsupported ;(Reserved) ;2 - dw Unsupported ;ErrStat ;3 - dw Unsupported ;AudInfo ;4 - dw DrvBytes ;DrvBytes ;5 - dw DevStat ;DevStat ;6 - dw SectSize ;SectSize ;7 - dw VolSize ;VolSize ;8 - dw MedChng ;MedChng ;9 - -SpecPkt times 19 db 0 ; offset 77h in 1.4 - times 13 db 0 ; unknown extra 00s in 1.4 - -;Greeting db 'El-Torito Bootable CD-ROM Driver for Dos v',Ver,', http://www.nu2.nu/eltorito/',CR -Greeting db 'El-Torito Bootable CD-ROM Driver for Dos, built along with GRUB4DOS',CR - db ' (c) 2000 by Gary Tong',CR - db ' (c) 2001-2002 by Bart Lagerweij',CR,0 -DblSpace db ' ',0 - -;============================================================================= - -Strategy: - - mov word [cs:ReqHdrLoc],bx - mov word [cs:ReqHdrLoc+2],es - retf - - -;============================================================================= - -Commands: - - push ax - push bx - push cx - push dx - push si - push di - push bp -; pushad - push ds - push es - TRACER 'C' - - cld ;Clear direction - sti ;Enable interrupts - - mov ax, cs ;ds=cs - mov ds, ax - - les bx,[ReqHdrLoc] ;seg:offset ptr into es:bx - xor ax,ax - mov al,[es:bx+2] ;Get Command code -%ifdef DEBUG - call print_hex8 -%endif - cmp al,15 - jb Mult2 ;If 0-14 - cmp al,128 - jb UnknownCmd ;If 15-127 - cmp al,129 - jb ShiftDown ;If 128 -UnknownCmd: mov al,121 ;8 = Unsupported (Reserved) -ShiftDown: sub al,113 ;128 --> 15, 121 --> 8 -Mult2: shl al,1 ;Convert into offset (*2) - mov di,Routines - add di,ax - call word [di] ;Execute desired command - or ax,100h ;Set Return Status's Done bit - lds bx,[ReqHdrLoc] ;seg:offset ptr into ds:bx - mov [bx+3],ax ;Save Status - -%ifdef DEBUG - cmp byte [cs:buffer+2048], 96h - je buffer_ok - mov al, '!' - call print_char - jmp $ -buffer_ok: -%endif - - TRACER 'c' - pop es - pop ds -; popad - pop bp - pop di - pop si - pop dx - pop cx - pop bx - pop ax - retf - - -;============================================================================= - -Unsupported: ;Unsupported Command - - mov ax,8003h ;Set Status Error bit, - TRACER 'U' - TRACER 'C' - retn ; Error 3 = Unknown Command - - -;============================================================================= - -IoctlInput: ;IOCTL Input Routine - - mov di,[es:bx+14] ;es:bx --> Request Header - mov es,[es:bx+16] ;Get Xfer Address into es:di - xor ax,ax ;Get Control Block Code - mov al,[es:di] -%ifdef DEBUG - TRACER 'I' - TRACER 'O' - call print_hex8 -%endif - cmp al,10 - jb UnkIoctlI ;If 0-9 - mov al,2 ;Map to Unsupported -UnkIoctlI: shl al,1 ;Convert into offset (*2) - mov si,IoctlICtrl - add si,ax - call word [si] ;Execute desired command - retn - - -;============================================================================= - -Raddr: ;Return Device Header Address - - TRACER 'A' - mov word [es:di+1],0 - mov [es:di+3],cs - xor ax, ax ;Set Return Status = success - TRACER 'a' - retn - - -;============================================================================= - -DrvBytes: ;Read Drive Bytes - - TRACER 'B' - push di ;Save original Xfer Addr - add di,2 ;Point to 1st dest byte - mov si,Greeting ;Point to Greeting -DrvB: movsb ;Copy over a byte - cmp byte [si],13 ;Is next char a CR? - jne DrvB ;Loop if not - - sub di,2 ;Get #bytes copied into ax - mov ax,di - pop di ;Retrieve original Xfer Addr - sub ax,di - mov byte [es:di+1],al ;and save it - mov ax,0 ;Set Return Status = success - TRACER 'b' - retn - - -;============================================================================= - -DevStat: ;Return Device Status - - TRACER 'D' - mov word [es:di+1],202h ;Door closed - mov word [es:di+3],0 ;Door unlocked - ;Supports only cooked reading - ;Read only - ;Data read only - ;No interleaving - ;No prefetching - ;No audio channel manipulation - ;Supports both HSG and Redbook - ; addressing modes - - xor ax, ax ;Set Return Status = success - TRACER 'd' - retn - - -;============================================================================= - -SectSize: ;Return Sector Size - - TRACER 'S' - mov word [es:di+2],2048 - mov ax,0 ;Set Return Status = success - TRACER 's' - retn - - -;============================================================================= - -VolSize: ;Return Volume Size - - TRACER 'V' - call PriVolDesc ;Get and Check Primary Volume - ; Descriptor - mov ax,800Fh ;Assume Invalid Disk Change - jc VolExit ;If Read Failure - - mov ax,word [Buffer+80] ;Read Successful - mov word [es:di+1],ax ;Copy over Volume Size - mov ax,word [Buffer+82] - mov word [es:di+3],ax - mov ax,0 ;Set Return Status = success -VolExit: - TRACER 'v' - retn - - -;============================================================================= - -MedChng: ;Return Media Changed Status - - TRACER 'M' - call PriVolDesc ;Get and Check Primary Volume - ; Descriptor - mov byte [es:di+1],-1 ;Assume Media Changed - mov ax,800Fh ; and Invalid Disk Change - jc MedExit ;If Media Changed or Bad - - mov byte [es:di+1],1 ;Media has not changed - mov ax,0 ;Set Return Status = success -MedExit: - TRACER 'm' - retn - - -;============================================================================= - -PriVolDesc: ;Get and Check Primary Volume - ; Descriptor - TRACER 'P' - mov ax,cs ;Set ds:si --> SpecPkt - mov ds,ax - - mov cx, 5 -PriVolAgain: - mov byte [SpecPkt],16 ;SpecPkt Size - mov byte [SpecPkt+1],0 ;Reserved - mov word [SpecPkt+2],1 ;Transfer one 2048-byte sector - push cx - mov cl,byte [ReadBytes] ;Multiply by 4 if reading 512 - shl word [SpecPkt+2],cl ; bytes at a time - pop cx - mov word [SpecPkt+6],cs ;Into our Buffer - mov word [SpecPkt+4], Buffer - mov word [SpecPkt+8],16 ;From CD Sector 16 - mov word [SpecPkt+10],0 - mov word [SpecPkt+12],0 - mov word [SpecPkt+14],0 - - mov si, SpecPkt - mov dl, [DriveNumber] - mov ah, 42h ;Extended Read - int 13h - jnc PriVolPass ;If success - -; TRACER '1' - ; read error - loop PriVolAgain - - TRACER '2' - ; read retries exhausted - ; flow into below - jmp PriReadErr - -PriVolPass: - mov si,Buffer ;Point input to Buffer - mov ax,-1 ;Init Checksum registers - mov bx,ax ; bx,ax = 0FFFFFFFFh - jc PriNew ;If Read Failure - - push di ;Read Successful, - ; so Calculate Checksum - mov di,1024 ;Init Word counter -PriWord: mov dx,[cs:si] ;Grab next word from buffer - mov cx,16 ;Init bit counter -PriBit: shr dx,1 ;Shift everything right 1 bit - rcr bx,1 - rcr ax,1 - jnc NoMult ;If a zero shifted out - - xor bx,RPolyH ;A one shifted out, so XOR - xor ax,RPolyL ; Checksum with RPoly -NoMult: - loop PriBit - - add si,2 ;Inc Word Pointer - dec di - ja PriWord - TRACER '3' - - pop di ;Checksum calculation complete - cmp bx,[Checksum+2] ;Has Checksum changed? - jne PriNew ;If Checksum Changed - - cmp ax,[Checksum] - jne PriNew ;If Checksum Changed - - clc ;Checksum not changed, CF=0 - mov ax,0 ;Status = success - jmp PriOld - -PriReadErr: - mov WORD [Checksum+2],bx ;Save New Checksum - mov [Checksum],ax ; or 0FFFFFFFFh if bad read - stc ;Checksum change, CF=1 - mov ax, 800bh ;Status = read fault - jmp PriOld - -PriNew: mov WORD [Checksum+2],bx ;Save New Checksum - mov [Checksum],ax ; or 0FFFFFFFFh if bad read - stc ;Checksum Changed, CF=1 - mov ax,800Fh ;Status = Invalid Media Change -PriOld: - TRACER 'p' - retn - - -;============================================================================= - -IoctlOutput: ;IOCTL Output Routine - - TRACER 'O' - mov di,[es:bx+14] ;es:bx --> Request Header - mov es,[es:bx+16] ;Get Xfer Address into es:di - xor ax,ax ;Get Control Block Code - mov al,[es:di] - cmp al,2 - jne UnkIoctlO ;If not 2 (ResetDrv) - call DoNothing ;Reset Drive - jmp IoctlODone -UnkIoctlO: - call Unsupported ;Unsupported command -IoctlODone: - TRACER 'o' - retn - - -;============================================================================= - -DoNothing: ;Do Nothing Command - - mov ax,0 ;Set Return Status = success - retn - - -;============================================================================= - -ReadL: ;Read Long Command - - TRACER 'R' - mov ax,cs ;Set ds=cs - mov ds,ax - ;es:bx --> Request Header - cmp byte [es:bx+24],0 ;Check Data Read Mode - jne ReadLErr ;If Cooked Mode - - cmp byte [es:bx+13],2 ;Check Addressing Mode - jb ReadLOK ;If HSG or Redbook Mode - -ReadLErr: - TRACER '8' - mov ax,8003h ;Set Return Status = Unknown - jmp ReadLExit ; Command Error and exit - -ReadLOK: - mov ax,[es:bx+20] ;Get Starting Sector Number, - mov dx,[es:bx+22] ; Assume HSG Addressing Mode - cmp byte [es:bx+13],0 ;Check Addressing Mode again - je ReadLHSG ;If HSG Addressing Mode - - TRACER '7' - ;Using Redbook Addressing Mode. Convert to HSG format - mov al,dl ;Get Minutes - mov dl,60 - mul dl ;ax = Minutes * 60 - add al,byte [es:bx+21] ;Add in Seconds - adc ah,0 - mov dx,75 ;dx:ax = - mul dx ; ((Min * 60) + Sec) * 75 - add al,byte [es:bx+20] ;Add in Frames - adc ah,0 - adc dx,0 - sub ax,150 ;Subtract 2-Second offset - sbb dx,0 ;dx:ax = HSG Starting Sector - -ReadLHSG: - mov word [SpecPkt+8], ax ;Store Starting - mov word [SpecPkt+10], dx ; Sector Number - mov word [SpecPkt+12], 0 ; (HSG Format) - mov word [SpecPkt+14], 0 - - mov ax,[es:bx+14] ;Get Transfer Address - mov word [SpecPkt+4],ax - mov ax,[es:bx+16] - mov word [SpecPkt+6],ax - - mov byte [SpecPkt],16 ;Size of Disk Address Packet - mov byte [SpecPkt+1],0 ;Reserved - - mov cx, 5 -ReadLAgain: - mov ax,[es:bx+18] ;Get number of sectors to read - mov word [SpecPkt+2],ax - cmp ax, 3FFFh ;Too large? - ja ReadLBad ;If yes - - push cx - mov cl,byte [ReadBytes] ;Multiply by 4 if reading 512 - shl word [SpecPkt+2],cl ; bytes at a time - pop cx - -%ifdef DEBUG - push ax - push cx - push si - mov cx, 16 - mov si,SpecPkt -ReadDump: mov al, ' ' - call print_char - mov al, byte [si] ;Hexdump a SpecPkt byte - call print_hex8 - inc si ;Point to next byte - loop ReadDump - pop si - pop cx - pop ax -%endif - mov si,SpecPkt - mov dl,[DriveNumber] - mov ah,42h ;Extended Read - int 13h - jnc ReadLGd ;If success - -;hang: -; jmp hang -; TRACER '1' - loop ReadLAgain - TRACER '2' - jmp short ReadLBad -ReadLGd: - TRACER '3' - xor ax, ax ;Status 0 = success - jmp short ReadLExit - -ReadLBad: - TRACER '9' - mov ax, 800Bh ;Set Read Fault Error - ; flow into ReadLExit -ReadLExit: - TRACER 'r' - retn - - - -%ifdef DEBUG_TRACERS -debug_tracer: pushad - pushfd - - mov al, '[' - mov ah,0Eh ;BIOS video teletype output - xor bh, bh - int 10h ;Print it - - mov bp,sp - mov bx,[bp+9*4] ; Get return address - mov al,[cs:bx] ; Get data byte - inc word [bp+9*4] ; Return to after data byte - - mov ah,0Eh ;BIOS video teletype output - xor bh, bh - int 10h ;Print it - - mov al, ']' - mov ah,0Eh ;BIOS video teletype output - xor bh, bh - int 10h ;Print it - - popfd - popad - retn -%endif - -;----------------------------------------------------------------------------- -; PRINT_HEX4 -;----------------------------------------------------------------------------- -; print a 4 bits integer in hex -; -; Input: -; AL - 4 bits integer to print (low) -; -; Output: None -; -; Registers destroyed: None -; -print_hex4: - - push ax - and al, 0fh ; we only need the first nibble - cmp al, 10 - jae hex_A_F - add al, '0' - jmp hex_0_9 -hex_A_F: - add al, 'A'-10 -hex_0_9: - call print_char - pop ax - retn - - -;----------------------------------------------------------------------------- -; print_hex8 -;----------------------------------------------------------------------------- -; print a 8 bits integer in hex -; -; Input: -; AL - 8 bits integer to print -; -; Output: None -; -; Registers destroyed: None -; -print_hex8: - - push ax - push bx - - mov ah, al - shr al, 4 - call print_hex4 - - mov al, ah - and al, 0fh - call print_hex4 - - pop bx - pop ax - retn - - -;============================================================================= -; print_hex16 - print a 16 bits integer in hex -; -; Input: -; AX - 16 bits integer to print -; -; Output: None -; -; Registers destroyed: None -;============================================================================= -print_hex16: - - push ax - push bx - push cx - - mov cx, 4 -print_hex16_loop: - rol ax, 4 - call print_hex4 - loop print_hex16_loop - - pop cx - pop bx - pop ax - retn - -;============================================================================= -; print_hex32 - print a 32 bits integer in hex -; -; Input: -; EAX - 32 bits integer to print -; -; Output: None -; -; Registers destroyed: None -;============================================================================= -print_hex32: - - push eax - push bx - push cx - - mov cx, 8 -print_hex32_loop: - rol eax, 4 - call print_hex4 - loop print_hex32_loop - - pop cx - pop bx - pop eax - retn - -;============================================================================= -; print_string - print string at current cursor location -; -; Input: -; DS:SI - ASCIIZ string to print -; -; Output: None -; -; Registers destroyed: None -;============================================================================= -print_string: - push ax - push si - -print_string_again: - mov al, [si] - or al, al - jz print_string_exit - call print_char - inc si - jmp print_string_again - -print_string_exit: - pop si - pop ax - retn - -;----------------------------------------------------------------------------- -; PRINT_CHAR -;----------------------------------------------------------------------------- -; Print's a character at current cursor position -; -; Input: -; AL - Character to print -; -; Output: None -; -; Registers destroyed: None -; -print_char: - - push ax - push bx - - mov ah,0Eh ;BIOS video teletype output - xor bh, bh - int 10h ;Print it - -print_char_exit: - pop bx - pop ax - retn - - -;============================================================================= - -;This space is used as a 2048-byte read buffer plus one test byte. -;The 96h data is used for testing the number of bytes returned by an Extended -; CD-ROM sector read - - align 16, db 0 -Buffer times 2049 db 96h - - ; Init will read 2 sectors at Buffer - times 2047 db 0 - -;============================================================================= - -Init: ;Initialization Routine - - TRACER 'I' - mov ax,cs ;ds=cs - mov ds,ax - -%ifdef DEBUG -; print CS value (load segment) - call print_hex16 -%endif - - mov si, Greeting ;Display Greeting - call print_string - - mov ax,Unsupported ;Init is executed only once - mov [Routines],ax - - mov ax, 5400h - int 13h ; Get diskemu status - jc FindBoot ; If CF=1 no diskemu loaded - - mov [DriveNumber], cl ; Store drive number - - call keyflag - and al, 8 ; alt key ? - jz extread - - mov si, DrvNumMsg ; Display "drive number=" - call print_string - mov al, [DriveNumber] - call print_hex8 - mov si, LineEnd ; CR/LF - call print_string - jmp extread - -; Diskemu is not loaded -; so loop to find drive number - ; *** start of 1.4 changes *** - ; ??? mov dl, 0ffh ;Start at Drive 0xff - ; *** FindBoot at c47 in 1.4, at c0c in 1.3 *** -FindBoot: call ScanDrives ; call new helper in 1.4 - jnc FoundBoot ; ded*df3 -; mov si,offset SpecPkt ;Locate booted CD-ROM drive -; mov [SpecPkt],0 ;Clear 1st byte of SpecPkt -; mov ax,4B01h ;Get Bootable CD-ROM Status -; int 13h -; jnc FindPass ;If booted CD found -; -; Carry is not cleared in buggy Dell BIOSes, -; so I'm checking packet size byte -; some bogus bioses (Dell Inspiron 2500) returns packet size 0xff when failed -; Dell Dimension XPsT returns packet size 0x14 when OK - -; cmp [SpecPkt], 0 -; jne FoundBoot - -; cmp [SpecPkt], 13h ; anything between 13h and 20h should be OK -; jb FindFail -; cmp [SpecPkt], 20h -; ja FindFail -; jmp short FoundBoot -; -; FindFail: -; dec dl ;Next drive -; cmp dl, 80h -; jae FindBoot ;Check from ffh..80h - ; *** end of 1.4 changes *** - - mov si,NoBootCD ;No booted CD found, - call print_string - jmp NoEndAddr ;Do not install driver - -FoundBoot: -; mov dl, [SpecPkt+2] ; 1.4 change - ; *** next line at c57 in 1.4, at c3d in 1.3 *** - mov [DriveNumber],dl ;Booted CD-ROM found, - ; so save Drive # - - call keyflag - and al, 8 ; alt key ? - jz extread - - mov si, CDStat - call print_string - mov si, SpecPkt ;Point to returned CD SpecPkt - mov cx, 19 ; containing 19 bytes -StatDump: mov al, ' ' ;Print a space - call print_char - mov al, byte [si] ;Hexdump a SpecPkt byte - call print_hex8 - inc si ;Point to next byte - loop StatDump - - mov si, LineEnd ;Print a CR/LF - call print_string - -extread: -;See how many CD Sector bytes are returned by an Extended Read - mov byte [SpecPkt],16 ;SpecPkt Size - mov byte [SpecPkt+1],0 ;Reserved - mov word [SpecPkt+2],1 ;Transfer one sector - mov word [SpecPkt+6],cs ;Into our Buffer - mov word [SpecPkt+4],Buffer - mov word [SpecPkt+8],16 ;From CD Sector 16 - mov word [SpecPkt+10],0 - mov word [SpecPkt+12],0 - mov word [SpecPkt+14],0 - - mov si, SpecPkt ;Set ds:si --> SpecPkt - mov dl, [DriveNumber] - mov ah, 42h ;Extended Read - int 13h - jnc SecSize ;If success - - mov ah, 42h ;Always make 2 read attempts - int 13h - ;How many bytes did we get? -SecSize: std ;Count down - mov ax,cs ;Point to end of Buffer - mov es,ax - mov di,Buffer+2047 ;Find end of read data - mov si,Buffer+2048 - mov cx,2049 - repe cmpsb ;cx = number of bytes read - - cld ;Restore count direction to up - mov si,CDBytes ;Display number of bytes read - call print_string - - mov al, [DriveNumber] - call print_hex8 - - mov si,CDBytesA ;Remainder A of message - call print_string - - mov al,ch ;Hex-dump cx - and al,0Fh ;Second nibble - call print_hex8 ; (don't need the First) - mov al,cl - call print_hex8 ; (don't need the First) - - mov si,CDBytesB ;Remainder B of message - call print_string - - cmp cx,2048 ;Did we read 2048 bytes? - je ParseParm ;If yes <-- O.K. - - mov byte [ReadBytes],1 - cmp cx,1024 ;Did we read 1024 bytes? - je ParseParm ;If yes <-- O.K. - - mov byte [ReadBytes],2 - cmp cx,512 ;Did we read 512 bytes? - jne NoEndAddr ;If not, do not load driver - -ParseParm: mov bx,word [cs:ReqHdrLoc] ;Parse command line - mov es,word [cs:ReqHdrLoc+2] ; parameters - mov si,[es:bx+18] ;Get BPB array ptr into DS:SI - mov ds,[es:bx+20] -FindParm: inc si -FindParm1: cmp byte [si],0Dh ;CR? (End of parameters) - je EndOfParms - - cmp byte [si],0Ah ;LF? - je EndOfParms - - cmp byte [si],'/' ;A parameter? - jne FindParm - - inc si - cmp byte [si],'D' ;Device Name parameter? - jne FindParm1 - - inc si - cmp byte [si],':' - jne FindParm1 - -;bbb - push si - mov si, DevName ;Device Name is at ds:si - push ds ;Keep ptr to Device Name - mov ax, cs - mov ds, ax - call print_string - pop ds ;Retrieve Device Name ptr - pop si - mov cx, 8 ;Get next 8 chars - inc si ; = Device Name - mov ax, cs - mov es, ax - mov di, DeviceName -NextChar: cmp byte [si],' ' - ja AboveSpace - - mov ax,cs ;Pad end of Device Name with - mov ds,ax ; spaces if necessary - mov si,DblSpace ;A space -AboveSpace: mov al, [si] - call print_char - movsb ;ds:[si] --> es:[di] - loop NextChar - - mov si,LineEnd - mov ax,cs - mov ds,ax - call print_string - - ;mov ax,Init-2 ;Last byte of driver to keep - mov ax,Buffer+2048 ;Last byte of driver to keep - jmp EndAddr ;Install driver - -EndOfParms: - mov ax, cs ; Restore segment registers (fix) - mov ds, ax - mov es, ax - - mov si,NoDevName ;No Device Name Found - call print_string - -NoEndAddr: mov ax,0 ;Do not install driver - -EndAddr: mov es,[ReqHdrLoc+2] ;Write End Address - mov bx,[ReqHdrLoc] - mov [es:bx+14],ax - mov [es:bx+16],cs - mov bx,ax ;Hold onto install status - - mov si, DrvInst ;Display driver install status - call print_string - mov si, DrvInst1 ;Assume driver installed - cmp bx,0 ;Was driver installed? - jne DrvStatus ;If yes - mov si, NoDrvInst ;Driver not installed -DrvStatus: call print_string - - mov ax,0 ;Set Return Status = success - cmp bx,0 ;Was INIT successful? - jne InitStat ;If yes - mov ax,800Ch ;Status = General Failure -InitStat: - push ax ;Save Return Status - - call keyflag - and al, 8 ; alt key ? - jz InitExit - -WaitHere: - mov si, WaitMsg ;Display Halted message - call print_string - -AltWait: - call keyflag - and al, 8 ; Alt key? - jnz AltWait ; Pressed? yes -> wait - -InitExit: - pop ax ;Retrieve Return Status - TRACER 'i' - retn ;That's it for Init! - - ; *** start 1.4 changes at ded *** -;SpecGo: mov si,SpecPkt -; int 13h -; retn - -check_eltorito: - - mov ax, 4200h ; EBIOS read sectors - - mov WORD [si],10h ; packet size and reserved byte - mov WORD [si+2],2 ; 2 sectors to read and reserved byte - mov WORD [si+4],Buffer - mov WORD [si+6],ds - mov DWORD [si+8],16 ; read starts at sector 16 - mov DWORD [si+12],0 ; hi 32-bit of starting sector number - - ; fill Buffer with 96h - push es - pusha - mov ax, ds - mov es, ax - mov di, Buffer - mov cx, 4096 - mov al, 96h - cld - repz stosb - popa - pop es - - ; read 2 sectors into Buffer - push ds - push es - pusha - int 13h - popa - pop es - pop ds - - cmp DWORD [Buffer], 30444301h - jne FindFail_42 - cmp DWORD [Buffer+4], 00013130h - jne FindFail_42 - cmp DWORD [Buffer+800h], 30444300h - jne FindFail_42 - cmp DWORD [Buffer+804h], 45013130h - jne FindFail_42 - cmp DWORD [Buffer+808h], 4F54204Ch - jne FindFail_42 - cmp DWORD [Buffer+80Ch], 4F544952h - jne FindFail_42 - cmp DWORD [Buffer+810h], 45505320h - jne FindFail_42 - cmp DWORD [Buffer+814h], 49464943h - jne FindFail_42 - cmp DWORD [Buffer+818h], 49544143h - jne FindFail_42 - cmp WORD [Buffer+81Ch], 4E4Fh - jne FindFail_42 - cmp BYTE [Buffer+81Eh], 0 - jne FindFail_42 - - ; fill Buffer with 96h - push es - pusha - mov ax, ds - mov es, ax - mov di, Buffer - mov cx, 4096 - mov al, 96h - cld - repz stosb - popa - pop es - - clc - retn - -FindFail_42: - stc - retn - -ScanDrives: push ax ; at df3 in 1.4 - push si - mov si, SpecPkt - mov dl, 0h ;Start at Drive 0xFF -NextDrv: dec dl - clc - mov ax,4B01h ;Get Bootable CD-ROM Status - ;mov BYTE [SpecPkt],0 ;Clear 1st byte of SpecPkt - mov BYTE [si],13h ;Set 1st byte to 13h on input - mov BYTE [si+2],0 ;Clear drive number on input - ;call SpecGo - push ds - push es - pusha - int 13h - popa - pop es - pop ds -; Carry is not cleared in buggy Dell BIOSes, -; so I'm checking packet size byte -; some bogus bioses (Dell Inspiron 2500) returns packet size 0xff when failed -; Dell Dimension XPsT returns packet size 0x14 when OK - - cmp BYTE [si], 13h ; anything between 13h and 20h should be OK - jb FindFail - cmp BYTE [si], 20h - ja FindFail ; in 1.4 at e16 - test BYTE [si+1], 0Fh ; media_type=0 means no-emulation mode - jnz FindFail - cmp dl, [si+2] - jnz FindFail - - ; read 2 sectors to confirm the success - call check_eltorito - jnc SendFound ; success with CF=0 - -FindFail: - cmp dl, 80h ; Check from 80h..ffh - jne NextDrv ; Next drive - -; The fast 4B01 scan failed, so try a slow scan of 4200 (by reading sectors). - - mov dl, 0h ;Start at Drive 0xFF -NextDrv_42: dec dl - - ; read 2 sectors and check the contents - call check_eltorito - jnc SendFound ; success with CF=0 - - cmp dl, 80h ; Check from 80h..ffh - jne NextDrv_42 ; Next drive - -SendFail: xor dl,dl - stc - ;jmp short ThingDone ; yes, this jmp can be omitted. -SendFound: ;mov dl, [SpecPkt+2] ; already equal on success - ;clc ; already cleared CF on success -ThingDone: pop si - pop ax - retn - ; *** end 1.4 changes *** - -;============================================================================= - -;------------------------------------------------------------ -; keyboard flags - return keyboard flags in AL -; bit 3 = ALT key -keyflag: ; at dbc in 1.3, at e2e in 1.4 - push bx - mov ah, 2 - int 16h - pop bx - retn - -;============================================================================= - -DrvNumMsg db ' Diskemxx.bin returned drive number=', 0 -NoBootCD db ' No booted CD-ROM found.',CR,0 - -CDStat db ' INT 13h / AX=4B01h Specification Packet for ' - db 'Booted CD-ROM:',CR,' ', 0 - -CDBytes db ' Drive ', 0 -CDBytesA db ' returns ', 0 -CDBytesB db 'h bytes per Sector.',CR,0 - -DevName db ' Device Name: ', 0 -NoDevName db ' No Device Name found. ' - db 'Usage: device=eltorito.sys /D:',CR,0 - -DrvInst db ' Driver ', 0 -NoDrvInst db 7,'not ' ;7 = Ctrl-G = Beep -DrvInst1 db 'installed',CR,0 - -WaitMsg db ' Alt pressed, waiting...', CR, 0 -;ContMsg db ' Continuing...' -LineEnd db CR,0 - - -;============================================================================= diff --git a/stage2/fat.h b/stage2/fat.h index dad7e955..4034d45c 100644 --- a/stage2/fat.h +++ b/stage2/fat.h @@ -113,14 +113,11 @@ struct fat_bpb { && !(FAT_DIRENTRY_ATTRIB(entry) & FAT_ATTRIB_NOT_OK_MASK) ) #define FAT_DIRENTRY_FIRST_CLUSTER(entry) \ ((*(unsigned short *)(entry+26))+((*(unsigned short *)(entry+20)) << 16)) -#define FAT_DIRENTRY_FILELENGTH(entry) (*(unsigned long *)(entry+28)) +#define FAT_DIRENTRY_FILELENGTH(entry) (*(unsigned int *)(entry+28)) #define FAT_LONGDIR_ID(entry) (*(unsigned char *)(entry)) #define FAT_LONGDIR_ALIASCHECKSUM(entry) (*(unsigned char *)(entry+13)) -//#define EXFAT_FIRST_DATA_CLUSTER 2 -//#define EXFAT_CLUSTER_FREE 0 /* free cluster */ -//#define EXFAT_CLUSTER_BAD 0xfffffff7 /* cluster contains bad sector */ #define EXFAT_CLUSTER_END 0xffffffff /* final cluster of file or directory */ diff --git a/stage2/filesys.h b/stage2/filesys.h index 43925fa8..349cbd61 100644 --- a/stage2/filesys.h +++ b/stage2/filesys.h @@ -22,35 +22,12 @@ #include "pc_slice.h" #endif -#ifdef FSYS_FFS -#define FSYS_FFS_NUM 1 -#ifndef ASM_FILE -int ffs_mount (void); -unsigned long long ffs_read (unsigned long long buf, unsigned long long len, unsigned long write); -int ffs_dir (char *dirname); -unsigned long ffs_embed (unsigned long *start_sector, unsigned long needed_sectors); -#endif -#else -#define FSYS_FFS_NUM 0 -#endif - -#ifdef FSYS_UFS2 -#define FSYS_UFS2_NUM 1 -#ifndef ASM_FILE -int ufs2_mount (void); -unsigned long long ufs2_read (unsigned long long buf, unsigned long long len, unsigned long write); -int ufs2_dir (char *dirname); -unsigned long ufs2_embed (unsigned long *start_sector, unsigned long needed_sectors); -#endif -#else -#define FSYS_UFS2_NUM 0 -#endif #ifdef FSYS_FAT #define FSYS_FAT_NUM 1 #ifndef ASM_FILE int fat_mount (void); -unsigned long long fat_read (unsigned long long buf, unsigned long long len, unsigned long write); +unsigned long long fat_read (unsigned long long buf, unsigned long long len, unsigned int write); int fat_dir (char *dirname); #endif #else @@ -61,7 +38,7 @@ int fat_dir (char *dirname); #define FSYS_NTFS_NUM 1 #ifndef ASM_FILE int ntfs_mount (void); -unsigned long long ntfs_read (unsigned long long buf, unsigned long long len, unsigned long write); +unsigned long long ntfs_read (unsigned long long buf, unsigned long long len, unsigned int write); int ntfs_dir (char *dirname); #endif #else @@ -72,75 +49,18 @@ int ntfs_dir (char *dirname); #define FSYS_EXT2FS_NUM 1 #ifndef ASM_FILE int ext2fs_mount (void); -unsigned long long ext2fs_read (unsigned long long buf, unsigned long long len, unsigned long write); +unsigned long long ext2fs_read (unsigned long long buf, unsigned long long len, unsigned int write); int ext2fs_dir (char *dirname); #endif #else #define FSYS_EXT2FS_NUM 0 #endif -#ifdef FSYS_MINIX -#define FSYS_MINIX_NUM 1 -#ifndef ASM_FILE -int minix_mount (void); -unsigned long long minix_read (unsigned long long buf, unsigned long long len, unsigned long write); -int minix_dir (char *dirname); -#endif -#else -#define FSYS_MINIX_NUM 0 -#endif - -#ifdef FSYS_REISERFS -#define FSYS_REISERFS_NUM 1 -#ifndef ASM_FILE -int reiserfs_mount (void); -unsigned long long reiserfs_read (unsigned long long buf, unsigned long long len, unsigned long write); -int reiserfs_dir (char *dirname); -unsigned long reiserfs_embed (unsigned long *start_sector, unsigned long needed_sectors); -#endif -#else -#define FSYS_REISERFS_NUM 0 -#endif - -#ifdef FSYS_VSTAFS -#define FSYS_VSTAFS_NUM 1 -#ifndef ASM_FILE -int vstafs_mount (void); -unsigned long long vstafs_read (unsigned long long buf, unsigned long long len, unsigned long write); -int vstafs_dir (char *dirname); -#endif -#else -#define FSYS_VSTAFS_NUM 0 -#endif - -#ifdef FSYS_JFS -#define FSYS_JFS_NUM 1 -#ifndef ASM_FILE -int jfs_mount (void); -unsigned long long jfs_read (unsigned long long buf, unsigned long long len, unsigned long write); -int jfs_dir (char *dirname); -unsigned long jfs_embed (unsigned long *start_sector, unsigned long needed_sectors); -#endif -#else -#define FSYS_JFS_NUM 0 -#endif - -#ifdef FSYS_XFS -#define FSYS_XFS_NUM 1 -#ifndef ASM_FILE -int xfs_mount (void); -unsigned long long xfs_read (unsigned long long buf, unsigned long long len, unsigned long write); -int xfs_dir (char *dirname); -#endif -#else -#define FSYS_XFS_NUM 0 -#endif - #ifdef FSYS_TFTP #define FSYS_TFTP_NUM 1 #ifndef ASM_FILE int tftp_mount (void); -unsigned long long tftp_read (unsigned long long buf, unsigned long long len, unsigned long write); +unsigned long long tftp_read (unsigned long long buf, unsigned long long len, unsigned int write); int tftp_dir (char *dirname); void tftp_close (void); #endif @@ -152,7 +72,7 @@ void tftp_close (void); #define FSYS_ISO9660_NUM 1 #ifndef ASM_FILE int iso9660_mount (void); -unsigned long long iso9660_read (unsigned long long buf, unsigned long long len, unsigned long write); +unsigned long long iso9660_read (unsigned long long buf, unsigned long long len, unsigned int write); int iso9660_dir (char *dirname); int big_to_little (char *filename, unsigned int n); #endif @@ -164,7 +84,7 @@ int big_to_little (char *filename, unsigned int n); #define FSYS_PXE_NUM 1 #ifndef ASM_FILE int pxe_mount (void); -unsigned long long pxe_read (unsigned long long buf, unsigned long long len, unsigned long write); +unsigned long long pxe_read (unsigned long long buf, unsigned long long len, unsigned int write); int pxe_dir (char *dirname); void pxe_close (void); #endif @@ -176,7 +96,7 @@ void pxe_close (void); #define FSYS_INITRD_NUM 1 #ifndef ASM_FILE int initrdfs_mount (void); -unsigned long long initrdfs_read (unsigned long long buf, unsigned long long len, unsigned long write); +unsigned long long initrdfs_read (unsigned long long buf, unsigned long long len, unsigned int write); int initrdfs_dir (char *dirname); void initrdfs_close (void); #endif @@ -188,7 +108,7 @@ void initrdfs_close (void); #define FSYS_FB_NUM 1 #ifndef ASM_FILE int fb_mount (void); -unsigned long long fb_read (unsigned long long buf, unsigned long long len, unsigned long write); +unsigned long long fb_read (unsigned long long buf, unsigned long long len, unsigned int write); int fb_dir (char *dirname); #endif #else @@ -197,20 +117,19 @@ int fb_dir (char *dirname); #ifndef NUM_FSYS #define NUM_FSYS \ - (FSYS_FFS_NUM + FSYS_FAT_NUM + FSYS_NTFS_NUM + FSYS_EXT2FS_NUM + FSYS_MINIX_NUM \ - + FSYS_REISERFS_NUM + FSYS_VSTAFS_NUM + FSYS_JFS_NUM + FSYS_XFS_NUM \ - + FSYS_TFTP_NUM + FSYS_ISO9660_NUM + FSYS_UFS2_NUM + FSYS_PXE_NUM + FSYS_FB_NUM + FSYS_INITRD_NUM) + (FSYS_FAT_NUM + FSYS_NTFS_NUM + FSYS_EXT2FS_NUM \ + + FSYS_TFTP_NUM + FSYS_ISO9660_NUM + FSYS_PXE_NUM + FSYS_FB_NUM + FSYS_INITRD_NUM) #endif #ifndef ASM_FILE /* defines for the block filesystem info area */ #ifndef NO_BLOCK_FILES -#define BLK_CUR_FILEPOS (*((unsigned long*)FSYS_BUF)) -#define BLK_CUR_BLKLIST (*((unsigned long*)(FSYS_BUF+4))) -#define BLK_CUR_BLKNUM (*((unsigned long*)(FSYS_BUF+8))) +#define BLK_CUR_FILEPOS (*((unsigned int*)FSYS_BUF)) +#define BLK_CUR_BLKLIST (*((unsigned int*)(FSYS_BUF+4))) +#define BLK_CUR_BLKNUM (*((unsigned int*)(FSYS_BUF+8))) #define BLK_MAX_ADDR (FSYS_BUF+0x77F9) -#define BLK_BLKSTART(l) (*((unsigned long*)l)) -#define BLK_BLKLENGTH(l) (*((unsigned long*)(l+4))) +#define BLK_BLKSTART(l) (*((unsigned int*)l)) +#define BLK_BLKLENGTH(l) (*((unsigned int*)(l+4))) #define BLK_BLKLIST_START (FSYS_BUF+12) #define BLK_BLKLIST_INC_VAL 8 #endif /* NO_BLOCK_FILES */ @@ -221,10 +140,10 @@ struct fsys_entry { char *name; int (*mount_func) (void); - unsigned long long (*read_func) (unsigned long long buf, unsigned long long len, unsigned long write); + unsigned long long (*read_func) (unsigned long long buf, unsigned long long len, unsigned int write); int (*dir_func) (char *dirname); void (*close_func) (void); - unsigned long (*embed_func) (unsigned long *start_sector, unsigned long needed_sectors); + unsigned int (*embed_func) (unsigned int *start_sector, unsigned int needed_sectors); }; extern int print_possibilities; diff --git a/stage2/freebsd.h b/stage2/freebsd.h index 0b1baf85..45d5f592 100644 --- a/stage2/freebsd.h +++ b/stage2/freebsd.h @@ -57,7 +57,7 @@ #define B_PARTITIONSHIFT 8 #define B_TYPESHIFT 0 -#define B_DEVMAGIC ((unsigned long)0xa0000000) +#define B_DEVMAGIC ((unsigned int)0xa0000000) #define MAKEBOOTDEV(type, adaptor, controller, unit, partition) \ (((type) << B_TYPESHIFT) | ((adaptor) << B_ADAPTORSHIFT) | \ @@ -83,13 +83,13 @@ struct bootinfo /* End of fields that are always present. */ //#define bi_endcommon bi_n_bios_used unsigned int bi_n_bios_used; - unsigned long bi_bios_geom[N_BIOS_GEOM]; + unsigned int bi_bios_geom[N_BIOS_GEOM]; unsigned int bi_size; unsigned char bi_memsizes_valid; unsigned char bi_bios_dev; unsigned char bi_pad[2]; - unsigned long bi_basemem; - unsigned long bi_extmem; - unsigned long bi_symtab; - unsigned long bi_esymtab; + unsigned int bi_basemem; + unsigned int bi_extmem; + unsigned int bi_symtab; + unsigned int bi_esymtab; }; diff --git a/stage2/fsys_ext2fs.c b/stage2/fsys_ext2fs.c index 9b8ba4b0..6ab4c865 100644 --- a/stage2/fsys_ext2fs.c +++ b/stage2/fsys_ext2fs.c @@ -158,7 +158,7 @@ struct ext2_super_block __u16 s_reserved_pad; __u64 s_kbytes_written; /* nr of lifetime kilobytes written */ __u32 s_reserved[160]; /* Padding to the end of the block */ - }; + } __attribute__ ((packed)); struct ext4_group_desc { @@ -180,7 +180,7 @@ struct ext4_group_desc __u16 bg_used_dirs_count_hi; /* Directories count MSB */ __u16 bg_itable_unused_hi; /* Unused inodes count MSB */ __u32 bg_reserved2[3]; - }; + } __attribute__ ((packed)); struct ext2_inode { @@ -256,7 +256,7 @@ struct ext2_inode __u32 i_crtime; /* File Creation time */ __u32 i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */ __u32 i_version_hi; /* high 32 bits for 64-bit version */ - }; + } __attribute__ ((packed)); #define EXT4_FEATURE_INCOMPAT_META 0x0010 #define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */ @@ -276,7 +276,7 @@ struct ext2_inode #define NAME_MAX 255 /* # chars in a file name */ /* linux/posix_type.h */ -typedef long linux_off_t; +typedef int linux_off_t; /* linux/ext2fs.h */ #define EXT2_NAME_LEN 255 @@ -287,7 +287,7 @@ struct ext2_dir_entry __u8 name_len; /* Name length */ __u8 file_type; char name[EXT2_NAME_LEN]; /* File name */ - }; + } __attribute__ ((packed)); /* linux/ext4_fs_extents.h */ /* This is the extent on-disk structure. @@ -299,7 +299,7 @@ struct ext4_extent __u16 ee_len; /* number of blocks covered by extent */ __u16 ee_start_hi; /* high 16 bits of physical block */ __u32 ee_start_lo; /* low 32 bits of physical block */ - }; + } __attribute__ ((packed)); /* * This is index on-disk structure. @@ -312,7 +312,7 @@ struct ext4_extent_idx * level. leaf or next index could be there */ __u16 ei_leaf_hi; /* high 16 bits of physical block */ __u16 ei_unused; - }; + } __attribute__ ((packed)); /* * Each block (leaves and indexes), even inode-stored has header. @@ -324,7 +324,7 @@ struct ext4_extent_header __u16 eh_max; /* capacity of store in entries */ __u16 eh_depth; /* has tree real underlying blocks? */ __u32 eh_generation; /* generation of the tree */ - }; + } __attribute__ ((packed)); #define EXT4_EXT_MAGIC (0xf30a) #define EXT_FIRST_EXTENT(__hdr__) \ @@ -360,6 +360,7 @@ struct ext4_extent_header #define PATH_MAX 1024 /* include/linux/limits.h */ #define MAX_LINK_COUNT 5 /* number of symbolic links to follow */ + /* made up, these are pointers into FSYS_BUF */ /* read once, always stays there: */ #define NAME_BUF ((char *)(FSYS_BUF)) /* 512 bytes */ @@ -367,13 +368,13 @@ struct ext4_extent_header ((struct ext2_super_block *)((FSYS_BUF)+512)) /* 1024 bytes */ #define GROUP_DESC \ ((struct ext2_group_desc *) \ - ((int)SUPERBLOCK + sizeof(struct ext2_super_block))) /* 32 bytes */ + ((grub_size_t)SUPERBLOCK + sizeof(struct ext2_super_block))) /* 32 bytes */ #define INODE \ - ((struct ext2_inode *)((int)GROUP_DESC + EXT2_BLOCK_SIZE(SUPERBLOCK))) + ((struct ext2_inode *)((grub_size_t)GROUP_DESC + EXT2_BLOCK_SIZE(SUPERBLOCK))) #define DATABLOCK1 \ - ((int)((int)INODE + sizeof(struct ext2_inode))) + ((grub_size_t)((grub_size_t)INODE + sizeof(struct ext2_inode))) #define DATABLOCK2 \ - ((int)((int)DATABLOCK1 + EXT2_BLOCK_SIZE(SUPERBLOCK))) + ((grub_size_t)((grub_size_t)DATABLOCK1 + EXT2_BLOCK_SIZE(SUPERBLOCK))) /* linux/ext2_fs.h */ #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32)) @@ -420,37 +421,22 @@ struct ext4_extent_header #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) -static char *linkbuf = (char *)(FSYS_BUF - PATH_MAX); /* buffer for following symbolic links */ - +#define linkbuf ((char *)(FSYS_BUF - PATH_MAX)) /* buffer for following symbolic links */ /* include/asm-i386/bitops.h */ /* * ffz = Find First Zero in word. Undefined if no zero exists, * so code should check against ~0UL first.. */ -//static __inline__ unsigned long -//ffz (unsigned long word) -//{ -// __asm__ ("bsfl %1,%0" -//: "=r" (word) -//: "r" (~word)); -// return word; -//} /* check filesystem types and read superblock into memory buffer */ +int ext2fs_mount (void); int ext2fs_mount (void) { -// if (((current_drive & 0x80) || (current_slice != 0)) -// && (current_slice != PC_SLICE_TYPE_EXT2FS) -// && (current_slice != PC_SLICE_TYPE_LINUX_RAID) -// && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_EXT2FS)) -// && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_OTHER))) -// return 0; - - if ((unsigned long)part_length < (SBLOCK + (sizeof(struct ext2_super_block) / DEV_BSIZE))) + if ((unsigned int)part_length < (SBLOCK + (sizeof(struct ext2_super_block) / DEV_BSIZE))) return 0; - if (!devread(SBLOCK, 0, sizeof(struct ext2_super_block), (unsigned long long)(unsigned int) (char *)SUPERBLOCK, 0xedde0d90)) + if (!devread(SBLOCK, 0, sizeof(struct ext2_super_block), (unsigned long long)(grub_size_t) (char *)SUPERBLOCK, 0xedde0d90)) return 0; if (SUPERBLOCK->s_magic != EXT2_SUPER_MAGIC) @@ -459,7 +445,6 @@ ext2fs_mount (void) if (SUPERBLOCK->s_inodes_count == 0) return 0; -// if (SUPERBLOCK->s_blocks_count == 0) if ((SUPERBLOCK->s_blocks_count_lo | SUPERBLOCK->s_blocks_count_hi) == 0) return 0; @@ -496,15 +481,15 @@ ext2fs_mount (void) } /* Takes a file system block number and reads it into BUFFER. */ +static int ext2_rdfsb (unsigned long long fsblock, unsigned long long buffer); static int -//ext2_rdfsb (int fsblock, int buffer) -ext2_rdfsb (unsigned long long fsblock, int buffer) +ext2_rdfsb (unsigned long long fsblock, unsigned long long buffer) { #ifdef E2DEBUG printf ("fsblock %d buffer %d\n", fsblock, buffer); #endif /* E2DEBUG */ return devread (fsblock * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE), 0, - EXT2_BLOCK_SIZE (SUPERBLOCK), (unsigned long long)(unsigned int)(char *) buffer, 0xedde0d90); + EXT2_BLOCK_SIZE (SUPERBLOCK), buffer, 0xedde0d90); } /* from @@ -512,8 +497,9 @@ ext2_rdfsb (unsigned long long fsblock, int buffer) */ /* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into a physical block (the location in the file system) via an inode. */ +static int ext2fs_block_map (unsigned int logical_block); static int -ext2fs_block_map (unsigned long logical_block) +ext2fs_block_map (unsigned int logical_block) { #ifdef E2DEBUG @@ -557,12 +543,12 @@ ext2fs_block_map (unsigned long logical_block) return -1; } mapblock1 = 1; - return ((__u32 *) DATABLOCK1)[logical_block]; + return ((__u32 *)(grub_size_t) DATABLOCK1)[logical_block]; } /* else */ logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK); /* now try the double indirect block */ - if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2))) + if (logical_block < (unsigned int)(1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2))) { int bnum; if (mapblock1 != 2 @@ -572,7 +558,7 @@ ext2fs_block_map (unsigned long logical_block) return -1; } mapblock1 = 2; - if ((bnum = (((__u32 *) DATABLOCK1) + if ((bnum = (((__u32 *)(grub_size_t) DATABLOCK1) [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)])) != mapblock2 && !ext2_rdfsb (bnum, DATABLOCK2)) @@ -581,7 +567,7 @@ ext2fs_block_map (unsigned long logical_block) return -1; } mapblock2 = bnum; - return ((__u32 *) DATABLOCK2) + return ((__u32 *)(grub_size_t) DATABLOCK2) [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]; } /* else */ @@ -597,7 +583,7 @@ ext2fs_block_map (unsigned long logical_block) mapblock1 = 3; - if (!ext2_rdfsb (((__u32 *) DATABLOCK1) + if (!ext2_rdfsb (((__u32 *)(grub_size_t) DATABLOCK1) [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)], DATABLOCK2)) @@ -606,7 +592,7 @@ ext2fs_block_map (unsigned long logical_block) return -1; } - if (! ext2_rdfsb (((__u32 *) DATABLOCK2) + if (! ext2_rdfsb (((__u32 *)(grub_size_t) DATABLOCK2) [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)) & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)], DATABLOCK2)) @@ -615,13 +601,14 @@ ext2fs_block_map (unsigned long logical_block) return -1; } - return ((__u32 *) DATABLOCK2)[logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]; + return ((__u32 *)(grub_size_t) DATABLOCK2)[logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]; } /* extent binary search index * find closest index in the current level extent tree * kind of from ext4_ext_binsearch_idx in ext4/extents.c */ +static struct ext4_extent_idx* ext4_ext_binsearch_idx(struct ext4_extent_header* eh, int logical_block); static struct ext4_extent_idx* ext4_ext_binsearch_idx(struct ext4_extent_header* eh, int logical_block) { @@ -631,7 +618,7 @@ ext4_ext_binsearch_idx(struct ext4_extent_header* eh, int logical_block) while (l <= r) { m = l + (r - l) / 2; - if (logical_block < m->ei_block) + if (logical_block < (int)m->ei_block) r = m - 1; else l = m + 1; @@ -643,6 +630,7 @@ ext4_ext_binsearch_idx(struct ext4_extent_header* eh, int logical_block) * find closest extent in the leaf level * kind of from ext4_ext_binsearch in ext4/extents.c */ +static struct ext4_extent* ext4_ext_binsearch(struct ext4_extent_header* eh, int logical_block); static struct ext4_extent* ext4_ext_binsearch(struct ext4_extent_header* eh, int logical_block) { @@ -652,7 +640,7 @@ ext4_ext_binsearch(struct ext4_extent_header* eh, int logical_block) while (l <= r) { m = l + (r - l) / 2; - if (logical_block < m->ee_block) + if (logical_block < (int)m->ee_block) r = m - 1; else l = m + 1; @@ -664,6 +652,7 @@ ext4_ext_binsearch(struct ext4_extent_header* eh, int logical_block) * EXT4_HUGE_FILE_FL should be checked before calling this. */ //static int +static unsigned long long ext4fs_block_map (int logical_block); static unsigned long long ext4fs_block_map (int logical_block) { @@ -671,7 +660,6 @@ ext4fs_block_map (int logical_block) struct ext4_extent *ex;//, *extent; struct ext4_extent_idx *ei;//, *index; int depth; - //int i; #ifdef E2DEBUG unsigned char *i; @@ -706,18 +694,12 @@ ext4fs_block_map (int logical_block) return -1; } ei = ext4_ext_binsearch_idx(eh, logical_block); -// if (ei->ei_leaf_hi) -// {/* 64bit physical block number not supported */ -// errnum = ERR_FILELENGTH; -// return -1; -// } -// if (!ext2_rdfsb(ei->ei_leaf_lo, DATABLOCK1)) if (!ext2_rdfsb(((unsigned long long)ei->ei_leaf_hi<<32) + ei->ei_leaf_lo, DATABLOCK1)) { errnum = ERR_FSYS_CORRUPT; return -1; } - eh = (struct ext4_extent_header*)DATABLOCK1; + eh = (struct ext4_extent_header*)(grub_size_t)DATABLOCK1; } /* depth==0, we come to the leaf */ @@ -727,7 +709,7 @@ ext4fs_block_map (int logical_block) // errnum = ERR_FILELENGTH; // return -1; // } - if ((ex->ee_block + ex->ee_len) < logical_block) + if ((int)(ex->ee_block + ex->ee_len) < logical_block) { errnum = ERR_FSYS_CORRUPT; return -1; @@ -737,14 +719,14 @@ ext4fs_block_map (int logical_block) } /* preconditions: all preconds of ext2fs_block_map */ +unsigned long long ext2fs_read (unsigned long long buf, unsigned long long len, unsigned int write); unsigned long long -ext2fs_read (unsigned long long buf, unsigned long long len, unsigned long write) +ext2fs_read (unsigned long long buf, unsigned long long len, unsigned int write) { - unsigned long logical_block; - unsigned long offset; - unsigned long ret = 0; - unsigned long size = 0; -// int map; + unsigned int logical_block; + unsigned int offset; + unsigned int ret = 0; + unsigned int size = 0; unsigned long long map; #ifdef E2DEBUG @@ -785,7 +767,7 @@ ext2fs_read (unsigned long long buf, unsigned long long len, unsigned long write printf ("map=%d\n", map); #endif /* E2DEBUG */ - if (map < 0) + if ((long long)map < 0) break; size = EXT2_BLOCK_SIZE (SUPERBLOCK); @@ -820,36 +802,13 @@ ext2fs_read (unsigned long long buf, unsigned long long len, unsigned long write return ret; } - -/* Based on: - def_blk_fops points to - blkdev_open, which calls (I think): - sys_open() - do_open() - open_namei() - dir_namei() which accesses current->fs->root - fs->root was set during original mount: - (something)... which calls (I think): - ext2_read_super() - iget() - __iget() - read_inode() - ext2_read_inode() - uses desc_per_block_bits, which is set in ext2_read_super() - also uses group descriptors loaded during ext2_read_super() - lookup() - ext2_lookup() - ext2_find_entry() - ext2_getblk() - -*/ - +static inline int ext2_is_fast_symlink (void); static inline int ext2_is_fast_symlink (void) { int ea_blocks; ea_blocks = INODE->i_file_acl_lo ? EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE : 0; - return INODE->i_blocks_lo == ea_blocks; + return (int)INODE->i_blocks_lo == ea_blocks; } /* preconditions: ext2fs_mount already executed, therefore supblk in buffer @@ -859,16 +818,15 @@ int ext2_is_fast_symlink (void) * inode of the file we were trying to look up * side effects: messes up GROUP_DESC buffer area */ +int ext2fs_dir (char *dirname); int ext2fs_dir (char *dirname) { int current_ino = EXT2_ROOT_INO; /* start at the root */ int updir_ino = current_ino; /* the parent of the current directory */ int group_id,tem; /* which group the inode is in */ -// int group_desc; /* fs pointer to that group */ unsigned long long group_desc; /* fs pointer to that group */ int desc; /* index within that group */ -// int ino_blk; /* fs pointer of the inode's information */ unsigned long long ino_blk; /* fs pointer of the inode's information */ int str_chk = 0; /* used to hold the results of a string compare */ struct ext4_group_desc *ext4_gdp; @@ -881,10 +839,9 @@ ext2fs_dir (char *dirname) char ch; /* temp char holder */ int off; /* offset within block of directory entry (off mod blocksize) */ -// int loc; /* location within a directory */ unsigned long long loc; /* location within a directory */ int blk; /* which data blk within dir entry (off div blocksize) */ - long map; /* fs pointer of a particular block from dir entry */ + int map; /* fs pointer of a particular block from dir entry */ struct ext2_dir_entry *dp; /* pointer to directory entry */ #ifdef E2DEBUG unsigned char *i; @@ -907,7 +864,7 @@ ext2fs_dir (char *dirname) /* look up an inode */ group_id = tem = (current_ino - 1) / SUPERBLOCK->s_inodes_per_group; if ((EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK,EXT4_FEATURE_INCOMPAT_META)) - && (group_id >= SUPERBLOCK->s_first_meta_bg)) + && (group_id >= (int)SUPERBLOCK->s_first_meta_bg)) { group_id = (group_id - SUPERBLOCK->s_first_meta_bg) % EXT4_META_GROUP_SIZE(SUPERBLOCK); @@ -921,28 +878,19 @@ ext2fs_dir (char *dirname) group_desc = (group_id >> log2_tmp (EXT2_DESC_PER_BLOCK (SUPERBLOCK))) + WHICH_SUPER + SUPERBLOCK->s_first_data_block; } -// group_desc = group_id >> log2_tmp (EXT2_DESC_PER_BLOCK (SUPERBLOCK)); desc = group_id & (EXT2_DESC_PER_BLOCK (SUPERBLOCK) - 1); #ifdef E2DEBUG printf ("ipg=%d, dpb=%d\n", SUPERBLOCK->s_inodes_per_group, EXT2_DESC_PER_BLOCK (SUPERBLOCK)); printf ("group_id=%d group_desc=%d desc=%d\n", group_id, group_desc, desc); #endif /* E2DEBUG */ -// if (!ext2_rdfsb ((WHICH_SUPER + group_desc + SUPERBLOCK->s_first_data_block), -// (int) GROUP_DESC)) - if (!ext2_rdfsb (group_desc,(int) GROUP_DESC)) + if (!ext2_rdfsb (group_desc,(grub_size_t) GROUP_DESC)) { return 0; } ext4_gdp = (struct ext4_group_desc *)( (__u8*)GROUP_DESC + desc * EXT2_DESC_SIZE(SUPERBLOCK)); -// if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK, EXT4_FEATURE_INCOMPAT_64BIT) -// && (! ext4_gdp->bg_inode_table_hi)) -// {/* 64bit itable not supported */ -// errnum = ERR_FILELENGTH; -// return -1; -// } -// ino_blk = ext4_gdp->bg_inode_table + + ino_blk = (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK,EXT4_FEATURE_INCOMPAT_64BIT) ? ((unsigned long long)ext4_gdp->bg_inode_table_hi<<32) : 0) + ext4_gdp->bg_inode_table_lo + (((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group)) @@ -950,7 +898,7 @@ ext2fs_dir (char *dirname) #ifdef E2DEBUG printf ("inode table fsblock=%d\n", ino_blk); #endif /* E2DEBUG */ - if (!ext2_rdfsb (ino_blk, (int) INODE)) + if (!ext2_rdfsb (ino_blk, (grub_size_t) INODE)) { return 0; } @@ -965,7 +913,7 @@ ext2fs_dir (char *dirname) printf ("ipb=%d, sizeof(inode)=%d\n", EXT2_INODES_PER_BLOCK (SUPERBLOCK), EXT2_INODE_SIZE (SUPERBLOCK)); printf ("inode=%x, raw_inode=%x\n", INODE, raw_inode); - printf ("offset into inode table block=%d\n", ((int) raw_inode - (int) INODE)); + printf ("offset into inode table block=%d\n", ((grub_size_t) raw_inode - (grub_size_t) INODE)); for (i = (unsigned char *) INODE; i <= (unsigned char *) raw_inode; i++) { @@ -1001,23 +949,11 @@ ext2fs_dir (char *dirname) } /* Find out how long our remaining name is. */ - //len = 0; - //while (dirname[len] && !isspace (dirname[len])) - // len++; for (len = 0; (ch = dirname[len]) /*&& !isspace (ch)*/; len++) { -#if 0 - if (ch == '\\') - { - len++; - if (! (ch = dirname[len])) - break; - } -#endif } /* Get the symlink size. */ -// filemax = (INODE->i_size); filemax = (INODE->i_size_lo); if (filemax + len > PATH_MAX - 2) { @@ -1040,7 +976,7 @@ ext2fs_dir (char *dirname) if (! ext2_is_fast_symlink ()) { /* Read the necessary blocks, and reset the file pointer. */ - len = grub_read ((unsigned long long)(unsigned int)linkbuf, filemax, 0xedde0d90); + len = grub_read ((unsigned long long)(grub_size_t)linkbuf, filemax, 0xedde0d90); filepos = 0; if (!len) return 0; @@ -1084,14 +1020,6 @@ ext2fs_dir (char *dirname) return 0; } /* if file is too large, just stop and report an error*/ -// if ( (INODE->i_flags & EXT4_HUGE_FILE_FL) && !(INODE->i_size_high)) -// { -// /* file too large, stop reading */ -// errnum = ERR_FILELENGTH; -// return 0; -// } - -// filemax = (INODE->i_size); filemax = ((unsigned long long)INODE->i_size_high<<32) + INODE->i_size_lo; return 1; } @@ -1104,7 +1032,6 @@ ext2fs_dir (char *dirname) dirname++; /* if this isn't a directory of sufficient size to hold our file, abort */ -// if (!(INODE->i_size) || !S_ISDIR (INODE->i_mode)) if (!(((unsigned long long)INODE->i_size_high<<32) + INODE->i_size_lo) || !S_ISDIR (INODE->i_mode)) { errnum = ERR_BAD_FILETYPE; @@ -1112,18 +1039,9 @@ ext2fs_dir (char *dirname) } /* skip to next slash or end of filename (space) */ -// for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; -// rest++); for (rest = dirname; (ch = *rest) /*&& !isspace (ch)*/ && ch != '/'; rest++) { -#if 0 - if (ch == '\\') - { - rest++; - if (! (ch = *rest)) - break; - } -#endif + } /* look through this directory and find the next filename component */ @@ -1140,7 +1058,6 @@ ext2fs_dir (char *dirname) /* if our location/byte offset into the directory exceeds the size, give up */ -// if (loc >= INODE->i_size) if (loc >= (((unsigned long long)INODE->i_size_high<<32) + INODE->i_size_lo)) { if (print_possibilities < 0) @@ -1185,7 +1102,7 @@ ext2fs_dir (char *dirname) return 0; } off = loc & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1); - dp = (struct ext2_dir_entry *) (DATABLOCK2 + off); + dp = (struct ext2_dir_entry *)(grub_size_t) (DATABLOCK2 + off); /* advance loc prematurely to next on-disk directory entry */ loc += dp->rec_len; @@ -1209,15 +1126,11 @@ ext2fs_dir (char *dirname) { if (! (ch1 = dp->name[j])) break; -#if 0 - if (ch1 == ' ') - tmp_name[k++] = '\\'; -#endif + tmp_name[k++] = ch1; } tmp_name[k] = 0; - //dp->name[dp->name_len] = 0; str_chk = substring (dirname, tmp_name, 0); if (print_possibilities && ch != '/' @@ -1226,22 +1139,23 @@ ext2fs_dir (char *dirname) if (print_possibilities > 0) print_possibilities = -print_possibilities; unsigned long long clo64 = current_color_64bit; - unsigned long clo = current_color; + unsigned int clo = current_color; if (dp->file_type == 2) { if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_HIGHLIGHT); current_color_64bit = (current_color_64bit & 0xffffff) | (clo64 & 0xffffff00000000); current_color = (current_color & 0x0f) | (clo & 0xf0); + console_setcolorstate (current_color | 0x100); //设置控制台文本模式的颜色(UEFI) } print_a_completion (tmp_name, 0); - current_color_64bit = clo64; - current_color = clo; + if (cursor_state & 1) + current_term->setcolorstate (COLOR_STATE_STANDARD); + else + current_term->setcolorstate (COLOR_STATE_NORMAL); if (*tmp_name != 0x2e) empty = 1; } - - //dp->name[dp->name_len] = saved_c; } } diff --git a/stage2/fsys_fat.c b/stage2/fsys_fat.c index 1a18f1ff..8f2671fa 100644 --- a/stage2/fsys_fat.c +++ b/stage2/fsys_fat.c @@ -27,49 +27,47 @@ struct fat_superblock { - unsigned long fat_offset; - unsigned long fat_length; + unsigned int fat_offset; + unsigned int fat_length; int fat_size; int fat_type; - unsigned long root_offset; + unsigned int root_offset; int root_max; - unsigned long data_offset; + unsigned int data_offset; unsigned long long num_sectors; - unsigned long num_clust; - unsigned long clust_eof_marker; - unsigned long sects_per_clust; + unsigned int num_clust; + unsigned int clust_eof_marker; + unsigned int sects_per_clust; int sectsize_bits; int clustsize_bits; - unsigned long root_cluster; + unsigned int root_cluster; long long cached_fat; - unsigned long file_cluster; + unsigned int file_cluster; unsigned long long contig_size; - unsigned long current_cluster_num; + unsigned int current_cluster_num; - unsigned long current_cluster; + unsigned int current_cluster; unsigned long long vol_sector; -}; + unsigned int sectsize; +} __attribute__ ((packed)); unsigned int fats_type; - +#if 0 /* pointer(s) into filesystem info buffer for DOS stuff */ -#define FAT_SUPER ((struct fat_superblock *)(FSYS_BUF + 32256))/* 512 bytes long */ +#define FAT_SUPER ((struct fat_superblock *)(FSYS_BUF + 32256))/* 512 bytes long*/ #define FAT_BUF (FSYS_BUF + 30208) /* 4 sector FAT buffer(2048 bytes) */ #define NAME_BUF (FSYS_BUF + 28160) /* unicode name buffer(833*2 bytes)*/ #define UTF8_BUF (FSYS_BUF + 25600) /* UTF8 name buffer (833*3 bytes)*/ +#else +#define FAT_SUPER ((struct fat_superblock *)(FSYS_BUF + 0x7000))/* 4096 bytes long*/ +#define FAT_BUF (FSYS_BUF + 0x6000) /* 4 sector FAT buffer(2048 bytes) */ +#define NAME_BUF (FSYS_BUF + 0x5800) /* unicode name buffer(833*2 bytes)*/ +#define UTF8_BUF (FSYS_BUF + 0x4e00) /* UTF8 name buffer (833*3 bytes)*/ +#endif +#define FAT_CACHE_SIZE 4096 -#define FAT_CACHE_SIZE 2048 - -//static __inline__ unsigned long -//log2_tmp (unsigned long word) -//{ -// __asm__ ("bsfl %1,%0" -// : "=r" (word) -// : "r" (word)); -// return word; -//} - +int fat_mount (void); int fat_mount (void) { @@ -77,14 +75,8 @@ fat_mount (void) __u32 first_fat; __u32 magic; - /* Check partition type for harddisk */ -// if (((current_drive & 0x80) || (current_slice != 0)) -// && ! IS_PC_SLICE_TYPE_FAT (current_slice) -// && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_MSDOS))) -// return 0; - /* Read bpb */ - if (! devread (0, 0, sizeof (bpb), (unsigned long long)(unsigned int)(char *) &bpb, 0xedde0d90)) + if (! devread (0, 0, sizeof (bpb), (unsigned long long)(grub_size_t)(char *) &bpb, 0xedde0d90)) return 0; if (! bpb.fat_length && ! bpb.fat32_length) @@ -100,27 +92,25 @@ fat_mount (void) if (128 % bpb.sects_per_clust) return 0; - FAT_SUPER->sectsize_bits = log2_tmp (FAT_CVT_U16 (bpb.bytes_per_sect)); - + unsigned short *a1 = (unsigned short *)(bpb.bytes_per_sect); +// FAT_SUPER->sectsize = FAT_CVT_U16 (bpb.bytes_per_sect); + FAT_SUPER->sectsize = *a1; +// FAT_SUPER->sectsize_bits = log2_tmp (FAT_CVT_U16 (bpb.bytes_per_sect)); + FAT_SUPER->sectsize_bits = log2_tmp (*a1); /* sector size must be 512 */ - if (FAT_SUPER->sectsize_bits != 9) +// if (FAT_SUPER->sectsize_bits != 9) + if (FAT_SUPER->sectsize_bits != 9 && FAT_SUPER->sectsize_bits != 12) return 0; FAT_SUPER->clustsize_bits = FAT_SUPER->sectsize_bits + log2_tmp (bpb.sects_per_clust); - - /* cluster size must be <= 32768 */ -// if (FAT_SUPER->clustsize_bits > 15) -// { -// if (debug > 0) -// grub_printf ("Warning! FAT cluster size(=%d) larger than 32K!\n", (1 << (FAT_SUPER->clustsize_bits))); - //return 0; -// } /* reserved sectors should not be 0 for fat_fs */ - if (FAT_CVT_U16 (bpb.reserved_sects) == 0) + a1 = (unsigned short *)(bpb.reserved_sects); +// if (FAT_CVT_U16 (bpb.reserved_sects) == 0) + if (*a1 == 0) return 0; - + FAT_SUPER->fat_offset = *a1; /* Number of FATs(nearly always 2). */ if ((unsigned char)(bpb.num_fats - 1) > 1) return 0; @@ -134,32 +124,36 @@ fat_mount (void) return 0; /* Fill in info about super block */ - FAT_SUPER->num_sectors = FAT_CVT_U16 (bpb.short_sectors) - ? FAT_CVT_U16 (bpb.short_sectors) : bpb.long_sectors; - + a1 = (unsigned short *)(bpb.short_sectors); +// FAT_SUPER->num_sectors = FAT_CVT_U16 (bpb.short_sectors) +// ? FAT_CVT_U16 (bpb.short_sectors) : bpb.long_sectors; + FAT_SUPER->num_sectors = *a1 ? *a1 : bpb.long_sectors; /* FAT offset and length */ - FAT_SUPER->fat_offset = FAT_CVT_U16 (bpb.reserved_sects); +// FAT_SUPER->fat_offset = FAT_CVT_U16 (bpb.reserved_sects); FAT_SUPER->fat_length = bpb.fat_length ? bpb.fat_length : bpb.fat32_length; /* Rootdir offset and length for FAT12/16 */ FAT_SUPER->root_offset = FAT_SUPER->fat_offset + bpb.num_fats * FAT_SUPER->fat_length; - FAT_SUPER->root_max = FAT_DIRENTRY_LENGTH * FAT_CVT_U16(bpb.dir_entries); - + a1 = (unsigned short *)(bpb.dir_entries); +// FAT_SUPER->root_max = FAT_DIRENTRY_LENGTH * FAT_CVT_U16(bpb.dir_entries); + FAT_SUPER->root_max = FAT_DIRENTRY_LENGTH * *a1; /* Data offset and number of clusters */ FAT_SUPER->data_offset = FAT_SUPER->root_offset - + ((FAT_SUPER->root_max + SECTOR_SIZE - 1) >> FAT_SUPER->sectsize_bits); +// + ((FAT_SUPER->root_max + SECTOR_SIZE - 1) >> FAT_SUPER->sectsize_bits); + + ((FAT_SUPER->root_max + FAT_SUPER->sectsize - 1) >> FAT_SUPER->sectsize_bits); FAT_SUPER->num_clust = - 2 + (((unsigned long)FAT_SUPER->num_sectors - FAT_SUPER->data_offset) + 2 + (((unsigned int)FAT_SUPER->num_sectors - FAT_SUPER->data_offset) / bpb.sects_per_clust); FAT_SUPER->sects_per_clust = bpb.sects_per_clust; if (!bpb.fat_length) { /* This is a FAT32 */ - if (FAT_CVT_U16(bpb.dir_entries)) +// if (FAT_CVT_U16(bpb.dir_entries)) + if (*a1) return 0; if (bpb.flags & 0x0080) @@ -199,7 +193,7 @@ fat_mount (void) } /* Now do some sanity checks */ - +#if 0 if (FAT_CVT_U16(bpb.bytes_per_sect) != (1 << FAT_SUPER->sectsize_bits) || FAT_CVT_U16(bpb.bytes_per_sect) != SECTOR_SIZE || bpb.sects_per_clust != (1 << (FAT_SUPER->clustsize_bits @@ -208,11 +202,15 @@ fat_mount (void) || (FAT_SUPER->fat_size * FAT_SUPER->num_clust / (2 * SECTOR_SIZE) > FAT_SUPER->fat_length)) return 0; - +#endif + if (FAT_SUPER->num_clust <= 2 + || (((FAT_SUPER->fat_size * FAT_SUPER->num_clust) >> (1 + FAT_SUPER->sectsize_bits)) + > FAT_SUPER->fat_length)) + return 0; /* kbs: Media check on first FAT entry [ported from PUPA] */ if (!devread(FAT_SUPER->fat_offset, 0, - sizeof(first_fat), (unsigned long long)(unsigned int)(char *)&first_fat, 0xedde0d90)) + sizeof(first_fat), (unsigned long long)(grub_size_t)(char *)&first_fat, 0xedde0d90)) return 0; if (FAT_SUPER->fat_size == 8) @@ -235,33 +233,27 @@ fat_mount (void) descriptor, even if it is a so-called superfloppy (e.g. an USB key). The check may be too strict for this kind of stupid BIOSes, as they overwrite the media descriptor. */ -// if ((first_fat | 0x8) != (magic | bpb.media | 0x8)) -// if ((first_fat | 0x8) != (magic | 0xF8)) if ((first_fat | 0xF) != (magic | 0xFF)) - { - if (debug > 0) printf_warning ("Warning! Invalid first FAT entry(=0x%X)!\n", first_fat); - //return 0; - } - fats_type = FAT_SUPER->fat_type; + fats_type = FAT_SUPER->fat_type; FAT_SUPER->cached_fat = - 2 * FAT_CACHE_SIZE; return 1; label_exfat: /* bytes per sector for exFAT must be 0 */ - if (FAT_CVT_U16 (bpb.bytes_per_sect)) + a1 = (unsigned short *)(bpb.bytes_per_sect); +// if (FAT_CVT_U16 (bpb.bytes_per_sect)) + if (*a1) return 0; /* sector_bits - Power of 2. Minimum 9 (512 bytes per sector), maximum 12 (4096 bytes per sector) */ FAT_SUPER->sectsize_bits = bpb.sector_bits; -// if ((FAT_SUPER->sectsize_bits < 9) || (FAT_SUPER->sectsize_bits > 12)) -// return 0; - /* sector size must be 512 */ - if (FAT_SUPER->sectsize_bits != 9) +// if (FAT_SUPER->sectsize_bits != 9) + if (FAT_SUPER->sectsize_bits != 9 && FAT_SUPER->sectsize_bits != 12) return 0; /* spc_bits - Power of 2. Minimum 0 (1 sector per cluster), @@ -274,11 +266,7 @@ fat_mount (void) /* cluster size must be <= 32768 */ if (FAT_SUPER->clustsize_bits > 15) - { - if (debug > 0) printf_warning ("Warning! FAT cluster size(=%d) larger than 32K!\n", (1 << (FAT_SUPER->clustsize_bits))); - //return 0; - } /* Number of FATs(nearly always 1, 2 is for TexFAT only). */ if ((unsigned char)(bpb.fat_count - 1) > 1) @@ -300,16 +288,14 @@ fat_mount (void) /* Rootdir offset and length for FAT12/16 */ FAT_SUPER->root_offset = FAT_SUPER->data_offset; FAT_SUPER->root_max = 0; - - /* Test data offset */ -// if (FAT_SUPER->data_offset != FAT_SUPER->fat_offset + bpb.fat_count * FAT_SUPER->fat_length) -// return 0; FAT_SUPER->num_clust = bpb.cluster_count; - FAT_SUPER->sects_per_clust = (unsigned long)1 << bpb.spc_bits; + FAT_SUPER->sects_per_clust = (unsigned int)1 << bpb.spc_bits; - if (FAT_CVT_U16(bpb.dir_entries)) + a1 = (unsigned short *)(bpb.dir_entries); +// if (FAT_CVT_U16(bpb.dir_entries)) + if (*a1) return 0; /* ActiveFat 0 - First FAT and Allocation Bitmap are active, 1- Second. */ @@ -329,36 +315,33 @@ fat_mount (void) /* Now do some sanity checks */ if (FAT_SUPER->num_clust <= 2 - || (FAT_SUPER->fat_size * FAT_SUPER->num_clust / (2 * SECTOR_SIZE) +// || (FAT_SUPER->fat_size * FAT_SUPER->num_clust / (2 * SECTOR_SIZE) + || (((FAT_SUPER->fat_size * FAT_SUPER->num_clust) >> (1 + FAT_SUPER->sectsize_bits)) > FAT_SUPER->fat_length)) return 0; /* check first FAT entry */ if (!devread(FAT_SUPER->fat_offset, 0, sizeof(first_fat), - (unsigned long long)(unsigned int)(char *)&first_fat, 0xedde0d90)) + (unsigned long long)(grub_size_t)(char *)&first_fat, 0xedde0d90)) return 0; if (first_fat != 0xfffffff8) - { - if (debug > 0) printf_warning ("Warning! Invalid first FAT entry(=0x%X)!\n", first_fat); - //return 0; - } - fats_type = FAT_SUPER->fat_type; + fats_type = FAT_SUPER->fat_type; FAT_SUPER->cached_fat = - 2 * FAT_CACHE_SIZE; return 1; } +unsigned long long fat_read (unsigned long long buf, unsigned long long len, unsigned int write); unsigned long long -fat_read (unsigned long long buf, unsigned long long len, unsigned long write) +fat_read (unsigned long long buf, unsigned long long len, unsigned int write) { - unsigned long logical_clust; - unsigned long offset; + unsigned int logical_clust; + unsigned int offset; unsigned long long ret = 0; unsigned long long size; -// unsigned long long sector; #define sector FAT_SUPER->vol_sector if (! len) @@ -368,7 +351,7 @@ fat_read (unsigned long long buf, unsigned long long len, unsigned long write) { if (! FAT_SUPER->root_max) return 0; - if (FAT_SUPER->root_max <= filepos) + if ((unsigned long long)FAT_SUPER->root_max <= filepos) return 0; if (FAT_SUPER->fat_type > 16) return 0; @@ -386,7 +369,6 @@ fat_read (unsigned long long buf, unsigned long long len, unsigned long write) if ((FAT_SUPER->fat_type == 64) && (FAT_SUPER->contig_size)) { -// unsigned long sector; // sector = FAT_SUPER->data_offset + ((FAT_SUPER->file_cluster - 2) sector = (unsigned long long)FAT_SUPER->data_offset + ((unsigned long long)(FAT_SUPER->file_cluster - 2) << (FAT_SUPER->clustsize_bits - FAT_SUPER->sectsize_bits)); @@ -423,30 +405,25 @@ fat_read (unsigned long long buf, unsigned long long len, unsigned long write) while (len > 0) { -// unsigned long sector; while (logical_clust > FAT_SUPER->current_cluster_num) { /* calculate next cluster */ -// unsigned long fat_entry = -// FAT_SUPER->current_cluster * FAT_SUPER->fat_size; unsigned long long fat_entry = (unsigned long long)FAT_SUPER->current_cluster * FAT_SUPER->fat_size; - unsigned long next_cluster; - unsigned long cached_pos = (fat_entry - FAT_SUPER->cached_fat); + unsigned int next_cluster; + unsigned int cached_pos = (fat_entry - FAT_SUPER->cached_fat); - if (fat_entry < FAT_SUPER->cached_fat || + if (fat_entry < (unsigned long long)FAT_SUPER->cached_fat || (cached_pos + FAT_SUPER->fat_size) > 2*FAT_CACHE_SIZE) { - FAT_SUPER->cached_fat = (fat_entry & ~(2*SECTOR_SIZE - 1)); + FAT_SUPER->cached_fat = fat_entry & ~((FAT_SUPER->sectsize << 1) - 1); cached_pos = (fat_entry - FAT_SUPER->cached_fat); -// sector = FAT_SUPER->fat_offset -// + FAT_SUPER->cached_fat / (2*SECTOR_SIZE); sector = (unsigned long long)FAT_SUPER->fat_offset - + (unsigned long long)FAT_SUPER->cached_fat / (2*SECTOR_SIZE); - if (!devread (sector, 0, FAT_CACHE_SIZE, (unsigned long long)(unsigned int)(char*) FAT_BUF, 0xedde0d90)) + + ((unsigned long long)FAT_SUPER->cached_fat >> (FAT_SUPER->sectsize_bits + 1)); + if (!devread (sector, 0, FAT_CACHE_SIZE, (unsigned long long)(grub_size_t)(char*) FAT_BUF, 0xedde0d90)) return 0; } - next_cluster = * (unsigned long *) (FAT_BUF + (cached_pos >> 1)); + next_cluster = * (unsigned int *) (FAT_BUF + (cached_pos >> 1)); if (FAT_SUPER->fat_size == 3) { if (cached_pos & 1) @@ -476,7 +453,7 @@ fat_read (unsigned long long buf, unsigned long long len, unsigned long write) if (size > len) size = len; - + disk_read_func = disk_read_hook; devread(sector, offset, size, buf, write); @@ -495,6 +472,7 @@ fat_read (unsigned long long buf, unsigned long long len, unsigned long write) } char vol_name[256]; +int fat_dir (char *dirname); int fat_dir (char *dirname) { @@ -503,18 +481,15 @@ fat_dir (char *dirname) unsigned char *utf8 = (unsigned char *) UTF8_BUF; /* utf8 filename */ int attrib = FAT_ATTRIB_DIR; int exfat_attrib = FAT_ATTRIB_DIR; -// int exfat_flags = 0; unsigned char exfat_flags = 0; int exfat_secondarycount = 0; int exfat_namecount = 0; int exfat_nextentry = EXFAT_ENTRY_FILE; unsigned long long exfat_filemax = 0; - unsigned long exfat_file_cluster = 0; + unsigned int exfat_file_cluster = 0; int empty = 0; int i, j; -// int do_possibilities = 0; - /* XXX I18N: * the positions 2,4,6 etc are high bytes of a 16 bit unicode char */ @@ -532,10 +507,9 @@ fat_dir (char *dirname) loop: filepos = 0; FAT_SUPER->current_cluster_num = MAXINT; - + /* if we have a real file (and we're not just printing possibilities), then this is where we want to exit */ - if (!*dirname || isspace (*dirname)) { if (attrib & FAT_ATTRIB_DIR) @@ -543,7 +517,6 @@ fat_dir (char *dirname) errnum = ERR_BAD_FILETYPE; return 0; } - return 1; } @@ -552,7 +525,7 @@ fat_dir (char *dirname) /* skip over slashes */ while (*dirname == '/') dirname++; - + if (!(attrib & FAT_ATTRIB_DIR)) { errnum = ERR_BAD_FILETYPE; @@ -562,27 +535,14 @@ fat_dir (char *dirname) filemax = MAXINT; /* check if the dirname ends in a slash(saved in CH) and end it in a NULL */ - for (rest = dirname; (ch = *rest) /*&& !isspace (ch)*/ && ch != '/'; rest++) - { -#if 0 - if (ch == '\\') - { - rest++; - if (! (ch = *rest)) - break; - } -#endif - } + for (rest = dirname; (ch = *rest) /*&& !isspace (ch)*/ && ch != '/'; rest++); *rest = 0; -// if (print_possibilities && ch != '/') -// do_possibilities = 1; - while (1) { /* read the dir entry */ - if (fat_read ((unsigned long long)(unsigned int)dir_buf, FAT_DIRENTRY_LENGTH, 0xedde0d90) != FAT_DIRENTRY_LENGTH + if (fat_read ((unsigned long long)(grub_size_t)dir_buf, FAT_DIRENTRY_LENGTH, 0xedde0d90) != FAT_DIRENTRY_LENGTH /* read failure */ || dir_buf[0] == 0 /* end of dir entry */) { @@ -630,8 +590,7 @@ fat_dir (char *dirname) continue; case EXFAT_ENTRY_FILE_INFO: exfat_filemax = (*(unsigned long long *)(dir_buf+8)); - exfat_file_cluster = (*(unsigned long *)(dir_buf+20)); -// exfat_flags = (*(unsigned short *)(dir_buf+1)); + exfat_file_cluster = (*(unsigned int *)(dir_buf+20)); exfat_flags = (*(unsigned char *)(dir_buf+1)); exfat_nextentry = EXFAT_ENTRY_FILE_NAME; continue; @@ -709,36 +668,8 @@ fat_dir (char *dirname) sum = ((sum >> 1) | (sum << 7)) + dir_buf[i]; if (sum == alias_checksum) - { goto valid_filename; -// if (do_possibilities) -// goto print_filename; -// -// if (substring (dirname, filename, 1) == 0) -// break; } - } - -#if 0 -short_name: - /* XXX convert to 8.3 filename format here */ - { - int i, j, c; - - for (i = 0; i < 8 && (c = filename[i] = tolower (dir_buf[i])) - && /*!isspace (c)*/ c != ' '; i++); - - filename[i++] = '.'; - - for (j = 0; j < 3 && (c = filename[i + j] = tolower (dir_buf[8 + j])) - && /*!isspace (c)*/ c != ' '; j++); - - if (j == 0) - i--; - - filename[i + j] = 0; - } -#endif short_name: /* XXX convert to 8.3 filename format here */ @@ -767,23 +698,25 @@ fat_dir (char *dirname) j = unicode_to_utf8 (filename, utf8, 255); if (print_possibilities && ch != '/') { -// print_filename: if (substring (dirname, (char *)utf8, 1) <= 0) { if (print_possibilities > 0) print_possibilities = -print_possibilities; unsigned long long clo64 = current_color_64bit; - unsigned long clo = current_color; + unsigned int clo = current_color; if ((FAT_SUPER->fat_type == 64 && exfat_attrib & 0x10) || (FAT_SUPER->fat_type != 64 && FAT_DIRENTRY_ATTRIB (dir_buf) & 0x10)) { if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_HIGHLIGHT); current_color_64bit = (current_color_64bit & 0xffffff) | (clo64 & 0xffffff00000000); current_color = (current_color & 0x0f) | (clo & 0xf0); + console_setcolorstate (current_color | 0x100); //设置控制台文本模式的颜色(UEFI) } print_a_completion ((char *)utf8, 1); - current_color_64bit = clo64; - current_color = clo; + if (cursor_state & 1) + current_term->setcolorstate (COLOR_STATE_STANDARD); + else + current_term->setcolorstate (COLOR_STATE_NORMAL); if (*(char *)utf8 != 0x2e) empty = 1; } @@ -812,11 +745,9 @@ fat_dir (char *dirname) FAT_SUPER->contig_size = 0; goto loop; } - attrib = FAT_DIRENTRY_ATTRIB (dir_buf); filemax = FAT_DIRENTRY_FILELENGTH (dir_buf); FAT_SUPER->file_cluster = FAT_DIRENTRY_FIRST_CLUSTER (dir_buf); - /* go back to main loop at top of function */ goto loop; } diff --git a/stage2/fsys_fb.c b/stage2/fsys_fb.c index 6dd79cfe..c03e046e 100644 --- a/stage2/fsys_fb.c +++ b/stage2/fsys_fb.c @@ -26,8 +26,8 @@ /* Emm... Room between address 15M and 16M may be used by chipset. * Use 64K at 0x150000 instead. -- tinybit 2012-11-07 */ //#define FB_MENU_ADDR 0xff0000 -#define FB_MENU_ADDR 0x150000 - +//#define FB_MENU_ADDR 0x150000 +char *FB_MENU_ADDR = 0; #define FB_MAGIC "FBBF" #define FB_MAGIC_LONG 0x46424246 @@ -38,7 +38,7 @@ #define uchar unsigned char #define uchar2 unsigned short -#define uchar4 unsigned long +#define uchar4 unsigned int struct fb_mbr @@ -92,22 +92,24 @@ struct fbm_file */ char ver_min; static int fb_inited = FB_DRIVE; -static unsigned long fb_drive; +static unsigned int fb_drive; static uchar4 fb_ofs; static uchar4 fb_pri_size; static struct fbm_file *cur_file; static uchar *fbm_buff = NULL; static uchar4 ud_ofs; static uchar4 ud_pri_size; -static unsigned long ud_inited = 0; +static unsigned int ud_inited = 0; -extern unsigned long ROM_int13; -extern unsigned long ROM_int15; -static unsigned long is_virtual (unsigned long drive) +//extern unsigned long ROM_int13; +//extern unsigned long ROM_int15; +#if 0 +static unsigned int is_virtual (unsigned int drive); +static unsigned int is_virtual (unsigned int drive) { - unsigned long i; - unsigned long addr; - unsigned long low_mem; + unsigned int i; + unsigned int addr; + unsigned int low_mem; struct drive_map_slot *drive_map; low_mem = (*(unsigned short *)0x413); @@ -116,21 +118,21 @@ static unsigned long is_virtual (unsigned long drive) low_mem <<= (16 + 6); low_mem |= 0x100; addr = low_mem; - if (low_mem != (*(unsigned long *)0x4C)) + if (low_mem != (*(unsigned int *)0x4C)) return 0; low_mem >>= 12; /* int13_handler base address */ - if (grub_memcmp ((char *)(low_mem + 0x103), "$INT13SFGRUB4DOS", 16)) - return 0; - if (*(unsigned long *)(low_mem + 0x1C) < 0x5A000000) // old int13 + if (grub_memcmp ((char *)(grub_size_t)(low_mem + 0x103), "$INT13SFGRUB4DOS", 16)) return 0; - if (*(unsigned long *)(low_mem + 0x0C) < 0x5A000000) // old int15 + if (*(unsigned int *)(grub_size_t)(low_mem + 0x1C) < 0x5A000000) // old int13 return 0; - if (*(unsigned long *)(low_mem + 0x1C) != ROM_int13) // old int13 - return 0; - if (*(unsigned long *)(low_mem + 0x0C) != ROM_int15) // old int15 + if (*(unsigned int *)(grub_size_t)(low_mem + 0x0C) < 0x5A000000) // old int15 return 0; + //if (*(unsigned long *)(low_mem + 0x1C) != ROM_int13) // old int13 + //return 0; + //if (*(unsigned long *)(low_mem + 0x0C) != ROM_int15) // old int15 + //return 0; /* Yes, hooked. The drive map slots begins at (low_mem + 0x20). */ - drive_map = (struct drive_map_slot *)(low_mem + 0x20); + drive_map = (struct drive_map_slot *)(grub_size_t)(low_mem + 0x20); for (i = 0; i < DRIVE_MAP_SIZE; i++) { if (drive_map_slot_empty (drive_map[i])) @@ -141,9 +143,10 @@ static unsigned long is_virtual (unsigned long drive) return 0; } -static unsigned long quick_hook (unsigned long addr) +static unsigned int quick_hook (unsigned int addr); +static unsigned int quick_hook (unsigned int addr) { - unsigned long low_mem; + unsigned int low_mem; if (addr) goto hook; @@ -153,33 +156,34 @@ static unsigned long quick_hook (unsigned long addr) low_mem <<= (16 + 6); low_mem |= 0x100; addr = low_mem; - if (low_mem != (*(unsigned long *)0x4C)) + if (low_mem != (*(unsigned int *)0x4C)) return 0; low_mem >>= 12; /* int13_handler base address */ - if (grub_memcmp ((char *)(low_mem + 0x103), "$INT13SFGRUB4DOS", 16)) - return 0; - if (*(unsigned long *)(low_mem + 0x1C) < 0x5A000000) // old int13 + if (grub_memcmp ((char *)(grub_size_t)(low_mem + 0x103), "$INT13SFGRUB4DOS", 16)) return 0; - if (*(unsigned long *)(low_mem + 0x0C) < 0x5A000000) // old int15 + if (*(unsigned int *)(grub_size_t)(low_mem + 0x1C) < 0x5A000000) // old int13 return 0; - if (*(unsigned long *)(low_mem + 0x1C) != ROM_int13) // old int13 - return 0; - if (*(unsigned long *)(low_mem + 0x0C) != ROM_int15) // old int15 + if (*(unsigned int *)(grub_size_t)(low_mem + 0x0C) < 0x5A000000) // old int15 return 0; + //if (*(unsigned long *)(low_mem + 0x1C) != ROM_int13) // old int13 + //return 0; + //if (*(unsigned long *)(low_mem + 0x0C) != ROM_int15) // old int15 + //return 0; /* Yes, hooked. The drive map slots begins at (low_mem + 0x20). */ - (*(unsigned long *)0x4C) = ROM_int13; + //(*(unsigned long *)0x4C) = ROM_int13; buf_drive = -1; buf_track = -1; return addr; hook: - (*(unsigned long *)0x4C) = addr; + (*(unsigned int *)0x4C) = addr; buf_drive = -1; buf_track = -1; return addr; } - +#endif +static int fb_init (void); static int fb_init (void) { struct fb_mbr m; @@ -188,15 +192,16 @@ static int fb_init (void) uchar *fb_list, *p1, *p2; uchar4 t_fb_ofs = 0; uchar4 t_fb_pri_size = 0; - unsigned long ret; - unsigned long fb_drive_virtual; - - fb_drive_virtual = is_virtual(fb_drive); + unsigned int ret; +// unsigned int fb_drive_virtual; + if (!FB_MENU_ADDR) + FB_MENU_ADDR = grub_malloc (0x10000); +// fb_drive_virtual = is_virtual(fb_drive); - if (fb_drive_virtual && fb_status && fb_drive == (unsigned char)(fb_status >> 8)) - quick_hook (0); +// if (fb_drive_virtual && fb_status && fb_drive == (unsigned char)(fb_status >> 8)) +// quick_hook (0); - ret = rawread (fb_drive, 0, 0, 512, (unsigned long long)(unsigned int)&m, 0xedde0d90); + ret = rawread (fb_drive, 0, 0, 512, (unsigned long long)(grub_size_t)&m, 0xedde0d90); if (! ret) goto init_end; @@ -206,13 +211,13 @@ static int fb_init (void) boot_base = m.boot_base; t_fb_ofs = m.lba; ret = rawread (fb_drive, boot_base + 1 - t_fb_ofs, 0, 512, - (unsigned long long)(unsigned int)(char *)data, 0xedde0d90); + (unsigned long long)(grub_size_t)(char *)data, 0xedde0d90); if (! ret) goto init_end; boot_size = data->boot_size; t_fb_pri_size = data->pri_size; } - else if (*(unsigned long *)&m != FB_AR_MAGIC_LONG) + else if (*(unsigned int *)&m != FB_AR_MAGIC_LONG) { ret = 0; goto init_end; @@ -254,7 +259,7 @@ static int fb_init (void) } ret = rawread (fb_drive, boot_base + 1 + boot_size - t_fb_ofs, 0, - (unsigned long long)list_used << 9, (unsigned long long)(unsigned int)fb_list, 0xedde0d90); + (unsigned long long)list_used << 9, (unsigned long long)(grub_size_t)fb_list, 0xedde0d90); if (! ret) goto init_end; @@ -274,12 +279,13 @@ static int fb_init (void) init_end: - if (fb_drive_virtual && fb_status && fb_drive == (unsigned char)(fb_status >> 8)) - quick_hook (fb_drive_virtual); +// if (fb_drive_virtual && fb_status && fb_drive == (unsigned char)(fb_status >> 8)) +// quick_hook (fb_drive_virtual); return ret; } +int fb_mount (void); int fb_mount (void) { int ret; @@ -306,7 +312,7 @@ int fb_mount (void) if (current_partition != 0xFFFFFF) return 0; fb_drive = current_drive; - if (fb_inited == current_drive) + if ((unsigned int)fb_inited == current_drive) goto return_true; ret = fb_init(); @@ -321,12 +327,13 @@ int fb_mount (void) } +unsigned long long fb_read (unsigned long long buf, unsigned long long len, unsigned int write); unsigned long long -fb_read (unsigned long long buf, unsigned long long len, unsigned long write) +fb_read (unsigned long long buf, unsigned long long len, unsigned int write) { unsigned long long ret; - unsigned long sector, ofs, saved_len; - unsigned long fb_drive_virtual; + unsigned int sector, ofs, saved_len; +// unsigned int fb_drive_virtual; if (! cur_file->size) return 0; @@ -334,21 +341,21 @@ fb_read (unsigned long long buf, unsigned long long len, unsigned long write) if (! (ret = len)) return 0; - fb_drive_virtual = is_virtual(fb_drive); +// fb_drive_virtual = is_virtual(fb_drive); if (cur_file->data_start >= fb_pri_size) { sector = cur_file->data_start + (filepos >> 9) - fb_ofs; - if (fb_drive_virtual && fb_status && fb_drive == (unsigned char)(fb_status >> 8)) - quick_hook (0); +// if (fb_drive_virtual && fb_status && fb_drive == (unsigned char)(fb_status >> 8)) +// quick_hook (0); disk_read_func = disk_read_hook; ret = rawread (fb_drive, sector, filepos & 0x1ff, len, buf, write); disk_read_func = NULL; - if (fb_drive_virtual && fb_status && fb_drive == (unsigned char)(fb_status >> 8)) - quick_hook (fb_drive_virtual); +// if (fb_drive_virtual && fb_status && fb_drive == (unsigned char)(fb_status >> 8)) +// quick_hook (fb_drive_virtual); if (ret) filepos += len; @@ -362,16 +369,16 @@ fb_read (unsigned long long buf, unsigned long long len, unsigned long write) return len; } - sector = cur_file->data_start + ((unsigned long) filepos / 510) - fb_ofs; - ofs = (unsigned long) filepos % 510; + sector = cur_file->data_start + ((unsigned int) filepos / 510) - fb_ofs; + ofs = (unsigned int) filepos % 510; saved_len = len; - if (fb_drive_virtual && fb_status && fb_drive == (unsigned char)(fb_status >> 8)) - quick_hook (0); +// if (fb_drive_virtual && fb_status && fb_drive == (unsigned char)(fb_status >> 8)) +// quick_hook (0); while (len) { - unsigned long n; + unsigned int n; n = 510 - ofs; if (n > len) @@ -388,8 +395,8 @@ fb_read (unsigned long long buf, unsigned long long len, unsigned long write) len -= n; } - if (fb_drive_virtual && fb_status && fb_drive == (unsigned char)(fb_status >> 8)) - quick_hook (fb_drive_virtual); +// if (fb_drive_virtual && fb_status && fb_drive == (unsigned char)(fb_status >> 8)) +// quick_hook (fb_drive_virtual); if (! ret) return 0; @@ -399,10 +406,11 @@ fb_read (unsigned long long buf, unsigned long long len, unsigned long write) return saved_len; } +int fb_dir (char *dirname); int fb_dir (char *dirname) { - unsigned long found = 0; - unsigned long i; + unsigned int found = 0; + unsigned int i; char *dirpath; while (*dirname == '/') @@ -415,17 +423,17 @@ int fb_dir (char *dirname) if (*dirpath == '/') i++; - cur_file = (struct fbm_file *)((current_drive == FB_DRIVE)?FB_MENU_ADDR:(int)fbm_buff); + cur_file = (struct fbm_file *)(grub_size_t)((current_drive == FB_DRIVE)?(grub_size_t)FB_MENU_ADDR:(grub_size_t)fbm_buff); while (cur_file->size) { char tmp_name[512];/* max name len=255, so 512 byte buffer is needed. */ - unsigned long j, k; + unsigned int j, k; char ch1; /* copy cur_file->name to tmp_name, and quote spaces with '\\' */ // for (j = 0, k = 0; j < cur_file->size - 12; j++) - for (j = 0, k = 0; j < cur_file->size - ((ver_min==6)?12:16); j++) + for (j = 0, k = 0; j < (unsigned int)cur_file->size - ((ver_min==6)?12:16); j++) { // if (! (ch1 = cur_file->name[j])) if (! (ch1 = cur_file->name[j+((ver_min==6)?0:4)])) @@ -450,8 +458,10 @@ int fb_dir (char *dirname) if (substring (dirname, tmp_name/*cur_file->name*/, 1) == 0) { found = 1; -// filemax = cur_file->data_size; - filemax = (ver_min==6)?cur_file->data_size:(*(unsigned long long *)(&cur_file->data_size)); +// unsigned long long *a = (unsigned long long *)&cur_file->data_size; + int offse = offsetof(struct fbm_file, data_size); + unsigned long long *a = (unsigned long long *)((char *)cur_file + offse); + filemax = (ver_min==6)?cur_file->data_size:(*a); break; } diff --git a/stage2/fsys_ffs.c b/stage2/fsys_ffs.c deleted file mode 100644 index f25184b9..00000000 --- a/stage2/fsys_ffs.c +++ /dev/null @@ -1,799 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2000, 2001 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * Elements of this file were originally from the FreeBSD "biosboot" - * bootloader file "disk.c" dated 4/12/95. - * - * The license and header comments from that file are included here. - */ - -/* - * Mach Operating System - * Copyright (c) 1992, 1991 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - * - * from: Mach, Revision 2.2 92/04/04 11:35:49 rpd - * $Id: fsys_ffs.c,v 1.10 2001/11/12 06:57:29 okuji Exp $ - */ - -#ifdef FSYS_FFS - -#include "shared.h" - -#include "filesys.h" - -/* - * The I node is the focus of all file activity in the BSD Fast File System. - * There is a unique inode allocated for each active file, - * each current directory, each mounted-on file, text file, and the root. - * An inode is 'named' by its dev/inumber pair. (iget/iget.c) - * Data in icommon is read in from permanent inode on volume. - */ - -#define FFS_NDADDR 12 /* direct addresses in inode */ -#define FFS_NIADDR 3 /* indirect addresses in inode */ - -#define FFS_MAX_FASTLINK_SIZE ((FFS_NDADDR + FFS_NIADDR) \ - * sizeof (unsigned int)) - -struct icommon - { - unsigned short ic_mode; /* 0: mode and type of file */ - short ic_nlink; /* 2: number of links to file */ - unsigned short ic_uid; /* 4: owner's user id */ - unsigned short ic_gid; /* 6: owner's group id */ - unsigned long long ic_size; /* 8: number of bytes in file */ - unsigned int ic_atime; /* 16: time last accessed */ - int ic_atspare; - unsigned int ic_mtime; /* 24: time last modified */ - int ic_mtspare; - unsigned int ic_ctime; /* 32: last time inode changed */ - int ic_ctspare; - union - { - struct - { - unsigned int Mb_db[FFS_NDADDR]; /* 40: disk block addresses */ - unsigned int Mb_ib[FFS_NIADDR]; /* 88: indirect blocks */ - } - ic_Mb; - char ic_Msymlink[FFS_MAX_FASTLINK_SIZE]; - /* 40: symbolic link name */ - } - ic_Mun; -#define ic_db ic_Mun.ic_Mb.Mb_db -#define ic_ib ic_Mun.ic_Mb.Mb_ib -#define ic_symlink ic_Mun.ic_Msymlink - int ic_flags; /* 100: status, currently unused */ - int ic_blocks; /* 104: blocks actually held */ - int ic_gen; /* 108: generation number */ - int ic_spare[4]; /* 112: reserved, currently unused */ - }; - -/* - * Same structure, but on disk. - */ -struct dinode - { - union - { - struct icommon di_com; - char di_char[128]; - } - di_un; - }; -#define di_ic di_un.di_com - -#define NDADDR FFS_NDADDR -#define NIADDR FFS_NIADDR - -#define MAX_FASTLINK_SIZE FFS_MAX_FASTLINK_SIZE - -#define IC_FASTLINK 0x0001 /* Symbolic link in inode */ - -#define i_mode ic_mode -#define i_nlink ic_nlink -#define i_uid ic_uid -#define i_gid ic_gid -//#if defined(BYTE_MSF) && BYTE_MSF -//#define i_size ic_size.val[1] -//#else /* BYTE_LSF */ -//#define i_size ic_size.val[0] -//#endif -#define i_db ic_db -#define i_ib ic_ib -#define i_atime ic_atime -#define i_mtime ic_mtime -#define i_ctime ic_ctime -#define i_blocks ic_blocks -#define i_rdev ic_db[0] -#define i_symlink ic_symlink -#define i_flags ic_flags -#define i_gen ic_gen - -/* modes */ -#define IFMT 0xf000 /* type of file */ -#define IFCHR 0x2000 /* character special */ -#define IFDIR 0x4000 /* directory */ -#define IFBLK 0x6000 /* block special */ -#define IFREG 0x8000 /* regular */ -#define IFLNK 0xa000 /* symbolic link */ -#define IFSOCK 0xc000 /* socket */ - - -#define ISUID 0x0800 /* set user id on execution */ -#define ISGID 0x0400 /* set group id on execution */ -#define ISVTX 0x0200 /* save swapped text even after use */ -#define IREAD 0x0100 /* read, write, execute permissions */ -#define IWRITE 0x0080 -#define IEXEC 0x0040 - -#define MAXNAMLEN 255 - -struct direct - { - unsigned int d_ino; /* inode number of entry */ - unsigned short d_reclen; /* length of this record */ - unsigned short d_namlen; /* length of string in d_name */ - char d_name[MAXNAMLEN + 1]; /* name with length <= MAXNAMLEN */ - }; - -#define DEV_BSIZE 512 -#define BBSIZE 8192 -#define SBSIZE 8192 -#define BBOFF ((unsigned int)(0)) -#define SBOFF ((unsigned int)(BBOFF + BBSIZE)) -#define BBLOCK ((unsigned int)(0)) -#define SBLOCK ((unsigned int)(BBLOCK + BBSIZE / DEV_BSIZE)) - -/* - * MINBSIZE is the smallest allowable block size. - * In order to insure that it is possible to create files of size - * 2^32 with only two levels of indirection, MINBSIZE is set to 4096. - * MINBSIZE must be big enough to hold a cylinder group block, - * thus changes to (struct cg) must keep its size within MINBSIZE. - * Note that super blocks are always of size SBSIZE, - * and that both SBSIZE and MAXBSIZE must be >= MINBSIZE. - */ -#define MINBSIZE 4096 - -/* - * The path name on which the file system is mounted is maintained - * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in - * the super block for this name. - * The limit on the amount of summary information per file system - * is defined by MAXCSBUFS. It is currently parameterized for a - * maximum of two million cylinders. - */ -#define MAXMNTLEN 512 -#define MAXCSBUFS 32 - -/* - * Per cylinder group information; summarized in blocks allocated - * from first cylinder group data blocks. These blocks have to be - * read in from fs_csaddr (size fs_cssize) in addition to the - * super block. - * - * N.B. sizeof(struct csum) must be a power of two in order for - * the ``fs_cs'' macro to work (see below). - */ -struct csum - { - int cs_ndir; /* number of directories */ - int cs_nbfree; /* number of free blocks */ - int cs_nifree; /* number of free inodes */ - int cs_nffree; /* number of free frags */ - }; - -/* - * Super block for a file system. - */ -#define FS_MAGIC 0x011954 -struct fs - { - int xxx1; /* struct fs *fs_link; */ - int xxx2; /* struct fs *fs_rlink; */ - unsigned int fs_sblkno; /* addr of super-block in filesys */ - unsigned int fs_cblkno; /* offset of cyl-block in filesys */ - unsigned int fs_iblkno; /* offset of inode-blocks in filesys */ - unsigned int fs_dblkno; /* offset of first data after cg */ - int fs_cgoffset; /* cylinder group offset in cylinder */ - int fs_cgmask; /* used to calc mod fs_ntrak */ - unsigned int fs_time; /* last time written */ - int fs_size; /* number of blocks in fs */ - int fs_dsize; /* number of data blocks in fs */ - int fs_ncg; /* number of cylinder groups */ - int fs_bsize; /* size of basic blocks in fs */ - int fs_fsize; /* size of frag blocks in fs */ - int fs_frag; /* number of frags in a block in fs */ -/* these are configuration parameters */ - int fs_minfree; /* minimum percentage of free blocks */ - int fs_rotdelay; /* num of ms for optimal next block */ - int fs_rps; /* disk revolutions per second */ -/* these fields can be computed from the others */ - int fs_bmask; /* ``blkoff'' calc of blk offsets */ - int fs_fmask; /* ``fragoff'' calc of frag offsets */ - int fs_bshift; /* ``lblkno'' calc of logical blkno */ - int fs_fshift; /* ``numfrags'' calc number of frags */ -/* these are configuration parameters */ - int fs_maxcontig; /* max number of contiguous blks */ - int fs_maxbpg; /* max number of blks per cyl group */ -/* these fields can be computed from the others */ - int fs_fragshift; /* block to frag shift */ - int fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ - int fs_sbsize; /* actual size of super block */ - int fs_csmask; /* csum block offset */ - int fs_csshift; /* csum block number */ - int fs_nindir; /* value of NINDIR */ - int fs_inopb; /* value of INOPB */ - int fs_nspf; /* value of NSPF */ -/* yet another configuration parameter */ - int fs_optim; /* optimization preference, see below */ -/* these fields are derived from the hardware */ - int fs_npsect; /* # sectors/track including spares */ - int fs_interleave; /* hardware sector interleave */ - int fs_trackskew; /* sector 0 skew, per track */ - int fs_headswitch; /* head switch time, usec */ - int fs_trkseek; /* track-to-track seek, usec */ -/* sizes determined by number of cylinder groups and their sizes */ - unsigned int fs_csaddr; /* blk addr of cyl grp summary area */ - int fs_cssize; /* size of cyl grp summary area */ - int fs_cgsize; /* cylinder group size */ -/* these fields are derived from the hardware */ - int fs_ntrak; /* tracks per cylinder */ - int fs_nsect; /* sectors per track */ - int fs_spc; /* sectors per cylinder */ -/* this comes from the disk driver partitioning */ - int fs_ncyl; /* cylinders in file system */ -/* these fields can be computed from the others */ - int fs_cpg; /* cylinders per group */ - int fs_ipg; /* inodes per group */ - int fs_fpg; /* blocks per group * fs_frag */ -/* this data must be re-computed after crashes */ - struct csum fs_cstotal; /* cylinder summary information */ -/* these fields are cleared at mount time */ - char fs_fmod; /* super block modified flag */ - char fs_clean; /* file system is clean flag */ - char fs_ronly; /* mounted read-only flag */ - char fs_flags; /* currently unused flag */ - char fs_fsmnt[MAXMNTLEN]; /* name mounted on */ -/* these fields retain the current block allocation info */ - int fs_cgrotor; /* last cg searched */ -#if 1 - int was_fs_csp[MAXCSBUFS]; -#else - struct csum *fs_csp[MAXCSBUFS]; /* list of fs_cs info buffers */ -#endif - int fs_cpc; /* cyl per cycle in postbl */ - short fs_opostbl[16][8]; /* old rotation block list head */ - long fs_sparecon[50]; /* reserved for future constants */ - long fs_contigsumsize; /* size of cluster summary array */ - long fs_maxsymlinklen; /* max length of an internal symlink */ - long fs_inodefmt; /* format of on-disk inodes */ - unsigned long long fs_maxfilesize; /* maximum representable file size */ - unsigned long long fs_qbmask; /* ~fs_bmask - for use with quad size */ - unsigned long long fs_qfmask; /* ~fs_fmask - for use with quad size */ - long fs_state; /* validate fs_clean field */ - int fs_postblformat; /* format of positional layout tables */ - int fs_nrpos; /* number of rotaional positions */ - int fs_postbloff; /* (short) rotation block list head */ - int fs_rotbloff; /* (u_char) blocks for each rotation */ - int fs_magic; /* magic number */ - unsigned char fs_space[1]; /* list of blocks for each rotation */ -/* actually longer */ - }; -/* - * Preference for optimization. - */ -#define FS_OPTTIME 0 /* minimize allocation time */ -#define FS_OPTSPACE 1 /* minimize disk fragmentation */ - -/* - * Rotational layout table format types - */ -#define FS_42POSTBLFMT -1 /* 4.2BSD rotational table format */ -#define FS_DYNAMICPOSTBLFMT 1 /* dynamic rotational table format */ -/* - * Macros for access to superblock array structures - */ -#define fs_postbl(fs, cylno) \ - (((fs)->fs_postblformat == FS_42POSTBLFMT) \ - ? ((fs)->fs_opostbl[cylno]) \ - : ((short *)((char *)(fs) + (fs)->fs_postbloff) + (cylno) * (fs)->fs_nrpos)) -#define fs_rotbl(fs) \ - (((fs)->fs_postblformat == FS_42POSTBLFMT) \ - ? ((fs)->fs_space) \ - : ((unsigned char *)((char *)(fs) + (fs)->fs_rotbloff))) - -/* - * Convert cylinder group to base address of its global summary info. - * - * N.B. This macro assumes that sizeof(struct csum) is a power of two. - */ -#define fs_cs(fs, indx) \ - fs_csp[(indx) >> (fs)->fs_csshift][(indx) & ~(fs)->fs_csmask] - -/* - * Cylinder group block for a file system. - */ -#define CG_MAGIC 0x090255 -#define MAXFRAG 8 -struct cg - { - int xxx1; /* struct cg *cg_link; */ - int cg_magic; /* magic number */ - unsigned int cg_time; /* time last written */ - int cg_cgx; /* we are the cgx'th cylinder group */ - short cg_ncyl; /* number of cyl's this cg */ - short cg_niblk; /* number of inode blocks this cg */ - int cg_ndblk; /* number of data blocks this cg */ - struct csum cg_cs; /* cylinder summary information */ - int cg_rotor; /* position of last used block */ - int cg_frotor; /* position of last used frag */ - int cg_irotor; /* position of last used inode */ - int cg_frsum[MAXFRAG]; /* counts of available frags */ - int cg_btotoff; /* (long) block totals per cylinder */ - int cg_boff; /* (short) free block positions */ - int cg_iusedoff; /* (char) used inode map */ - int cg_freeoff; /* (u_char) free block map */ - int cg_nextfreeoff; /* (u_char) next available space */ - int cg_sparecon[16]; /* reserved for future use */ - unsigned char cg_space[1]; /* space for cylinder group maps */ -/* actually longer */ - }; -/* - * Macros for access to cylinder group array structures - */ -#define cg_blktot(cgp) \ - (((cgp)->cg_magic != CG_MAGIC) \ - ? (((struct ocg *)(cgp))->cg_btot) \ - : ((int *)((char *)(cgp) + (cgp)->cg_btotoff))) -#define cg_blks(fs, cgp, cylno) \ - (((cgp)->cg_magic != CG_MAGIC) \ - ? (((struct ocg *)(cgp))->cg_b[cylno]) \ - : ((short *)((char *)(cgp) + (cgp)->cg_boff) + (cylno) * (fs)->fs_nrpos)) -#define cg_inosused(cgp) \ - (((cgp)->cg_magic != CG_MAGIC) \ - ? (((struct ocg *)(cgp))->cg_iused) \ - : ((char *)((char *)(cgp) + (cgp)->cg_iusedoff))) -#define cg_blksfree(cgp) \ - (((cgp)->cg_magic != CG_MAGIC) \ - ? (((struct ocg *)(cgp))->cg_free) \ - : ((unsigned char *)((char *)(cgp) + (cgp)->cg_freeoff))) -#define cg_chkmagic(cgp) \ - ((cgp)->cg_magic == CG_MAGIC || ((struct ocg *)(cgp))->cg_magic == CG_MAGIC) - -/* - * The following structure is defined - * for compatibility with old file systems. - */ -struct ocg - { - int xxx1; /* struct ocg *cg_link; */ - int xxx2; /* struct ocg *cg_rlink; */ - unsigned int cg_time; /* time last written */ - int cg_cgx; /* we are the cgx'th cylinder group */ - short cg_ncyl; /* number of cyl's this cg */ - short cg_niblk; /* number of inode blocks this cg */ - int cg_ndblk; /* number of data blocks this cg */ - struct csum cg_cs; /* cylinder summary information */ - int cg_rotor; /* position of last used block */ - int cg_frotor; /* position of last used frag */ - int cg_irotor; /* position of last used inode */ - int cg_frsum[8]; /* counts of available frags */ - int cg_btot[32]; /* block totals per cylinder */ - short cg_b[32][8]; /* positions of free blocks */ - char cg_iused[256]; /* used inode map */ - int cg_magic; /* magic number */ - unsigned char cg_free[1]; /* free block map */ -/* actually longer */ - }; - -/* - * Turn file system block numbers into disk block addresses. - * This maps file system blocks to device size blocks. - */ -#define fsbtodb(fs, b) ((b) << (fs)->fs_fsbtodb) -#define dbtofsb(fs, b) ((b) >> (fs)->fs_fsbtodb) - -/* - * Cylinder group macros to locate things in cylinder groups. - * They calc file system addresses of cylinder group data structures. - */ -#define cgbase(fs, c) ((unsigned int)((fs)->fs_fpg * (c))) -#define cgstart(fs, c) \ - (cgbase(fs, c) + (fs)->fs_cgoffset * ((c) & ~((fs)->fs_cgmask))) -#define cgsblock(fs, c) (cgstart(fs, c) + (fs)->fs_sblkno) /* super blk */ -#define cgtod(fs, c) (cgstart(fs, c) + (fs)->fs_cblkno) /* cg block */ -#define cgimin(fs, c) (cgstart(fs, c) + (fs)->fs_iblkno) /* inode blk */ -#define cgdmin(fs, c) (cgstart(fs, c) + (fs)->fs_dblkno) /* 1st data */ - -/* - * Macros for handling inode numbers: - * inode number to file system block offset. - * inode number to cylinder group number. - * inode number to file system block address. - */ -#define itoo(fs, x) ((x) % INOPB(fs)) -#define itog(fs, x) ((x) / (fs)->fs_ipg) -#define itod(fs, x) \ - ((unsigned int)(cgimin(fs, itog(fs, x)) + \ - (blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs)))))) - -/* - * Give cylinder group number for a file system block. - * Give cylinder group block number for a file system block. - */ -#define dtog(fs, d) ((d) / (fs)->fs_fpg) -#define dtogd(fs, d) ((d) % (fs)->fs_fpg) - -/* - * The following macros optimize certain frequently calculated - * quantities by using shifts and masks in place of divisions - * modulos and multiplications. - */ -#define blkoff(fs, loc) /* calculates (loc % fs->fs_bsize) */ \ - ((loc) & ~(fs)->fs_bmask) -#define fragoff(fs, loc) /* calculates (loc % fs->fs_fsize) */ \ - ((loc) & ~(fs)->fs_fmask) -#define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \ - ((loc) >> (fs)->fs_bshift) -#define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \ - ((loc) >> (fs)->fs_fshift) -#define blkroundup(fs, size) /* calculates roundup(size, fs->fs_bsize) */ \ - (((size) + (fs)->fs_bsize - 1) & (fs)->fs_bmask) -#define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \ - (((size) + (fs)->fs_fsize - 1) & (fs)->fs_fmask) -#define fragstoblks(fs, frags) /* calculates (frags / fs->fs_frag) */ \ - ((frags) >> (fs)->fs_fragshift) -#define blkstofrags(fs, blks) /* calculates (blks * fs->fs_frag) */ \ - ((blks) << (fs)->fs_fragshift) -#define fragnum(fs, fsb) /* calculates (fsb % fs->fs_frag) */ \ - ((fsb) & ((fs)->fs_frag - 1)) -#define blknum(fs, fsb) /* calculates rounddown(fsb, fs->fs_frag) */ \ - ((fsb) &~ ((fs)->fs_frag - 1)) - -/* - * Determine the number of available frags given a - * percentage to hold in reserve - */ -#define freespace(fs, percentreserved) \ - (blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \ - (fs)->fs_cstotal.cs_nffree - ((fs)->fs_dsize * (percentreserved) / 100)) - -/* - * Determining the size of a file block in the file system. - */ -#define blksize(fs, ip, lbn) \ - (((lbn) >= NDADDR || (unsigned long)((ip)->ic_size) >= ((lbn) + 1) << (fs)->fs_bshift) \ - ? (fs)->fs_bsize \ - : (fragroundup(fs, blkoff(fs, (unsigned long)((ip)->ic_size))))) -#define dblksize(fs, dip, lbn) \ - (((lbn) >= NDADDR || (dip)->di_size >= ((lbn) + 1) << (fs)->fs_bshift) \ - ? (fs)->fs_bsize \ - : (fragroundup(fs, blkoff(fs, (dip)->di_size)))) - -/* - * Number of disk sectors per block; assumes DEV_BSIZE byte sector size. - */ -#define NSPB(fs) ((fs)->fs_nspf << (fs)->fs_fragshift) -#define NSPF(fs) ((fs)->fs_nspf) - -/* - * INOPB is the number of inodes in a secondary storage block. - */ -#define INOPB(fs) ((fs)->fs_inopb) -#define INOPF(fs) ((fs)->fs_inopb >> (fs)->fs_fragshift) - -/* - * NINDIR is the number of indirects in a file system block. - */ -#define NINDIR(fs) ((fs)->fs_nindir) - -/* used for filesystem map blocks */ -static int mapblock; -static int mapblock_offset; -static int mapblock_bsize; - -/* pointer to superblock */ -#define SUPERBLOCK ((struct fs *) ( FSYS_BUF + 8192 )) -#define INODE ((struct icommon *) ( FSYS_BUF + 16384 )) -#define MAPBUF ( FSYS_BUF + 24576 ) -#define MAPBUF_LEN 8192 -#define NAME_BUF (FSYS_BUF - 512) - - -int -ffs_mount (void) -{ - int retval = 1; - - if (/*(((current_drive & 0x80) || (current_slice != 0)) - && ! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_BSDFFS)) - ||*/ (unsigned long)part_length < (SBLOCK + (SBSIZE / DEV_BSIZE)) - || ! devread (SBLOCK, 0, SBSIZE, (unsigned long long)(unsigned int)(char *) SUPERBLOCK, 0xedde0d90) - || SUPERBLOCK->fs_magic != FS_MAGIC) - retval = 0; - - mapblock = -1; - mapblock_offset = -1; - - return retval; -} - -static int -block_map (int file_block) -{ - int bnum, offset, bsize; - - if (file_block < NDADDR) - return (INODE->i_db[file_block]); - - /* If the blockmap loaded does not include FILE_BLOCK, - load a new blockmap. */ - if ((bnum = fsbtodb (SUPERBLOCK, INODE->i_ib[0])) != mapblock - || (mapblock_offset <= bnum && bnum <= mapblock_offset + mapblock_bsize)) - { - if (MAPBUF_LEN < SUPERBLOCK->fs_bsize) - { - offset = ((file_block - NDADDR) % NINDIR (SUPERBLOCK)); - bsize = MAPBUF_LEN; - - if (offset + MAPBUF_LEN > SUPERBLOCK->fs_bsize) - offset = (SUPERBLOCK->fs_bsize - MAPBUF_LEN) / sizeof (int); - } - else - { - bsize = SUPERBLOCK->fs_bsize; - offset = 0; - } - - if (! devread (bnum, offset * sizeof (int), bsize, (unsigned long long)(unsigned int)(char *) MAPBUF, 0xedde0d90)) - { - mapblock = -1; - mapblock_bsize = -1; - mapblock_offset = -1; - errnum = ERR_FSYS_CORRUPT; - return -1; - } - - mapblock = bnum; - mapblock_bsize = bsize; - mapblock_offset = offset; - } - - return (((int *) MAPBUF)[((file_block - NDADDR) % NINDIR (SUPERBLOCK)) - - mapblock_offset]); -} - - -unsigned long long -ffs_read (unsigned long long buf, unsigned long long len, unsigned long write) -{ - unsigned long logno, off, size, map, ret = 0; - - while (len && ! errnum) - { - off = blkoff (SUPERBLOCK, filepos); - logno = lblkno (SUPERBLOCK, filepos); - size = blksize (SUPERBLOCK, INODE, logno); - - if ((map = block_map (logno)) < 0) - break; - - size -= off; - - if (size > len) - size = len; - - disk_read_func = disk_read_hook; - - devread (fsbtodb (SUPERBLOCK, map), off, size, buf, write); - - disk_read_func = NULL; - - if (buf) - buf += size; - len -= size; /* len always >= 0 */ - filepos += size; - ret += size; - } - - if (errnum) - ret = 0; - - return ret; -} - - -int -ffs_dir (char *dirname) -{ - char *rest, ch; - unsigned long block, off, loc, map, ino = 2; - struct direct *dp; - int j, k; - char ch1; - char *tmp_name = (char *)(NAME_BUF); /* MAXNAMLEN is 255, so 512 byte buffer is needed. */ - -/* main loop to find destination inode */ -loop: - - /* load current inode (defaults to the root inode) */ - - if (! devread (fsbtodb (SUPERBLOCK, itod (SUPERBLOCK, ino)), - ino % (SUPERBLOCK->fs_inopb) * sizeof (struct dinode), - sizeof (struct dinode), (unsigned long long)(unsigned int)(char *) INODE, 0xedde0d90)) - return 0; /* XXX what return value? */ - - /* if we have a real file (and we're not just printing possibilities), - then this is where we want to exit */ - - if (! *dirname || isspace (*dirname)) - { - if ((INODE->i_mode & IFMT) != IFREG) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - filemax = (unsigned long)(INODE->ic_size); - - /* incomplete implementation requires this! */ - fsmax = (NDADDR + NINDIR (SUPERBLOCK)) * SUPERBLOCK->fs_bsize; - return 1; - } - - /* continue with file/directory name interpretation */ - - while (*dirname == '/') - dirname++; - - if (! ((unsigned long)(INODE->ic_size)) || ((INODE->i_mode & IFMT) != IFDIR)) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - //for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++); - for (rest = dirname; (ch = *rest) /*&& !isspace (ch)*/ && ch != '/'; rest++) - { -#if 0 - if (ch == '\\') - { - rest++; - if (! (ch = *rest)) - break; - } -#endif - } - - *rest = 0; - loc = 0; - - /* loop for reading a the entries in a directory */ - - do - { - if (loc >= (unsigned long)(INODE->ic_size)) - { -#if 0 - putchar ('\n'); -#endif - - if (print_possibilities < 0) - return 1; - - errnum = ERR_FILE_NOT_FOUND; - *rest = ch; - return 0; - } - - if (! (off = blkoff (SUPERBLOCK, loc))) - { - block = lblkno (SUPERBLOCK, loc); - - if ((map = block_map (block)) < 0 - || ! devread (fsbtodb (SUPERBLOCK, map), 0, - blksize (SUPERBLOCK, INODE, block), - (unsigned long long)(unsigned int)(char *) FSYS_BUF, 0xedde0d90)) - { - errnum = ERR_FSYS_CORRUPT; - *rest = ch; - return 0; - } - } - - dp = (struct direct *) (FSYS_BUF + off); - loc += dp->d_reclen; - - /* copy dp->name to tmp_name, and quote the spaces with a '\\' */ - for (j = 0, k = 0; j < dp->d_namlen; j++) - { - if (! (ch1 = dp->d_name[j])) - break; -#if 0 - if (ch1 == ' ') - tmp_name[k++] = '\\'; -#endif - tmp_name[k++] = ch1; - } - tmp_name[k] = 0; - - if (dp->d_ino && print_possibilities && ch != '/' - && (!*dirname || substring (dirname, tmp_name, 0) <= 0)) - { - if (print_possibilities > 0) - print_possibilities = -print_possibilities; - - print_a_completion (tmp_name, 0); - } - } - while (!dp->d_ino || (substring (dirname, dp->d_name, 0) != 0 - || (print_possibilities && ch != '/'))); - - /* only get here if we have a matching directory entry */ - - ino = dp->d_ino; - *(dirname = rest) = ch; - - /* go back to main loop at top of function */ - goto loop; -} - -unsigned long -ffs_embed (unsigned long *start_sector, unsigned long needed_sectors) -{ - /* XXX: I don't know if this is really correct. Someone who is - familiar with BSD should check for this. */ - if (needed_sectors > 14) - return 0; - - *start_sector = 1; -#if 1 - /* FIXME: Disable the embedding in FFS until someone checks if - the code above is correct. */ - return 0; -#else - return 1; -#endif -} - -#endif /* FSYS_FFS */ diff --git a/stage2/fsys_initrd.c b/stage2/fsys_initrd.c index 78c65b4e..99ecd740 100644 --- a/stage2/fsys_initrd.c +++ b/stage2/fsys_initrd.c @@ -44,13 +44,13 @@ static int test_file(const char *dirname) { if (print_possibilities) { - if (substring (dirname,(char*)cur_file.name, 1) <= 0) + if (substring (dirname,(const char*)cur_file.name, 1) <= 0) { print_a_completion ((char*)cur_file.name + path_len, 1); return 1; } } - else if (substring (dirname, (char*)cur_file.name, 1) == 0) + else if (substring (dirname, (const char*)cur_file.name, 1) == 0) { filemax = cur_file.size; return 2; @@ -71,8 +71,8 @@ static grub_u32_t cpio_file(struct cpio_header *hdr) return 0; } hdr_sz = cpio_image_align(sizeof(struct cpio_header) + namesize); - cur_file.base = (grub_u32_t)hdr + hdr_sz; - cur_file.name = (grub_u32_t)hdr + sizeof(struct cpio_header); + cur_file.base = (grub_size_t)hdr + hdr_sz; + cur_file.name = (grub_size_t)hdr + sizeof(struct cpio_header); cur_file.isdir &= CPIO_MODE_DIR; cur_file.name_size = namesize; @@ -89,7 +89,7 @@ static int cpio_dir(const char* dirname) while(cur_pos < initrdfs_size) { - p_cpio_hdr = (struct cpio_header *)(grub_u32_t)(initrdfs_base + cur_pos); + p_cpio_hdr = (struct cpio_header *)(grub_size_t)(initrdfs_base + cur_pos); if (*(grub_u32_t*)p_cpio_hdr->c_magic != 0x37303730 || p_cpio_hdr->c_magic[5] == 0x30)//07070 { if (node_size) @@ -119,39 +119,46 @@ static int cpio_dir(const char* dirname) int initrdfs_mount (void) { - int i; - if (current_drive == ram_drive) { initrdfs_base = rd_base; initrdfs_size = rd_size; } - else if (current_drive == 0xFFFF) + else + if (current_drive == 0xFFFF) { initrdfs_base = md_part_base; initrdfs_size = md_part_size; } else { - if (unset_int13_handler (1)) - return 0; - for (i = 0; i < DRIVE_MAP_SIZE && !drive_map_slot_empty (hooked_drive_map[i]); i++) +#if 0 + for (i = 0; i < DRIVE_MAP_SIZE && !drive_map_slot_empty (disk_drive_map[i]); i++) { - if (hooked_drive_map[i].from_drive == (unsigned char)current_drive) + if (disk_drive_map[i].from_drive == (unsigned char)current_drive) { - if (hooked_drive_map[i].to_drive == 0xFF) + if (disk_drive_map[i].to_drive == 0xFF) { - initrdfs_base = (grub_u64_t)hooked_drive_map[i].start_sector << 9; - initrdfs_size = (grub_u64_t)hooked_drive_map[i].sector_count << 9; + initrdfs_base = (grub_u64_t)disk_drive_map[i].start_sector << 9; + initrdfs_size = (grub_u64_t)disk_drive_map[i].sector_count << 9; } break; } } +#else + struct grub_disk_data *d; + d = get_device_by_drive (current_drive,1); + if (d && d->to_drive == 0xFF) + { + initrdfs_base = d->start_sector << 9; + initrdfs_size = d->sector_count << 9; + } +#endif } if (initrdfs_base == 0) return 0; - switch(*(grub_u32_t*)(grub_u32_t)initrdfs_base) + switch(*(grub_u32_t*)(grub_size_t)initrdfs_base) { case BAT_SIGN: initrdfs_type = 1; @@ -186,14 +193,14 @@ int initrdfs_dir (char *dirname) grub_u16_t filename = '0'; grub_u32_t pos=0; grub_u32_t test = 0; - cur_file.name = (grub_u32_t)&filename; + cur_file.name = (grub_size_t)&filename; cur_file.isdir = 0; cur_file.name_size = 2; while(pos < initrdfs_size) { cur_file.base = initrdfs_base + pos; - cur_file.size = (*(grub_u32_t*)(grub_u32_t)cur_file.base == BAT_SIGN)?grub_strlen((char*)cur_file.base):initrdfs_size - pos; + cur_file.size = (*(grub_u32_t*)cur_file.base == BAT_SIGN)?grub_strlen((char*)cur_file.base):initrdfs_size - pos; test = test_file(dirname); if (test) found = 1; if (test == 2) break; @@ -207,7 +214,7 @@ int initrdfs_dir (char *dirname) return found; } -unsigned long long initrdfs_read (unsigned long long buf, unsigned long long len, unsigned long write) +unsigned long long initrdfs_read (unsigned long long buf, unsigned long long len, unsigned int write) { if (filepos > cur_file.size) return 0; if (len > cur_file.size - filepos) len = cur_file.size - filepos; diff --git a/stage2/fsys_initrd.h b/stage2/fsys_initrd.h index e5e77129..6552c668 100644 --- a/stage2/fsys_initrd.h +++ b/stage2/fsys_initrd.h @@ -2,14 +2,15 @@ #define _INITRDFS_H_ #include "cpio.h" - struct initrdfs_file { - grub_u32_t base; - grub_u32_t size; - grub_u32_t name; - grub_u16_t isdir; - grub_u16_t name_size; +// grub_u32_t base; +// grub_u32_t size; +// grub_u32_t name; + grub_size_t base; //基址 =hdr+对齐的(hdr尺寸+hdr->c_namesize) + grub_size_t size; //尺寸 =(hdr->c_filesize) + grub_size_t name; //名称 =hdr+hdr尺寸 + grub_u16_t isdir; //属性 =hdr->c_mode & 0040000 0/1=文件/目录 + grub_u16_t name_size; //名称尺寸 =hdr->c_namesize }; - #endif /* _INITRDFS_H_ */ diff --git a/stage2/fsys_ipxe.c b/stage2/fsys_ipxe.c index 30a3c3d0..e45caec7 100644 --- a/stage2/fsys_ipxe.c +++ b/stage2/fsys_ipxe.c @@ -25,6 +25,7 @@ #include "ipxe.h" #include "fsys_ipxe.h" +#if 0 grub_u32_t has_ipxe = 0; static grub_u32_t ipxe_funcs; static grub_u32_t ipxe_file_opened; @@ -39,7 +40,7 @@ static inline SEGOFF16_t FAR_PTR(void *ptr) return _fptr; } /* - * See if we have iPXE + * See if we have iPXE 看看我们有没有iPXE */ void ipxe_init(void) { @@ -47,18 +48,18 @@ void ipxe_init(void) pxenv.file_api_check.Size = sizeof(struct s_PXENV_FILE_API_CHECK); pxenv.file_api_check.Magic = 0x91d447b2; - err = pxe_call(PXENV_FILE_API_CHECK, &pxenv.file_api_check); +// err = pxe_call(PXENV_FILE_API_CHECK, &pxenv.file_api_check); //文件API检查 if (!err && pxenv.file_api_check.Magic == 0xe9c17b20) ipxe_funcs = pxenv.file_api_check.APIMask; - /* Necessary functions for us to use the iPXE file API */ + /* Necessary functions for us to use the iPXE file API 使用iPXE文件API所需的功能*/ has_ipxe = (~ipxe_funcs & 0x4b) == 0; } static void ipxe_unload(void) { -// pxe_call(PXENV_FILE_EXIT_HOOK,&pxenv.file_exit_hook); +// pxe_call(PXENV_FILE_EXIT_HOOK,&pxenv.file_exit_hook); //文件退出挂钩 ipxe_funcs = 0; has_ipxe = 0; } @@ -79,12 +80,12 @@ static int ipxe_open(const char *dirname) while (*filename == '/' || *filename == ' ') ++filename; - if ((unsigned long)debug >= 0x7FFFFFFF) printf("O:%s\n",filename); + if ((unsigned int)debug >= 0x7FFFFFFF) printf("O:%s\n",filename); pxenv.file_open.FileName = FAR_PTR(filename); - if (PXENV_EXIT_SUCCESS != pxe_call(PXENV_FILE_OPEN, &pxenv.file_open)) - return 0; +// if (PXENV_EXIT_SUCCESS != pxe_call(PXENV_FILE_OPEN, &pxenv.file_open)) //文件打开 +// return 0; ipxe_file_opened = pxenv.file_open.FileHandle; @@ -100,8 +101,8 @@ static grub_u32_t ipxe_get_size(void) pxenv.file_open.FileHandle = ipxe_file_opened; - if (pxe_call(PXENV_GET_FILE_SIZE, &pxenv.get_file_size) != PXENV_EXIT_SUCCESS) - return 0; +// if (pxe_call(PXENV_GET_FILE_SIZE, &pxenv.get_file_size) != PXENV_EXIT_SUCCESS) //获得文件尺寸 +// return 0; filemax = pxenv.get_file_size.FileSize; return pxenv.get_file_size.FileSize; } @@ -124,7 +125,7 @@ static grub_u32_t ipxe_read_blk (grub_u32_t buf, grub_u32_t num) { pxenv.file_read.Buffer = FAR_PTR((void*)(buf + read_len)); pxenv.file_read.BufferSize = max_len - read_len; - status = pxe_call(PXENV_FILE_READ, &pxenv.file_read); +// status = pxe_call(PXENV_FILE_READ, &pxenv.file_read); //读 if (status != PXENV_EXIT_SUCCESS) { if (pxenv.file_read.Status == PXENV_STATUS_TFTP_OPEN) @@ -135,16 +136,16 @@ static grub_u32_t ipxe_read_blk (grub_u32_t buf, grub_u32_t num) break; read_len += pxenv.file_read.BufferSize; } - if ((unsigned long)debug >= 0x7FFFFFFF) printf("R[%d]: %d,%d,%d\n",ipxe_file_opened,num,pxe_blksize,read_len); + if ((unsigned int)debug >= 0x7FFFFFFF) printf("R[%d]: %d,%d,%d\n",ipxe_file_opened,num,pxe_blksize,read_len); return read_len; } -static void ipxe_close (void) +static void ipxe_close (void) //关闭 { - if (!ipxe_file_opened) return; - pxenv.file_close.FileHandle = ipxe_file_opened; - if (pxe_call(PXENV_FILE_CLOSE, &pxenv.file_close) == PXENV_EXIT_SUCCESS) - ipxe_file_opened = 0; + if (!ipxe_file_opened) return; //如果文件没有打开 + pxenv.file_close.FileHandle = ipxe_file_opened; //结构.文件关闭,文件句柄= +// if (pxe_call(PXENV_FILE_CLOSE, &pxenv.file_close) == PXENV_EXIT_SUCCESS) //关闭(关闭指令, 结构.文件关闭) +// ipxe_file_opened = 0; } int ipxe_func(char* arg,int flags) @@ -152,6 +153,8 @@ int ipxe_func(char* arg,int flags) if (!(ipxe_funcs & (1<<(PXENV_FILE_EXEC - PXENV_FILE_MIN)))) return !(errnum = ERR_FUNC_CALL); memmove((void*)IPXE_BUF,arg,strlen(arg)+1); pxenv.file_exec.Command=FAR_PTR((void*)IPXE_BUF); - return pxe_call(PXENV_FILE_EXEC, &pxenv.file_exec) == PXENV_EXIT_SUCCESS; +// return pxe_call(PXENV_FILE_EXEC, &pxenv.file_exec) == PXENV_EXIT_SUCCESS; //文件执行 } +#endif + #endif /* FSYS_IPXE */ diff --git a/stage2/fsys_ipxe.h b/stage2/fsys_ipxe.h index bf42b27a..906b6399 100644 --- a/stage2/fsys_ipxe.h +++ b/stage2/fsys_ipxe.h @@ -6,11 +6,13 @@ #define IPXE_BUF BUFFERADDR #define iPXE_BUFLEN 0xFE00 +#if 0 static int ipxe_open(const char *dirname); static grub_u32_t ipxe_get_size(void); static grub_u32_t ipxe_read_blk (grub_u32_t buf, grub_u32_t num); static void ipxe_close (void); static void ipxe_unload(void); +#endif #endif /* _FSYS_IPXE_H_ */ #endif \ No newline at end of file diff --git a/stage2/fsys_iso9660.c b/stage2/fsys_iso9660.c index ebe15243..5f15ebb4 100644 --- a/stage2/fsys_iso9660.c +++ b/stage2/fsys_iso9660.c @@ -38,68 +38,38 @@ /* iso9660 super-block data in memory */ struct iso_sb_info { - unsigned long vol_sector; + unsigned int vol_sector; }; /* iso fs inode data in memory */ struct iso_inode_info { - unsigned long file_start; + unsigned int file_start; }; #define ISO_SUPER \ ((struct iso_sb_info *)(FSYS_BUF)) #define INODE \ ((struct iso_inode_info *)(FSYS_BUF+sizeof(struct iso_sb_info))) -#define PRIMDESC ((struct iso_primary_descriptor *)(FSYS_BUF + 2048)) -#define UDF_ROOT ((struct udf_descriptor *)(FSYS_BUF + 2048)) -#define RRCONT_BUF ((unsigned char *)(FSYS_BUF + 4096)) -#define NAME_BUF ((unsigned char *)(FSYS_BUF + 6144)) -#define OLD_IDENTIFIER ((struct udf_File_Identifier *)(FSYS_BUF + 8192)) -#define DIRREC ((struct iso_directory_record *)(FSYS_BUF + 10240)) -#define UDF_IDENTIFIER ((struct udf_File_Identifier *)(FSYS_BUF + 10240)) -#define UDF_ENTRY ((struct udf_descriptor *)(FSYS_BUF + 12288)) +#define PRIMDESC ((struct iso_primary_descriptor *)(FSYS_BUF + 0x800)) +#define UDF_ROOT ((struct udf_descriptor *)(FSYS_BUF + 0x800)) +#define RRCONT_BUF ((unsigned char *)(FSYS_BUF + 0x1000)) +#define NAME_BUF ((unsigned char *)(FSYS_BUF + 0x1800)) +#define OLD_IDENTIFIER ((struct udf_File_Identifier *)(FSYS_BUF + 0x2000)) +#define DIRREC ((struct iso_directory_record *)(FSYS_BUF + 0x2800)) +#define UDF_IDENTIFIER ((struct udf_File_Identifier *)(FSYS_BUF + 0x2800)) +#define UDF_ENTRY ((struct udf_descriptor *)(FSYS_BUF + 0x3000)) unsigned int iso_type; //0/1/2/3=ISO_TYPE_9660/ISO_TYPE_udf/ISO_TYPE_Joliet/ISO_TYPE_RockRidge -unsigned long udf_partition_start; -unsigned long udf_BytePerSector; -unsigned long udf_EntrySector; - -#if 0 -static int -iso9660_devread (unsigned long sector, unsigned long byte_offset, unsigned long byte_len, char *buf) -{ - unsigned short sector_size_lg2 = log2_tmp(buf_geom.sector_size); - - /* - * We have to use own devread() function since BIOS return wrong geometry - */ -// if (sector < 0) -// { -// errnum = ERR_OUTSIDE_PART; -// return 0; -// } - if (byte_len <= 0) - return 1; - - sector += (byte_offset >> sector_size_lg2); - byte_offset &= (buf_geom.sector_size - 1); - asm volatile ("shl%L0 %1,%0" - : "=r"(sector) - : "Ic"((int8_t)(ISO_SECTOR_BITS - sector_size_lg2)), - "0"(sector)); - - if (disk_read_hook && debug) - printf ("<%d, %d, %d>", sector, byte_offset, byte_len); - - return rawread (current_drive, part_start + sector, byte_offset, byte_len, buf); -} -#endif +unsigned int udf_partition_start; +unsigned int udf_BytePerSector; +unsigned int udf_EntrySector; +int iso9660_mount (void); int iso9660_mount (void) { - unsigned long sector, size, extent; + unsigned int sector, size, extent; struct iso_directory_record *idr; idr = &PRIMDESC->root_directory_record; @@ -109,31 +79,7 @@ iso9660_mount (void) * (2) if current partition is BSD style sub-partition whose ID is * ISO-9660. */ -// if ((current_partition != 0xFFFFFF) -// && !IS_PC_SLICE_TYPE_BSD_WITH_FS(current_slice, FS_ISO9660)) -// return 0; - /* - * Currently, only FIRST session of MultiSession disks are supported !!! - */ -// for (sector = 16 ; sector < 32 ; sector++) -// { -// emu_iso_sector_size_2048 = 1; -// if (! devread(sector, 0, sizeof(*PRIMDESC), (unsigned long long)(unsigned int)(char *)PRIMDESC, 0xedde0d90)) -// break; -// /* check ISO_VD_PRIMARY and ISO_STANDARD_ID */ -// if (PRIMDESC->type.l == ISO_VD_PRIMARY -// && ! memcmp ((char *)(PRIMDESC->id), ISO_STANDARD_ID, sizeof(PRIMDESC->id))) -// { -// ISO_SUPER->vol_sector = sector; -// INODE->file_start = 0; -// fsmax = PRIMDESC->volume_space_size.l; -// return 1; -// } -// } -// -// return 0; -//} iso_type = ISO_TYPE_9660; //0 udf_partition_start = 0; udf_BytePerSector = 0x800; @@ -141,7 +87,7 @@ iso9660_mount (void) for (sector = 16 ; sector < 32 ; sector++) { emu_iso_sector_size_2048 = 1; - if (! devread(sector, 0, 0x100, (unsigned long long)(unsigned int)(char *)PRIMDESC, 0xedde0d90)) + if (! devread(sector, 0, 0x100, (unsigned long long)(grub_size_t)(char *)PRIMDESC, 0xedde0d90)) return 0; //Check UDF_STANDARD_ID if ( (iso_types & (1<id), UDF_STANDARD_ID, 5)) //UDF_STANDARD_ID="BEA01" @@ -156,10 +102,10 @@ iso9660_mount (void) sector = 0x100; //The reading anchor Volume Descriptor Pointer emu_iso_sector_size_2048 = 1; - devread(sector, 0, 0x800, (unsigned long long)(unsigned int)(char *)UDF_ROOT, 0xedde0d90); + devread(sector, 0, 0x800, (unsigned long long)(grub_size_t)(char *)UDF_ROOT, 0xedde0d90); if (UDF_ROOT->Tag != UDF_Anchor) { - devread(sector, 0, 0x200, (unsigned long long)(unsigned int)(char *)UDF_ROOT, 0xedde0d90); + devread(sector, 0, 0x200, (unsigned long long)(grub_size_t)(char *)UDF_ROOT, 0xedde0d90); if (UDF_ROOT->Tag != UDF_Anchor) //0002 return 0; udf_BytePerSector = 0x200; @@ -170,7 +116,7 @@ iso9660_mount (void) { if (udf_BytePerSector == 0x800) emu_iso_sector_size_2048 = 1; - devread(sector, 0, udf_BytePerSector, (unsigned long long)(unsigned int)(char *)UDF_ROOT, 0xedde0d90); + devread(sector, 0, udf_BytePerSector, (unsigned long long)(grub_size_t)(char *)UDF_ROOT, 0xedde0d90); if (i) break; switch (UDF_ROOT->Tag) @@ -200,7 +146,7 @@ iso9660_mount (void) for (sector = 17 ; sector < 32 ; sector++) { emu_iso_sector_size_2048 = 1; - devread(sector, 0, 0x800, (unsigned long long)(unsigned int)(char *)PRIMDESC, 0xedde0d90); + devread(sector, 0, 0x800, (unsigned long long)(grub_size_t)(char *)PRIMDESC, 0xedde0d90); if ((iso_types & (1<type.l == ISO_VD_ENHANCED) && (! memcmp ((char *)(PRIMDESC->id), ISO_STANDARD_ID, 5)) && (*(unsigned short *)((char *)PRIMDESC + 0x58) == 0x2F25)) //ISO_STANDARD_ID="CD001" { @@ -216,42 +162,38 @@ iso9660_mount (void) break; } emu_iso_sector_size_2048 = 1; - devread(16, 0, 0x800, (unsigned long long)(unsigned int)(char *)PRIMDESC, 0xedde0d90); + devread(16, 0, 0x800, (unsigned long long)(grub_size_t)(char *)PRIMDESC, 0xedde0d90); if ((PRIMDESC->type.l != ISO_VD_PRIMARY) || memcmp ((char *)(PRIMDESC->id), ISO_STANDARD_ID, 5)) return 0; size = idr->size.l; extent = idr->extent.l; emu_iso_sector_size_2048 = 1; - devread (extent, 0, size, (unsigned long long)(unsigned int)(char *)DIRREC, 0xedde0d90); + devread (extent, 0, size, (unsigned long long)(grub_size_t)(char *)DIRREC, 0xedde0d90); idr = (struct iso_directory_record *)DIRREC; idr = (struct iso_directory_record *)((char *)idr + idr->length.l); idr = (struct iso_directory_record *)((char *)idr + idr->length.l); if ((iso_types & (1<length.l - idr->name_len.l - sizeof(struct iso_directory_record) + sizeof(idr->name)) > 1) iso_type = ISO_TYPE_RockRidge; //iso9600_RockRidge -// if ((PRIMDESC->type.l == ISO_VD_PRIMARY) -// && ! memcmp ((char *)(PRIMDESC->id), ISO_STANDARD_ID, 5)) -// { ISO_SUPER->vol_sector = 16; INODE->file_start = 0; fsmax = PRIMDESC->volume_space_size.l; return 1; -// } -// return 0; } } +int iso9660_dir (char *dirname); int iso9660_dir (char *dirname) { struct iso_directory_record *idr; RR_ptr_t rr_ptr; struct rock_ridge *ce_ptr; - unsigned long pathlen; - unsigned long size = 0; - unsigned long extent = 0; + unsigned int pathlen; + unsigned int size = 0; + unsigned int extent = 0; unsigned char file_type; - unsigned long rr_len; + unsigned int rr_len; unsigned char rr_flag; char tmp_name[256]; char *ch; @@ -262,10 +204,10 @@ iso9660_dir (char *dirname) struct udf_descriptor *udf_105_or_10a; struct udf_File_Identifier *udf_101; char tmp_name1[256]; - int name_offset = 0; - unsigned long Allocation_offset = 0; - long Allocation_Number = 1; - unsigned long *tmp = NULL; + grub_size_t name_offset = 0; + unsigned int Allocation_offset = 0; + int Allocation_Number = 1; + unsigned int *tmp = NULL; idr = &PRIMDESC->root_directory_record; udf_105_or_10a = (struct udf_descriptor *)UDF_ROOT; @@ -276,20 +218,8 @@ iso9660_dir (char *dirname) while (*dirname == '/') /* skip leading slashes */ dirname++; /* pathlen = strcspn(dirname, "/\n\t "); */ -// for (pathlen = 0 ; -// dirname[pathlen] -// && !isspace(dirname[pathlen]) && dirname[pathlen] != '/' ; -// pathlen++) -// ; for (ch = tmp_name;*dirname;++dirname) { -#if 0 - if (*dirname == '\\') - { - *ch++ = *dirname++; - *ch++ = *dirname++; - } -#endif if (/*isspace(*dirname) || */*dirname == '/') break; if (ch - tmp_name >= 255 || !(*ch = *dirname)) @@ -304,12 +234,12 @@ iso9660_dir (char *dirname) if (udf_105_or_10a->Tag == UDF_FileEntry) //105 { size = udf_105_or_10a->FileEntry_LengthofAllocationDescriptors; - tmp = (unsigned long *)(&udf_105_or_10a->FileEntry_BaseAddress + udf_105_or_10a->FileEntry_LengthofExtendedAttributes); + tmp = (unsigned int *)(&udf_105_or_10a->FileEntry_BaseAddress + udf_105_or_10a->FileEntry_LengthofExtendedAttributes); } else if (udf_105_or_10a->Tag == UDF_ExtendedFileEntry) //10a { size = udf_105_or_10a->ExtFileEntry_LengthofAllocationDescriptors; - tmp = (unsigned long *)(&udf_105_or_10a->ExtFileEntry_BaseAddress + udf_105_or_10a->ExtFileEntry_LengthofExtendedAttributes); + tmp = (unsigned int *)(&udf_105_or_10a->ExtFileEntry_BaseAddress + udf_105_or_10a->ExtFileEntry_LengthofExtendedAttributes); } Allocation_Number = size >> 3; } @@ -321,7 +251,7 @@ iso9660_dir (char *dirname) if ((udf_105_or_10a->ICB_Flags & 7) == 3) { Allocation_Number = 1; - grub_memmove ((char *)((int)UDF_IDENTIFIER),(char *)((int)tmp),udf_BytePerSector); + grub_memmove ((char *)((grub_size_t)UDF_IDENTIFIER),(char *)((grub_size_t)tmp),udf_BytePerSector); udf_101 = (struct udf_File_Identifier *)UDF_IDENTIFIER; goto asdf; } @@ -346,7 +276,7 @@ iso9660_dir (char *dirname) { if (udf_BytePerSector == 0x800) emu_iso_sector_size_2048 = 1; - if (! devread (extent, 0, udf_BytePerSector, (unsigned long long)(unsigned int)(char *)DIRREC, 0xedde0d90)) + if (! devread (extent, 0, udf_BytePerSector, (unsigned long long)(grub_size_t)(char *)DIRREC, 0xedde0d90)) { errnum = ERR_FSYS_CORRUPT; return 0; @@ -354,7 +284,8 @@ iso9660_dir (char *dirname) extent++; idr = (struct iso_directory_record *)DIRREC; - udf_101 = (struct udf_File_Identifier *)((int)UDF_IDENTIFIER - name_offset); + udf_101 = (struct udf_File_Identifier *)((grub_size_t)UDF_IDENTIFIER - name_offset); + name_offset = 0; asdf: for (; ((iso_type == ISO_TYPE_udf)?(udf_101->Tag != 0):(idr->length.l > 0)); ) { @@ -374,7 +305,7 @@ iso9660_dir (char *dirname) { name++; big_to_little (name, name_len); - name_len = unicode_to_utf8 ((unsigned short *)name, utf8, (unsigned long)(name_len/2)); + name_len = unicode_to_utf8 ((unsigned short *)name, utf8, (unsigned int)(name_len/2)); } name = (char *)utf8; file_type = (udf_101->FileCharacteristics & 2) ? ISO_DIRECTORY : ISO_REGULAR; @@ -398,7 +329,7 @@ iso9660_dir (char *dirname) if (iso_type == ISO_TYPE_Joliet) { big_to_little (name, name_len); - name_len = unicode_to_utf8 ((unsigned short *)name, utf8, (unsigned long)(name_len/2)); + name_len = unicode_to_utf8 ((unsigned short *)name, utf8, (unsigned int)(name_len/2)); name = (char *)utf8; goto dddd; } @@ -429,12 +360,12 @@ iso9660_dir (char *dirname) { if (rr_ptr.rr->version != 1) { - if (((unsigned long)debug) >= 0x7FFFFFFF) + if (((unsigned int)debug) >= 0x7FFFFFFF) printf( "Non-supported version (%d) RockRidge chunk " "`%c%c'\n", rr_ptr.rr->version, - (unsigned long)(unsigned char)rr_ptr.rr->signature, - (unsigned long)(unsigned char)(rr_ptr.rr->signature >> 8)); + (unsigned int)(unsigned char)rr_ptr.rr->signature, + (unsigned int)(unsigned char)(rr_ptr.rr->signature >> 8)); rr_flag = 0; } else @@ -552,7 +483,7 @@ iso9660_dir (char *dirname) rr_ptr.ptr = (char *)(RRCONT_BUF + ce_ptr->u.ce.offset.l); rr_len = ce_ptr->u.ce.size.l; emu_iso_sector_size_2048 = 1; - if (! devread(ce_ptr->u.ce.extent.l, 0, ISO_SECTOR_SIZE, (unsigned long long)(unsigned int)(char *)(RRCONT_BUF), 0xedde0d90)) + if (! devread(ce_ptr->u.ce.extent.l, 0, ISO_SECTOR_SIZE, (unsigned long long)(grub_size_t)(char *)(RRCONT_BUF), 0xedde0d90)) { errnum = 0; /* this is not fatal. */ break; @@ -563,7 +494,7 @@ iso9660_dir (char *dirname) } //if (iso_type !== 1) dddd: filemax = MAXINT; - for (j = 0, k = 0;j < name_len;) + for (j = 0, k = 0;j < (int)name_len;) { #if 0 if (name[j] == '\\') @@ -596,11 +527,11 @@ iso9660_dir (char *dirname) { if (iso_type == ISO_TYPE_udf) { - size = udf_101->FileEntryLength; //File entry length in bytes + size = (udf_101->FileEntryLength) & 0x3fffffff; //File entry length in bytes extent = udf_101->FileEntryLocation + udf_partition_start; //File entrance logical sector if (udf_BytePerSector == 0x800) emu_iso_sector_size_2048 = 1; - devread (extent, 0, size, (unsigned long long)(unsigned int)(char *)UDF_ENTRY, 0xedde0d90); + devread (extent, 0, size, (unsigned long long)(grub_size_t)(char *)UDF_ENTRY, 0xedde0d90); udf_105_or_10a = (struct udf_descriptor *)UDF_ENTRY; } if (*dirname == '/') @@ -620,9 +551,9 @@ iso9660_dir (char *dirname) if (iso_type == ISO_TYPE_udf) { if (udf_105_or_10a->Tag == UDF_FileEntry) //105 - tmp = (unsigned long *)(&udf_105_or_10a->FileEntry_BaseAddress + udf_105_or_10a->FileEntry_LengthofExtendedAttributes); + tmp = (unsigned int *)(&udf_105_or_10a->FileEntry_BaseAddress + udf_105_or_10a->FileEntry_LengthofExtendedAttributes); else //10a - tmp = (unsigned long *)(&udf_105_or_10a->ExtFileEntry_BaseAddress + udf_105_or_10a->ExtFileEntry_LengthofExtendedAttributes); + tmp = (unsigned int *)(&udf_105_or_10a->ExtFileEntry_BaseAddress + udf_105_or_10a->ExtFileEntry_LengthofExtendedAttributes); INODE->file_start = *(tmp + 1) + udf_partition_start; filepos = 0; filemax = udf_105_or_10a->InformationLength; @@ -639,56 +570,45 @@ iso9660_dir (char *dirname) } else /* Completion */ { -// int j, k; -// char ch1; -// char *tmp_name1 = (char *)(NAME_BUF); - if (print_possibilities > 0) print_possibilities = -print_possibilities; //memcpy(NAME_BUF, name, name_len); //NAME_BUF[name_len] = '\0'; /* copy name to tmp_name1, and quote spaces with '\\' */ -// for (j = 0, k = 0; j < name_len; j++) -// { -// if (! (ch1 = name[j])) -// break; -// if (ch1 == ' ') -// tmp_name1[k++] = '\\'; -// tmp_name1[k++] = ch1; -// } -// tmp_name1[k] = 0; unsigned long long clo64 = current_color_64bit; - unsigned long clo = current_color; + unsigned int clo = current_color; if (file_type == ISO_DIRECTORY) { if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_HIGHLIGHT); current_color_64bit = (current_color_64bit & 0xffffff) | (clo64 & 0xffffff00000000); current_color = (current_color & 0x0f) | (clo & 0xf0); + console_setcolorstate (current_color | 0x100); //设置控制台文本模式的颜色(UEFI) } print_a_completion (tmp_name1, 0); - current_color_64bit = clo64; - current_color = clo; + if (cursor_state & 1) + current_term->setcolorstate (COLOR_STATE_STANDARD); + else + current_term->setcolorstate (COLOR_STATE_NORMAL); } } -// } /* for */ ssss: if (iso_type == ISO_TYPE_udf) { name = (char *)(&udf_101->NameBaseAddress + udf_101->LengthofImplementationUse + udf_101->NameLength); - //int j; - name += (((int)name & 3) ? (4 - ((int)name & 3)) : 0); + name += (((grub_size_t)name & 3) ? (4 - ((grub_size_t)name & 3)) : 0); udf_101 = (struct udf_File_Identifier *)name; - int temp = 0; - if ((int)name + 0x26 - (int)UDF_IDENTIFIER < udf_BytePerSector) - temp = (int)(&udf_101->NameBaseAddress + udf_101->LengthofImplementationUse + udf_101->NameLength); - if (temp && (temp - (int)UDF_IDENTIFIER <= udf_BytePerSector)) +// int temp = 0; + unsigned int temp = 0; //内存大于2048Mb时出现错误 2023-04-09 + if ((grub_size_t)name + 0x26 - (grub_size_t)UDF_IDENTIFIER < udf_BytePerSector) + temp = (grub_size_t)(&udf_101->NameBaseAddress + udf_101->LengthofImplementationUse + udf_101->NameLength); + if (temp && (temp - (grub_size_t)UDF_IDENTIFIER <= udf_BytePerSector)) continue; else { - grub_memmove ((char *)((int)UDF_IDENTIFIER - udf_BytePerSector),(char *)((int)UDF_IDENTIFIER),udf_BytePerSector); - name_offset = udf_BytePerSector + (int)UDF_IDENTIFIER - (int)name; + grub_memmove ((char *)((grub_size_t)UDF_IDENTIFIER - udf_BytePerSector),(char *)((grub_size_t)UDF_IDENTIFIER),udf_BytePerSector); + name_offset = udf_BytePerSector + (grub_size_t)UDF_IDENTIFIER - (grub_size_t)name; break; } } @@ -713,32 +633,32 @@ iso9660_dir (char *dirname) next_dir_level: ; -// dirname += pathlen; } while (*dirname == '/'); return 1; } +unsigned long long iso9660_read (unsigned long long buf, unsigned long long len, unsigned int write); unsigned long long -iso9660_read (unsigned long long buf, unsigned long long len, unsigned long write) +iso9660_read (unsigned long long buf, unsigned long long len, unsigned int write) { - unsigned long sector, size; + unsigned int sector, size; unsigned long long blkoffset = 0, ret; if (INODE->file_start == 0) return 0; ret = 0; - unsigned long *p = 0; + unsigned int *p = 0; unsigned long long sum = 0; if (iso_type == ISO_TYPE_udf) { if (UDF_ENTRY->Tag == UDF_FileEntry) //105 - p = (unsigned long *)(&UDF_ENTRY->FileEntry_BaseAddress + UDF_ENTRY->FileEntry_LengthofExtendedAttributes); + p = (unsigned int *)(&UDF_ENTRY->FileEntry_BaseAddress + UDF_ENTRY->FileEntry_LengthofExtendedAttributes); else //10a - p = (unsigned long *)(&UDF_ENTRY->ExtFileEntry_BaseAddress + UDF_ENTRY->ExtFileEntry_LengthofExtendedAttributes); + p = (unsigned int *)(&UDF_ENTRY->ExtFileEntry_BaseAddress + UDF_ENTRY->ExtFileEntry_LengthofExtendedAttributes); while (filepos >= sum) { @@ -796,6 +716,7 @@ iso9660_read (unsigned long long buf, unsigned long long len, unsigned long writ return ret; } +int big_to_little (char *filename, unsigned int n); int big_to_little (char *filename, unsigned int n) //unicode16 Tai Mei turn a small tail { diff --git a/stage2/fsys_jfs.c b/stage2/fsys_jfs.c deleted file mode 100644 index 5756907e..00000000 --- a/stage2/fsys_jfs.c +++ /dev/null @@ -1,436 +0,0 @@ -/* fsys_jfs.c - an implementation for the IBM JFS file system */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2001,2002 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifdef FSYS_JFS - -#include "shared.h" -#include "filesys.h" -#include "jfs.h" - -#define MAX_LINK_COUNT 8 - -#define DTTYPE_INLINE 0 -#define DTTYPE_PAGE 1 - -struct jfs_info -{ - unsigned long bsize; - unsigned long l2bsize; - unsigned long bdlog; - unsigned long xindex; - unsigned long xlastindex; - unsigned long sindex; - unsigned long slastindex; - unsigned long de_index; - unsigned long dttype; - struct xad *xad; - ldtentry_t *de; -}; - -static struct jfs_info jfs; - -#define xtPage ((xtpage_t *)FSYS_BUF) -#define dtPage ((dtpage_t *)((char *)FSYS_BUF + 4096)) -#define fileSet ((dinode_t *)((char *)FSYS_BUF + 8192)) -#define iNode ((dinode_t *)((char *)FSYS_BUF + 8192 + sizeof(dinode_t))) -#define dtRoot ((dtroot_t *)(&iNode->di_xtroot)) - -static char *linkbuf = (char *)(FSYS_BUF - JFS_PATH_MAX); /* buffer for following symbolic links */ -static char *namebuf = (char *)(FSYS_BUF - JFS_PATH_MAX - JFS_NAME_MAX - 1); - -static ldtentry_t de_always[2] = { - {1, -1, 2, {'.', '.'}}, - {1, -1, 1, {'.'}} -}; - -static int -isinxt (s64 key, s64 offset, s64 len) -{ - return (key >= offset) ? (key < offset + len ? 1 : 0) : 0; -} - -static struct xad * -first_extent (dinode_t *di) -{ - xtpage_t *xtp; - - jfs.xindex = 2; - xtp = (xtpage_t *)&di->di_xtroot; - jfs.xad = &xtp->xad[2]; - if (xtp->header.flag & BT_LEAF) { - jfs.xlastindex = xtp->header.nextindex; - } else { - do { - devread (addressXAD (jfs.xad) << jfs.bdlog, 0, - sizeof(xtpage_t), (unsigned long long)(unsigned int)(char *)xtPage, 0xedde0d90); - jfs.xad = &xtPage->xad[2]; - } while (!(xtPage->header.flag & BT_LEAF)); - jfs.xlastindex = xtPage->header.nextindex; - } - - return jfs.xad; -} - -static struct xad * -next_extent (void) -{ - if (++jfs.xindex < jfs.xlastindex) { - } else if (xtPage->header.next) { - devread (xtPage->header.next << jfs.bdlog, 0, - sizeof(xtpage_t), (unsigned long long)(unsigned int)(char *)xtPage, 0xedde0d90); - jfs.xlastindex = xtPage->header.nextindex; - jfs.xindex = XTENTRYSTART; - jfs.xad = &xtPage->xad[XTENTRYSTART]; - } else { - return NULL; - } - return ++jfs.xad; -} - - -static void -di_read (u32 inum, dinode_t *di) -{ - s64 key; - u32 xd, ioffset; - s64 offset; - struct xad *xad; - pxd_t pxd; /* struct size = 8 */ - - key = (((inum >> L2INOSPERIAG) << L2INOSPERIAG) + 4096) >> jfs.l2bsize; - xd = (inum & (INOSPERIAG - 1)) >> L2INOSPEREXT; - ioffset = ((inum & (INOSPERIAG - 1)) & (INOSPEREXT - 1)) << L2DISIZE; - xad = first_extent (fileSet); - do { - offset = offsetXAD (xad); - if (isinxt (key, offset, lengthXAD (xad))) { - devread ((addressXAD (xad) + key - offset) << jfs.bdlog, - 3072 + xd*sizeof(pxd_t), sizeof(pxd_t), (unsigned long long)(unsigned int)(char *)&pxd, 0xedde0d90); - devread (addressPXD (&pxd) << jfs.bdlog, - ioffset, DISIZE, (unsigned long long)(unsigned int)(char *)di, 0xedde0d90); - break; - } - } while ((xad = next_extent ())); -} - -static ldtentry_t * -next_dentry (void) -{ - ldtentry_t *de; - s8 *stbl; - - if (jfs.dttype == DTTYPE_INLINE) { - if (jfs.sindex < jfs.slastindex) { - return (ldtentry_t *)&dtRoot->slot[(int)dtRoot->header.stbl[jfs.sindex++]]; - } - } else { - de = (ldtentry_t *)dtPage->slot; - stbl = (s8 *)&de[(int)dtPage->header.stblindex]; - if (jfs.sindex < jfs.slastindex) { - return &de[(int)stbl[jfs.sindex++]]; - } else if (dtPage->header.next) { - devread (dtPage->header.next << jfs.bdlog, 0, - sizeof(dtpage_t), (unsigned long long)(unsigned int)(char *)dtPage, 0xedde0d90); - jfs.slastindex = dtPage->header.nextindex; - jfs.sindex = 1; - return &de[(int)((s8 *)&de[(int)dtPage->header.stblindex])[0]]; - } - } - - return (jfs.de_index < 2) ? &de_always[jfs.de_index++] : NULL; -} - -static ldtentry_t * -first_dentry (void) -{ - dtroot_t *dtr; - pxd_t *xd; - idtentry_t *de; - - dtr = (dtroot_t *)&iNode->di_xtroot; - jfs.sindex = 0; - jfs.de_index = 0; - - de_always[0].inumber = iNode->di_parent; - de_always[1].inumber = iNode->di_number; - if (dtr->header.flag & BT_LEAF) { - jfs.dttype = DTTYPE_INLINE; - jfs.slastindex = dtr->header.nextindex; - } else { - de = (idtentry_t *)dtPage->slot; - jfs.dttype = DTTYPE_PAGE; - xd = &((idtentry_t *)dtr->slot)[(int)dtr->header.stbl[0]].xd; - for (;;) { - devread (addressPXD (xd) << jfs.bdlog, 0, - sizeof(dtpage_t), (unsigned long long)(unsigned int)(char *)dtPage, 0xedde0d90); - if (dtPage->header.flag & BT_LEAF) - break; - xd = &de[(int)((s8 *)&de[(int)dtPage->header.stblindex])[0]].xd; - } - jfs.slastindex = dtPage->header.nextindex; - } - - return next_dentry (); -} - - -static dtslot_t * -next_dslot (int next) -{ - return (jfs.dttype == DTTYPE_INLINE) - ? (dtslot_t *)&dtRoot->slot[next] - : &((dtslot_t *)dtPage->slot)[next]; -} - -#if 0 -static void -uni2ansi (UniChar *uni, char *ansi, int len) -{ - for (; len; len--, uni++) - *ansi++ = (*uni & 0xff80) ? '?' : *(char *)uni; -} -#else -#define uni2ansi unicode_to_utf8 -#endif - -int -jfs_mount (void) -{ - struct jfs_superblock super; /* struct size = 160 */ - - if ((unsigned long)part_length < MINJFS >> SECTOR_BITS - || !devread (SUPER1_OFF >> SECTOR_BITS, 0, - sizeof(struct jfs_superblock), (unsigned long long)(unsigned int)(char *)&super, 0xedde0d90) - || (super.s_magic != JFS_MAGIC) - || !devread ((AITBL_OFF >> SECTOR_BITS) + FILESYSTEM_I, - 0, DISIZE, (unsigned long long)(unsigned int)(char*)fileSet, 0xedde0d90)) { - return 0; - } - - jfs.bsize = super.s_bsize; - jfs.l2bsize = super.s_l2bsize; - jfs.bdlog = jfs.l2bsize - SECTOR_BITS; - - return 1; -} - -unsigned long long -jfs_read (unsigned long long buf, unsigned long long len, unsigned long write) -{ - struct xad *xad; - s64 endofprev, endofcur; - s64 offset, xadlen; - unsigned long toread, startpos, endpos; - - startpos = filepos; - endpos = filepos + len; - endofprev = (1ULL << 62) - 1; - xad = first_extent (iNode); - do { - offset = offsetXAD (xad); - xadlen = lengthXAD (xad); - if (isinxt (filepos >> jfs.l2bsize, offset, xadlen)) { - endofcur = (offset + xadlen) << jfs.l2bsize; - toread = (endofcur >= endpos) - ? len : (endofcur - filepos); - - disk_read_func = disk_read_hook; - devread (addressXAD (xad) << jfs.bdlog, - filepos - (offset << jfs.l2bsize), toread, buf, write); - disk_read_func = NULL; - - if (buf) - buf += toread; - len -= toread; /* len always >= 0 */ - filepos += toread; - } else if (offset > endofprev) { - toread = ((offset << jfs.l2bsize) >= endpos) - ? len : ((offset - endofprev) << jfs.l2bsize); - filepos += toread; -#if 0 - { - unsigned long tmp_pos = toread; - for (; tmp_pos; tmp_pos--) { - if (buf) - *(buf++) = 0; - } - } -#else - if (buf) - { - grub_memset64 (buf, 0, toread); - buf += toread; - } -#endif - if (len <= toread) - break; - len -= toread; - continue; - } - endofprev = offset + xadlen; - xad = next_extent (); - } while (len > 0 && xad); - - return filepos - startpos; -} - -int -jfs_dir (char *dirname) -{ - char *ptr, *rest, ch; - ldtentry_t *de; - dtslot_t *ds; - u32 inum, parent_inum; - s64 di_size; - u32 di_mode; - int cmp; - unsigned long namlen, n, link_count; -// char namebuf[JFS_NAME_MAX + 1], linkbuf[JFS_PATH_MAX]; - - parent_inum = inum = ROOT_I; - link_count = 0; - for (;;) { - di_read (inum, iNode); - di_size = iNode->di_size; - di_mode = iNode->di_mode; - - if ((di_mode & IFMT) == IFLNK) { - if (++link_count > MAX_LINK_COUNT) { - errnum = ERR_SYMLINK_LOOP; - return 0; - } - if (di_size < (di_mode & INLINEEA ? 256 : 128)) { - grub_memmove (linkbuf, iNode->di_fastsymlink, di_size); - n = di_size; - } else if (di_size < JFS_PATH_MAX - 1) { - filepos = 0; - filemax = di_size; - n = jfs_read ((unsigned long long)(unsigned int)linkbuf, filemax, 0xedde0d90); - } else { - errnum = ERR_FILELENGTH; - return 0; - } - - inum = (linkbuf[0] == '/') ? ROOT_I : parent_inum; - while (n < (JFS_PATH_MAX - 1) && (linkbuf[n++] = *dirname++)); - linkbuf[n] = 0; - dirname = linkbuf; - continue; - } - - if (!*dirname || isspace (*dirname)) { - if ((di_mode & IFMT) != IFREG) { - errnum = ERR_BAD_FILETYPE; - return 0; - } - filepos = 0; - filemax = di_size; - return 1; - } - - if ((di_mode & IFMT) != IFDIR) { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - for (; *dirname == '/'; dirname++); - - //for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++); - for (rest = dirname; (ch = *rest) /*&& !isspace (ch)*/ && ch != '/'; rest++) - { -#if 0 - if (ch == '\\') - { - rest++; - if (! (ch = *rest)) - break; - } -#endif - } - - *rest = 0; - - de = first_dentry (); - for (;;) { - namlen = de->namlen; - if (de->next == -1) { - uni2ansi (de->name, (unsigned char *)namebuf, namlen); - namebuf[namlen] = 0; - } else { - uni2ansi (de->name, (unsigned char *)namebuf, DTLHDRDATALEN); - ptr = namebuf; - ptr += DTLHDRDATALEN; - namlen -= DTLHDRDATALEN; - ds = next_dslot (de->next); - while (ds->next != -1) { - uni2ansi (ds->name, (unsigned char *)ptr, DTSLOTDATALEN); - ptr += DTSLOTDATALEN; - namlen -= DTSLOTDATALEN; - ds = next_dslot (ds->next); - } - uni2ansi (ds->name, (unsigned char *)ptr, namlen); - ptr += namlen; - *ptr = 0; - } - - cmp = (!*dirname) ? -1 : substring (dirname, namebuf, 0); - if (print_possibilities && ch != '/' - && cmp <= 0) { - if (print_possibilities > 0) - print_possibilities = -print_possibilities; - print_a_completion (namebuf, 0); - } else - if (cmp == 0) { - parent_inum = inum; - inum = de->inumber; - *(dirname = rest) = ch; - break; - } - de = next_dentry (); - if (de == NULL) { - if (print_possibilities < 0) - return 1; - - errnum = ERR_FILE_NOT_FOUND; - *rest = ch; - return 0; - } - } - } -} - -unsigned long -jfs_embed (unsigned long *start_sector, unsigned long needed_sectors) -{ - struct jfs_superblock super; /* struct size = 160 */ - - if (needed_sectors > 63 - || !devread (SUPER1_OFF >> SECTOR_BITS, 0, - sizeof (struct jfs_superblock), - (unsigned long long)(unsigned int)(char *)&super, 0xedde0d90) - || (super.s_magic != JFS_MAGIC)) { - return 0; - } - - *start_sector = 1; - return 1; -} - -#endif /* FSYS_JFS */ diff --git a/stage2/fsys_minix.c b/stage2/fsys_minix.c deleted file mode 100644 index afb3517e..00000000 --- a/stage2/fsys_minix.c +++ /dev/null @@ -1,575 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* Restrictions: - This is MINIX V1 only (yet) - Disk creation is like: - mkfs.minix -c DEVICE -*/ - -#ifdef FSYS_MINIX - -#include "shared.h" -#include "filesys.h" - -/* #define DEBUG_MINIX */ - -/* indirect blocks */ -static int mapblock1, mapblock2, namelen; - -/* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */ -#define DEV_BSIZE 512 - -/* include/linux/fs.h */ -#define BLOCK_SIZE_BITS 10 -#define BLOCK_SIZE (1<. Oh well. */ -#define MINIX_LINK_MAX 250 -#define MINIX2_LINK_MAX 65530 - -#define MINIX_I_MAP_SLOTS 8 -#define MINIX_Z_MAP_SLOTS 64 -#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ -#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */ -#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs */ -#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */ -#define MINIX_VALID_FS 0x0001 /* Clean fs. */ -#define MINIX_ERROR_FS 0x0002 /* fs has errors. */ - -#define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode))) -#define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode))) - -#define MINIX_V1 0x0001 /* original minix fs */ -#define MINIX_V2 0x0002 /* minix V2 fs */ - -/* originally this is : -#define INODE_VERSION(inode) inode->i_sb->u.minix_sb.s_version - here we have */ -#define INODE_VERSION(inode) (SUPERBLOCK->s_version) - -/* - * This is the original minix inode layout on disk. - * Note the 8-bit gid and atime and ctime. - */ -struct minix_inode { - __u16 i_mode; - __u16 i_uid; - __u32 i_size; - __u32 i_time; - __u8 i_gid; - __u8 i_nlinks; - __u16 i_zone[9]; -}; - -/* - * The new minix inode has all the time entries, as well as - * long block numbers and a third indirect block (7+1+1+1 - * instead of 7+1+1). Also, some previously 8-bit values are - * now 16-bit. The inode is now 64 bytes instead of 32. - */ -struct minix2_inode { - __u16 i_mode; - __u16 i_nlinks; - __u16 i_uid; - __u16 i_gid; - __u32 i_size; - __u32 i_atime; - __u32 i_mtime; - __u32 i_ctime; - __u32 i_zone[10]; -}; - -/* - * minix super-block data on disk - */ -struct minix_super_block { - __u16 s_ninodes; - __u16 s_nzones; - __u16 s_imap_blocks; - __u16 s_zmap_blocks; - __u16 s_firstdatazone; - __u16 s_log_zone_size; - __u32 s_max_size; - __u16 s_magic; - __u16 s_state; - __u32 s_zones; -}; - -struct minix_dir_entry { - __u16 inode; - char name[0]; -}; - -/* made up, these are pointers into FSYS_BUF */ -/* read once, always stays there: */ -#define NAME_BUF ((char *)(FSYS_BUF)) /* 512 bytes */ -#define SUPERBLOCK \ - ((struct minix_super_block *)((FSYS_BUF)+512)) -#define INODE \ - ((struct minix_inode *)((int) SUPERBLOCK + BLOCK_SIZE)) -#define DATABLOCK1 \ - ((int)((int)INODE + sizeof(struct minix_inode))) -#define DATABLOCK2 \ - ((int)((int)DATABLOCK1 + BLOCK_SIZE)) - -/* linux/stat.h */ -#define S_IFMT 00170000 -#define S_IFLNK 0120000 -#define S_IFREG 0100000 -#define S_IFDIR 0040000 -#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) -#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) -#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) - -#define PATH_MAX 1024 /* include/linux/limits.h */ -#define MAX_LINK_COUNT 5 /* number of symbolic links to follow */ - -static char *linkbuf = (char *)(FSYS_BUF - PATH_MAX); /* buffer for following symbolic links */ - -/* check filesystem types and read superblock into memory buffer */ -int -minix_mount (void) -{ -// if (((current_drive & 0x80) || current_slice != 0) -// && ! IS_PC_SLICE_TYPE_MINIX (current_slice) -// && ! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_OTHER)) -// return 0; /* The partition is not of MINIX type */ - - if ((unsigned long)part_length < (SBLOCK + - (sizeof (struct minix_super_block) / DEV_BSIZE))) - return 0; /* The partition is too short */ - - if (!devread (SBLOCK, 0, sizeof (struct minix_super_block), - (unsigned long long)(unsigned int)(char *) SUPERBLOCK, 0xedde0d90)) - return 0; /* Cannot read superblock */ - - switch (SUPERBLOCK->s_magic) - { - case MINIX_SUPER_MAGIC: - namelen = 14; - break; - case MINIX_SUPER_MAGIC2: - namelen = 30; - break; - default: - return 0; /* Unsupported type */ - } - - return 1; -} - -/* Takes a file system block number and reads it into BUFFER. */ -static int -minix_rdfsb (int fsblock, int buffer) -{ - return devread (fsblock * (BLOCK_SIZE / DEV_BSIZE), 0, - BLOCK_SIZE, (unsigned long long)(unsigned int)(char *) buffer, 0xedde0d90); -} - -/* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into - a physical block (the location in the file system) via an inode. */ -static int -minix_block_map (int logical_block) -{ - int i; - - if (logical_block < 7) - return INODE->i_zone[logical_block]; - - logical_block -= 7; - if (logical_block < 512) - { - i = INODE->i_zone[7]; - - if (!i || ((mapblock1 != 1) - && !minix_rdfsb (i, DATABLOCK1))) - { - errnum = ERR_FSYS_CORRUPT; - return -1; - } - mapblock1 = 1; - return ((__u16 *) DATABLOCK1) [logical_block]; - } - - logical_block -= 512; - i = INODE->i_zone[8]; - if (!i || ((mapblock1 != 2) - && !minix_rdfsb (i, DATABLOCK1))) - { - errnum = ERR_FSYS_CORRUPT; - return -1; - } - mapblock1 = 2; - i = ((__u16 *) DATABLOCK1)[logical_block >> 9]; - if (!i || ((mapblock2 != i) - && !minix_rdfsb (i, DATABLOCK2))) - { - errnum = ERR_FSYS_CORRUPT; - return -1; - } - mapblock2 = i; - return ((__u16 *) DATABLOCK2)[logical_block & 511]; -} - -/* read from INODE into BUF */ -unsigned long long -minix_read (unsigned long long buf, unsigned long long len, unsigned long write) -{ - unsigned long logical_block; - unsigned long offset; - unsigned long map; - unsigned long ret = 0; - unsigned long size = 0; - - while (len > 0) - { - /* find the (logical) block component of our location */ - logical_block = filepos >> BLOCK_SIZE_BITS; - offset = filepos & (BLOCK_SIZE - 1); - map = minix_block_map (logical_block); -#ifdef DEBUG_MINIX - printf ("map=%d\n", map); -#endif - if (map < 0) - break; - - size = BLOCK_SIZE; - size -= offset; - - if (size > len) - size = len; - - disk_read_func = disk_read_hook; - - devread (map * (BLOCK_SIZE / DEV_BSIZE), offset, size, buf, write); - - disk_read_func = NULL; - - if (buf) - buf += size; - len -= size; /* len always >= 0 */ - filepos += size; - ret += size; - } - - if (errnum) - ret = 0; - - return ret; -} - -/* preconditions: minix_mount already executed, therefore supblk in buffer - known as SUPERBLOCK - returns: 0 if error, nonzero iff we were able to find the file successfully - postconditions: on a nonzero return, buffer known as INODE contains the - inode of the file we were trying to look up - side effects: none yet */ -int -minix_dir (char *dirname) -{ - unsigned long current_ino = MINIX_ROOT_INO; /* start at the root */ - unsigned long updir_ino = current_ino; /* the parent of the current directory */ - unsigned long ino_blk; /* fs pointer of the inode's info */ - - unsigned long str_chk = 0; /* used ot hold the results of a string - compare */ - - struct minix_inode * raw_inode; /* inode info for current_ino */ - -//char linkbuf[PATH_MAX]; /* buffer for following sym-links */ - unsigned long link_count = 0; - - char * rest; - char ch; - - unsigned long off; /* offset within block of directory - entry */ - unsigned long loc; /* location within a directory */ - unsigned long blk; /* which data blk within dir entry */ - unsigned long map; /* fs pointer of a particular block from - dir entry */ - struct minix_dir_entry * dp; /* pointer to directory entry */ - - /* loop invariants: - current_ino = inode to lookup - dirname = pointer to filename component we are cur looking up within - the directory known pointed to by current_ino (if any) */ - -#ifdef DEBUG_MINIX - printf ("\n"); -#endif - - while (1) - { -#ifdef DEBUG_MINIX - printf ("inode %d, dirname %s\n", current_ino, dirname); -#endif - - ino_blk = (2 + SUPERBLOCK->s_imap_blocks + SUPERBLOCK->s_zmap_blocks - + (current_ino - 1) / MINIX_INODES_PER_BLOCK); - if (! minix_rdfsb (ino_blk, (int) INODE)) - return 0; - - /* reset indirect blocks! */ - mapblock2 = mapblock1 = -1; - - raw_inode = INODE + ((current_ino - 1) % MINIX_INODES_PER_BLOCK); - - /* copy inode to fixed location */ - memmove ((void *) INODE, (void *) raw_inode, - sizeof (struct minix_inode)); - - /* If we've got a symbolic link, then chase it. */ - if (S_ISLNK (INODE->i_mode)) - { - unsigned long len; - - if (++link_count > MAX_LINK_COUNT) - { - errnum = ERR_SYMLINK_LOOP; - return 0; - } -#ifdef DEBUG_MINIX - printf ("S_ISLNK (%s)\n", dirname); -#endif - - /* Find out how long our remaining name is. */ - //len = 0; - //while (dirname[len] && !isspace (dirname[len])) - // len++; - for (len = 0; (ch = dirname[len]) /*&& !isspace (ch)*/; len++) - { -#if 0 - if (ch == '\\') - { - len++; - if (! (ch = dirname[len])) - break; - } -#endif - } - - /* Get the symlink size. */ - filemax = (INODE->i_size); - if (filemax + len > PATH_MAX - 2) - { - errnum = ERR_FILELENGTH; - return 0; - } - - if (len) - { - /* Copy the remaining name to the end of the symlink data. - Note that DIRNAME and LINKBUF may overlap! */ - memmove (linkbuf + filemax, dirname, len); - } - linkbuf[filemax + len] = '\0'; - - /* Read the necessary blocks, and reset the file pointer. */ - len = grub_read ((unsigned long long)(unsigned int)linkbuf, filemax, 0xedde0d90); - filepos = 0; - if (!len) - return 0; - -#ifdef DEBUG_MINIX - printf ("symlink=%s\n", linkbuf); -#endif - - dirname = linkbuf; - if (*dirname == '/') - { - /* It's an absolute link, so look it up in root. */ - current_ino = MINIX_ROOT_INO; - updir_ino = current_ino; - } - else - { - /* Relative, so look it up in our parent directory. */ - current_ino = updir_ino; - } - - /* Try again using the new name. */ - continue; - } - - /* If end of filename, INODE points to the file's inode */ - if (!*dirname || isspace (*dirname)) - { - if (!S_ISREG (INODE->i_mode)) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - filemax = (INODE->i_size); - return 1; - } - - /* else we have to traverse a directory */ - updir_ino = current_ino; - - /* skip over slashes */ - while (*dirname == '/') - dirname++; - - /* if this isn't a directory of sufficient size to hold our file, - abort */ - if (!(INODE->i_size) || !S_ISDIR (INODE->i_mode)) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - /* skip to next slash or end of filename (space) */ -// for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; -// rest++); - for (rest = dirname; (ch = *rest) /*&& !isspace (ch)*/ && ch != '/'; rest++) - { -#if 0 - if (ch == '\\') - { - rest++; - if (! (ch = *rest)) - break; - } -#endif - } - - /* look through this directory and find the next filename component */ - /* invariant: rest points to slash after the next filename component */ - *rest = 0; - loc = 0; - - do - { -#ifdef DEBUG_MINIX - printf ("dirname=`%s', rest=`%s', loc=%d\n", dirname, rest, loc); -#endif - - /* if our location/byte offset into the directory exceeds the size, - give up */ - if (loc >= INODE->i_size) - { - if (print_possibilities < 0) - { -#if 0 - putchar ('\n'); -#endif - } - else - { - errnum = ERR_FILE_NOT_FOUND; - *rest = ch; - } - return (print_possibilities < 0); - } - - /* else, find the (logical) block component of our location */ - blk = loc >> BLOCK_SIZE_BITS; - - /* we know which logical block of the directory entry we are looking - for, now we have to translate that to the physical (fs) block on - the disk */ - map = minix_block_map (blk); -#ifdef DEBUG_MINIX - printf ("fs block=%d\n", map); -#endif - mapblock2 = -1; - if ((map < 0) || !minix_rdfsb (map, DATABLOCK2)) - { - errnum = ERR_FSYS_CORRUPT; - *rest = ch; - return 0; - } - off = loc & (BLOCK_SIZE - 1); - dp = (struct minix_dir_entry *) (DATABLOCK2 + off); - /* advance loc prematurely to next on-disk directory entry */ - loc += sizeof (dp->inode) + namelen; - - /* NOTE: minix filenames are NULL terminated if < NAMELEN - else exact */ - -#ifdef DEBUG_MINIX - printf ("directory entry ino=%d\n", dp->inode); - if (dp->inode) - printf ("entry=%s\n", dp->name); -#endif - - if (dp->inode) - { - //unsigned long saved_c = dp->name[namelen]; - int j, k; - char ch1; - char *tmp_name= NAME_BUF; /* NAME_LEN is 255, so 512 byte buffer is needed. */ - - /* copy dp->name to tmp_name, and quote spaces with '\\' */ - for (j = 0, k = 0; j < namelen; j++) - { - if (! (ch1 = dp->name[j])) - break; -#if 0 - if (ch1 == ' ') - tmp_name[k++] = '\\'; -#endif - tmp_name[k++] = ch1; - } - tmp_name[k] = 0; - - - //dp->name[namelen] = 0; - str_chk = substring (dirname, tmp_name, 0); - - if (print_possibilities && ch != '/' - && (!*dirname || str_chk <= 0)) - { - if (print_possibilities > 0) - print_possibilities = -print_possibilities; - print_a_completion (tmp_name, 0); - } - - //dp->name[namelen] = saved_c; - } - - } - while (!dp->inode || (str_chk || (print_possibilities && ch != '/'))); - - current_ino = dp->inode; - *(dirname = rest) = ch; - } - /* never get here */ -} - -#endif /* FSYS_MINIX */ diff --git a/stage2/fsys_ntfs.c b/stage2/fsys_ntfs.c index f4febaed..c4ac2108 100644 --- a/stage2/fsys_ntfs.c +++ b/stage2/fsys_ntfs.c @@ -88,12 +88,7 @@ #define FLAG_ENCRYPTED 0x4000 #define FLAG_SPARSE 0x8000 -#define BLK_SHR 9 - -#define MAX_MFT (1024 >> BLK_SHR) -#define MAX_IDX (16384 >> BLK_SHR) - -#define valueat(buf,ofs,type) *((type*)(((char*)buf)+ofs)) +#define valueat(buf,ofs,type) *((type*)(((char*)(grub_size_t)buf)+ofs)) #define AF_ALST 1 #define AF_GPOS 2 @@ -108,23 +103,23 @@ #define set_rflag(a,b) if (b) ctx->flags|=(a); else ctx->flags&=~(a); #define get_rflag(a) (ctx->flags & (a)) -static unsigned long mft_size,idx_size,spc,blocksize,mft_start; +static unsigned int mft_size,idx_size,spc,blocksize,mft_start; static unsigned char log2_bps, log2_bpc, log2_spc, file_backup[48]; typedef struct { int flags; - unsigned long target_vcn,curr_vcn,next_vcn,curr_lcn; - unsigned long vcn_offset; + unsigned int target_vcn,curr_vcn,next_vcn,curr_lcn; + unsigned int vcn_offset; char *mft,*cur_run; } read_ctx; /* sbuf must be at 4K boundary!! read_block() require this.*/ -#define NAME_BUF ((char *)(FSYS_BUF)) /* 4096 bytes */ -#define TEMP_BUF NAME_BUF /* 4096 bytes */ -#define mmft ((char *)((FSYS_BUF)+4096)) -#define cmft (mmft+1024+1024+4096) -#define sbuf (cmft+1024+1024+4096) /* 4096 bytes */ -#define cbuf (sbuf+4096) /* 4096 bytes */ +#define NAME_BUF ((char *)(FSYS_BUF)) /* 4096 bytes */ //3e0000 +#define TEMP_BUF NAME_BUF /* 4096 bytes */ //3e0000 +#define mmft ((char *)((FSYS_BUF)+0x1000)) //3e1000 +#define cmft (mmft+0x3000) //3e4000 +#define sbuf (cmft+0x3000) //3e7000 +#define cbuf ((char *)((FSYS_BUF)+0x8000)) //3e8000 #define attr_flg valueat(cur_mft,0,unsigned short) @@ -136,19 +131,15 @@ typedef struct { #define list_len valueat(cur_mft,16,unsigned short) #define list_ofs valueat(cur_mft,18,unsigned short) -#define emft_buf (cur_mft+1024) -#define edat_buf (cur_mft+2048) +#define emft_buf (cur_mft+0x1000) +#define edat_buf (cur_mft+0x2000) #define ofs2ptr(a) (cur_mft+(a)) #define ptr2ofs(a) ((unsigned short)((a)-cur_mft)) -//#ifdef NTFS_DEBUG -//#define dbg_printf printf -//#else -//#define dbg_printf if (0) printf -//#endif -#define dbg_printf if (((unsigned long)debug) >= 0x7FFFFFFF) printf +#define dbg_printf if (((unsigned int)debug) >= 0x7FFFFFFF) printf +static int fixup(char* buf,int len,char* magic,int tag); static int fixup(char* buf,int len,char* magic,int tag) { int ss; @@ -157,23 +148,25 @@ static int fixup(char* buf,int len,char* magic,int tag) if (tag) { - grub_memmove64 ((unsigned long long)(unsigned int)buf,(unsigned long long)(unsigned int)file_backup,20); + grub_memmove64 ((unsigned long long)(grub_size_t)buf,(unsigned long long)(grub_size_t)file_backup,20); } else { - grub_memmove64 ((unsigned long long)(unsigned int)file_backup,(unsigned long long)(unsigned int)buf,48); + grub_memmove64 ((unsigned long long)(grub_size_t)file_backup,(unsigned long long)(grub_size_t)buf,48); } - if (valueat(buf,0,unsigned long)!=valueat(magic,0,unsigned long)) + if (valueat(buf,0,unsigned int)!=valueat(magic,0,unsigned int)) { dbg_printf("%s label not found\n",magic); return 0; } ss=valueat(buf,6,unsigned short)-1; - if (ss*blocksize!=len*512) +// if (ss*blocksize!=len*512) + if (ss*(int)512 != len*(int)blocksize) { - dbg_printf("Size not match %d!=%d\n",(ss*blocksize),(len*512)); +// dbg_printf("Size not match %d!=%d\n",(ss*blocksize),(len*512)); + dbg_printf("Size not match %d!=%d\n",(ss*512),(len*blocksize)); return 0; } qu=pu=buf+valueat(buf,4,unsigned short); @@ -181,7 +174,8 @@ static int fixup(char* buf,int len,char* magic,int tag) buf-=2; while (ss>0) { - buf+=blocksize; +// buf+=blocksize; + buf+=512; pu+=2; if (tag) { @@ -202,11 +196,12 @@ static int fixup(char* buf,int len,char* magic,int tag) return 1; } -/*static*/ int read_mft(char* buf,unsigned long mftno); -static int read_attr(char* cur_mft,unsigned long long dest,unsigned long long ofs,unsigned long long len,int cached,unsigned long write); -static int read_data(char* cur_mft,char* pa,unsigned long long dest,unsigned long long ofs,unsigned long long len,int cached,unsigned long write); -static int read_list(char* cur_mft,char* pa,int cached,unsigned long write); +/*static*/ int read_mft(char* buf,unsigned int mftno); +static int read_attr(char* cur_mft,unsigned long long dest,unsigned long long ofs,unsigned long long len,int cached,unsigned int write); +static int read_data(char* cur_mft,char* pa,unsigned long long dest,unsigned long long ofs,unsigned long long len,int cached,unsigned int write); +static int read_list(char* cur_mft,char* pa,int cached,unsigned int write); +static void init_attr(char* cur_mft); static void init_attr(char* cur_mft) { attr_flg=0; @@ -216,6 +211,7 @@ static void init_attr(char* cur_mft) list_ofs=0; } +static char* find_attr(char* cur_mft,unsigned char attr); static char* find_attr(char* cur_mft,unsigned char attr) { char* pa; @@ -234,22 +230,25 @@ static char* find_attr(char* cur_mft,unsigned char attr) if (cur_mft==mmft) { - if ((! devread(valueat(pa,0x10,unsigned long),0,512,(unsigned long long)(unsigned int)emft_buf, 0xedde0d90)) || - (! devread(valueat(pa,0x14,unsigned long),0,512,(unsigned long long)(unsigned int)(emft_buf+512), 0xedde0d90))) +// if ((! devread(valueat(pa,0x10,unsigned long),0,512,(unsigned long long)(unsigned int)emft_buf, 0xedde0d90)) || +// (! devread(valueat(pa,0x14,unsigned long),0,512,(unsigned long long)(unsigned int)(emft_buf+512), 0xedde0d90))) + if ((! devread(valueat(pa,0x10,unsigned int),0,blocksize,(unsigned long long)(grub_size_t)emft_buf, 0xedde0d90)) || + ((blocksize == 512) && + (! devread(valueat(pa,0x14,unsigned int),0,blocksize,(unsigned long long)(grub_size_t)(emft_buf+blocksize), 0xedde0d90)))) { dbg_printf("Read Error\n"); return NULL; } - if (! fixup(emft_buf,mft_size,"FILE",0)) + if (! fixup(emft_buf,mft_size,(char*)"FILE",0)) { - dbg_printf("Invalid MFT at 0x%X\n",(valueat(pa,0x10,unsigned long))); + dbg_printf("Invalid MFT at 0x%X\n",(valueat(pa,0x10,unsigned int))); return NULL; } } else { - if (! read_mft(emft_buf,valueat(pa,0x10,unsigned long))) + if (! read_mft(emft_buf,valueat(pa,0x10,unsigned int))) return NULL; } @@ -261,9 +260,9 @@ static char* find_attr(char* cur_mft,unsigned char attr) { return new_pos; } - new_pos+=valueat(new_pos,4,unsigned long); + new_pos+=valueat(new_pos,4,unsigned int); } - dbg_printf("Can\'t find 0x%X in attribute list\n",(unsigned long)(unsigned char)*pa); + dbg_printf("Can\'t find 0x%X in attribute list\n",(grub_size_t)(unsigned char)*pa); return NULL; } } @@ -275,9 +274,10 @@ static char* find_attr(char* cur_mft,unsigned char attr) while ((unsigned char)*pa!=0xFF) { attr_cur=attr_nxt; - attr_nxt+=valueat(pa,4,unsigned long); + attr_nxt+=valueat(pa,4,unsigned int); pa=ofs2ptr(attr_nxt); - if ((unsigned char)*pa==0x20) +// if ((unsigned char)*pa==0x20) + if ((unsigned char)*pa==AT_ATTRIBUTE_LIST) break; } if (! read_list(cur_mft,pa,0,0xedde0d90)) @@ -290,7 +290,7 @@ static char* find_attr(char* cur_mft,unsigned char attr) while ((unsigned char)*pa!=0xFF) { attr_cur=attr_nxt; - attr_nxt+=valueat(pa,4,unsigned long); + attr_nxt+=valueat(pa,4,unsigned int); if ((unsigned char)*pa==AT_ATTRIBUTE_LIST) attr_end=attr_cur; if (((unsigned char)*pa==attr) || (attr==0)) @@ -303,14 +303,14 @@ static char* find_attr(char* cur_mft,unsigned char attr) if (pa[8]) { attr_cur=attr_end; - list_len = valueat(pa,0x30,unsigned long); + list_len = valueat(pa,0x30,unsigned int); if (! read_list(cur_mft,pa,0,0xedde0d90)) return NULL; } else { attr_nxt=attr_end+valueat(pa,0x14,unsigned short); - attr_end=attr_end+valueat(pa,4,unsigned long); + attr_end=attr_end+valueat(pa,4,unsigned int); } set_aflag(AF_ALST,1); while (attr_nxt=attr_end) return NULL; @@ -330,15 +330,16 @@ static char* find_attr(char* cur_mft,unsigned char attr) set_aflag(AF_GPOS,1); attr_cur=attr_nxt; pa=ofs2ptr(attr_cur); - valueat(pa,0x10,unsigned long)=mft_start; - valueat(pa,0x14,unsigned long)=mft_start+1; + valueat(pa,0x10,unsigned int)=mft_start; + valueat(pa,0x14,unsigned int)=mft_start+1; new_pos=attr_nxt+valueat(pa,4,unsigned short); while (new_pos 4096) @@ -365,7 +366,7 @@ static int read_list(char* cur_mft,char* pa,int cached,unsigned long write) n = (list_len + blocksize -1) & (~(blocksize -1)); list_len = 0; } - if (! read_data(cur_mft,pa,(unsigned long long)(unsigned int)edat_buf,(unsigned long long)(unsigned int)list_ofs,n,cached, write)) + if (! read_data(cur_mft,pa,(unsigned long long)(grub_size_t)edat_buf,(unsigned long long)(grub_size_t)list_ofs,n,cached, write)) { dbg_printf("Fail to read non-resident attribute list\n"); return 0; @@ -374,6 +375,7 @@ static int read_list(char* cur_mft,char* pa,int cached,unsigned long write) return 1; } +static char* locate_attr(char* cur_mft,unsigned char attr); static char* locate_attr(char* cur_mft,unsigned char attr) { char* pa; @@ -396,9 +398,10 @@ static char* locate_attr(char* cur_mft,unsigned char attr) return pa; } -static char* read_run_data(char* run,int nn,unsigned long* val,int sig) +static char* read_run_data(char* run,int nn,unsigned int* val,int sig); +static char* read_run_data(char* run,int nn,unsigned int* val,int sig) { - unsigned long r, v; + unsigned int r, v; r = 0; v = 1; @@ -416,10 +419,11 @@ static char* read_run_data(char* run,int nn,unsigned long* val,int sig) return run; } +static char* read_run_list(read_ctx* ctx,char* run); static char* read_run_list(read_ctx* ctx,char* run) { int c1,c2; - unsigned long val; + unsigned int val; back: c1=((unsigned char)(*run) & 0xF); @@ -431,7 +435,7 @@ static char* read_run_list(read_ctx* ctx,char* run) cur_mft=ctx->mft; if ((cur_mft) && (get_aflag(AF_ALST))) { - void (*save_hook)(unsigned long long, unsigned long, unsigned long long); + void (*save_hook)(unsigned long long, unsigned int, unsigned long long); save_hook=disk_read_func; disk_read_func=NULL; @@ -461,9 +465,10 @@ static char* read_run_list(read_ctx* ctx,char* run) return run; } -static unsigned long comp_table[16][2]; +static unsigned int comp_table[16][2]; static int comp_head,comp_tail,cbuf_ofs,cbuf_vcn; +static int decomp_nextvcn(void); static int decomp_nextvcn(void) { if (comp_head>=comp_tail) @@ -471,21 +476,24 @@ static int decomp_nextvcn(void) dbg_printf("C1\n"); return 0; } - if (! devread((comp_table[comp_head][1]-(comp_table[comp_head][0]-cbuf_vcn))*spc,0,spc << BLK_SHR,(unsigned long long)(unsigned int)cbuf, 0xedde0d90)) +// if (! devread((comp_table[comp_head][1]-(comp_table[comp_head][0]-cbuf_vcn))*spc,0,spc << BLK_SHR,(unsigned long long)(unsigned int)cbuf, 0xedde0d90)) + if (! devread((comp_table[comp_head][1]-(comp_table[comp_head][0]-cbuf_vcn))*spc,0,spc << log2_bps,(unsigned long long)(grub_size_t)cbuf, 0xedde0d90)) { dbg_printf("Read Error\n"); return 0; } cbuf_vcn++; - if ((cbuf_vcn>=comp_table[comp_head][0])) + if ((cbuf_vcn>=(int)comp_table[comp_head][0])) comp_head++; cbuf_ofs=0; return 1; } +static int decomp_getch(void); static int decomp_getch(void) { - if (cbuf_ofs>=(spc << BLK_SHR)) +// if (cbuf_ofs>=(spc << BLK_SHR)) + if (cbuf_ofs>=(int)(spc << log2_bps)) { if (! decomp_nextvcn()) return 0; @@ -494,6 +502,7 @@ static int decomp_getch(void) } // Decompress a block (4096 bytes) +static int decomp_block(char* dest); static int decomp_block(char* dest) { unsigned short flg,cnt; @@ -506,7 +515,7 @@ static int decomp_block(char* dest) { if (flg & 0x8000) { - unsigned long bits,copied,tag; + unsigned int bits,copied,tag; bits=copied=tag=0; while (cnt > 0) @@ -521,7 +530,7 @@ static int decomp_block(char* dest) } if (tag & 1) { - unsigned long i, len, delta, code, lmask, dshift; + unsigned int i, len, delta, code, lmask, dshift; code=decomp_getch(); code+=decomp_getch()*256; @@ -583,7 +592,8 @@ static int decomp_block(char* dest) { int n; - n=(spc << BLK_SHR) - cbuf_ofs; +// n=(spc << BLK_SHR) - cbuf_ofs; + n=(spc << log2_bps) - cbuf_ofs; if (n>cnt) n=cnt; if ((dest) && (n)) @@ -599,11 +609,12 @@ static int decomp_block(char* dest) return 1; } -static int read_block(read_ctx* ctx, unsigned long long buf, unsigned long num, unsigned long long len, unsigned long write) +static int read_block(read_ctx* ctx, unsigned long long buf, unsigned int num, unsigned long long len, unsigned int write); +static int read_block(read_ctx* ctx, unsigned long long buf, unsigned int num, unsigned long long len, unsigned int write) { if (get_rflag(RF_COMP)) { - unsigned long cpb=(8/spc); + unsigned int cpb=(8/spc); if (write == 0x900ddeed) { @@ -613,7 +624,7 @@ static int read_block(read_ctx* ctx, unsigned long long buf, unsigned long num, while (num) { - unsigned long nn; + unsigned int nn; if ((ctx->target_vcn & 0xF)==0) { @@ -624,7 +635,8 @@ static int read_block(read_ctx* ctx, unsigned long long buf, unsigned long num, } comp_head=comp_tail=0; cbuf_vcn=ctx->target_vcn; - cbuf_ofs=(spc<target_vcn>=ctx->next_vcn) { ctx->cur_run=read_run_list(ctx,ctx->cur_run); @@ -642,11 +654,6 @@ static int read_block(read_ctx* ctx, unsigned long long buf, unsigned long num, if (ctx->cur_run==NULL) return 0; } - //if (ctx->target_vcn+16next_vcn) - // { - // dbg_printf("A2\n"); - // return 0; - // } } nn=(16 - (ctx->target_vcn & 0xF)) / cpb; @@ -675,7 +682,7 @@ static int read_block(read_ctx* ctx, unsigned long long buf, unsigned long num, return 0; if (buf) { - grub_memmove64 (buf, (unsigned long long)(unsigned int)dest, 4096); + grub_memmove64 (buf, (unsigned long long)(grub_size_t)dest, 4096); buf+=4096; } nn--; @@ -690,17 +697,19 @@ static int read_block(read_ctx* ctx, unsigned long long buf, unsigned long num, int tt; tt=comp_table[comp_head][0] - ctx->target_vcn; - if (tt>nn) + if (tt>(int)nn) tt=nn; ctx->target_vcn+=tt; if (buf) { - if (! devread((comp_table[comp_head][1]-(comp_table[comp_head][0] - ctx->target_vcn))*spc,0,(unsigned long long)tt*(spc << BLK_SHR),buf, 0xedde0d90)) +// if (! devread((comp_table[comp_head][1]-(comp_table[comp_head][0] - ctx->target_vcn))*spc,0,(unsigned long long)tt*(spc << BLK_SHR),buf, 0xedde0d90)) + if (! devread((comp_table[comp_head][1]-(comp_table[comp_head][0] - ctx->target_vcn))*spc,0,(unsigned long long)tt*(spc << log2_bps),buf, 0xedde0d90)) { dbg_printf("Read Error\n"); return 0; } - buf+=(unsigned long long)tt*(spc << BLK_SHR); +// buf+=(unsigned long long)tt*(spc << BLK_SHR); + buf+=(unsigned long long)tt*(spc << log2_bps); } nn-=tt; if (ctx->target_vcn>=comp_table[comp_head][0]) @@ -710,12 +719,14 @@ static int read_block(read_ctx* ctx, unsigned long long buf, unsigned long num, { if (buf) { - if (! devread((ctx->target_vcn - ctx->curr_vcn + ctx->curr_lcn)*spc,0,(unsigned long long)nn*(spc << BLK_SHR),buf, 0xedde0d90)) +// if (! devread((ctx->target_vcn - ctx->curr_vcn + ctx->curr_lcn)*spc,0,(unsigned long long)nn*(spc << BLK_SHR),buf, 0xedde0d90)) + if (! devread((ctx->target_vcn - ctx->curr_vcn + ctx->curr_lcn)*spc,0,(unsigned long long)nn*(spc << log2_bps),buf, 0xedde0d90)) { dbg_printf("Read Error\n"); return 0; } - buf+=(unsigned long long)nn*(spc << BLK_SHR); +// buf+=(unsigned long long)nn*(spc << BLK_SHR); + buf+=(unsigned long long)nn*(spc << log2_bps); } ctx->target_vcn+=nn; } @@ -726,7 +737,7 @@ static int read_block(read_ctx* ctx, unsigned long long buf, unsigned long num, { while (num) { - unsigned long nn; + unsigned int nn; unsigned long long ss; nn = (ctx->next_vcn - ctx->target_vcn) * spc - ctx->vcn_offset; @@ -744,31 +755,34 @@ static int read_block(read_ctx* ctx, unsigned long long buf, unsigned long num, return 0; } if (buf) - grub_memset64 (buf, 0, (unsigned long long)nn << BLK_SHR); +// grub_memset64 (buf, 0, (unsigned long long)nn << BLK_SHR); + grub_memset64 (buf, 0, (unsigned long long)nn << log2_bps); } else { - unsigned long s = (ctx->target_vcn - ctx->curr_vcn + ctx->curr_lcn) * spc + ctx->vcn_offset; - unsigned long o = 0; + unsigned int s = (ctx->target_vcn - ctx->curr_vcn + ctx->curr_lcn) * spc + ctx->vcn_offset; + unsigned int o = 0; if (write != 0x900ddeed) /* read */ - ss = ((unsigned long long)nn << BLK_SHR); +// ss = ((unsigned long long)nn << BLK_SHR); + ss = ((unsigned long long)nn << log2_bps); else if (len == -1ULL) /* long long of -1 for normal whole-block writing */ - ss = ((unsigned long long)nn << BLK_SHR); +// ss = ((unsigned long long)nn << BLK_SHR); + ss = ((unsigned long long)nn << log2_bps); else if ((long long)len < 0) /* long long of -2, -3, ... for writing a piece of block */ { ss = -len; ss--; - if (ss >= 512) +// if (ss >= 512) + if (ss >= blocksize) { - grub_printf ("Fatal! ss(=%ld) should not be >= 512.\n", ss); + grub_printf ("Fatal! ss(=%ld) should not be >= %d.\n", ss,blocksize); return 0; } - //o = 512 - (unsigned long)len; /* sbuf must be 4K align!! buf is now offset to sbuf. */ - //o = ((unsigned long)buf) % 4096; - o = ((unsigned long)buf) & 4095; + //o = ((unsigned long)buf) % 4096; //sbuf必须是4K对齐 + o = (unsigned int)filepos % (1UL << log2_bps); //2022-07-15 解决写偏移的问题 sbuf无需4K对齐 } else { ss = len; @@ -780,14 +794,12 @@ static int read_block(read_ctx* ctx, unsigned long long buf, unsigned long num, } } if (buf) - buf += ((unsigned long long)nn << BLK_SHR); +// buf += ((unsigned long long)nn << BLK_SHR); + buf += ((unsigned long long)nn << log2_bps); } - //ss = ctx->target_vcn * spc + ctx->vcn_offset + nn; - //ctx->target_vcn = ss / spc; - //ctx->vcn_offset = ss % spc; ss = (ctx->target_vcn << log2_spc) + ctx->vcn_offset + nn; - ctx->target_vcn = ((unsigned long)ss) >> log2_spc; - ctx->vcn_offset = ((unsigned long)ss) & (spc-1); + ctx->target_vcn = ((unsigned int)ss) >> log2_spc; + ctx->vcn_offset = ((unsigned int)ss) & (spc-1); num -= nn; if (num == 0) break; @@ -803,11 +815,11 @@ static int read_block(read_ctx* ctx, unsigned long long buf, unsigned long num, return 1; } -static int read_data(char* cur_mft,char* pa,unsigned long long dest,unsigned long long ofs,unsigned long long len,int cached,unsigned long write) +static int read_data(char* cur_mft,char* pa,unsigned long long dest,unsigned long long ofs,unsigned long long len,int cached,unsigned int write) { - unsigned long vcn, blk_size; + unsigned int vcn, blk_size; unsigned char log2_blk_size; - read_ctx cc, *ctx; + read_ctx cc={0}, *ctx; int ret=0; if (len == 0) @@ -819,35 +831,33 @@ static int read_data(char* cur_mft,char* pa,unsigned long long dest,unsigned lon { if (write == 0x900ddeed) /* write */ { -// grub_printf ("Fatal: Cannot write resident/small file! Enlarge it to 2KB and try again.\n"); -// return 0; - if (valueat(file_backup,0x2c,unsigned long) != valueat(cur_mft,0x2c,unsigned long)) + if (valueat(file_backup,0x2c,unsigned int) != valueat(cur_mft,0x2c,unsigned int)) goto fail; - grub_memmove64 (((unsigned long long)(unsigned int)(pa + valueat(pa,0x14,unsigned long))+ofs),dest,len); - fixup(cur_mft,mft_size,"FILE",1); - if (! devread(mft_start + valueat(cur_mft,0x2c,unsigned long) * mft_size,0,mft_size << log2_bps,(unsigned long long)(unsigned int)cur_mft,0x900ddeed)) + grub_memmove64 (((unsigned long long)(grub_size_t)(pa + valueat(pa,0x14,unsigned int))+ofs),dest,len); + fixup(cur_mft,mft_size,(char*)"FILE",1); + if (! devread(mft_start + valueat(cur_mft,0x2c,unsigned int) * mft_size,0,mft_size << log2_bps,(unsigned long long)(grub_size_t)cur_mft,0x900ddeed)) goto fail; return 1; } - if (ofs + len > valueat(pa,0x10,unsigned long)) + if (ofs + len > valueat(pa,0x10,unsigned int)) { dbg_printf("Read out of range\n"); return 0; } if (dest) - grub_memmove64 (dest, (unsigned long long)(unsigned int)(pa + valueat(pa,0x14,unsigned long) + ofs), len); + grub_memmove64 (dest, (unsigned long long)(grub_size_t)(pa + valueat(pa,0x14,unsigned int) + ofs), len); - disk_read_func = disk_read_hook; - devread(mft_start + valueat(cur_mft,0x2c,unsigned long) * mft_size, pa - cur_mft + valueat(pa,0x14,unsigned long), len, 0, GRUB_LISTBLK); - disk_read_func = NULL; + disk_read_func = disk_read_hook; + devread(mft_start + valueat(cur_mft,0x2c,unsigned int) * mft_size, pa - cur_mft + valueat(pa,0x14,unsigned int), len, 0, GRUB_LISTBLK); + disk_read_func = NULL; return 1; } ctx->mft = cur_mft; set_rflag(RF_COMP, valueat(pa,0xC,unsigned short) & FLAG_COMPRESSED); ctx->cur_run = pa + valueat(pa,0x20,unsigned short); - //blk_size = (get_rflag(RF_COMP)) ? 4096 : 512; - log2_blk_size = (get_rflag(RF_COMP)) ? 12 : 9 ; +// log2_blk_size = (get_rflag(RF_COMP)) ? 12 : 9 ; + log2_blk_size = (get_rflag(RF_COMP)) ? 12 : log2_bps ; blk_size = 1UL << log2_blk_size; if ((get_rflag(RF_COMP)) && (! cached)) @@ -858,27 +868,18 @@ static int read_data(char* cur_mft,char* pa,unsigned long long dest,unsigned lon if (cached && write != 0x900ddeed) /* read */ { - //if ((ofs & (~(blk_size - 1))) == save_pos) if ((ofs & (-(unsigned long long)blk_size)) == save_pos) { - unsigned long n,bofs; - - //if (write == 0x900ddeed) /* write */ - //{ - // grub_printf ("Fatal: Cannot write file with save_pos!\n"); - // return 0; - //} - bofs = (unsigned long)ofs - (unsigned long)save_pos; + unsigned int n,bofs; + + bofs = (unsigned int)ofs - (unsigned int)save_pos; n = blk_size - bofs; if (n > len) n = len; if (dest) { -// if (write == 0x900ddeed) /* write */ -// memcpy (sbuf + ofs - save_pos, dest, n); -// else - grub_memmove64 (dest, (unsigned long long)(unsigned long)(sbuf + bofs), n); + grub_memmove64 (dest, (unsigned long long)(grub_size_t)(sbuf + bofs), n); } if (n == len) return 1; @@ -899,13 +900,12 @@ static int read_data(char* cur_mft,char* pa,unsigned long long dest,unsigned lon } else { - //vcn = ctx->target_vcn = (ofs >> BLK_SHR) / spc; - //ctx->vcn_offset = (ofs >> BLK_SHR) % spc; vcn = ctx->target_vcn = ofs >> log2_bpc; - ctx->vcn_offset = (ofs >> BLK_SHR) & (spc-1); +// ctx->vcn_offset = (ofs >> BLK_SHR) & (spc-1); + ctx->vcn_offset = (ofs >> log2_bps) & (spc-1); } - ctx->next_vcn = valueat(pa,0x10,unsigned long); + ctx->next_vcn = valueat(pa,0x10,unsigned int); ctx->curr_lcn = 0; while (ctx->next_vcn <= ctx->target_vcn) { @@ -916,14 +916,14 @@ static int read_data(char* cur_mft,char* pa,unsigned long long dest,unsigned lon if (get_aflag(AF_GPOS)) { - unsigned long tmp1, tmp2; + unsigned int tmp1, tmp2; tmp2 = tmp1 = (ctx->target_vcn - ctx->curr_vcn + ctx->curr_lcn) * spc + ctx->vcn_offset; tmp2++; if (dest) { - valueat((char *)(unsigned int)dest,0,unsigned long) = tmp1; - valueat((char *)(unsigned int)dest,4,unsigned long) = tmp2; + valueat((char *)(grub_size_t)dest,0,unsigned int) = tmp1; + valueat((char *)(grub_size_t)dest,4,unsigned int) = tmp2; } if (tmp2 == (ctx->next_vcn - ctx->curr_vcn + ctx->curr_lcn) * spc) { @@ -931,19 +931,16 @@ static int read_data(char* cur_mft,char* pa,unsigned long long dest,unsigned lon if (ctx->cur_run == NULL) return 0; if (dest) - valueat((char *)(unsigned int)dest,4,unsigned long) = ctx->curr_lcn * spc; + valueat((char *)(grub_size_t)dest,4,unsigned int) = ctx->curr_lcn * spc; } return 1; } if ((vcn > ctx->target_vcn) && - //(! read_block (ctx, 0ULL, ((vcn - ctx->target_vcn) * spc) / 8, 0, 0xedde0d90))) (! read_block (ctx, 0ULL, ((vcn - ctx->target_vcn) << log2_spc) >> 3, 0, 0xedde0d90))) return 0; - // ret = 0; - - if ((cached) && (valueat(pa,0xC,unsigned short) & (FLAG_COMPRESSED + FLAG_SPARSE))==0) + if ((cached)/* && (valueat(pa,0xC,unsigned short) & (FLAG_COMPRESSED + FLAG_SPARSE))==0*/) //解除NTFS文件系统对压缩与稀疏文件读挂钩的限制 2025-08-19 disk_read_func = disk_read_hook; else if (write == 0x900ddeed) /* write */ { @@ -952,11 +949,10 @@ static int read_data(char* cur_mft,char* pa,unsigned long long dest,unsigned lon } /* read the beginning piece of data(if any) upto a block boundary. */ - //if (ofs % blk_size) - if ((unsigned long)ofs & (blk_size-1)) + if ((unsigned int)ofs & (blk_size-1)) { unsigned long long t; - unsigned long n, o; + unsigned int n, o; if (! cached) { @@ -970,14 +966,12 @@ static int read_data(char* cur_mft,char* pa,unsigned long long dest,unsigned lon n = len; if (dest && write == 0x900ddeed) /* write */ - grub_memmove64 ((unsigned long long)(unsigned int)&sbuf[o], dest, n); + grub_memmove64 ((unsigned long long)(grub_size_t)&sbuf[o], dest, n); - //t = ctx->target_vcn * (spc << BLK_SHR); t = (unsigned long long)(ctx->target_vcn) << log2_bpc; - //if (! read_block (ctx, sbuf, 1, -1, 0xedde0d90)) /* read */ /* (-n-1) is long long value ranging from -2, -3, ..., -blk_size */ /* sbuf must be 4K align !! */ - if (! read_block (ctx, (unsigned long long)(unsigned int)(write == 0x900ddeed ? &sbuf[o] : sbuf), 1, ((-(long long)n)-1), write)) /* read/write */ + if (! read_block (ctx, (unsigned long long)(grub_size_t)(write == 0x900ddeed ? &sbuf[o] : sbuf), 1, ((-(long long)n)-1), write)) /* read/write */ goto fail; if (write != 0x900ddeed) /* read */ @@ -985,19 +979,10 @@ static int read_data(char* cur_mft,char* pa,unsigned long long dest,unsigned lon save_pos = t; if (dest) { - //if (write == 0x900ddeed) /* write */ - //{ - // if (grub_memcmp (dest, &sbuf[o], n) == 0) - // goto next; - // memcpy (&sbuf[o], dest, n); - // if (! read_block (ctx, sbuf, 1, -1, write)) /* write */ - // goto fail; - // goto next; - //} - grub_memmove64 (dest, (unsigned long long)(unsigned int)&sbuf[o], n); + grub_memmove64 (dest, (unsigned long long)(grub_size_t)&sbuf[o], n); } } -//next: + if (n == len) goto done; if (dest) @@ -1005,16 +990,14 @@ static int read_data(char* cur_mft,char* pa,unsigned long long dest,unsigned lon len -= n; } - //if (! read_block (ctx, dest, ((unsigned int)len) / blk_size, -1ULL, write)) /* read/write */ /* XXX: 64-bit ? */ if (! read_block (ctx, dest, len >> log2_blk_size, -1ULL, write)) /* read/write */ goto fail; if (dest) - //dest += (((unsigned int)len) / blk_size) * blk_size; /* XXX: 64-bit ? */ dest += len & (-(unsigned long long)blk_size); //len = ((unsigned int)len) % blk_size; /* XXX: 64-bit ? */ - len = ((unsigned long)len) & (blk_size-1); + len = ((unsigned int)len) & (blk_size-1); if (len) { @@ -1027,11 +1010,10 @@ static int read_data(char* cur_mft,char* pa,unsigned long long dest,unsigned lon } if (dest && write == 0x900ddeed) /* write */ - grub_memmove64 ((unsigned long long)(unsigned int)sbuf, dest, len); + grub_memmove64 ((unsigned long long)(grub_size_t)sbuf, dest, len); - //t = ctx->target_vcn * (spc << BLK_SHR); t = (unsigned long long)(ctx->target_vcn) << log2_bpc; - if (! read_block (ctx, (unsigned long long)(unsigned int)sbuf, 1, len, write)) /* read/write */ + if (! read_block (ctx, (unsigned long long)(grub_size_t)sbuf, 1, len, write)) /* read/write */ goto fail; if (write != 0x900ddeed) /* read */ @@ -1039,16 +1021,7 @@ static int read_data(char* cur_mft,char* pa,unsigned long long dest,unsigned lon save_pos = t; if (dest) { - //if (write == 0x900ddeed) /* write */ - //{ - // if (grub_memcmp (dest, sbuf, len) == 0) - // goto done; - // memcpy (sbuf, dest, len); - // if (! read_block (ctx, sbuf, 1, -1, write)) /* write */ - // goto fail; - // goto done; - //} - grub_memmove64 (dest, (unsigned long long)(unsigned int)sbuf, len); + grub_memmove64 (dest, (unsigned long long)(grub_size_t)sbuf, len); } } } @@ -1059,32 +1032,33 @@ static int read_data(char* cur_mft,char* pa,unsigned long long dest,unsigned lon return ret; } -static int read_attr(char* cur_mft,unsigned long long dest,unsigned long long ofs,unsigned long long len,int cached, unsigned long write) +static int read_attr(char* cur_mft,unsigned long long dest,unsigned long long ofs,unsigned long long len,int cached, unsigned int write) { - unsigned short save_cur; +// unsigned short save_cur; unsigned char attr; char* pp; int ret; - save_cur=attr_cur; +// save_cur=attr_cur; attr_nxt=attr_cur; attr=valueat(ofs2ptr(attr_nxt),0,unsigned char); if (get_aflag(AF_ALST)) { unsigned short new_pos; - unsigned long vcn; + unsigned int vcn; - //vcn=ofs / (spc<> log2_bpc; new_pos=attr_nxt+valueat(ofs2ptr(attr_nxt),4,unsigned short); while (new_posvcn) + if (valueat(pa,8,unsigned int)>vcn) break; attr_nxt=new_pos; new_pos+=valueat(pa,4,unsigned short); @@ -1092,21 +1066,24 @@ static int read_attr(char* cur_mft,unsigned long long dest,unsigned long long of } pp=find_attr(cur_mft,attr); ret=(pp)?read_data(cur_mft,pp,dest,ofs,len,cached,write):0; - attr_cur=save_cur; +// attr_cur=save_cur; return ret; } -/*static*/ int read_mft(char* buf,unsigned long mftno) +int read_mft(char* buf,unsigned int mftno); +/*static*/ int read_mft(char* buf,unsigned int mftno) { - if (! read_attr(mmft,(unsigned long long)(unsigned int)buf,mftno*(mft_size << BLK_SHR),((unsigned long long)(mft_size)) << BLK_SHR,0, 0xedde0d90)) +// if (! read_attr(mmft,(unsigned long long)(unsigned int)buf,mftno*(mft_size << BLK_SHR),((unsigned long long)(mft_size)) << BLK_SHR,0, 0xedde0d90)) + if (! read_attr(mmft,(unsigned long long)(grub_size_t)buf,mftno*(mft_size << log2_bps),((unsigned long long)(mft_size)) << log2_bps,0, 0xedde0d90)) { dbg_printf("Read MFT 0x%X fails\n",mftno); return 0; } - return fixup(buf,mft_size,"FILE",0); + return fixup(buf,mft_size,(char*)"FILE",0); } -static int init_file(char* cur_mft,unsigned long mftno) +static int init_file(char* cur_mft,unsigned int mftno); +static int init_file(char* cur_mft,unsigned int mftno) { unsigned short flag; @@ -1133,7 +1110,7 @@ static int init_file(char* cur_mft,unsigned long mftno) } if (! pa[8]) - filemax=valueat(pa,0x10,unsigned long); + filemax=valueat(pa,0x10,unsigned int); else filemax=valueat(pa,0x30,unsigned long long); @@ -1151,11 +1128,12 @@ static int init_file(char* cur_mft,unsigned long mftno) static char ch; +static int list_file(char* cur_mft,char *fn,char *pos); static int list_file(char* cur_mft,char *fn,char *pos) { char *np; unsigned char *utf8 = (unsigned char *)(NAME_BUF); - unsigned long i,ns,len; + unsigned int i,ns,len; //len=strlen(fn); for (len=strlen(fn); ! (pos[0xC] & 2); pos+=valueat(pos,8,unsigned short)) @@ -1178,28 +1156,27 @@ static int list_file(char* cur_mft,char *fn,char *pos) { if (is_print) { - //if ((i) || ((utf8[0]!='$') && ((utf8[0]!='.') || (ns!=1)))) { if (print_possibilities>0) print_possibilities=-print_possibilities; -// for (i=1;isetcolorstate) current_term->setcolorstate (COLOR_STATE_HIGHLIGHT); current_color_64bit = (current_color_64bit & 0xffffff) | (clo64 & 0xffffff00000000); current_color = (current_color & 0x0f) | (clo & 0xf0); + console_setcolorstate (current_color | 0x100); //设置控制台文本模式的颜色(UEFI) } print_a_completion((char *)utf8, 1); - current_color_64bit = clo64; - current_color = clo; + if (cursor_state & 1) + current_term->setcolorstate (COLOR_STATE_STANDARD); + else + current_term->setcolorstate (COLOR_STATE_NORMAL); #endif } } @@ -1210,15 +1187,15 @@ static int list_file(char* cur_mft,char *fn,char *pos) dbg_printf("64-bit MFT number\n"); return 0; } - return init_file(cur_mft,valueat(pos,0,unsigned long)); + return init_file(cur_mft,valueat(pos,0,unsigned int)); } } } - //pos+=valueat(pos,8,unsigned short); } return -1; } +static int scan_dir(char* cur_mft,char *fn); static int scan_dir(char* cur_mft,char *fn) { unsigned char *bitmap; @@ -1242,9 +1219,9 @@ static int scan_dir(char* cur_mft,char *fn) // Resident, Namelen=4, Offset=0x18, Flags=0x00 // Name="$I30" - if ((valueat(cur_pos,8,unsigned long)!=0x180400) || - (valueat(cur_pos,0x18,unsigned long)!=0x490024) || - (valueat(cur_pos,0x1C,unsigned long)!=0x300033)) + if ((valueat(cur_pos,8,unsigned int)!=0x180400) || + (valueat(cur_pos,0x18,unsigned int)!=0x490024) || + (valueat(cur_pos,0x1C,unsigned int)!=0x300033)) continue; cur_pos+=valueat(cur_pos,0x14,unsigned short); if (*cur_pos!=0x30) // Not filename index @@ -1265,12 +1242,12 @@ static int scan_dir(char* cur_mft,char *fn) int ofs=(unsigned char)cur_pos[0xA]; // Namelen=4, Name="$I30" if ((cur_pos[9]==4) && - (valueat(cur_pos,ofs,unsigned long)==0x490024) && - (valueat(cur_pos,ofs+4,unsigned long)==0x300033)) + (valueat(cur_pos,ofs,unsigned int)==0x490024) && + (valueat(cur_pos,ofs+4,unsigned int)==0x300033)) { if (cur_pos[8]==0) { - bitmap_len=valueat(cur_pos,0x10,unsigned long); + bitmap_len=valueat(cur_pos,0x10,unsigned int); if (bitmap_len>4096) { dbg_printf("Resident $BITMAP too large\n"); @@ -1280,14 +1257,14 @@ static int scan_dir(char* cur_mft,char *fn) memcpy((char *)bitmap,(char *)(cur_pos+valueat(cur_pos,0x14,unsigned short)),bitmap_len); break; } - if (valueat(cur_pos,0x28,unsigned long)>4096) + if (valueat(cur_pos,0x28,unsigned int)>4096) { dbg_printf("Non-resident $BITMAP too large\n"); goto error; } bitmap=(unsigned char*)cbuf; - bitmap_len=valueat(cur_pos,0x30,unsigned long); - if (! read_data(cur_mft,cur_pos,(unsigned long long)(unsigned int)cbuf,0,valueat(cur_pos,0x28,unsigned long),0, 0xedde0d90)) + bitmap_len=valueat(cur_pos,0x30,unsigned int); + if (! read_data(cur_mft,cur_pos,(unsigned long long)(grub_size_t)cbuf,0,valueat(cur_pos,0x28,unsigned int),0, 0xedde0d90)) { dbg_printf("Fails to read non-resident $BITMAP\n"); goto error; @@ -1301,9 +1278,9 @@ static int scan_dir(char* cur_mft,char *fn) { // Non-resident, Namelen=4, Offset=0x40, Flags=0 // Name="$I30" - if ((valueat(cur_pos,8,unsigned long)==0x400401) && - (valueat(cur_pos,0x40,unsigned long)==0x490024) && - (valueat(cur_pos,0x44,unsigned long)==0x300033)) + if ((valueat(cur_pos,8,unsigned int)==0x400401) && + (valueat(cur_pos,0x40,unsigned int)==0x490024) && + (valueat(cur_pos,0x44,unsigned int)==0x300033)) break; cur_pos=find_attr(cur_mft,AT_INDEX_ALLOCATION); } @@ -1316,15 +1293,16 @@ static int scan_dir(char* cur_mft,char *fn) if (bitmap) { - unsigned long v,i; + unsigned int v,i; v=1; - for (i=0;i=0) @@ -1352,6 +1330,7 @@ static int scan_dir(char* cur_mft,char *fn) return 0; } +int ntfs_mount (void); int ntfs_mount (void) { #if 0 @@ -1360,27 +1339,29 @@ int ntfs_mount (void) return 0; #endif - if (! devread (0, 0, 512, (unsigned long long)(unsigned int)mmft, 0xedde0d90)) + if (! devread (0, 0, 512, (unsigned long long)(grub_size_t)mmft, 0xedde0d90)) return 0; #if 0 - if (valueat(mmft,3,unsigned long)!=0x5346544E) + if (valueat(mmft,3,unsigned int)!=0x5346544E) return 0; #endif blocksize=valueat(mmft,0xb,unsigned short); - if (blocksize != 512) +// if (blocksize != 512) + if (blocksize != 512 && blocksize != 4096) return 0; log2_bps = log2_tmp(blocksize); - //spc=(blocksize*valueat(mmft,0xd,unsigned char)) >> BLK_SHR; - spc = valueat(mmft,0xd,unsigned char) << (log2_bps - BLK_SHR); +// spc = valueat(mmft,0xd,unsigned char) << (log2_bps - BLK_SHR); + spc = valueat(mmft,0xd,unsigned char); if (!spc || (128 % spc)) return 0; log2_spc = log2_tmp(spc); - log2_bpc = log2_spc + BLK_SHR; +// log2_bpc = log2_spc + BLK_SHR; + log2_bpc = log2_spc + log2_bps; - if (valueat(mmft,0x10,unsigned long) != 0) + if (valueat(mmft,0x10,unsigned int) != 0) return 0; if (mmft[0x14] != 0) @@ -1388,38 +1369,45 @@ int ntfs_mount (void) if (valueat(mmft,0x16,unsigned short) != 0) return 0; - +#if 0 +//使用'Macrorit Partition Expert'格式化,BPB的0x18、0x1A,0x1C为零! 2024-02-19 if ((unsigned short)(valueat(mmft,0x18,unsigned short) - 1) > 62) return 0; if ((unsigned short)(valueat(mmft,0x1A,unsigned short) - 1) > 255) return 0; - - if (valueat(mmft,0x20,unsigned long) != 0) +#endif + if (valueat(mmft,0x20,unsigned int) != 0) return 0; if (mmft[0x44]>0) idx_size=spc*mmft[0x44]; else - idx_size=1<<(-mmft[0x44]-BLK_SHR); +// idx_size=1<<(-mmft[0x44]-BLK_SHR); + idx_size=1<<(-mmft[0x44]-log2_bps); if (mmft[0x40]>0) mft_size=spc*mmft[0x40]; else - mft_size=1<<(-mmft[0x40]-BLK_SHR); +// mft_size=1<<(-mmft[0x40]-BLK_SHR); + mft_size=1<<(-mmft[0x40]-log2_bps); - mft_start=spc*valueat(mmft,0x30,unsigned long); + mft_start=spc*valueat(mmft,0x30,unsigned int); - if ((mft_size>MAX_MFT) ||(idx_size>MAX_IDX)) +// if ((mft_size>MAX_MFT) ||(idx_size>MAX_IDX)) + if ((mft_size>(unsigned int)(4096>>log2_bps)) ||(idx_size>(unsigned int)(4096>>log2_bps))) return 0; - *(unsigned long long *)0x3e7e00 = mft_start; - *(unsigned long long *)0x3e7e08 = spc*valueat(mmft,0x38,unsigned long); +// *(unsigned long long *)0x3e7e00 = mft_start; +// *(unsigned long long *)0x3e7e08 = spc*valueat(mmft,0x38,unsigned long); + *(unsigned long long *)(FSYS_BUF+0x9000) = mft_start + 3 * mft_size; + *(unsigned long long *)(FSYS_BUF+0x9008) = spc*valueat(mmft,0x38,unsigned int) + 3 * mft_size; - if (! devread(mft_start,0,mft_size << BLK_SHR,(unsigned long long)(unsigned int)mmft, 0xedde0d90)) +// if (! devread(mft_start,0,mft_size << BLK_SHR,(unsigned long long)(unsigned int)mmft, 0xedde0d90)) + if (! devread(mft_start,0,mft_size << log2_bps,(unsigned long long)(grub_size_t)mmft, 0xedde0d90)) return 0; - if (! fixup(mmft,mft_size,"FILE",0)) + if (! fixup(mmft,mft_size,(char*)"FILE",0)) return 0; if (! locate_attr(mmft,AT_DATA)) @@ -1430,6 +1418,7 @@ int ntfs_mount (void) return 1; } +int ntfs_dir (char *dirname); int ntfs_dir (char *dirname) { int ret; @@ -1446,7 +1435,7 @@ int ntfs_dir (char *dirname) dirname++; if (! safe_parse_maxint(&dirname,&mftno)) return 0; - return init_file(cmft,(unsigned long)mftno); + return init_file(cmft,(grub_size_t)mftno); } if (! init_file(cmft,FILE_ROOT)) @@ -1459,24 +1448,10 @@ int ntfs_dir (char *dirname) char *next/*, ch*/; /* skip to next slash or end of filename (space) */ - for (next = dirname; (ch = *next) && ch != '/' /*&& !isspace (ch)*/; next++) - { -#if 0 - if (ch == '\\') - { - next++; - if (! (ch = *next)) - break; - } -#endif - } + for (next = dirname; (ch = *next) && ch != '/' /*&& !isspace (ch)*/; next++); *next = 0; -// print_possibilities=(ch=='/')?0:is_print; - ret=scan_dir(cmft,dirname); - -// print_possibilities=is_print; *next=ch; if (! ret) @@ -1491,17 +1466,16 @@ int ntfs_dir (char *dirname) return ret; } +unsigned long long ntfs_read(unsigned long long buf, unsigned long long len, unsigned int write); unsigned long long -ntfs_read(unsigned long long buf, unsigned long long len, unsigned long write) +ntfs_read(unsigned long long buf, unsigned long long len, unsigned int write) { char *cur_mft; cur_mft=cmft; if (valueat(cur_mft,0x16,unsigned short) & 2) goto error; - - //if (disk_read_hook) /* commented out by chenall, 2010-05-13 */ - save_pos=1; + save_pos=1; if (! read_attr(cmft,buf,filepos,len,1,write)) goto error; @@ -1516,19 +1490,25 @@ ntfs_read(unsigned long long buf, unsigned long long len, unsigned long write) #ifdef FS_UTIL +void ntfs_info(int level); void ntfs_info(int level) { dbg_printf("blocksize: %u\nspc: %u\nmft_size: %u\nidx_size: %u\nmft_start: 0x%X\n", blocksize,spc,mft_size,idx_size,mft_start); } +int ntfs_inode_read(char* buf); int ntfs_inode_read(char* buf) { if (buf) - memcpy(buf,cmft,mft_size<> 8) | \ - (((unsigned long int)(x) & 0xff000000U) >> 24))) -#endif -#if !defined(__constant_htons) -#define __constant_htons(x) \ - ((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \ - (((unsigned short int)(x) & 0xff00) >> 8))) -#endif - -#define ntohl(x) \ -(__builtin_constant_p(x) ? \ - __constant_htonl((x)) : \ - __swap32(x)) -#define htonl(x) \ -(__builtin_constant_p(x) ? \ - __constant_htonl((x)) : \ - __swap32(x)) -#define ntohs(x) \ -(__builtin_constant_p(x) ? \ - __constant_htons((x)) : \ - __swap16(x)) -#define htons(x) \ -(__builtin_constant_p(x) ? \ - __constant_htons((x)) : \ - __swap16(x)) - -static inline unsigned long int __swap32(unsigned long int x) -{ - __asm__("xchgb %b0,%h0\n\t" - "rorl $16,%0\n\t" - "xchgb %b0,%h0" - : "=q" (x) - : "0" (x)); - return x; -} - -static inline unsigned short int __swap16(unsigned short int x) -{ - __asm__("xchgb %b0,%h0" - : "=q" (x) - : "0" (x)); - return x; -} - - -#ifndef TFTP_PORT -#define TFTP_PORT 69 -#endif - -//#define PXE_MIN_BLKSIZE 512 -//#define PXE_MAX_BLKSIZE 1432 -#define PXE_MIN_BLKSIZE 128 -#define PXE_MAX_BLKSIZE 16384 - -#define DOT_SIZE 1048576 - -/* PXE_BUF must be in low memory */ -//#define PXE_BUF FSYS_BUF -//#define PXE_BUFLEN FSYS_BUFLEN -/* use disk buffer for PXE_BUF */ -#define PXE_BUF BUFFERADDR -#if (BUFFERLEN >= 0x10000) -#define PXE_BUFLEN 0xFE00 -#else -#define PXE_BUFLEN BUFFERLEN -#endif - -//#define PXE_DEBUG 1 - -unsigned long pxe_entry = 0, pxe_blksize = 512 /*PXE_MAX_BLKSIZE*/; -unsigned short pxe_basemem, pxe_freemem; -unsigned long pxe_keep; - -//IP4 pxe_yip, pxe_sip, pxe_gip; -grub_u8_t pxe_mac_len, pxe_mac_type; +#include "term.h" + +grub_u32_t cur_pxe_type = 0; //当前传输协议类型 0/1=tftp/http +grub_u32_t http_feature; //1=支持断点续传 +int map_pd; +int only_tftp = 0; +struct grub_efi_pxe *pxe_entry; +grub_u32_t pxe_sip; //服务器IP tftp使用 +grub_u32_t pxe_yip; //自己的IP +grub_u32_t station_ip; //站IP +grub_u32_t subnet_mask; //子网掩码 +grub_u8_t *bootfile; MAC_ADDR pxe_mac; -static grub_u8_t pxe_tftp_opened; -static unsigned long pxe_saved_pos, pxe_cur_ofs, pxe_read_ofs; - -extern PXENV_TFTP_OPEN_t pxe_tftp_open; /* now it is defined in asm.S */ -static char *pxe_tftp_name; - -extern unsigned long ROM_int15; -extern unsigned long ROM_int13; -extern unsigned long ROM_int13_dup; -extern struct drive_map_slot bios_drive_map[DRIVE_MAP_SIZE + 1]; +static void print_ip (grub_u32_t ip); +static int pxe_opened = 0; +static char filename[128]; +static char *pxe_name = filename; +static int read_status; +static char *http_range = 0; +grub_u32_t pxe_http_type = 0; //0/1=http/https +static int pxe_need_read = 0; //0/1=不用读/需要读 +int is_ip6 = 0; +static char default_server[128]; //默认服务器IPv4 http使用 +//static grub_efi_net_interface_t *net_interface; +struct grub_efi_net_device *net_devices = 0; +grub_efi_pxe_dhcpv4_packet_t *discover_reply = 0; //引导播放器 +unsigned int max_packet_size; //最大包尺寸 +grub_efi_simple_network_t *net0; +unsigned long long hex; +char *g4e_options; +unsigned int g4e_options_size; static int pxe_open (char* name); -grub_u32_t pxe_read_blk (grub_u32_t buf, grub_u32_t num); - -static int tftp_open(const char *dirname); -static grub_u32_t tftp_get_size(void); -static grub_u32_t tftp_read_blk (grub_u32_t buf, grub_u32_t num); -static void tftp_close (void); -static void tftp_unload(void); - -s_PXE_FILE_FUNC tftp_file_func = {tftp_open,tftp_get_size,tftp_read_blk,tftp_close,tftp_unload}; - -grub_u32_t cur_pxe_type = 0; -grub_u32_t def_pxe_type = 0; -s_PXE_FILE_FUNC *pxe_file_func[2]={ - &tftp_file_func, - #ifdef FSYS_IPXE - &ipxe_file_func, - #endif -}; - -static char* pxe_outhex (char* pc, unsigned char c) +int pxe_mount (void); +int pxe_dir (char *dirname); +unsigned long long pxe_read (unsigned long long buf, unsigned long long len, unsigned int write); +void pxe_close (void); +void pxe_unload (void); +int pxe_allocate(void); + +static int tftp_open(void); +//static grub_u32_t tftp_get_size(void); +static unsigned long long tftp_read (char *buf, grub_u64_t len); +int tftp_write (const char *name); + +static int http_open(void); +static unsigned long long http_read (char *buf, grub_u64_t len); +static void pxe_configure (void); +static void http_configure (void); +//static grub_efi_ip6_config_manual_address_t *efi_ip6_config_manual_address (grub_efi_ip6_config_protocol_t *ip6_config); +//static grub_efi_ip4_config2_manual_address_t * efi_ip4_config_manual_address (grub_efi_ip4_config2_protocol_t *ip4_config); +static grub_err_t efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https, int headeronly, char *range); +unsigned long grub_strtoul (const char * restrict str, const char ** const restrict end, int base); +//static inline char *grub_lltoa (char *str, int c, unsigned long long n); +//grub_size_t grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize, const grub_uint8_t *src, grub_size_t srcsize, const grub_uint8_t **srcend); +grub_uint8_t *grub_utf16_to_utf8 (grub_uint8_t *dest, const grub_uint16_t *src, grub_size_t size); +//static int grub_efi_ip4_interface_set_manual_address (struct grub_efi_net_device *dev, grub_efi_net_ip_manual_address_t *net_ip, int with_subnet); +//static grub_efi_net_interface_t * grub_efi_ip4_interface_match (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *ip_address); +//static grub_efi_net_interface_t * grub_efi_ip6_interface_match (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *ip_address); +//static int grub_efi_net_add_pxebc_to_cards (void); +static void set_ip_policy_to_static (void); +static grub_efi_handle_t grub_efi_service_binding (grub_efi_handle_t dev, grub_efi_guid_t *service_binding_guid); + + +static grub_efi_guid_t ip4_config_guid = GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID; +//static grub_efi_guid_t ip6_config_guid = GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID; +static grub_efi_guid_t http_service_binding_guid = GRUB_EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID; +static grub_efi_guid_t http_guid = GRUB_EFI_HTTP_PROTOCOL_GUID; +static grub_efi_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID; +static grub_efi_guid_t net_io_guid = GRUB_EFI_SIMPLE_NETWORK_GUID; //简单网络 + +static char* pxe_outhex (char* pc, unsigned char c); +static char* pxe_outhex (char* pc, unsigned char c) //pxe十六进制 { int i; @@ -155,647 +114,95 @@ static char* pxe_outhex (char* pc, unsigned char c) return pc; } -grub_u32_t pxe_read_blk (grub_u32_t buf, grub_u32_t num) -{ - grub_u32_t ret = pxe_file_func[cur_pxe_type]->readblk(buf,num); - return ret; -} - - -/* - return 0 for seccess, 1 for failure -*/ -static int try_blksize (int tmp) -{ - unsigned long nr; - -#ifdef FSYS_IPXE - if (cur_pxe_type == PXE_FILE_TYPE_IPXE) return 0; -#endif - pxe_blksize = tmp; - printf_debug0 ("\nTry block size %d ...\n", pxe_blksize); - nr = 0; - tmp = pxe_open(pxe_tftp_name); - - if (!tmp) - { - printf_debug0 ("\nFailure: bootfile not found.\n"); - return 1; - } - - if (filemax <= pxe_blksize) - { - printf_debug0 ("\nFailure: Size %ld too small.\n", filemax); - pxe_close (); - return 1; - } - - nr = pxe_read_blk (PXE_BUF, 1); - - if (nr == PXE_ERR_LEN) - { - printf_debug0 ("\nFailure: Cannot read the first block.\n"); - pxe_close (); - return 1; - } - - if (pxe_blksize != nr && filemax >= nr && nr <= PXE_MAX_BLKSIZE && nr >= PXE_MIN_BLKSIZE) - { - printf_debug0 ("\npxe_blksize tuned from %d to %d\n", pxe_blksize, nr); - pxe_blksize = nr; - } - - printf_debug0 ("\nUse block size %d\n", pxe_blksize); - - pxe_close (); - return 0; -} - -//unsigned long pxe_inited = 0; /* pxe_detect only run once */ -static unsigned long config_already_restarted = 0; -static unsigned long server_is_dos = 0; -BOOTPLAYER *discover_reply = 0; - -static void set_basedir(char *config) -{ - unsigned long n; - grub_u8_t path_sep = (cur_pxe_type == PXE_FILE_TYPE_TFTP && server_is_dos) ? '\\' : '/'; - n = grub_strlen (config); - - if (n > 126) - { - printf_warning("Warning! base name(%d chars) too long (> 126 chars).\n", n); - n = 126; - config[n] = 0; - } - - if (*config != path_sep) - { - #ifdef FSYS_IPXE - char *ch = strstr(config,":"); - if (has_ipxe && ch && (grub_u32_t)(ch - config) < 10) - { - pxe_tftp_name = (char*)&pxe_tftp_open.FileName; - cur_pxe_type = def_pxe_type = PXE_FILE_TYPE_IPXE; - } - else - { - if (cur_pxe_type == PXE_FILE_TYPE_TFTP) - #endif - pxe_tftp_name = (char*)&pxe_tftp_open.FileName; - *pxe_tftp_name++ = path_sep; - #ifdef FSYS_IPXE - } - #endif - } - - grub_memmove(pxe_tftp_name, config, n); - - while (n >= 0) if (pxe_tftp_name[--n] == path_sep) break; - - pxe_tftp_name += n; -} - -static void print_ip (IP4 ip); - -int pxe_detect (int blksize, char *config) //void pxe_detect (void) +unsigned long long buf_start, buf_len; +//对于tftp,判断是否首次打开文件名,确定是否必须读 +//配置tftp/http +//打开tftp/http +static int pxe_open (char* name) //pxe打开 { - unsigned long tmp; - char *pc; - int i, ret; - -// if (pxe_inited) -// return 0; - - if (! pxe_entry) //if (! pxe_scan ()) - return 0; + grub_strcpy (pxe_name, name); -// pxe_inited = 1; -// for proxyDHCP compatible and auto reset sip/gip with pxe_detect - if (discover_reply->sip) - pxe_sip = discover_reply->sip; - if (discover_reply->gip) - pxe_gip = discover_reply->gip; - else - {//get route gateway - grub_u8_t *p = discover_reply->vendor.d; - if (*(long*)p == 0x63538263)//DHCP magic cookie 99.130.83.99 - { - for(i=4;ibootfile[0]) - { - unsigned long n; - - for (n = 0; n < 127; n++) - { - if (discover_reply->bootfile[n] == '\\') - { - server_is_dos = 1; - break; - } - } - - grub_printf("\nBoot Server: "); - print_ip(pxe_sip); - grub_printf("\tBoot File: %s\n", discover_reply->bootfile); - - set_basedir((char*)discover_reply->bootfile); - - /* read the boot file to determine the block size. */ - - if (blksize) - pxe_blksize = blksize; - else if (try_blksize (1408) && try_blksize (512)) - { - pxe_blksize = 512; /* default to 512 */ - printf_warning ("Warning! Cannot open bootfile. pxe_blksize set to default 512.\n"); - } - - //grub_strcpy (pxe_tftp_name, "/menu.lst/"); - } else - { - pxe_blksize = (blksize ? blksize : 512); /* default to 512 */ - printf_warning ("\nNo bootfile! pxe_blksize set to %d\n", pxe_blksize); - pxe_tftp_name = (char*)&pxe_tftp_open.FileName[0]; - } - - pxe_tftp_opened = 0; - - ret = 0; - - grub_memcpy ((char *) saved_pxe_mac, (char *) pxe_mac, 6); - saved_pxe_ip = pxe_yip; - - if (config) { - if ((ret = grub_open(config))) - { - set_basedir(config); - grub_close(); - goto done; - } - return 1; + http_configure(); //网络接口 + pxe_opened = http_open(); } - - //if (pxe_dir ("/menu.lst")) - //{ - // grub_strcpy (pxe_tftp_name, "/menu.lst"); - // ret = 1; - // goto done; - //} - - grub_strcpy (pxe_tftp_name, "/menu.lst"); - #if 0 - grub_printf ("\nFrom now on, we first try to open this FILE: %s\n" - "\nCaution: The PXE server should NOT have a DIR of \"%s\"." - "\nCaution: The system could hang if \"%s\" is a DIR." - "\nCaution: Your original \"menu.lst\" DIR should be renamed to \"menu\".\n" - , pxe_tftp_open.FileName - , pxe_tftp_open.FileName - , pxe_tftp_open.FileName); - #endif - ret = pxe_dir (pxe_tftp_name); - if (ret && filemax) - goto done; - if (pxe_tftp_open.Status != PXENV_STATUS_TFTP_FILE_NOT_FOUND)//bad server - goto done; - /* Reports from Ruymbeke: opening /menu.lst will hang if it is a dir. - * Do NOT use /menu.lst as a dir any more!! Use /menu for it instead. - */ - if (!config) - config = "/menu.lst/"; - - grub_strcpy (pxe_tftp_name, config); - -//#define MENU_DIR_NAME_LENGTH (sizeof("/menu.lst/") - 1) - int MENU_DIR_NAME_LENGTH = grub_strlen(config); - - pc = pxe_tftp_name + MENU_DIR_NAME_LENGTH; - pc = pxe_outhex (pc, pxe_mac_type); - for (i = 0; i < pxe_mac_len; i++) - { - *(pc++) = '-'; - pc = pxe_outhex (pc, pxe_mac[i]); - } - *pc = 0; - grub_printf ("\n%s\n", pxe_tftp_open.FileName); - if (pxe_dir (pxe_tftp_name)) - { - ret = 1; - goto done; - } - - pc = pxe_tftp_name + MENU_DIR_NAME_LENGTH; - tmp = pxe_yip; - for (i = 0; i < 4; i++) - { - pc = pxe_outhex (pc, tmp & 0xFF); - tmp >>= 8; - } - *pc = 0; - do - { - grub_printf ("%s\n", pxe_tftp_open.FileName); - if (pxe_dir (pxe_tftp_name)) - { - ret = 1; - goto done; - } - if (checkkey() == 0x11b) break; - *(--pc) = 0; - } while (pc > pxe_tftp_name + MENU_DIR_NAME_LENGTH); - grub_strcpy (pc, "default"); - grub_printf ("%s\n", pxe_tftp_open.FileName); - ret = pxe_dir (pxe_tftp_name); - -#undef MENU_DIR_NAME_LENGTH - -done: - - if (ret && filemax) - { -#if 1 - char *new_config = config_file; - char *filename = pxe_tftp_name; - if (debug > 1) - { - printf_debug("\rPXE boot configfile:%s\n",(char *)pxe_tftp_open.FileName); - DEBUG_SLEEP - } - pxe_close (); - /* got file name. put it in config_file */ - if (grub_strlen (filename) >= ((char *)0x8270 - new_config)) - return ! (errnum = ERR_WONT_FIT); - /* set (pd) as root device. */ - saved_drive = PXE_DRIVE; - saved_partition = current_partition; - /* Copy FILENAME to CONFIG_FILE. */ - while ((*new_config++ = *filename++) != 0); - if (pxe_restart_config == 0) - { - if (config_already_restarted == 0) - { - pxe_restart_config = 1; - config_already_restarted = 1; - } - return ret; - } - use_config_file = 1; - - /* Make sure that the user will not be authoritative. */ - auth = 0; - buf_drive = -1; /* invalidate disk cache. */ - buf_track = -1; /* invalidate disk cache. */ - saved_entryno = 0; - //force_cdrom_as_boot_device = 0; - boot_drive = saved_drive; - install_partition = saved_partition; - current_drive = GRUB_INVALID_DRIVE; - current_partition = 0xFFFFFF; - fsys_type = NUM_FSYS; - boot_part_addr = 0; - current_slice = 0; - - ///* Restart pre_stage2. */ - //(*(char *)0x8205) |= 2; /* disable keyboard intervention */ - //chain_stage1(0, 0x8200, boot_part_addr); - /* Restart cmain. */ - asm volatile ("movl $0x7000, %esp"); /* set stack to STACKOFF */ -#ifdef HAVE_ASM_USCORE - asm volatile ("call _cmain"); - asm volatile ("jmp _stop"); -#else - asm volatile ("call cmain"); - asm volatile ("jmp stop"); -#endif - - /* Never reach here. */ -#else - unsigned long nr; - - nr = 4096 - 1; - if (nr > filemax) - nr = filemax; - nr = pxe_read ((char*)0x800, nr); - if (nr != PXE_ERR_LEN) - { - *(char*)(0x800 + nr) = 0; - - if (preset_menu != (char*)0x800) - preset_menu = (char*)0x800; - if (*config_file) - *config_file = 0; /* only use preset_menu with pxe */ - - if (nr < filemax) - { - grub_printf ("Boot menu truncated\n"); - //pxe_read (NULL, filemax - nr); - } - } - pxe_close (); -#endif - } - //getkey(); - return ret; -} - -static int pxe_reopen (void) -{ - pxe_close (); - pxe_tftp_opened = pxe_file_func[cur_pxe_type]->open(pxe_tftp_name); - return pxe_tftp_opened; -} - -static int pxe_open (char* name) -{ - if (name != pxe_tftp_name) - { - grub_strcpy (pxe_tftp_name, name); - - if (cur_pxe_type == PXE_FILE_TYPE_TFTP && server_is_dos) - { - unsigned long n; - for (n = 0; n < 128; n++) - { - if (pxe_tftp_open.FileName[n] == '/') - pxe_tftp_open.FileName[n] = '\\'; - } - } - name = pxe_tftp_name; - } - - pxe_close (); - /* - We always use pxe_tftp_open.FileName for full file path. - name is a relative path. - */ - pxe_tftp_opened = pxe_file_func[cur_pxe_type]->open(name); - if (!pxe_tftp_opened) - { - if ((unsigned long)debug >= 0x7FFFFFFF) printf("Err: %d\n",pxe_tftp_open.Status); - return 0; - } - if (pxe_file_func[cur_pxe_type]->getsize()) - return 1; - pxe_close (); - return (pxe_tftp_opened = 0); -} + if (!pxe_opened) + return !(errnum = ERR_FILE_NOT_FOUND); -void pxe_close (void) -{ - if (pxe_tftp_opened) - { - pxe_file_func[cur_pxe_type]->close(); - pxe_saved_pos = pxe_cur_ofs = pxe_read_ofs = 0; - pxe_tftp_opened = 0; - } + return 1; } -static unsigned long pxe_read_len (unsigned long long buf, unsigned long long len) +int pxe_mount (void) //pxe挂载 { - unsigned long old_ofs, sz; - - if (len == 0) + if (current_drive != PXE_DRIVE || ! pxe_entry) //0x21 return 0; - sz = 0; - old_ofs = pxe_cur_ofs; - pxe_cur_ofs += len; - if (pxe_cur_ofs > pxe_read_ofs) - { - unsigned long nb, nr; - long nb_del, nb_pos; - - sz = (pxe_read_ofs - old_ofs); - if ((buf) && (sz)) - { - grub_memmove64 (buf, (unsigned long long)(unsigned int)(char*)(PXE_BUF + old_ofs), sz); - buf += sz; - } - pxe_cur_ofs -= pxe_read_ofs; /* bytes to read */ - nb = pxe_cur_ofs / pxe_blksize; /* blocks to read */ - nb_del = DOT_SIZE / pxe_blksize; - if (nb_del > nb) - { - nb_del = 0; - nb_pos = -1; - } - else - nb_pos = nb - nb_del; - pxe_cur_ofs -= pxe_blksize * nb; /* bytes residual */ - if (pxe_read_ofs + pxe_blksize > PXE_BUFLEN) - pxe_read_ofs = 0; - while (nb > 0) - { - unsigned long nn; - - nn = (PXE_BUFLEN - pxe_read_ofs) / pxe_blksize; - if (nn > nb) - nn = nb; - nr = pxe_read_blk (PXE_BUF + pxe_read_ofs, nn); - if (nr == PXE_ERR_LEN) - return nr; - sz += nr; - if (buf) - { - grub_memmove64 (buf, (unsigned long long)(unsigned int)(char*)(PXE_BUF + pxe_read_ofs), nr); - buf += nr; - } - if (nr < nn * pxe_blksize) - { - pxe_read_ofs += nr; - pxe_cur_ofs = pxe_read_ofs; - return sz; - } - nb -= nn; - if (nb) - pxe_read_ofs = 0; - else - pxe_read_ofs += nr; - if ((long)nb <= nb_pos) - { - grub_putchar ('.', 255); - nb_pos -= nb_del; - } - } - - if (nb_del) - { - grub_putchar ('\r', 255); - grub_putchar ('\n', 255); - } - - if (pxe_cur_ofs) - { - if (pxe_read_ofs + pxe_blksize > PXE_BUFLEN) - pxe_read_ofs = 0; - - nr = pxe_read_blk (PXE_BUF + pxe_read_ofs, 1); - if (nr == PXE_ERR_LEN) - return nr; - if (pxe_cur_ofs > nr) - pxe_cur_ofs = nr; - sz += pxe_cur_ofs; - if (buf) - grub_memmove64 (buf, (unsigned long long)(unsigned int)(char*)(PXE_BUF + pxe_read_ofs), pxe_cur_ofs); - pxe_cur_ofs += pxe_read_ofs; - pxe_read_ofs += nr; - } - else - pxe_cur_ofs = pxe_read_ofs; - } - else - { - sz += len; - if (buf) - grub_memmove64 (buf, (unsigned long long)(unsigned int)(char *)PXE_BUF + old_ofs, len); - } - return sz; -} - -/* Mount the network drive. If the drive is ready, return 1, otherwise - return 0. */ -int pxe_mount (void) -{ - if (current_drive != PXE_DRIVE || ! pxe_entry) - return 0; -#ifdef FSYS_IPXE - if (current_partition != IPXE_PART) - cur_pxe_type = def_pxe_type; - else if (has_ipxe) - cur_pxe_type = PXE_FILE_TYPE_IPXE; - else - return 0; -#endif return 1; } -/* Read up to SIZE bytes, returned in ADDR. */ -unsigned long long -pxe_read (unsigned long long buf, unsigned long long len, unsigned long write) +/* Check if the file DIRNAME really exists. Get the size and save it in 检查文件DIRNAME是否确实存在 + FILEMAX. return 1 if succeed, 0 if fail. */ //获取尺寸并将其保存在FILEMAX中。 如果成功则返回1,如果失败则返回0 +struct pxe_dir_info //目录信息 { - unsigned long nr; - - if (write == GRUB_WRITE) - return !(errnum = ERR_WRITE); - - if (! pxe_tftp_opened) - return PXE_ERR_LEN; - - if (pxe_saved_pos != filepos) - { - if ((filepos < pxe_saved_pos) && (filepos+pxe_cur_ofs >= pxe_saved_pos)) - pxe_cur_ofs -= pxe_saved_pos - filepos; - else - { - if (pxe_saved_pos > filepos) - { - if (! pxe_reopen ()) - return PXE_ERR_LEN; - } - - nr = pxe_read_len (0ULL, filepos - pxe_saved_pos); - if ((nr == PXE_ERR_LEN) || (pxe_saved_pos + nr != filepos)) - return PXE_ERR_LEN; - } - pxe_saved_pos = filepos; - } - nr = pxe_read_len (buf, len); - if (nr != PXE_ERR_LEN) - { - filepos += nr; - pxe_saved_pos = filepos; - } - return nr; -} + char path[512]; //路径 尺寸0x200 e3d64c0 /boot/dir.txt + char *dir[512]; //目录 尺寸0x1000 e3d66c0 e3d76c0 e3d76c5 e3d76d2 ... + char data[]; //数据 尺寸0x2e00 e3d76c0 bcd\0\a bcdedit.exe\0\a boot.sdi\0\a bootmgr.exe\0\a wimboot\0\a +} *P_DIR_INFO = NULL;//尺寸0x4000 -/* Check if the file DIRNAME really exists. Get the size and save it in - FILEMAX. return 1 if succeed, 0 if fail. */ -struct pxe_dir_info -{ - char path[512]; - char *dir[512]; - char data[]; -} *P_DIR_INFO = NULL; -int pxe_dir (char *dirname) +int pxe_dir (char *dirname) //pxe查目录 { int ret; char ch; ret = 1; - ch = nul_terminate (dirname); - - if ((grub_u32_t)pxe_tftp_name + grub_strlen(dirname) > (grub_u32_t)&pxe_tftp_open.FileName[127]) - { - printf_debug0("Error: The file name exceeds the maximum number of characters.\n"); - return 0; - } - - if (print_possibilities) + ch = nul_terminate (dirname); //以00替换止字符串的空格,回车,换行,水平制表符 + + if (print_possibilities) //如果存在打印可能性 { char dir_tmp[128]; char *p_dir; - ret = grub_strlen(dirname); - p_dir = &dirname[ret]; + ret = grub_strlen(dirname); //目录尺寸 + p_dir = &dirname[ret]; //目录结束地址 - if (ret && ret <=120) + if (ret && ret <=120) //存在目录尺寸,并且<=120 { - while (ret && dirname[ret] != '/') + while (ret && dirname[ret] != '/') //取子目录 { ret--; } - grub_memmove(dir_tmp,dirname,ret); + grub_memmove(dir_tmp,dirname,ret); //复制子目录 } else ret = 0; - grub_strcpy(&dir_tmp[ret],"/dir.txt"); - if (P_DIR_INFO || (P_DIR_INFO = (struct pxe_dir_info*)grub_malloc(16384))) + grub_strcpy(&dir_tmp[ret],"/dir.txt");//追加"/dir.txt" +// if (P_DIR_INFO || (P_DIR_INFO = (struct pxe_dir_info*)grub_zalloc(16384))) //建立目录信息缓存 + if (P_DIR_INFO || (P_DIR_INFO = (struct pxe_dir_info*)grub_malloc(16384))) //建立目录信息缓存 { int i; char *p = P_DIR_INFO->data; - if (substring(dir_tmp,P_DIR_INFO->path,1) != 0) + if (substring(dir_tmp,P_DIR_INFO->path,1) != 0) //判断子字符串 { - memset(P_DIR_INFO,0,16384); + memset(P_DIR_INFO,0,16384); grub_strcpy(P_DIR_INFO->path,dir_tmp); if (pxe_open(dir_tmp)) { - if (pxe_read((unsigned long long)(int)P_DIR_INFO->data,13312,GRUB_READ)) +// if (pxe_read((unsigned long long)(grub_size_t)P_DIR_INFO->data,13312,GRUB_READ)) //13312计算错误 + if (pxe_read((unsigned long long)(grub_size_t)P_DIR_INFO->data,filemax,GRUB_READ)) //替换filemax,是因为读长了会把后面无用的字符串读入 2023-11-24 { P_DIR_INFO->dir[0] = P_DIR_INFO->data; - for (i = 1;i < 512 && (p = skip_to(0x100,p));++i) + for (i = 1;i < 512 && (p = skip_to(0x100,p));++i) //遇到首个"回车,换行",使用'\0'替换.然后跳过之后的"回车,换行,空格,水平制表符", { P_DIR_INFO->dir[i] = p; } @@ -807,10 +214,25 @@ int pxe_dir (char *dirname) ret = 0; for (i = 0; i < 512 && (p = P_DIR_INFO->dir[i]);++i) { - if (*dirname == 0 || substring (dirname, p, 1) < 1) +// if (*dirname == 0 || substring (dirname, p, 1) < 1) + if (*dirname == 0 || substring (dirname, p, 1) == 0) //*dirname为0,是'/''\0',打印全部; 其他只打印比较后一致的。 { ret = 1; - print_a_completion(p, 1); + unsigned long long clo64 = current_color_64bit; //在dir.txt中,文件夹大写,文件小写。这样打印时文件夹高亮。 + unsigned int clo = current_color; + if (*p < 0x61) + { + if (current_term->setcolorstate) + current_term->setcolorstate (COLOR_STATE_HIGHLIGHT); + current_color_64bit = (current_color_64bit & 0xffffff) | (clo64 & 0xffffff00000000); + current_color = (current_color & 0x0f) | (clo & 0xf0); + console_setcolorstate (current_color | 0x100); //设置控制台文本模式的颜色(UEFI) + } + print_a_completion(p, 1); //EXT,lt.jmp,menu.lst,unifont.hex + if (cursor_state & 1) + current_term->setcolorstate (COLOR_STATE_STANDARD); + else + current_term->setcolorstate (COLOR_STATE_NORMAL); } } } @@ -832,302 +254,1560 @@ int pxe_dir (char *dirname) return ret; } -void pxe_unload (void) +//对于tftp,如果必须读且文件指针为0,则网络读 +//从efi_pxe_buf复制len字节到buf (适用于buf/http) +unsigned long long +pxe_read (unsigned long long buf, unsigned long long len, unsigned int write) //pxe读 { - #ifdef FSYS_IPXE - if (has_ipxe) pxe_file_func[PXE_FILE_TYPE_IPXE]->unload(); -#endif - pxe_file_func[PXE_FILE_TYPE_TFTP]->unload(); -} + if (write == GRUB_WRITE) //如果写, 则错误 + return !(errnum = ERR_WRITE); + if (write == GRUB_LISTBLK) + return 0; + if (!len) + return 0; + if (only_tftp) + { + printf_warning ("The system does not support the HTTP protocol.\n"); + printf_warning ("Now enable TFTP protocol.\n"); + cur_pxe_type = 0; + } + else if (cur_pxe_type) + http_configure(); //http配置 必须每次读以前开启通道 -static int tftp_open(const char *name) -{ - PXENV_TFTP_GET_FSIZE_t *tftp_get_fsize; - tftp_close (); - if (!tftp_get_size()) return 0; - tftp_get_fsize = (void*)&pxe_tftp_open; - tftp_get_fsize->ServerIPAddress = pxe_sip; - tftp_get_fsize->GatewayIPAddress = pxe_gip; - tftp_get_fsize->FileSize = htons (TFTP_PORT); - pxe_tftp_open.PacketSize = pxe_blksize; - pxe_call (PXENV_TFTP_OPEN, &pxe_tftp_open); - - if (pxe_tftp_open.Status) - return 0; + if (pxe_need_read && (!cur_pxe_type || !http_feature)) //tftp或者http_200 + { + pxe_need_read = 0; + pxe_allocate(); //分配内存 + if (!cur_pxe_type) + tftp_read(efi_pxe_buf, filemax); + else + http_read(efi_pxe_buf, filemax); + } + else if (cur_pxe_type && http_feature) //http_206 + { +#define BUFLEN 4000 + //读尺寸大于1,直接读回数据 + if (len > 1) + { + http_read ((char *)(grub_size_t)buf, len); + goto aaa; + } + //读尺寸等于1,采用缓存 + //如果首次读 + if (buf_len == -1) + { +bbb: + //确定缓存范围长度 + if (filepos + BUFLEN > filemax) + buf_len = filemax - filepos; + else + buf_len = BUFLEN; + //确定缓存范围起始 + buf_start = filepos; + //读到缓存 + http_read ((char *)(grub_size_t)BUFFERADDR, buf_len); + //返回数据 + grub_memmove64 (buf, (unsigned long long)(grub_size_t)(char*)(BUFFERADDR), 1); + goto aaa; + } + //指针在缓存范围,返回数据 + if (filepos >= buf_start && filepos - buf_start < buf_len) + { + grub_memmove64 (buf, (unsigned long long)(grub_size_t)(char*)(BUFFERADDR + filepos - buf_start), 1); + goto aaa; + } + //如果指针不在缓存范围 + goto bbb; +#undef BUFLEN + } - pxe_blksize = pxe_tftp_open.PacketSize; - pxe_tftp_opened = 1; - return 1; + grub_memmove64 (buf, (unsigned long long)(grub_size_t)(char*)(efi_pxe_buf + filepos), len); +aaa: + filepos += len; + return len; } -static grub_u32_t tftp_get_size(void) +void pxe_close (void) //pxe关闭 grub_pxe_close (struct grub_net_card *dev __attribute__ ((unused))) { - PXENV_TFTP_GET_FSIZE_t *tftp_get_fsize; - if (pxe_tftp_opened) return 1; - tftp_get_fsize = (void*)&pxe_tftp_open; - tftp_get_fsize->ServerIPAddress = pxe_sip; - tftp_get_fsize->GatewayIPAddress = pxe_gip; - - pxe_call (PXENV_TFTP_GET_FSIZE, tftp_get_fsize); - filemax = tftp_get_fsize->FileSize; - - if (tftp_get_fsize->Status) - return 0; - - return tftp_get_fsize->FileSize; + if (pxe_opened) + { + pxe_http_type = 0; //0/1=http/https +// pxe_need_read = 0; //0/1=不用读/需要读 + } } -#if PXE_FAST_READ - -/* Read num packets , BUF must be segment aligned */ -static grub_u32_t tftp_read_blk (grub_u32_t buf, grub_u32_t num) +void pxe_unload (void) //pxe卸载 { - PXENV_TFTP_READ_t tftp_read; - unsigned long ofs; - - tftp_read.Buffer = SEGOFS(buf); - ofs = tftp_read.Buffer & 0xFFFF; - pxe_fast_read (&tftp_read, num); - - /* disk cache destroyed, so invalidate it. */ - buf_drive = -1; - buf_track = -1; - return (tftp_read.Status) ? PXE_ERR_LEN : ((tftp_read.Buffer & 0xFFFF) - ofs); } -#else - -static grub_u32_t tftp_read_blk (grub_u32_t buf, grub_u32_t num) +//如果是map操作,则分配页,不考虑释放 +//如果是其他操作,释放缓存,然后分配池 +//池清零 +int pxe_allocate(void) //分配内存 { - PXENV_TFTP_READ_t tftp_read; - unsigned long ofs; + grub_efi_status_t status; + grub_efi_boot_services_t *b; //引导服务 + b = grub_efi_system_table->boot_services; //系统表->引导服务 + unsigned long long bytes_needed; - /* disk cache will be destroyed, so invalidate it. */ - buf_drive = -1; - buf_track = -1; + if ((*(char *)IMG(0x8205) & 0x80)) //如果8205位7置1,pxe_open不要分配内存,使用efi_pxe_buf即可。 + return 1; - tftp_read.Buffer = SEGOFS(buf); - ofs = tftp_read.Buffer & 0xFFFF; - while (num > 0) + if (map_pd) //不释放内存 + { + bytes_needed = ((filemax+4095)&(-4096ULL)); + status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES, + GRUB_EFI_RESERVED_MEMORY_TYPE, //保留内存类型 0 + (grub_efi_uintn_t)bytes_needed >> 12, (unsigned long long *)(grub_size_t)&efi_pxe_buf); //调用(分配页面,分配类型->任意页面,存储类型->运行时服务数据(6),分配页,地址) + if (status != GRUB_EFI_SUCCESS) //如果失败 { - pxe_call (PXENV_TFTP_READ, &tftp_read); - if (tftp_read.Status) - return PXE_ERR_LEN; - tftp_read.Buffer += tftp_read.BufferSize; - if (tftp_read.BufferSize < pxe_blksize) - break; - num--; + printf_errinfo ("out of map memory: %d\n",(int)status); + errnum = ERR_WONT_FIT; + return 0; } - return (tftp_read.Buffer & 0xFFFF) - ofs; -} -#endif - -static void tftp_close (void) -{ - PXENV_TFTP_CLOSE_t tftp_file_close; - pxe_call (PXENV_TFTP_CLOSE, &tftp_file_close); -} - -static void tftp_unload(void) + } + else + { + if (efi_pxe_buf) + efi_call_1 (b->free_pool, efi_pxe_buf); //调用(释放池,释放数据) + status = efi_call_3 (b->allocate_pool, GRUB_EFI_BOOT_SERVICES_DATA, //启动服务数据 4 + filemax, (void **)(grub_size_t)&efi_pxe_buf); //(分配池,存储器类型->装载数据,分配字节,返回分配地址} + if (status != GRUB_EFI_SUCCESS) //失败 + { + printf_errinfo ("Couldn't allocate pool."); + return !(errnum = 0x1234); + } + } + + memset(efi_pxe_buf,0,filemax); //2023-11-24 + return 1; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//返回filemax, filepos置0 +static int tftp_open(void) //tftp打开 { - PXENV_UNLOAD_STACK_t unload; - unsigned char code[] = {PXENV_UNDI_SHUTDOWN, PXENV_UNLOAD_STACK, PXENV_STOP_UNDI, 0}; - int i, h; + grub_efi_status_t status; - if (! pxe_entry) - return; + //将 UTF-8 转为 GBK 编码 +/* +1. 在 mtftp 中,文件名使用 ansi 编码。 +2. 在 mtftp 中,中文使用 gbk 码。 +3. 在 mtftp 中,空格可以直接使用,无需转换。 +*/ + grub_size_t len = grub_strlen (pxe_name); + utf8_to_multimode ((void *)pxe_name, (unsigned char *)pxe_name, len, 0); + + status = efi_call_10 (pxe_entry->mtftp, //tftp功能 + pxe_entry, //pxe结构 + GRUB_EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE, //TFTP获得文件尺寸 + NULL, //缓存 + 0, + (grub_efi_uint64_t *)(grub_size_t)&filemax, //缓存尺寸 + NULL, //块尺寸 + (grub_u32_t *)(grub_size_t)&pxe_sip, //服务器IP + pxe_name, //文件名 + NULL, + 0); + if (status != GRUB_EFI_SUCCESS) //失败 + { + printf_errinfo ("Couldn't get file size. %d\n",(unsigned int)status); + return 0; + } - pxe_close (); + return 1; +} - if (pxe_keep) - return; +//读filemax字节尺寸到buf +static unsigned long long +tftp_read (char *buf, grub_u64_t len) //efi读 +{ + grub_efi_status_t status; + printf ("Copy data from the network via TFTP, please wait......\r"); + status = efi_call_10 (pxe_entry->mtftp, //tftp功能 + pxe_entry, //pxe结构 + GRUB_EFI_PXE_BASE_CODE_TFTP_READ_FILE, //TFTP读文件 + buf, //缓存 + 0, + (grub_efi_uint64_t *)(grub_size_t)&len,//缓存尺寸 + NULL, //块尺寸 + (grub_u32_t *)(grub_size_t)&pxe_sip, //服务器IP + pxe_name, //文件名 + NULL, + 0); + if (status != GRUB_EFI_SUCCESS) //失败 + { + printf_errinfo ("Couldn't read file."); + return 0; + } + + return len; +} + +//写filemax字节尺寸从efi_pxe_buf +int tftp_write (const char *name) //tftp写 2023-11-24 +{ + grub_efi_status_t status; + + status = efi_call_10 (pxe_entry->mtftp, //tftp功能 + pxe_entry, //pxe结构 + GRUB_EFI_PXE_BASE_CODE_TFTP_WRITE_FILE, //TFTP写文件 + (char *)efi_pxe_buf, //缓存 + 1, //可以覆盖服务器上的文件 + (grub_efi_uint64_t *)(grub_size_t)&filemax,//缓存尺寸 + NULL, //块尺寸 + (grub_u32_t *)(grub_size_t)&pxe_sip, //服务器IP + (char *)name, //文件名 + NULL, + 0); + if (status != GRUB_EFI_SUCCESS) //失败 + { + printf_errinfo ("Couldn't write file."); + return !(errnum = 0x1234); + } + + return 1; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//net/efi/http.c +#define GRUB_MAX_UTF16_PER_UTF8 1 +#define GRUB_EFI_IP6_PREFIX_LENGTH 64 +int prefer_ip6; +static grub_efi_boolean_t request_callback_done; +static grub_efi_boolean_t response_callback_done; + +static void +grub_efi_http_request_callback (grub_efi_event_t event __attribute__ ((unused)), + void *context __attribute__ ((unused))) //请求回调 +{ + request_callback_done = 1; +} + +static void +grub_efi_http_response_callback (grub_efi_event_t event __attribute__ ((unused)), + void *context __attribute__ ((unused))) //响应回调 +{ + response_callback_done = 1; +} + +/* +响应/请求的结构,不能放在http_read内。即只能放在堆,不能放在栈。 +如果放在http_read内,随机发生错误: +1. 不返回响应。response_callback_done始终为零,response_token.status始终为6。 +2. 此时,response_message.body_length > len (正常为1460)。 +3. 不知何故,在‘while (len)’循环内,每次循环开始,响应结构都会重置: + 起始:response_message.body_length = e62e19e + ‘response_message.body_length = len;’后, response_message.body_length = 934f4 + ‘status = efi_call_2 (http->response, http, &response_token);’后,response_message.body_length = 958ee + 循环一阕返回‘while (len)’起始,response_message.body_length = e62e19e +*/ +static grub_efi_http_message_t response_message; //响应消息 +static grub_efi_http_response_data_t response_data; //响应数据 +static grub_efi_http_token_t response_token; //响应令牌 +static grub_efi_http_message_t request_message; //请求消息 +static grub_efi_http_request_data_t request_data; //请求数据 +static grub_efi_http_token_t request_token; //请求令牌 + +static grub_err_t +efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https, int headeronly, char *range) //http请求 +{ + grub_efi_http_header_t request_headers[4]; + grub_efi_status_t status; + grub_efi_boot_services_t *b = grub_efi_system_table->boot_services; + char *url = grub_malloc (128); + read_status = 200; //不支持断点续传 + + //请求标头 + request_headers[0].field_name = (grub_efi_char8_t *)"Host"; //请求标头.字段名称 主机,服务机 + request_headers[0].field_value = (grub_efi_char8_t *)default_server; //请求标头.字段值 "192.168.114.1" + request_headers[1].field_name = (grub_efi_char8_t *)"Accept"; //请求标头.字段名称 接受 + request_headers[1].field_value = (grub_efi_char8_t *)"*/*"; //请求标头.字段值 + request_headers[2].field_name = (grub_efi_char8_t *)"User-Agent"; //请求标头.字段名称 用户代理 + request_headers[2].field_value = (grub_efi_char8_t *)"UefiHttpBoot/1.1"; //请求标头.字段值 + request_headers[3].field_name = (grub_efi_char8_t *)""; //请求标头.字段名称 连接 + request_headers[3].field_value = (grub_efi_char8_t *)""; //请求标头.字段值 状态 + request_headers[3].field_name = (grub_efi_char8_t *)"Range"; //请求标头.字段名称 范围 + request_headers[3].field_value = (grub_efi_char8_t *)range; //请求标头.字段值 字节范围 + + grub_efi_char16_t *ucs2_url; //ucs2网址 + grub_size_t url_len, ucs2_url_len; //网址尺寸, ucs2网址尺寸 + + if (is_ip6) //是ip6 + grub_sprintf (url, "%s://[%s]%s", "http", default_server, pxe_name); //协议,服务器,名称 + else //ip4地址 + grub_sprintf (url, "%s://%s%s", "http", default_server, pxe_name); + + url_len = grub_strlen (url); //网址尺寸 + ucs2_url_len = url_len + url_len/2; //ucs2网址尺寸 + ucs2_url = grub_zalloc ((ucs2_url_len + 1) * 2); + if (!ucs2_url) + { + grub_free (url); + return 1; + } - h = unset_int13_handler (1); /* check if it was set. */ - if (! h) /* h==0 for set */ - unset_int13_handler (0); /* unset it */ + //将 UTF-8 转为 URL 编码 + ucs2_url_len = utf8_to_multimode ((void *)ucs2_url, (unsigned char *)url, url_len, 2); //2024-12-30 + grub_free (url); + ucs2_url[ucs2_url_len] = 0; //结束符 + request_data.url = ucs2_url; //请求信息.url +/* +空格探测 + /ifu+352.iso +2f 00 69 00 66 00 75 00 - 2b 00 33 00 35 00 32 00 +2e 00 69 00 73 00 6f 00 - 00 00 服务器:/ifu 352.iso http状态码:35(内部服务器错误) + /ifu\+352.iso +2f 00 69 00 66 00 75 00 - 5c 00 2b 00 33 00 35 00 +32 00 2e 00 69 00 73 00 - 6f 00 00 00 服务器:/ifu/ 352.iso http状态码:35(内部服务器错误) + /ifu%'2''0'352.iso +2f 00 69 00 66 00 75 00 - 25 00 32 00 30 00 33 00 +35 00 32 00 2e 00 69 00 - 73 00 6f 00 00 00 服务器:/ifu 352.iso http状态码:3(ok) + +中文探测 +gbk /ab中国cd.iso 服务器没有请求文件 +2f 61 62 d6 d0 b9 fa 63 - 64 2e 69 73 6f 00 +utf16 /ab中国cd.iso /ab-齝d.iso +2f 00 61 00 62 00 2d 4e - fd 56 63 00 64 00 2e 00 +69 00 73 00 6f 00 00 00 +gbk->utf8_to_multimode(2) /ab中国cd.iso ok! +61 00 62 00 d6 00 d0 00 - b9 00 fa 00 63 00 +64 00 2e 00 69 00 73 00 - 6f 00 00 00 +结论: +1. linux的url采用utf16方法表示。 +2. url中中文使用gbk码,一般使用两字节表示。在url里,中文的两字节要分别放在两个utf16中。 +3. 空格使用 %20 表示。即 25 00 32 00 30 00 +*/ + //请求数据.方法 + request_data.method = (headeronly > 0) ? GRUB_EFI_HTTPMETHODHEAD : GRUB_EFI_HTTPMETHODGET; //头朝前?头:获得 + //请求信息 + request_message.data.request = &request_data; //请求信息.数据请求 + request_message.headers = request_headers; //请求信息.标头 + request_message.body_length = 0; //请求信息.体尺寸 + request_message.body = NULL; //请求信息.体 + //请求令牌 + request_token.event = NULL; //请求令牌.事件 + request_token.status = GRUB_EFI_NOT_READY; //请求令牌.状态 未准备好 + request_token.message = &request_message; //请求令牌.消息 + + request_callback_done = 0; //请求回调完成=0 + status = efi_call_5 (b->create_event, //创建事件 + GRUB_EFI_EVT_NOTIFY_SIGNAL, //事件的类型 通知信号 +//使用GRUB_EFI_TPL_CALLBACK(回调)优先级别时,执行b->connect_controller、b->load_image、b->start_image时,回调函数不执行 +// GRUB_EFI_TPL_CALLBACK, //事件的优先级 回调 + GRUB_EFI_TPL_NOTIFY, //事件的优先级 通知 + grub_efi_http_request_callback, //事件处理函数 请求回调 + NULL, //传递给事件处理函数的参数 + &request_token.event); + if (status != GRUB_EFI_SUCCESS) //失败 + { + grub_free (request_data.url); + printf_errinfo ("Fail to create an event status=%x\n", status); + return 1; + } - /* at this moment, there should be no other handlers. - * if other handlers do exist, we should quit. - */ - if (*((unsigned short *)0x413) != pxe_basemem) + status = efi_call_2 (http->request, http, &request_token); //请求 有时莫名其妙地死在这里,必须重新启动虚拟机!!!! + if (status != GRUB_EFI_SUCCESS) //失败 + { + efi_call_1 (b->close_event, request_token.event); //关闭事件 + grub_free (request_data.url); + printf_errinfo ("Fail to send a request status=%x\n", status); //12超时 f拒绝访问 + return 1; + } + /* TODO: Add Timeout */ + int qqq = 0; + while (!request_callback_done) //等待请求回调完成 + { + efi_call_1(http->poll, http); //获得 + qqq++; + if (qqq >= 0xff) + { + printf_debug ("request_poll,%x\n",qqq); + break; + } + } + //响应数据 + response_data.status_code = GRUB_EFI_HTTP_STATUS_UNSUPPORTED_STATUS; //响应数据.状态代码 0=不受支持的状态 + //响应消息 + response_message.data.response = &response_data; //响应数据.数据响应 + //herader_count将由HTTP驱动程序在响应时更新 + response_message.header_count = 0; //响应数据.标头计数 + //标头将由驱动程序在响应时填充 + response_message.headers = NULL; //响应数据.标头 + //使用零BodyLength仅接收响应标头 + response_message.body_length = 0; //响应数据.体尺寸 + response_message.body = NULL; //响应数据.体 + //响应令牌.事件 + response_token.event = NULL; + + status = efi_call_5 (b->create_event, //创建事件 + GRUB_EFI_EVT_NOTIFY_SIGNAL, //事件的类型 通知信号 +// GRUB_EFI_TPL_CALLBACK, //事件的优先级 回调 + GRUB_EFI_TPL_NOTIFY, //事件的优先级 通知 + grub_efi_http_response_callback, //事件处理函数 响应回调 + NULL, //传递给事件处理函数的参数 + &response_token.event); + if (status != GRUB_EFI_SUCCESS) { - grub_printf ("PXE unload failed because of an unknown handler(e.g., of int13) loaded.\n"); - goto quit; + efi_call_1 (b->close_event, request_token.event); //关闭事件 + grub_free (request_data.url); + printf_errinfo ("Fail to create an event\n status=%x\n", status); + return 1; + } + //响应令牌 + response_token.status = GRUB_EFI_SUCCESS; //响应令牌.状态 成功 + response_token.message = &response_message; //响应令牌.消息 + + //等待HTTP响应 + response_callback_done = 0; //响应回调完成=0 + status = efi_call_2 (http->response, http, &response_token); //响应 + if (status != GRUB_EFI_SUCCESS) + { + efi_call_1 (b->close_event, response_token.event); //关闭事件 + efi_call_1 (b->close_event, request_token.event); //关闭事件 + grub_free (request_data.url); + printf_errinfo ("Fail to receive a response! status=%x\n", status); //12超时 + return 1; } - i = 0; - while (code[i]) + /* TODO: Add Timeout */ + qqq = 0; + while (!response_callback_done) //等待响应回调完成 + { + efi_call_1 (http->poll, http); //获得 + qqq++; + if (qqq >= 0xff) { - grub_memset (&unload, 0, sizeof(unload)); - pxe_call (code[i], &unload); - if (unload.Status) - { - grub_printf ("PXE unload fails: %d\n", unload.Status); - goto quit; - } - i++; + printf_debug ("response_poll,%x\n",qqq); + break; } - //if (*((unsigned short *)0x413) == pxe_basemem) - *((unsigned short *)0x413) = pxe_freemem; - pxe_entry = 0; - ROM_int15 = *((unsigned long *)0x54); - ROM_int13 = ROM_int13_dup = *((unsigned long *)0x4C); - grub_printf ("PXE stack unloaded\n"); -quit: - if (! h) /* h==0 for set */ - set_int13_handler (bios_drive_map); -} + } -#endif + //返回部分内容,是我们请求了范围,不是错误 + if (response_message.data.response->status_code == GRUB_EFI_HTTP_STATUS_206_PARTIAL_CONTENT) + { + read_status = 206; //支持断点续传 + goto aaa; + } -static void print_ip (IP4 ip) -{ - int i; + if (response_message.data.response->status_code != GRUB_EFI_HTTP_STATUS_200_OK) + { + grub_efi_http_status_code_t status_code = response_message.data.response->status_code; + + if (response_message.headers) + efi_call_1 (b->free_pool, response_message.headers); + efi_call_1 (b->close_event, response_token.event); //关闭事件 + efi_call_1 (b->close_event, request_token.event); //关闭事件 + grub_free (request_data.url); + if (status_code == GRUB_EFI_HTTP_STATUS_404_NOT_FOUND) //未找到 + printf_errinfo ("404: file `%s' not found\n", pxe_name); + else if (status_code == GRUB_EFI_HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED) //范围不满足要求 + printf_errinfo ("416: The scope does not meet the requirements\n"); + else + printf_errinfo ("unsupported uefi http status code %d\n", status_code); //不支持的uefi http + + return 1; + } - for (i = 0; i < 3; i++) +aaa:; + int i; + //从ContentLength标头解析文件的长度 + for (i = 0; i < (int)response_message.header_count; ++i) + { +//Connection close 连接: 关闭 +//Content-Type application/octet-stream 内容类型: 应用程序/八位字节流 +//Content-Length 6637568 内容尺寸: 6637568(ASCII码) +//Server Indy/9.00.10 服务器: Indy/9.00.10 +//Range 0-1023 范围: 0-1023字节 +//Last-Modified Thu, 30 Jun 2022 08:53:38 GMT 最后修改时间: Thu, 30 Jun 2022 08:53:38 GMT + if (!grub_strcmp((const char*)response_message.headers[i].field_name, "Content-Length")) { - grub_printf ("%d.", (unsigned long)(unsigned char)ip); - ip >>= 8; + safe_parse_maxint ((char**)&response_message.headers[i].field_value, &hex); + if (read_status == 200) + filemax = hex; + filesize = hex; } - grub_printf ("%d", (unsigned long)(unsigned char)ip); + else if (!grub_strcmp((const char*)response_message.headers[i].field_name, "Content-Range")) + { + char *value = (char *)response_message.headers[i].field_value; + while (*value != '/') + value++; + value++; + safe_parse_maxint (&value, &filemax); + } + } + + if (response_message.headers) + efi_call_1 (b->free_pool, response_message.headers); + efi_call_1 (b->close_event, response_token.event); //关闭事件 + efi_call_1 (b->close_event, request_token.event); //关闭事件 + grub_free (request_data.url); + + if (!filemax) //很不幸,dhcpsrv2.5.2自带的http服务(dhcpsrv),执行HEAD操作,返回filemax=0! + { + char tmp[4] = {0}; + char range0[16] = {0}; + http_range = range0; + grub_sprintf (range0, "bytes=1-1"); + http_read (tmp, 1); + http_range = 0; + } + return GRUB_ERR_NONE; } -int pxe_func (char *arg, int flags) +//返回filemax, filepos置0 +//读filemax字节尺寸到efi_pxe_buf +static int http_open(void) //http打开 { - if (! pxe_entry) + int err; + printf_debug ("http_open,%s\n",pxe_name); + request_message.header_count = 3; //请求信息.标头计数 + err = efihttp_request (net_devices->http, (char *)default_server, (char *)pxe_name, 0, 1, 0); //请求头部,返回尺寸 + if (err) + return 0; + +// printf_debug ("filemax=%x\n",filemax); + return 1; +} + +//读len字节尺寸到buf +static unsigned long long +http_read (char *buf, grub_u64_t len) //efi读 +{ + grub_efi_status_t status; //状态 + grub_size_t sum = 0, sum1 = 0; //和 + grub_efi_boot_services_t *b = grub_efi_system_table->boot_services; //引导服务 + grub_efi_http_t *http = net_devices->http; //http入口 + grub_u64_t back_len = len; + char *back_buf = buf; + char r[32]; + char *range = r; + int err; +#if 0 + //用于响应回调函数不执行的情况 + grub_u64_t range_len = len; +#endif + grub_u64_t range_end = filepos+len-1; //len在下面的循环中会改变 + +// printf_debug ("http_read: %x, %x, %x\n",buf,len,filepos); + if (!len) //尺寸为零 + { + printf_errinfo ("Invalid arguments to EFI HTTP Read\n"); //EFI HTTP读取的参数无效 + return 0; + } + + request_message.header_count = 4; //请求信息.标头计数 + if (!http_range) + { + if (!http_feature) + grub_sprintf (range, "bytes=0-"); + else + grub_sprintf (range, "bytes=%d-%d",filepos, range_end); + } + else + range = http_range; + + if (!http_feature) + printf ("Copy data from the network via HTTP, please wait......\r"); + +repeat: +// printf_debug ("read_range: %s; read_len: %x\n",r,len); + + err = efihttp_request (net_devices->http, (char *)default_server, (char *)pxe_name, 0, 0, range); //请求获得 + if (err) + return 0; + +/* +1.如果客户端读尺寸不等于服务器写尺寸,会搞乱通讯指针。使得下一次读取错误。 + len不能大于filesize。在这里判断及纠正。 +2.len也不能小于filesize,在调用http_read或者pxe_read前,需获得filemax。 +*/ + if (len > filesize) //len是客户端读尺寸,filesize是服务器写尺寸。 + len = filesize; +#if 0 + if (http_feature) + printf_debug ("206: "); + else + printf_debug ("200: "); + printf_debug ("filesize=%x, filemax=%x, len=%x\n",filesize,filemax,len); +#endif + response_token.event = NULL; //增加 + status = efi_call_5 (b->create_event, //创建事件 + GRUB_EFI_EVT_NOTIFY_SIGNAL, //事件的类型 通知信号 +// GRUB_EFI_TPL_CALLBACK, //事件的优先级 回调 + GRUB_EFI_TPL_NOTIFY, //事件的优先级 通知 + grub_efi_http_response_callback, //事件处理函数 响应回调 + NULL, //传递给事件处理函数的参数 + &response_token.event); //创建的事件 + if (status != GRUB_EFI_SUCCESS) //失败 + { + printf_errinfo ("Fail to create an event_response, status=%x\n", status); + return 0; + } + +// efi_call_1 (grub_efi_system_table->boot_services->stall, 10000); //延时10毫秒 + while ((long long)len > 0) + { + //响应消息 + response_message.data.response = NULL; //响应消息.数据.响应 + response_message.header_count = 0; //响应消息.标头计数 + response_message.headers = NULL; //响应消息.标头 +#if 0 + //用于响应回调函数不执行的情况 + response_message.body_length = range_len; //响应消息.体长 设置为654800,他实际读5b4, +#else + response_message.body_length = len; //响应消息.体长 +#endif + response_message.body = (void *)(grub_size_t)buf; //响应消息.体 + + //响应令牌 + response_token.message = &response_message; //响应令牌.消息 + response_token.status = GRUB_EFI_NOT_READY; //响应令牌.状态 还没准备好 + response_callback_done = 0; //响应回调已完成=0 + + status = efi_call_2 (http->response, http, &response_token); //响应 + if (status != GRUB_EFI_SUCCESS) //失败 { - //grub_printf ("No PXE stack\n"); - goto bad_argument; + printf_warning ("Fail to http->response! status=%x,len=%x,sum=%x\n", (int)status,len,sum); //f 拒绝访问; 68 通信对等体已关闭连接,并且实例的接收缓冲区中没有更多数据。 +//printf ("111,%d,%d,%d\n",response_message.body_length,len,sum); +//68,1b1800; f,d69eab5; +//1b1800,4a3000,654800; d69eab5,55af024,12c4dad9 +//68,1be +//491,491,21 + if (status == GRUB_EFI_CONNECTION_FIN) + { + efi_call_1 (b->close_event, response_token.event); //关闭事件 + efi_call_2 (http->cancel, http, NULL); + errnum = 0; + if (http_feature) //支持断点续传 + { + //不采用"bytes=%d-",是为了照顾TinyPXEServer-1.0.0.23自带http服务(Indy/9.00.10) +// grub_sprintf (r, "bytes=%d-%d", sum, sum + len - 1); + grub_sprintf (r, "bytes=%d-%d", filepos + sum, range_end); //不考虑http_range存在的情况 + } + else + { + buf = back_buf; + len = back_len; + grub_sprintf (r, "bytes=0-"); + } + + if (debug > 1) + getkey(); + http_configure(); //配置网络接口 + goto repeat; + } + if (status == GRUB_EFI_ACCESS_DENIED) + printf_errinfo ("The host has closed the TCP connection.\n"); + + return 0; } - if (*arg == 0) +// efi_call_1 (grub_efi_system_table->boot_services->stall, 1); //延时1微妙 必要 + + int qqq = 0; + grub_u64_t first = 0; + while (!response_callback_done) { - char buf[4], *pc; - int i; - - pxe_tftp_name[0] = '/'; - pxe_tftp_name[1] = 0; - grub_printf ("blksize: %d [%s]\n", pxe_blksize,def_pxe_type==1?"iPXE":"pxe"); - grub_printf ("basedir: %s\n",pxe_tftp_open.FileName); - grub_printf ("bootfile: %s\n", discover_reply->bootfile); - grub_printf ("client ip : "); - print_ip (pxe_yip); - grub_printf ("\nserver ip : "); - print_ip (pxe_sip); - grub_printf ("\ngateway ip : "); - print_ip (pxe_gip); - grub_printf ("\nmac : "); - for (i = 0; i < pxe_mac_len; i++) + efi_call_1(http->poll, http); //获得 + qqq++; +#if 0 + //以下用于响应回调函数不执行的情况 + if (qqq == 1) + { + if (response_message.body_length != filesize) + break; + first = response_message.body_length; + } + else if (qqq < 0xfff) + { + if (response_message.body_length != first) + { + printf_debug ("read_poll,%x,%x,%x\n",qqq,response_message.body_length,first); + //257,5d4,800; 4,5d4,1000; vm + break; + } + } + else +#endif + if (qqq >= 0xfff) + { + printf_debug ("read_poll,%x,%x,%x,%x,%x,%x,%x\n",qqq,filepos,response_message.body_length,len,filesize,first,sum); +//fff,2abe000,100000,d8000,100000,100000,2800; qemu +//fff,0,800,800,800,800,0; fff,8000,800,800,800,800,0; vm +//1a800,20000,9da0,20000,20000,16260 +//3a800,20000,9da0,20000,20000,16260 +//5a800,20000,9da0,20000,20000,16260 +//7a800,20000,9da0,20000,20000,16260 +//9a800,20000,9da0,20000,20000,16260 +//0,800,800,800,800,0 + efi_call_1 (b->close_event, response_token.event); //关闭事件 + efi_call_2 (http->cancel, http, NULL); + errnum = 0; + if (http_feature) //支持断点续传 + { + //不采用"bytes=%d-",是为了照顾TinyPXEServer-1.0.0.23自带http服务(Indy/9.00.10) + grub_sprintf (r, "bytes=%d-%d", filepos + sum, range_end); + } + else { - pc = buf; - pc = pxe_outhex (pc, pxe_mac[i]); - *pc = 0; - grub_printf ("%s%c", buf, ((i == pxe_mac_len - 1) ? '\n' : '-')); + buf = back_buf; + len = back_len; + grub_sprintf (r, "bytes=0-"); } + + if (debug > 1) + getkey(); + http_configure(); //配置网络接口 + goto repeat; + } } - else if (grub_memcmp(arg, "blksize", sizeof("blksize") - 1) == 0) + +#if 0 + //用于响应回调函数不执行的情况 + //修正下一次参数 + if (response_message.body_length > len) + response_message.body_length = len; +#endif + sum += response_message.body_length; //和 + len -= response_message.body_length; //剩余尺寸 + buf += response_message.body_length; //缓存 + + sum1 += response_message.body_length; //打印计数 + if (sum1 >= 0x800000) // 8MB打印一次 { - unsigned long long val; - grub_u32_t force=arg[7] != '='; - arg = skip_to (1, arg); - if (! safe_parse_maxint (&arg, &val)) - return 0; - if (val > PXE_MAX_BLKSIZE) - val = PXE_MAX_BLKSIZE; - if (val < PXE_MIN_BLKSIZE) - val = PXE_MIN_BLKSIZE; - pxe_blksize = val; - if (!force) try_blksize(val); + grub_printf("[%ldM/%ldM]\r",sum>>20,back_len>>20); //不能使用filesize,在读失败调整后跳转到repeat时,filesize值会变小。 + sum1 -= 0x800000; } - else if (grub_memcmp (arg, "basedir", sizeof("basedir") - 1) == 0) + +/* 使用qemu虚拟机,启动ifu352.iso,可以产生"Fail to http->response!68",用于测试断点续传。// + if (debug == 0) + printf ("000,%x,%x,%x\n",response_message.body_length,len,sum); +5a0,1b2625,4a21db +b40,1b1ae5,4a2d1b +2e5,1b1800,4a3000 + +5a0,b40,10e0, zemu +5b4, vm + +read_poll,f,5a0,654800; +1440,6479397,158171; +read_poll,fff,0,654800,62de25,654800,654800,269db; +6637568,-158171,6795739; +*/ + } + +// efi_call_1 (grub_efi_system_table->boot_services->stall, 10000); //延时10毫秒 必需,否则只能持续读3个文件 + efi_call_1 (b->close_event, response_token.event); //关闭事件 + return sum; //返回读尺寸 +} + +static void +http_configure (void) //http配置 +{ + grub_efi_http_config_data_t http_config; //HTTP配置数据 + grub_efi_httpv4_access_point_t httpv4_node; //HTTPv4访问点 +// grub_efi_httpv6_access_point_t httpv6_node; //HTTPv6访问点 + grub_efi_status_t status; + grub_efi_http_t *http = net_devices->http; //HTTP入口 + + grub_memset (&http_config, 0, sizeof(http_config)); //初始化HTTP配置数据 + http_config.http_version = GRUB_EFI_HTTPVERSION11; //HTTP配置数据.版本=11 + http_config.timeout_millisec = 5000; //HTTP配置数据.超时=5000毫秒 +#if 0 + if (prefer_ip6) //如果首选ip6 + { + grub_efi_uintn_t sz; + grub_efi_ip6_config_manual_address_t manual_address;//ip6配置手动地址 + + http_config.local_address_is_ipv6 = 1; //HTTP配置数据.本地地址是ipv6 = 0 + sz = sizeof (manual_address); //ip6配置手动地址尺寸 + status = efi_call_4 (net_devices->ip6_config->get_data, net_devices->ip6_config, + GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS, + &sz, &manual_address); //ip6配置获得手动地址 + + if (status == GRUB_EFI_NOT_FOUND) { - arg = skip_to (0, arg); - if (*arg == 0) - { - grub_printf ("No pathname\n"); - goto bad_argument; - } - set_basedir(arg); + printf_errinfo ("The MANUAL ADDRESS is not found\n"); + errnum = 0x1234; + return ; } - else if (grub_memcmp (arg, "keep", sizeof("keep") - 1) == 0) - pxe_keep = 1; - else if (grub_memcmp (arg, "nokeep", sizeof("nokeep") - 1) == 0) - pxe_keep = 0; - else if (grub_memcmp (arg, "unload", sizeof("unload") - 1) == 0) + + //手动界面将返回缓冲区太小!!! + if (status != GRUB_EFI_SUCCESS) { - pxe_keep = 0; - pxe_unload (); + printf_errinfo ("??? %d\n",(int) status); + errnum = 0x1234; + return; } -#ifdef PXE_DEBUG - else if (grub_memcmp (arg, "dump", sizeof("dump") - 1) == 0) + + grub_memcpy (httpv6_node.local_address, manual_address.address, sizeof (httpv6_node.local_address)); + httpv6_node.local_port = 0; + http_config.access_point.ipv6_node = &httpv6_node; + } + else //是ip4 +#endif + { + http_config.local_address_is_ipv6 = 0; //HTTP配置数据.本地地址是ipv6 = 0 + grub_memset (&httpv4_node, 0, sizeof(httpv4_node)); //HTTPv4访问点初始化 + httpv4_node.use_default_address = 1; //HTTPv4访问点. + + //在此处使用随机端口 + //请参阅edk2/NetworkPkg/TcpDxe/TcpDispatcher中的TcpBind().c + httpv4_node.local_port = 0; + http_config.access_point.ipv4_node = &httpv4_node; + } + status = efi_call_2 (http->configure, http, NULL); //停止 +// efi_call_1 (grub_efi_system_table->boot_services->stall, 10); //延时10微秒 非必需 +#if 0 + //设置手动地址 + grub_efi_net_ip_manual_address_t net_ip; + grub_efi_ip4_config2_manual_address_t *address = &net_ip.ip4; + *(int*)net_ip.ip4.address = station_ip; + *(int*)net_ip.ip4.subnet_mask = subnet_mask; + net_ip.is_ip6 = 0; + + status = efi_call_4 (net_devices->ip4_config->set_data, net_devices->ip4_config, + GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS, //手动地址 + sizeof(*address), address); + printf_debug ("status=%x\n",status); + if (status != GRUB_EFI_SUCCESS) + return; +#endif + status = efi_call_2 (http->configure, http, &http_config); //配置 +// efi_call_1 (grub_efi_system_table->boot_services->stall, 10); //延时10微秒 非必需 + if (status != GRUB_EFI_SUCCESS) + { + printf_errinfo ("couldn't configure http protocol, reason: %d\n", (int)status); + errnum = 0x1234; + return; + } +} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//net/efi/pxe.c +static void +pxe_configure (void) //pxe配置 +{ +// grub_efi_pxe_t *pxe = (is_ip6) ? net_devices->ip6_pxe : net_devices->ip4_pxe; //首选ip6,则选择ip6_pxe,否则选择ip4_pxe + grub_efi_pxe_t *pxe = pxe_entry; + grub_efi_pxe_mode_t *mode = pxe->mode; + + if (!mode->started) //如果未启动 + { + grub_efi_status_t status; + status = efi_call_2 (pxe->start, pxe, is_ip6); //启动 + if (status != GRUB_EFI_SUCCESS) //失败 + printf_debug ("Couldn't start PXE\n"); //无法启动PXE + } + //PXE指针 PXE状态 0/1/2=停止/已启动/已初始化 PXE使用ipv4/ipv6=0/1 + printf_debug ("pxe: %x pxe started: %u net started: %u\n", pxe,mode->started,net0->mode->state); +#if 0 + if (mode->using_ipv6) //如果使用ipv6 + { + grub_efi_ip6_config_manual_address_t *manual_address; + manual_address = efi_ip6_config_manual_address (net_devices->ip6_config); //获得ip6配置手动地址 + printf_debug ("ip6_manual_address=%x\n", manual_address); + + if (manual_address && + grub_memcmp ((const char *)manual_address->address, (const char *)mode->station_ip.v6, sizeof (manual_address->address)) != 0) //复制站ipv6作为手动地址成功 { - PXENV_GET_CACHED_INFO_t get_cached_info; - BOOTPLAYER *bp; - unsigned long long val; + grub_efi_status_t status; + grub_efi_pxe_ip_address_t station_ip; - arg = skip_to (0, arg); - if (! safe_parse_maxint (&arg, &val)) - return 0; - if ((val < 1) || (val > 3)) - { - grub_printf ("Invalid type\n"); - goto bad_argument; - } - get_cached_info.PacketType = val; - get_cached_info.Buffer = get_cached_info.BufferSize = 0; - pxe_call (PXENV_GET_CACHED_INFO, &get_cached_info); - if (get_cached_info.Status) - return 0; - bp = LINEAR(get_cached_info.Buffer); + grub_memcpy (station_ip.v6.addr, manual_address->address, sizeof (station_ip.v6.addr)); + status = efi_call_3 (pxe->set_station_ip, pxe, (grub_u32_t *)(grub_size_t)&station_ip, NULL); //设置站ip + + if (status != GRUB_EFI_SUCCESS) + printf_debug ("Couldn't set station ip\n"); + + grub_free (manual_address); + } + } + else + { + grub_efi_ip4_config2_manual_address_t *manual_address; + manual_address = efi_ip4_config_manual_address (net_devices->ip4_config); //获得配置ip4地址 + printf_debug ("ip4_manual_address=%x\n", manual_address); + printf_debug ("mode->station_ip.v4=%x,%x\n", mode->station_ip.v4,*(int*)mode->station_ip.v4); + printf_debug ("manual_address->address=%x,%x,%x,%x\n", manual_address->address,*(int*)manual_address->address,mode->station_ip.v4,*(int*)mode->station_ip.v4); + printf_debug ("manual_address->subnet_mask=%x,%x,%x,%x\n", manual_address->subnet_mask,*(int*)manual_address->subnet_mask,mode->subnet_mask.v4,*(int*)mode->subnet_mask.v4); + if (manual_address && + grub_memcmp ((const char *)manual_address->address, (const char *)mode->station_ip.v4, sizeof (manual_address->address)) != 0) //比较站ip,不同则复制 + { + grub_efi_status_t status; + grub_efi_pxe_ip_address_t station_ip0; + grub_efi_pxe_ip_address_t subnet_mask0; + + grub_memcpy (station_ip0.v4.addr, manual_address->address, sizeof (station_ip0.v4.addr)); + grub_memcpy (subnet_mask0.v4.addr, manual_address->subnet_mask, sizeof (subnet_mask0.v4.addr)); + printf_debug("manual_address->address=%s\n", manual_address->address); + printf_debug("manual_address->subnet_mask=%s\n", manual_address->subnet_mask); - grub_printf ("%X\n", (unsigned long)bp); - hexdump (0, bp, get_cached_info.BufferSize); + status = efi_call_3 (pxe->set_station_ip, pxe, (grub_u32_t *)(grub_size_t)&station_ip0, (grub_u32_t *)(grub_size_t)&subnet_mask0);//设置站ip + if (status != GRUB_EFI_SUCCESS) + printf_debug ("Couldn't set station ip\n"); + + grub_free (manual_address); } + } + + if (mode->using_ipv6) + { + printf_debug ("PXE STATION IP: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", //PXE站IP: + mode->station_ip.v6.addr[0], + mode->station_ip.v6.addr[1], + mode->station_ip.v6.addr[2], + mode->station_ip.v6.addr[3], + mode->station_ip.v6.addr[4], + mode->station_ip.v6.addr[5], + mode->station_ip.v6.addr[6], + mode->station_ip.v6.addr[7], + mode->station_ip.v6.addr[8], + mode->station_ip.v6.addr[9], + mode->station_ip.v6.addr[10], + mode->station_ip.v6.addr[11], + mode->station_ip.v6.addr[12], + mode->station_ip.v6.addr[13], + mode->station_ip.v6.addr[14], + mode->station_ip.v6.addr[15]); + } + else + { + printf_debug ("PXE STATION IP: %d.%d.%d.%d\n", //PXE站IP: + mode->station_ip.v4[0], + mode->station_ip.v4[1], + mode->station_ip.v4[2], + mode->station_ip.v4[3]); + printf_debug ("PXE SUBNET MASK: %d.%d.%d.%d\n", //PXE子网掩码: + mode->subnet_mask.v4[0], + mode->subnet_mask.v4[1], + mode->subnet_mask.v4[2], + mode->subnet_mask.v4[3]); + } #endif - else if (grub_memcmp (arg, "detect", sizeof("detect") - 1) == 0) + /* TODO: Set The Station IP to the IP2 Config 将站IP设置为IP2配置*/ +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//net->efi->net.c + +char card_name[10]; +static int grub_efi_net_find_cards (void); +static int +grub_efi_net_find_cards (void) //查找支持ip4配置2的卡 初始化http +{ + grub_efi_uintn_t num_handles; + grub_efi_handle_t *handles; + grub_efi_handle_t *handle; + int id; +// printf_debug ("grub_efi_net_find_cards:\n"); + //查找支持ip4配置的句柄 + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &ip4_config_guid, + 0, &num_handles); //定位ip4句柄 +// printf_debug ("ip4_handles=%x, num_handles=%x\n",handles,num_handles); + if (!handles) + { + printf_errinfo ("Does not support EFI_IP4FHIR G2-POTOCOL!\n"); + return 1; + } + + for (id = 0, handle = handles; num_handles--; handle++, id++) + { + grub_efi_device_path_t *dp; + grub_efi_ip4_config2_protocol_t *ip4_config; +// grub_efi_ip6_config_protocol_t *ip6_config; + grub_efi_handle_t http_handle; + grub_efi_http_t *http; + struct grub_efi_net_device *d; + +// printf_debug ("*handle=%x\n",*handle); + dp = grub_efi_get_device_path (*handle); //获得设备路径 + if (!dp) + continue; + if (debug > 1) + grub_efi_print_device_path(dp); //打印路径 + + ip4_config = grub_efi_open_protocol (*handle, &ip4_config_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); //打开ip4协议 + if (!ip4_config) //不支持ip4 + continue; +// printf_debug ("ip4_config=%x\n",ip4_config); + +// ip6_config = grub_efi_open_protocol (*handle, &ip6_config_guid, +// GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); //打开ip6协议 + http_handle = grub_efi_service_binding (*handle, &http_service_binding_guid); //http服务绑定 + http = (http_handle) + ? grub_efi_open_protocol (http_handle, &http_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL) //http服务绑定成功,打开http协议 + : NULL; +// printf_debug ("http=%x\n",http); + if (!http) { - unsigned long long blksize = 0; - /* pxe_detect should be done before any other command. */ - arg = skip_to (0, arg); -// if (*arg != '/') -// { - if (*arg >= '0' && *arg <= '9') - { - if (! safe_parse_maxint (&arg, &blksize)) - return 0; - arg = skip_to (0, arg); - if (*arg == 0) - arg = 0; - //else if (*arg != '/') - // goto bad_argument; - } else if (*arg == 0) - arg = 0; - //else - // goto bad_argument; -// } - return pxe_detect ((int)blksize, arg); + printf_errinfo ("Does not support EFI_HTTP_PROTOCOL!\n"); + errnum = 0x1234; + goto err; + } + + d = grub_malloc (sizeof (*d)); //分配内存 + if (!d) //如果失败 + { + while (net_devices) + { + d = net_devices->next; + grub_free (net_devices); + net_devices = d; + } + goto err; } - #ifdef FSYS_IPXE - else if (has_ipxe && grub_memcmp (arg ,"type",sizeof("type") - 1) == 0) + //创建网络设备 + d->handle = *handle; //句柄 + d->ip4_config = ip4_config; //ip4配置 +// d->ip6_config = ip6_config; //ip6配置 + d->http_handle = http_handle; //http句柄 + d->http = http; //http入口 + d->next = net_devices; //下一个 + grub_sprintf (card_name,"efinet%d", id); + d->card_name = card_name; //网卡名称 + d->net_interfaces = NULL; //网络接口 + net_devices = d; //网络设备入口 +// printf_debug ("net_devices=%x\n",net_devices); +// if (debug > 1) +// getkey(); + } + + grub_free (handles); + set_ip_policy_to_static (); //将ip策略设置为静态 + + //设置手动地址 + grub_efi_status_t status; + grub_efi_net_ip_manual_address_t net_ip; + grub_efi_ip4_config2_manual_address_t *address = &net_ip.ip4; +// printf_debug ("station_ip=%x\n",station_ip); +// printf_debug ("subnet_mask=%x\n",subnet_mask); + + *(int*)net_ip.ip4.address = station_ip; + *(int*)net_ip.ip4.subnet_mask = subnet_mask; + net_ip.is_ip6 = 0; + status = efi_call_4 (net_devices->ip4_config->set_data, net_devices->ip4_config, + GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS, //手动地址 + sizeof(*address), address); +// printf_debug ("status=%x\n",status); + if (status != GRUB_EFI_SUCCESS) + goto err; + + if (debug > 1) + getkey(); + return 0; + +err: + grub_free (handles); + return 1; +} + +static void +set_ip_policy_to_static (void) //将ip策略设置为静态 +{ + struct grub_efi_net_device *dev; +// printf_debug ("set_ip_policy_to_static:\n"); + + for (dev = net_devices; dev; dev = dev->next) + { + grub_efi_ip4_config2_policy_t ip4_policy = GRUB_EFI_IP4_CONFIG2_POLICY_STATIC; //静态 +// printf_debug ("dev=%x, ip4_config=%x\n",dev,dev->ip4_config); + + if (efi_call_4 (dev->ip4_config->set_data, dev->ip4_config, + GRUB_EFI_IP4_CONFIG2_DATA_TYPE_POLICY, //策略 + sizeof (ip4_policy), &ip4_policy) != GRUB_EFI_SUCCESS) + printf_debug ("could not set GRUB_EFI_IP4_CONFIG2_POLICY_STATIC on dev `%s'\n", dev->card_name); //无法在dev上设置GRUBEFI_IP4_CONFIG2_POLICY_STATIC +#if 0 + printf_debug ("ip6_config=%x\n",dev->ip6_config); + if (dev->ip6_config) { - arg = skip_to (0, arg); - switch(*arg) + grub_efi_ip6_config_policy_t ip6_policy = GRUB_EFI_IP6_CONFIG_POLICY_MANUAL; + + if (efi_call_4 (dev->ip6_config->set_data, dev->ip6_config, + GRUB_EFI_IP6_CONFIG_DATA_TYPE_POLICY, + sizeof (ip6_policy), &ip6_policy) != GRUB_EFI_SUCCESS) + printf_debug ("could not set GRUB_EFI_IP6_CONFIG_POLICY_MANUAL on dev `%s'\n", dev->card_name); //无法在dev上设置GRUB_EFI_IP6_CONFIG_POLICY_MANUAL + } +#endif + } +} + +static grub_efi_handle_t +grub_efi_service_binding (grub_efi_handle_t dev, grub_efi_guid_t *service_binding_guid) //dev服务绑定 +{ + grub_efi_service_binding_t *service; + grub_efi_status_t status; + grub_efi_handle_t child_dev = NULL; + + service = grub_efi_open_protocol (dev, service_binding_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); //打开服务绑定协议 + if (!service) //失败 + { + printf_errinfo ("couldn't open efi service binding protocol\n"); //无法打开efi服务绑定协议 + return NULL; + } + + status = efi_call_2 (service->create_child, service, &child_dev); //服务->创建子项 + if (status != GRUB_EFI_SUCCESS) //失败 + { + printf_errinfo ("Failed to create child device of http service\n"); //无法创建http服务的子设备 + return NULL; + } + + return child_dev; //子设备 +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//net\drivers\efi\efinet.c + +grub_u32_t get_dhcp_option_66(grub_efi_pxe_dhcpv4_packet_t *bp); +grub_u32_t get_dhcp_option_66(grub_efi_pxe_dhcpv4_packet_t *bp) //选项66支持 由江南一根葱提供 +{ + unsigned char *option_ptr = bp->dhcp_options; + +//01 客户端子网掩码; 03 路由器IP; 05 名称服务器IP; 06 DNS服务器IP; 12(0c) 指定客户端主机名; 15(0f) DNS域名; 28(1c) 广播地址; +//51(33) IP地址租用时间; 54(36) 标识服务器IP; 55(37) 客户端请求特定选项; 61(3d) 客户端硬件类型+MAC地址; 66(42) 标识TFTP服务器名称; +//67(43) 指定引导文件名; 150(96) TFTP服务器地址; +//TinyPXEServe dhcp +//63 82 53 63 35 01 05 36 - 04 c0 a8 58 01 3c 09 50 36:192.168.88.1 +//58 45 43 6c 69 65 6e 74 - 61 11 00 56 4d 5c a3 70 +//77 b7 3a 9b 4a 2b 44 b7 - 83 7a 6b 01 04 ff ff ff 01:255.255.255.0 +//00 03 04 c0 a8 58 01 06 - 04 c0 a8 58 01 33 04 00 03:192.168.88.1 06:192.168.88.1 33:0.1.81.128 +//01 51 80 ff 00 00 00 00 +//TinyPXEServe proxy +//63 82 53 63 35 01 05 36 - 04 c0 a8 58 fe 33 04 00 36:192.168.88.254 +//00 07 08 01 04 ff ff ff - 00 03 04 c0 a8 58 02 06 03:192.168.88.2 06:192.168.88.2 +//04 c0 a8 58 02 0f 0b 6c - 6f 63 61 6c 64 6f 6d 61 1c:192.168.88.255 +//69 6e 1c 04 c0 a8 58 ff - 3a 04 00 00 03 84 3b 04 +//00 00 06 27 ff 00 00 00 + + //如果存在魔术饼干则跳过(0x63825363) +// if (option_ptr[0] == 0x63 && option_ptr[1] == 0x82 && option_ptr[2] == 0x53 && option_ptr[3] == 0x63) +// option_ptr += 4; + while (*option_ptr != 0xFF) //循环到结束选项(0xFF) + { + unsigned char option_code = *option_ptr; + unsigned char option_len = *(option_ptr + 1); + if (option_code == 0x42) { //选项66:下一个服务器IP地址 + if (option_len == 4) //确保它是IPv4地址 + return *(grub_u32_t *)(option_ptr + 2); + } + option_ptr += (2 + option_len); //移动到下一个选项(代码+长度+值) + //基本健全性检查,防止对格式错误的数据包进行无限循环 + if (option_ptr >= (unsigned char *)bp + sizeof(grub_efi_pxe_dhcpv4_packet_t)) + break; + } + return 0; //没有找到 +} + +static int grub_efinet_findcards (void); +static int +grub_efinet_findcards (void) //查找支持简单网络接口的卡 初始化tftp +{ + grub_efi_uintn_t num_handles; + grub_efi_handle_t *handles; + grub_efi_handle_t *handle; +// printf_debug ("grub_efinet_findcards:\n"); + + /* 查找支持简单网络接口的句柄 */ + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &net_io_guid, + 0, &num_handles); //定位句柄 + if (! handles) //失败 + return 1; +// printf_debug ("handles=%x, num_handles=%x\n",handles,num_handles);//e59bd80,3 + + struct grub_efi_pxe *pxe = 0; + //查找MAC消息设备 + for (handle = handles; num_handles--; handle++) { - case '0': - case '1': - def_pxe_type = *arg - '0'; - break; - default: - goto bad_argument; + grub_efi_simple_network_t *net; //简单网络 + grub_efi_device_path_t *dp, *parent = NULL, *child = NULL; //设备路径 + + /* EDK2 UEFI PXE驱动程序将IPv4和IPv6消息设备创建为主MAC消息设备的子设备。 + 我们只需要每个物理卡一个绑定SNP的设备,否则它们在轮询传入数据包时会相互竞争。*/ +// printf_debug ("*handle=%x\n",*handle);//fcb9798 + dp = grub_efi_get_device_path (*handle); //设备路径 + if (!dp) //失败 + continue; + if (debug > 1) + grub_efi_print_device_path(dp); //打印路径 + + //尝试打开pxe协议 + if (!pxe) + { + pxe = grub_efi_open_protocol (*handle, &pxe_io_guid, //VM在MAC,QEMU在MAC/IPV4 + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (pxe) //失败 + { + pxe_entry = pxe; + pd_handle = *handle; + pd_dp = dp; +// printf_debug ("pxe_entry=%x\n",pxe_entry); + } + } + + for (; ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp); dp = GRUB_EFI_NEXT_DEVICE_PATH (dp)) + { + parent = child; + child = dp; + } + + if (child + && GRUB_EFI_DEVICE_PATH_TYPE (child) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE //并且是通讯设备路径 3 + && (GRUB_EFI_DEVICE_PATH_SUBTYPE (child) == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE //并且是IPV4设备子路径 12 + || GRUB_EFI_DEVICE_PATH_SUBTYPE (child) == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE) // 或者是IPV6设备子路径 13 + && parent + && GRUB_EFI_DEVICE_PATH_TYPE (parent) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE //并且是通讯设备路径 3 + && GRUB_EFI_DEVICE_PATH_SUBTYPE (parent) == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE) //并且是MAC地址设备子路径 11 + continue; + + //通过句柄打开网络协议. + net = grub_efi_open_protocol (*handle, &net_io_guid, //VM及QEMU都在MAC + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (! net) //失败 + continue; + + //启动并初始化网络设备 +// printf_debug ("net_start_state=%x\n",net->mode->state); //0/1/2=网络停止/网络起动/已初始化 2 + if (net->mode->state == GRUB_EFI_NETWORK_STOPPED //如果网络停止 + && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS) //则启动网络 + continue; //启动失败,继续 + + if (net->mode->state == GRUB_EFI_NETWORK_STOPPED) //如果网络停止,继续 + continue; + + if (net->mode->state == GRUB_EFI_NETWORK_STARTED //如果网络起动了 + && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS) //则网络初始化失败 + continue; //如果初始化失败,继续 +// printf_debug ("net_set_state=%x\n",net->mode->state); //0/1/2=网络停止/网络起动/已初始化 2 +// printf_debug ("max_packet_size=%x\n",net->mode->max_packet_size);//5dc + max_packet_size = net->mode->max_packet_size; + net0 = net; } + grub_free (handles); //释放 + +#if 0 + //通过启动句柄打开pxe协议 + pxe_entry = grub_efi_open_protocol (image->device_handle, &pxe_io_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); +#endif + if (! pxe_entry) //失败 + return 1; + + if (!*(grub_u32_t *)&pxe_entry->mode->station_ip.v4) //非网起时,开启网络功能 + { + printf ("Running DHCP request IP, please wait ......\n"); + grub_efi_status_t status; + status = efi_call_2 (pxe_entry->start, //启动pxe + pxe_entry, 0); + + status = efi_call_2 (pxe_entry->dhcp, //尝试完成DHCPv4(发现/提供/请求/确认) + pxe_entry, 0); + if (status == GRUB_EFI_SUCCESS) + printf_debug ("dhcp ok\n"); + else + printf_debug ("dhcp failure\n"); + } + + // ===================== PROXY DHCP MODIFICATION START ===================== + //由江南一根葱提供 + //从引导播放器获取IP地址 +// struct grub_efi_pxe_mode *pxe_mode = pxe_entry->mode; //模式 + //添加循环以等待PXE回复 + int i; + for (i = 0; i < 5; i++) //尝试5次 + { + if (pxe_entry->mode->pxe_reply_received) //pxe收到回复 + break; + efi_call_1(grub_efi_system_table->boot_services->stall, 1000000); //延时1秒 + } + + //从引导播放器获取IP地址 + //首先,将 discover_reply 指向 dhcp_ack,这是基础信息源 + discover_reply = (grub_efi_pxe_dhcpv4_packet_t *)((char *)&pxe_entry->mode->dhcp_ack.dhcpv4); //引导播放器 + image = grub_efi_get_loaded_image (grub_efi_image_handle); //通过映像句柄,获得加载映像grub_efi_loaded_image结构 + g4e_options = image->load_options; + g4e_options_size = image->load_options_size; + + //始终使用EFI PXE协议栈确定的客户端IP + pxe_yip = *(grub_u32_t *)&pxe_entry->mode->station_ip.v4; //站IP + station_ip = *(int*)pxe_entry->mode->station_ip.v4; //站IP + subnet_mask = *(int*)pxe_entry->mode->subnet_mask.v4; //子网掩码 + grub_memmove (&pxe_mac, &discover_reply->bootp_hw_addr, 6); //MAC + + //添加调试信息 +// printf_debug("DHCP ACK received: %u\n", pxe_mode->dhcp_ack_received); //收到dhcp ack +// printf_debug("Proxy Offer received: %u\n", pxe_mode->proxy_offer_received); //收到代理报文 + + // <<< 这是实现 Proxy DHCP 支持的核心逻辑 >>> + //检查是否收到了 Proxy Offer,并且主 DHCP ACK 中没有提供启动文件 + pxe_sip = 0; + if (pxe_entry->mode->proxy_offer_received && discover_reply->bootp_boot_file[0] == '\0') + { + //从Proxy Offer中复制启动文件名。 + grub_memcpy(discover_reply->bootp_boot_file, pxe_entry->mode->proxy_offer.dhcpv4.bootp_boot_file, sizeof(discover_reply->bootp_boot_file)); //代理提供 + + //从Proxy Offer中获取服务器IP。 + pxe_sip = pxe_entry->mode->proxy_offer.dhcpv4.bootp_si_addr; +// printf_debug("Use proxy offer information. %x,(%x)\n",pxe_sip,discover_reply->bootp_si_addr); + } + else if (g4e_options_size) + { + //如果从ipxe引导,使用其传入的服务器IP + unsigned char a0,a1,a2,a3; + unsigned long long val = 0; + char *utf8 = grub_malloc (g4e_options_size); + char *p = utf8; + unicode_to_utf8 ((unsigned short *)g4e_options, (unsigned char *)utf8, g4e_options_size); + + for (;*p;) + { + if (grub_memcmp ((const char *)p, "proxy=", 6) == 0) + { + p += 6; + if (safe_parse_maxint (&p, &val)) + a0 = val; + else + break; + p++; + safe_parse_maxint (&p, &val); + a1 = val; + p++; + safe_parse_maxint (&p, &val); + a2 = val; + p++; + safe_parse_maxint (&p, &val); + a3 = val; + pxe_sip = a0 + (a1 << 8) + (a2 << 16) + (a3 << 24); +// printf_debug("Use g4e_options information. %x \n",pxe_sip); + break; + } + p = skip_to (0, p); } - #endif - else + grub_free (utf8); + } + + if (pxe_sip == 0) + { + //如果没有 Proxy Offer,或者主 DHCP ACK 已经包含了启动信息,则直接使用 dhcp_ack 的信息 + pxe_sip = discover_reply->bootp_si_addr; +// printf_debug("Use standard DHCP ACK information. %x,(%x)\n",pxe_sip,pxe_entry->mode->proxy_offer.dhcpv4.bootp_si_addr); + } + + //最后的 fallback:如果 pxe_sip 仍然是0,尝试从 DHCP 选项66 获取 + if (pxe_sip == 0) + { +// printf_debug("Server IP is empty, try DHCP option 66...\n"); + grub_u32_t next_server_ip = get_dhcp_option_66(discover_reply); + if (next_server_ip) { -bad_argument: - errnum = ERR_BAD_ARGUMENT; + pxe_sip = next_server_ip; +// printf_debug("Use DHCP option 66 information.. %x\n",pxe_sip); + } + else return 0; + } + + //显式调用 pxe_entry->set_station_ip 函数,将DHCP分配的客户端IP和子网掩码传递给EFI PXE协议栈 + grub_efi_status_t status = efi_call_3(pxe_entry->set_station_ip, pxe_entry, + (grub_u32_t *)(grub_size_t)&station_ip, + (grub_u32_t *)(grub_size_t)&subnet_mask); + if (status != GRUB_EFI_SUCCESS) + printf_errinfo("Failed to set the IP address for the PXE station: %x\n", (int)status); + + // ===================== PROXY DHCP MODIFICATION END ===================== + + bootfile = discover_reply->bootp_boot_file; + grub_sprintf (default_server, "%d.%d.%d.%d", + ((grub_uint8_t *) &pxe_sip)[0], + ((grub_uint8_t *) &pxe_sip)[1], + ((grub_uint8_t *) &pxe_sip)[2], + ((grub_uint8_t *) &pxe_sip)[3]); + // 打印最终结果用于调试 +#if 0 + if (debug > 1) + { + printf("YIP : "); + print_ip (pxe_yip) ; + printf("\nSIP : "); + print_ip (pxe_sip); + printf("\n"); + printf("default_server=%s\n",default_server); + printf("bootfile: %s\n",bootfile); + getkey(); + } +#endif + return 0; + } +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static void print_ip (grub_u32_t ip) +{ + int i; + + for (i = 0; i < 3; i++) + { + grub_printf ("%d.", (unsigned long)(unsigned char)ip); + ip >>= 8; } - return 1; + grub_printf ("%d", (unsigned long)(unsigned char)ip); +} + +int pxe_func (char *arg, int flags); +int +pxe_func (char *arg, int flags) +{ + if (grub_memcmp(arg, "init", 4) == 0) + { + pxe_init (); + if (!only_tftp) + cur_pxe_type = 1; + saved_drive = PXE_DRIVE; + current_drive = PXE_DRIVE; + saved_partition = 0xFFFFFF; + current_partition = 0xFFFFFF; + + return 1; + } + + if (! pxe_entry) + return 0; + + if (*arg == 0) //获得PXE信息 + { + char buf[4], *pc; + int i; + grub_efi_pxe_t *pxe = pxe_entry; + grub_efi_pxe_mode_t *mode = pxe->mode; + grub_printf ("client ip\n"); //这一行不能打印,不知道为什么? + grub_printf ("client ip : "); + print_ip (pxe_yip); + grub_printf ("\nserver ip : "); + print_ip (pxe_sip); + grub_printf ("\npacket_size : %d",max_packet_size); + grub_printf ("\nmac : "); + for (i = 0; i < 6; i++) + { + pc = buf; + pc = pxe_outhex (pc, pxe_mac[i]); + *pc = 0; + grub_printf ("%s%c", buf, ((i == 5) ? ' ' : '-')); + } + grub_printf ("\nbootfile : %s",bootfile); + grub_printf ("\npxe_type : "); + if (cur_pxe_type) + grub_printf ("http"); + else + grub_printf ("tftp"); + grub_printf ("\nhttp_type : %d\n",(http_feature ? 206 : 200)); + + grub_printf ("mode->started : %d\n",mode->started); //pxe状态 0/1=停止/已启动 + grub_printf ("net0->state : %d\n",net0->mode->state); //net状态 0/1/2=停止/已启动/已初始化 + + return 1; + } + else if (grub_memcmp(arg, "read", 4) == 0) //读取文件 + { +/* +用法:pxe read /path/file range_start - range_end +例1: pxe read /boot/10pe.wim 64 - 83 //从第64字节开始读,至第83字节止,共读20字节。(文件从0字节开始) +例2: pxe read /boot/10pe.wim - 8 //从文件末尾读8字节。 +例3: pxe read /boot/10pe.wim 64 - //从文件第64字节开始读至文件结束。 +*/ + char *p = pxe_name; + char tmp[32] = {0}; + char range[64] = {0}; + http_range = range; + grub_u64_t range_start = 0, range_end = 0; + + char *buf = grub_zalloc (256); //分配内存, 并清零; + + arg = skip_to (0, arg); + while (*arg != ' ' && *arg != 0) + *p++ = *arg++; + *p = 0; + + //获取文件尺寸 + pxe_open (pxe_name); + printf_debug ("filemax=%x\n",filemax); + + arg = skip_to (0, arg); + if (*arg == 0) + { + grub_sprintf (range, "bytes=0-"); + } + else if (*arg != '-') + { + safe_parse_maxint (&arg, &range_start); + arg = skip_to (0, arg); + if (*arg == '-') + { + arg = skip_to (0, arg); + if (safe_parse_maxint (&arg, &range_end)) //例1 + grub_sprintf (range, "bytes=%d-%d", range_start,range_end); + else //例3 + grub_sprintf (range, "bytes=%d-", range_start); + } + else + return 0; + } + else //例2 + { + arg = skip_to (0, arg); + if (safe_parse_maxint (&arg, &range_end)) + grub_sprintf (range, "bytes=-%d", range_end); + else + return 0; + } + + pxe_read ((unsigned long long)(grub_size_t)buf, 256, GRUB_READ); + + grub_sprintf (tmp, "echo --mem=%d=%d", buf, 256); + run_line (tmp,flags); + http_range = 0; + grub_free (buf); + return 1; + } + return 0; +} + +int pxe_init (void); +int +pxe_init (void) +{ +// debug = 3; + int err; + + printf_debug ("UEFI revision: %x\n",grub_efi_system_table->hdr.revision); + + err = grub_efinet_findcards (); //查找支持简单网络接口的卡 初始化tftp + if (err) + return 1; + err = grub_efi_net_find_cards (); //查找支持ip4配置2的卡 初始化http + if (err) + { + only_tftp = 1; + cur_pxe_type = 0; //默认网起使用tftp。即'/'使用tftp。如果使用http,必需指明,即(http)/。或者使用 "set http"。 + pxe_configure (); //pxe配置 只要不以外关闭,设置一次即可。 +// printf_debug ("only_tftp!\n"); + } + else + { + //测试是否支持断点续传 + http_feature = 0; + cur_pxe_type = 1; + http_range = "bytes=0-"; + pxe_name = "/efi/grub/menu.lst"; + pxe_open (pxe_name); + char *buf = grub_zalloc (filemax); + http_configure(); //http配置 + http_read (buf, filemax); + if (read_status == 206) + http_feature = 1; //支持断点续传 + grub_free (buf); + http_range = 0; + } + + return 0; } +#endif //ifdef FSYS_PXE diff --git a/stage2/fsys_reiserfs.c b/stage2/fsys_reiserfs.c deleted file mode 100644 index a67cbaab..00000000 --- a/stage2/fsys_reiserfs.c +++ /dev/null @@ -1,1274 +0,0 @@ -/* fsys_reiserfs.c - an implementation for the ReiserFS filesystem */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2000, 2001 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifdef FSYS_REISERFS -#include "shared.h" -#include "filesys.h" -#include "iamath.h" - -#undef REISERDEBUG - -/* Some parts of this code (mainly the structures and defines) are - * from the original reiser fs code, as found in the linux kernel. - */ - -/* include/asm-i386/types.h */ -typedef __signed__ char __s8; -typedef unsigned char __u8; -typedef __signed__ short __s16; -typedef unsigned short __u16; -typedef __signed__ int __s32; -typedef unsigned int __u32; -typedef unsigned long long __u64; - -/* linux/posix_type.h */ -typedef long linux_off_t; - -/* linux/little_endian.h */ -#define __cpu_to_le64(x) ((__u64) (x)) -#define __le64_to_cpu(x) ((__u64) (x)) -#define __cpu_to_le32(x) ((__u32) (x)) -#define __le32_to_cpu(x) ((__u32) (x)) -#define __cpu_to_le16(x) ((__u16) (x)) -#define __le16_to_cpu(x) ((__u16) (x)) - -/* include/linux/reiser_fs.h */ -/* This is the new super block of a journaling reiserfs system */ -struct reiserfs_super_block -{ - __u32 s_block_count; /* blocks count */ - __u32 s_free_blocks; /* free blocks count */ - __u32 s_root_block; /* root block number */ - __u32 s_journal_block; /* journal block number */ - __u32 s_journal_dev; /* journal device number */ - __u32 s_journal_size; /* size of the journal on FS creation. used to make sure they don't overflow it */ - __u32 s_journal_trans_max; /* max number of blocks in a transaction. */ - __u32 s_journal_magic; /* random value made on fs creation */ - __u32 s_journal_max_batch; /* max number of blocks to batch into a trans */ - __u32 s_journal_max_commit_age; /* in seconds, how old can an async commit be */ - __u32 s_journal_max_trans_age; /* in seconds, how old can a transaction be */ - __u16 s_blocksize; /* block size */ - __u16 s_oid_maxsize; /* max size of object id array */ - __u16 s_oid_cursize; /* current size of object id array */ - __u16 s_state; /* valid or error */ - char s_magic[16]; /* reiserfs magic string indicates that file system is reiserfs */ - __u16 s_tree_height; /* height of disk tree */ - __u16 s_bmap_nr; /* amount of bitmap blocks needed to address each block of file system */ - __u16 s_version; - char s_unused[128]; /* zero filled by mkreiserfs */ -}; - -#define REISERFS_MAX_SUPPORTED_VERSION 2 -#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs" -#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs" -#define REISER3FS_SUPER_MAGIC_STRING "ReIsEr3Fs" - -#define MAX_HEIGHT 7 - -/* must be correct to keep the desc and commit structs at 4k */ -#define JOURNAL_TRANS_HALF 1018 - -/* first block written in a commit. */ -struct reiserfs_journal_desc { - __u32 j_trans_id; /* id of commit */ - __u32 j_len; /* length of commit. len +1 is the commit block */ - __u32 j_mount_id; /* mount id of this trans*/ - __u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for the first blocks */ - char j_magic[12]; -}; - -/* last block written in a commit */ -struct reiserfs_journal_commit { - __u32 j_trans_id; /* must match j_trans_id from the desc block */ - __u32 j_len; /* ditto */ - __u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for the last blocks */ - char j_digest[16]; /* md5 sum of all the blocks involved, including desc and commit. not used, kill it */ -}; - -/* this header block gets written whenever a transaction is considered - fully flushed, and is more recent than the last fully flushed - transaction. - fully flushed means all the log blocks and all the real blocks are - on disk, and this transaction does not need to be replayed. -*/ -struct reiserfs_journal_header { - /* id of last fully flushed transaction */ - __u32 j_last_flush_trans_id; - /* offset in the log of where to start replay after a crash */ - __u32 j_first_unflushed_offset; - /* mount id to detect very old transactions */ - __u32 j_mount_id; -}; - -/* magic string to find desc blocks in the journal */ -#define JOURNAL_DESC_MAGIC "ReIsErLB" - - -/* - * directories use this key as well as old files - */ -struct offset_v1 -{ - /* - * for regular files this is the offset to the first byte of the - * body, contained in the object-item, as measured from the start of - * the entire body of the object. - * - * for directory entries, k_offset consists of hash derived from - * hashing the name and using few bits (23 or more) of the resulting - * hash, and generation number that allows distinguishing names with - * hash collisions. If number of collisions overflows generation - * number, we return EEXIST. High order bit is 0 always - */ - __u32 k_offset; - __u32 k_uniqueness; -}; - -struct offset_v2 -{ - /* - * for regular files this is the offset to the first byte of the - * body, contained in the object-item, as measured from the start of - * the entire body of the object. - * - * for directory entries, k_offset consists of hash derived from - * hashing the name and using few bits (23 or more) of the resulting - * hash, and generation number that allows distinguishing names with - * hash collisions. If number of collisions overflows generation - * number, we return EEXIST. High order bit is 0 always - */ - __u64 k_offset:60; - __u64 k_type: 4; -}; - - -struct key -{ - /* packing locality: by default parent directory object id */ - __u32 k_dir_id; - /* object identifier */ - __u32 k_objectid; - /* the offset and node type (old and new form) */ - union - { - struct offset_v1 v1; - struct offset_v2 v2; - } - u; -}; - -#define KEY_SIZE (sizeof (struct key)) - -/* Header of a disk block. More precisely, header of a formatted leaf - or internal node, and not the header of an unformatted node. */ -struct block_head -{ - __u16 blk_level; /* Level of a block in the tree. */ - __u16 blk_nr_item; /* Number of keys/items in a block. */ - __u16 blk_free_space; /* Block free space in bytes. */ - struct key blk_right_delim_key; /* Right delimiting key for this block (supported for leaf level nodes - only) */ -}; -#define BLKH_SIZE (sizeof (struct block_head)) -#define DISK_LEAF_NODE_LEVEL 1 /* Leaf node level. */ - -struct item_head -{ - struct key ih_key; /* Everything in the tree is found by searching for it based on its key.*/ - - union - { - __u16 ih_free_space; /* The free space in the last unformatted node of an indirect item if this - is an indirect item. This equals 0xFFFF iff this is a direct item or - stat data item. Note that the key, not this field, is used to determine - the item type, and thus which field this union contains. */ - __u16 ih_entry_count; /* Iff this is a directory item, this field equals the number of directory - entries in the directory item. */ - } - u; - __u16 ih_item_len; /* total size of the item body */ - __u16 ih_item_location; /* an offset to the item body within the block */ - __u16 ih_version; /* ITEM_VERSION_1 for all old items, - ITEM_VERSION_2 for new ones. - Highest bit is set by fsck - temporary, cleaned after all done */ -}; -/* size of item header */ -#define IH_SIZE (sizeof (struct item_head)) - -#define ITEM_VERSION_1 0 -#define ITEM_VERSION_2 1 -#define IH_KEY_OFFSET(ih) ((ih)->ih_version == ITEM_VERSION_1 \ - ? (ih)->ih_key.u.v1.k_offset \ - : (ih)->ih_key.u.v2.k_offset) - -#define IH_KEY_ISTYPE(ih, type) ((ih)->ih_version == ITEM_VERSION_1 \ - ? (ih)->ih_key.u.v1.k_uniqueness == V1_##type \ - : (ih)->ih_key.u.v2.k_type == V2_##type) - -struct disk_child -{ - unsigned long dc_block_number; /* Disk child's block number. */ - unsigned short dc_size; /* Disk child's used space. */ -}; - -#define DC_SIZE (sizeof (struct disk_child)) - -/* Stat Data on disk. - * - * Note that reiserfs has two different forms of stat data. Luckily - * the fields needed by grub are at the same position. - */ -struct stat_data -{ - __u16 sd_mode; /* file type, permissions */ - __u16 sd_notused1[3]; /* fields not needed by reiserfs */ - __u32 sd_size; /* file size */ - __u32 sd_size_hi; /* file size high 32 bits (since version 2) */ -}; - -struct reiserfs_de_head -{ - __u32 deh_offset; /* third component of the directory entry key */ - __u32 deh_dir_id; /* objectid of the parent directory of the - object, that is referenced by directory entry */ - __u32 deh_objectid;/* objectid of the object, that is referenced by - directory entry */ - __u16 deh_location;/* offset of name in the whole item */ - __u16 deh_state; /* whether 1) entry contains stat data (for - future), and 2) whether entry is hidden - (unlinked) */ -}; - -#define DEH_SIZE (sizeof (struct reiserfs_de_head)) - -#define DEH_Statdata (1 << 0) /* not used now */ -#define DEH_Visible (1 << 2) - -#define SD_OFFSET 0 -#define SD_UNIQUENESS 0 -#define DOT_OFFSET 1 -#define DOT_DOT_OFFSET 2 -#define DIRENTRY_UNIQUENESS 500 - -#define V1_TYPE_STAT_DATA 0x0 -#define V1_TYPE_DIRECT 0xffffffff -#define V1_TYPE_INDIRECT 0xfffffffe -#define V1_TYPE_DIRECTORY_MAX 0xfffffffd -#define V2_TYPE_STAT_DATA 0 -#define V2_TYPE_INDIRECT 1 -#define V2_TYPE_DIRECT 2 -#define V2_TYPE_DIRENTRY 3 - -#define REISERFS_ROOT_OBJECTID 2 -#define REISERFS_ROOT_PARENT_OBJECTID 1 -#define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024) -/* the spot for the super in versions 3.5 - 3.5.11 (inclusive) */ -#define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024) -#define REISERFS_OLD_BLOCKSIZE 4096 - -#define S_ISREG(mode) (((mode) & 0170000) == 0100000) -#define S_ISDIR(mode) (((mode) & 0170000) == 0040000) -#define S_ISLNK(mode) (((mode) & 0170000) == 0120000) - -#define PATH_MAX 1024 /* include/linux/limits.h */ -#define MAX_LINK_COUNT 5 /* number of symbolic links to follow */ - -/* The size of the node cache */ -#define FSYSREISER_CACHE_SIZE 24*1024 -#define FSYSREISER_MIN_BLOCKSIZE SECTOR_SIZE -#define FSYSREISER_MAX_BLOCKSIZE FSYSREISER_CACHE_SIZE / 3 - -/* Info about currently opened file */ -struct fsys_reiser_fileinfo -{ - __u32 k_dir_id; - __u32 k_objectid; -}; - -/* In memory info about the currently mounted filesystem */ -struct fsys_reiser_info -{ - /* The last read item head */ - struct item_head *current_ih; - /* The last read item */ - char *current_item; - /* The information for the currently opened file */ - struct fsys_reiser_fileinfo fileinfo; - /* The start of the journal */ - __u32 journal_block; - /* The size of the journal */ - __u32 journal_block_count; - /* The first valid descriptor block in journal - (relative to journal_block) */ - __u32 journal_first_desc; - - /* The ReiserFS version. */ - __u16 version; - /* The current depth of the reiser tree. */ - __u16 tree_depth; - /* SECTOR_SIZE << blocksize_shift == blocksize. */ - __u8 blocksize_shift; - /* 1 << full_blocksize_shift == blocksize. */ - __u8 fullblocksize_shift; - /* The reiserfs block size (must be a power of 2) */ - __u16 blocksize; - /* The number of cached tree nodes */ - __u16 cached_slots; - /* The number of valid transactions in journal */ - __u16 journal_transactions; - - unsigned int blocks[MAX_HEIGHT]; - unsigned int next_key_nr[MAX_HEIGHT]; -}; - -/* The cached s+tree blocks in FSYS_BUF, see below - * for a more detailed description. - */ -#define ROOT ((char *) ((int) FSYS_BUF)) -#define CACHE(i) (ROOT + ((i) << INFO->fullblocksize_shift)) -#define LEAF CACHE (DISK_LEAF_NODE_LEVEL) - -#define BLOCKHEAD(cache) ((struct block_head *) cache) -#define ITEMHEAD ((struct item_head *) ((int) LEAF + BLKH_SIZE)) -#define KEY(cache) ((struct key *) ((int) cache + BLKH_SIZE)) -#define DC(cache) ((struct disk_child *) \ - ((int) cache + BLKH_SIZE + KEY_SIZE * nr_item)) -/* The fsys_reiser_info block. - */ -#define INFO \ - ((struct fsys_reiser_info *) ((int) FSYS_BUF + FSYSREISER_CACHE_SIZE)) -/* - * The journal cache. For each transaction it contains the number of - * blocks followed by the real block numbers of this transaction. - * - * If the block numbers of some transaction won't fit in this space, - * this list is stopped with a 0xffffffff marker and the remaining - * uncommitted transactions aren't cached. - */ -#define JOURNAL_START ((__u32 *) (INFO + 1)) -#define JOURNAL_END ((__u32 *) (FSYS_BUF + FSYS_BUFLEN)) - -static struct reiserfs_super_block *super = (struct reiserfs_super_block *)0x600; //struct size 202. -static struct reiserfs_journal_desc *desc = (struct reiserfs_journal_desc *)(FSYS_BUF - 0x2000); //struct size 4K -static struct reiserfs_journal_commit *commit = (struct reiserfs_journal_commit *)(FSYS_BUF - 0x1000);//struct size 4K -static char *linkbuf = (char *)(FSYS_BUF - PATH_MAX); /* buffer for following symbolic links */ -static char *tmp_name = (char *)(FSYS_BUF - 0x1000); /* 2048 bytes used */ - -//static __inline__ unsigned long -//log2_tmp (unsigned long word) -//{ -// __asm__ ("bsfl %1,%0" -// : "=r" (word) -// : "r" (word)); -// return word; -//} - -static __inline__ int -is_power_of_two (unsigned long word) -{ - return (word & -word) == word; -} - -static int -journal_read (int block, int len, char *buffer) -{ - return devread ((INFO->journal_block + block) << INFO->blocksize_shift, - 0, len, (unsigned long long)(unsigned int)buffer, 0xedde0d90); -} - -/* Read a block from ReiserFS file system, taking the journal into - * account. If the block nr is in the journal, the block from the - * journal taken. - */ -static int -block_read (int blockNr, int start, int len, unsigned long long buffer, unsigned long write) -{ - int transactions = INFO->journal_transactions; - int desc_block = INFO->journal_first_desc; - int journal_mask = INFO->journal_block_count - 1; - int translatedNr = blockNr; - __u32 *journal_table = JOURNAL_START; - while (transactions-- > 0) - { - int i = 0; - int j_len; - if (*journal_table != 0xffffffff) - { - /* Search for the blockNr in cached journal */ - j_len = *journal_table++; - while (i++ < j_len) - { - if (*journal_table++ == blockNr) - { - journal_table += j_len - i; - goto found; - } - } - } - else - { - /* This is the end of cached journal marker. The remaining - * transactions are still on disk. - */ - - if (! journal_read (desc_block, sizeof (struct reiserfs_journal_desc), (char *) desc)) - return 0; - - j_len = desc->j_len; - while (i < j_len && i < JOURNAL_TRANS_HALF) - if (desc->j_realblock[i++] == blockNr) - goto found; - - if (j_len >= JOURNAL_TRANS_HALF) - { - int commit_block = (desc_block + 1 + j_len) & journal_mask; - if (! journal_read (commit_block, - sizeof (struct reiserfs_journal_commit), (char *) commit)) - return 0; - while (i < j_len) - if (commit->j_realblock[i++ - JOURNAL_TRANS_HALF] == blockNr) - goto found; - } - } - goto not_found; - - found: - translatedNr = INFO->journal_block + ((desc_block + i) & journal_mask); -#ifdef REISERDEBUG - printf ("block_read: block %d is mapped to journal block %d.\n", - blockNr, (translatedNr - INFO->journal_block)); -#endif - /* We must continue the search, as this block may be overwritten - * in later transactions. - */ - not_found: - desc_block = (desc_block + 2 + j_len) & journal_mask; - } - return devread (translatedNr << INFO->blocksize_shift, start, len, buffer, write); -} - -/* Init the journal data structure. We try to cache as much as - * possible in the JOURNAL_START-JOURNAL_END space, but if it is full - * we can still read the rest from the disk on demand. - * - * The first number of valid transactions and the descriptor block of the - * first valid transaction are held in INFO. The transactions are all - * adjacent, but we must take care of the journal wrap around. - */ -static int -journal_init (void) -{ - unsigned int block_count = INFO->journal_block_count; - unsigned int desc_block; - unsigned int commit_block; - unsigned int next_trans_id; - struct reiserfs_journal_header header; //struct size 12 - __u32 *journal_table = JOURNAL_START; - - journal_read (block_count, sizeof (header), (char *) &header); - desc_block = header.j_first_unflushed_offset; - if (desc_block >= block_count) - return 0; - - INFO->journal_first_desc = desc_block; - next_trans_id = header.j_last_flush_trans_id + 1; - -#ifdef REISERDEBUG - printf ("journal_init: last flushed %d\n", - header.j_last_flush_trans_id); -#endif - - while (1) - { - journal_read (desc_block, sizeof (struct reiserfs_journal_desc), (char *) desc); - if (substring (JOURNAL_DESC_MAGIC, desc->j_magic, 0) > 0 - || desc->j_trans_id != next_trans_id - || desc->j_mount_id != header.j_mount_id) - /* no more valid transactions */ - break; - - commit_block = (desc_block + desc->j_len + 1) & (block_count - 1); - journal_read (commit_block, sizeof (struct reiserfs_journal_commit), (char *) commit); - if (desc->j_trans_id != commit->j_trans_id - || desc->j_len != commit->j_len) - /* no more valid transactions */ - break; - -#ifdef REISERDEBUG - printf ("Found valid transaction %d/%d at %d.\n", - desc->j_trans_id, desc->j_mount_id, desc_block); -#endif - - next_trans_id++; - if (journal_table < JOURNAL_END) - { - if ((journal_table + 1 + desc->j_len) >= JOURNAL_END) - { - /* The table is almost full; mark the end of the cached - * journal.*/ - *journal_table = 0xffffffff; - journal_table = JOURNAL_END; - } - else - { - int i; - /* Cache the length and the realblock numbers in the table. - * The block number of descriptor can easily be computed. - * and need not to be stored here. - */ - *journal_table++ = desc->j_len; - for (i = 0; i < desc->j_len && i < JOURNAL_TRANS_HALF; i++) - { - *journal_table++ = desc->j_realblock[i]; -#ifdef REISERDEBUG - printf ("block %d is in journal %d.\n", - desc->j_realblock[i], desc_block); -#endif - } - for ( ; i < desc->j_len; i++) - { - *journal_table++ = commit->j_realblock[i-JOURNAL_TRANS_HALF]; -#ifdef REISERDEBUG - printf ("block %d is in journal %d.\n", - commit->j_realblock[i-JOURNAL_TRANS_HALF], - desc_block); -#endif - } - } - } - desc_block = (commit_block + 1) & (block_count - 1); - } -#ifdef REISERDEBUG - printf ("Transaction %d/%d at %d isn't valid.\n", - desc->j_trans_id, desc->j_mount_id, desc_block); -#endif - - INFO->journal_transactions - = next_trans_id - header.j_last_flush_trans_id - 1; - return errnum == 0; -} - -/* check filesystem types and read superblock into memory buffer */ -int -reiserfs_mount (void) -{ - int superblock = REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS; - - if ((unsigned long)part_length < superblock + (sizeof (struct reiserfs_super_block) >> SECTOR_BITS) - || ! devread (superblock, 0, sizeof (struct reiserfs_super_block), - (unsigned long long)(unsigned int)(char *) super, 0xedde0d90) - || (substring (REISER3FS_SUPER_MAGIC_STRING, super->s_magic, 0) > 0 - && substring (REISER2FS_SUPER_MAGIC_STRING, super->s_magic, 0) > 0 - && substring (REISERFS_SUPER_MAGIC_STRING, super->s_magic, 0) > 0) - || (/* check that this is not a copy inside the journal log */ - super->s_journal_block * super->s_blocksize - <= REISERFS_DISK_OFFSET_IN_BYTES)) - { - /* Try old super block position */ - superblock = REISERFS_OLD_DISK_OFFSET_IN_BYTES >> SECTOR_BITS; - if ((unsigned long)part_length < superblock + (sizeof (struct reiserfs_super_block) >> SECTOR_BITS) - || ! devread (superblock, 0, sizeof (struct reiserfs_super_block), - (unsigned long long)(unsigned int)(char *) super, 0xedde0d90)) - return 0; - - if (substring (REISER3FS_SUPER_MAGIC_STRING, super->s_magic, 0) > 0 - && substring (REISER2FS_SUPER_MAGIC_STRING, super->s_magic, 0) > 0 - && substring (REISERFS_SUPER_MAGIC_STRING, super->s_magic, 0) > 0) - { - /* pre journaling super block ? */ - if (substring (REISERFS_SUPER_MAGIC_STRING, - (char*) ((int) super + 20), 0) > 0) - return 0; - - super->s_blocksize = REISERFS_OLD_BLOCKSIZE; - super->s_journal_block = 0; - super->s_version = 0; - } - } - - /* check the version number. */ - if (super->s_version > REISERFS_MAX_SUPPORTED_VERSION) - return 0; - - INFO->version = super->s_version; - INFO->blocksize = super->s_blocksize; - INFO->fullblocksize_shift = log2_tmp (super->s_blocksize); - INFO->blocksize_shift = INFO->fullblocksize_shift - SECTOR_BITS; - INFO->cached_slots = - (FSYSREISER_CACHE_SIZE >> INFO->fullblocksize_shift) - 1; - -#ifdef REISERDEBUG - printf ("reiserfs_mount: version=%d, blocksize=%d\n", - (INFO->version), (INFO->blocksize)); -#endif /* REISERDEBUG */ - - /* Clear node cache. */ - memset (INFO->blocks, 0, sizeof (INFO->blocks)); - - if (super->s_blocksize < FSYSREISER_MIN_BLOCKSIZE - || super->s_blocksize > FSYSREISER_MAX_BLOCKSIZE - || (SECTOR_SIZE << INFO->blocksize_shift) != super->s_blocksize) - return 0; - - /* Initialize journal code. If something fails we end with zero - * journal_transactions, so we don't access the journal at all. - */ - INFO->journal_transactions = 0; - if (super->s_journal_block != 0 && super->s_journal_dev == 0) - { - INFO->journal_block = super->s_journal_block; - INFO->journal_block_count = super->s_journal_size; - if (is_power_of_two (INFO->journal_block_count)) - journal_init (); - - /* Read in super block again, maybe it is in the journal */ - block_read (superblock >> INFO->blocksize_shift, - 0, sizeof (struct reiserfs_super_block), (unsigned long long)(unsigned int)(char *) super, 0xedde0d90); - } - - if (! block_read (super->s_root_block, 0, INFO->blocksize, (unsigned long long)(unsigned int)(char*) ROOT, 0xedde0d90)) - return 0; - - INFO->tree_depth = BLOCKHEAD (ROOT)->blk_level; - -#ifdef REISERDEBUG - printf ("root read_in: block=%d, depth=%d\n", - super->s_root_block, (INFO->tree_depth)); -#endif /* REISERDEBUG */ - - if (INFO->tree_depth >= MAX_HEIGHT) - return 0; - if (INFO->tree_depth == DISK_LEAF_NODE_LEVEL) - { - /* There is only one node in the whole filesystem, - * which is simultanously leaf and root */ - memcpy (LEAF, ROOT, INFO->blocksize); - } - return 1; -} - -/***************** TREE ACCESSING METHODS *****************************/ - -/* I assume you are familiar with the ReiserFS tree, if not go to - * http://www.namesys.com/content_table.html - * - * My tree node cache is organized as following - * 0 ROOT node - * 1 LEAF node (if the ROOT is also a LEAF it is copied here - * 2-n other nodes on current path from bottom to top. - * if there is not enough space in the cache, the top most are - * omitted. - * - * I have only two methods to find a key in the tree: - * search_stat(dir_id, objectid) searches for the stat entry (always - * the first entry) of an object. - * next_key() gets the next key in tree order. - * - * This means, that I can only sequential reads of files are - * efficient, but this really doesn't hurt for grub. - */ - -/* Read in the node at the current path and depth into the node cache. - * You must set INFO->blocks[depth] before. - */ -static char * -read_tree_node (unsigned int blockNr, int depth) -{ - char* cache = CACHE(depth); - int num_cached = INFO->cached_slots; - if (depth < num_cached) - { - /* This is the cached part of the path. Check if same block is - * needed. - */ - if (blockNr == INFO->blocks[depth]) - return cache; - } - else - cache = CACHE(num_cached); - -#ifdef REISERDEBUG - printf (" next read_in: block=%d (depth=%d)\n", - blockNr, depth); -#endif /* REISERDEBUG */ - if (! block_read (blockNr, 0, INFO->blocksize, (unsigned long long)(unsigned int)cache, 0xedde0d90)) - return 0; - /* Make sure it has the right node level */ - if (BLOCKHEAD (cache)->blk_level != depth) - { - errnum = ERR_FSYS_CORRUPT; - return 0; - } - - INFO->blocks[depth] = blockNr; - return cache; -} - -/* Get the next key, i.e. the key following the last retrieved key in - * tree order. INFO->current_ih and - * INFO->current_info are adapted accordingly. */ -static int -next_key (void) -{ - int depth; - struct item_head *ih = INFO->current_ih + 1; - char *cache; - -#ifdef REISERDEBUG - printf ("next_key:\n old ih: key %d:%d:%d:%d version:%d\n", - (INFO->current_ih->ih_key.k_dir_id), - (INFO->current_ih->ih_key.k_objectid), - (INFO->current_ih->ih_key.u.v1.k_offset), - (INFO->current_ih->ih_key.u.v1.k_uniqueness), - (INFO->current_ih->ih_version)); -#endif /* REISERDEBUG */ - - if (ih == &ITEMHEAD[BLOCKHEAD (LEAF)->blk_nr_item]) - { - depth = DISK_LEAF_NODE_LEVEL; - /* The last item, was the last in the leaf node. - * Read in the next block - */ - do - { - if (depth == INFO->tree_depth) - { - /* There are no more keys at all. - * Return a dummy item with MAX_KEY */ - ih = (struct item_head *) &BLOCKHEAD (LEAF)->blk_right_delim_key; - goto found; - } - depth++; -#ifdef REISERDEBUG - printf (" depth=%d, i=%d\n", depth, (INFO->next_key_nr[depth])); -#endif /* REISERDEBUG */ - } - while (INFO->next_key_nr[depth] == 0); - - if (depth == INFO->tree_depth) - cache = ROOT; - else if (depth <= INFO->cached_slots) - cache = CACHE (depth); - else - { - cache = read_tree_node (INFO->blocks[depth], depth); - if (! cache) - return 0; - } - - do - { - int nr_item = BLOCKHEAD (cache)->blk_nr_item; - int key_nr = INFO->next_key_nr[depth]++; -#ifdef REISERDEBUG - printf (" depth=%d, i=%d/%d\n", depth, key_nr, nr_item); -#endif /* REISERDEBUG */ - if (key_nr == nr_item) - /* This is the last item in this block, set the next_key_nr to 0 */ - INFO->next_key_nr[depth] = 0; - - cache = read_tree_node (DC (cache)[key_nr].dc_block_number, --depth); - if (! cache) - return 0; - } - while (depth > DISK_LEAF_NODE_LEVEL); - - ih = ITEMHEAD; - } - found: - INFO->current_ih = ih; - INFO->current_item = &LEAF[ih->ih_item_location]; -#ifdef REISERDEBUG - printf (" new ih: key %d:%d:%d:%d version:%d\n", - (INFO->current_ih->ih_key.k_dir_id), - (INFO->current_ih->ih_key.k_objectid), - (INFO->current_ih->ih_key.u.v1.k_offset), - (INFO->current_ih->ih_key.u.v1.k_uniqueness), - (INFO->current_ih->ih_version)); -#endif /* REISERDEBUG */ - return 1; -} - -/* preconditions: reiserfs_mount already executed, therefore - * INFO block is valid - * returns: 0 if error (errnum is set), - * nonzero iff we were able to find the key successfully. - * postconditions: on a nonzero return, the current_ih and - * current_item fields describe the key that equals the - * searched key. INFO->next_key contains the next key after - * the searched key. - * side effects: messes around with the cache. - */ -static int -search_stat (__u32 dir_id, __u32 objectid) -{ - char *cache; - int depth; - int nr_item; - int i; - struct item_head *ih; -#ifdef REISERDEBUG - printf ("search_stat:\n key %d:%d:0:0\n", dir_id, objectid); -#endif /* REISERDEBUG */ - - depth = INFO->tree_depth; - cache = ROOT; - - while (depth > DISK_LEAF_NODE_LEVEL) - { - struct key *key; - nr_item = BLOCKHEAD (cache)->blk_nr_item; - - key = KEY (cache); - - for (i = 0; i < nr_item; i++) - { - if (key->k_dir_id > dir_id - || (key->k_dir_id == dir_id - && (key->k_objectid > objectid - || (key->k_objectid == objectid - && (key->u.v1.k_offset - | key->u.v1.k_uniqueness) > 0)))) - break; - key++; - } - -#ifdef REISERDEBUG - printf (" depth=%d, i=%d/%d\n", depth, i, nr_item); -#endif /* REISERDEBUG */ - INFO->next_key_nr[depth] = (i == nr_item) ? 0 : i+1; - cache = read_tree_node (DC (cache)[i].dc_block_number, --depth); - if (! cache) - return 0; - } - - /* cache == LEAF */ - nr_item = BLOCKHEAD (LEAF)->blk_nr_item; - ih = ITEMHEAD; - for (i = 0; i < nr_item; i++) - { - if (ih->ih_key.k_dir_id == dir_id - && ih->ih_key.k_objectid == objectid - && ih->ih_key.u.v1.k_offset == 0 - && ih->ih_key.u.v1.k_uniqueness == 0) - { -#ifdef REISERDEBUG - printf (" depth=%d, i=%d/%d\n", depth, i, nr_item); -#endif /* REISERDEBUG */ - INFO->current_ih = ih; - INFO->current_item = &LEAF[ih->ih_item_location]; - return 1; - } - ih++; - } - errnum = ERR_FSYS_CORRUPT; - return 0; -} - -unsigned long long -reiserfs_read (unsigned long long buf, unsigned long long len, unsigned long write) -{ - unsigned long blocksize; - unsigned long offset; - unsigned long to_read; - unsigned long prev_filepos = filepos; - -#ifdef REISERDEBUG - printf ("reiserfs_read: filepos=%ld len=%ld, offset=%lx\n", - (unsigned long long)filepos, (unsigned long long)len, (__u64) IH_KEY_OFFSET (INFO->current_ih) - 1); -#endif /* REISERDEBUG */ - - if (INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid - || IH_KEY_OFFSET (INFO->current_ih) > filepos + 1) - { - search_stat (INFO->fileinfo.k_dir_id, INFO->fileinfo.k_objectid); - goto get_next_key; - } - - while (! errnum) - { - if (INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid) - break; - - offset = filepos - IH_KEY_OFFSET (INFO->current_ih) + 1; - blocksize = INFO->current_ih->ih_item_len; - -#ifdef REISERDEBUG - printf (" loop: filepos=%ld len=%ld, offset=%ld blocksize=%ld\n", - (unsigned long long)filepos, (unsigned long long)len, (unsigned long long)offset, (unsigned long long)blocksize); -#endif /* REISERDEBUG */ - - if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_DIRECT) - && offset < blocksize) - { -#ifdef REISERDEBUG - printf ("direct_read: offset=%ld, blocksize=%ld\n", - (unsigned long long)offset, (unsigned long long)blocksize); -#endif /* REISERDEBUG */ - to_read = blocksize - offset; - if (to_read > len) - to_read = len; - - if (disk_read_hook != NULL) - { - disk_read_func = disk_read_hook; - - block_read (INFO->blocks[DISK_LEAF_NODE_LEVEL], - (INFO->current_item - LEAF + offset), to_read, buf, write); - - disk_read_func = NULL; - } - else if (buf) - grub_memmove64 (buf, (unsigned long long)(unsigned int)(INFO->current_item + offset), to_read); - goto update_buf_len; - } - else if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_INDIRECT)) - { - blocksize = (blocksize >> 2) << INFO->fullblocksize_shift; -#ifdef REISERDEBUG - printf ("indirect_read: offset=%ld, blocksize=%ld\n", - (unsigned long long)offset, (unsigned long long)blocksize); -#endif /* REISERDEBUG */ - - while (offset < blocksize) - { - __u32 blocknr = ((__u32 *) INFO->current_item) - [offset >> INFO->fullblocksize_shift]; - unsigned long blk_offset = offset & (INFO->blocksize-1); - - to_read = INFO->blocksize - blk_offset; - if (to_read > len) - to_read = len; - - disk_read_func = disk_read_hook; - - /* Journal is only for meta data. Data blocks can be read - * directly without using block_read - */ - devread (blocknr << INFO->blocksize_shift, - blk_offset, to_read, buf, write); - - disk_read_func = NULL; -update_buf_len: - len -= to_read; - if (buf) - buf += to_read; - offset += to_read; - filepos += to_read; - if (len == 0) - goto done; - } - } -get_next_key: - next_key (); - } /* while (! errnum) */ -done: - return errnum ? 0 : filepos - prev_filepos; -} - - -/* preconditions: reiserfs_mount already executed, therefore - * INFO block is valid - * returns: 0 if error, nonzero iff we were able to find the file successfully - * postconditions: on a nonzero return, INFO->fileinfo contains the info - * of the file we were trying to look up, filepos is 0 and filemax is - * the size of the file. - */ -int -reiserfs_dir (char *dirname) -{ - struct reiserfs_de_head *de_head; - char *rest, ch; - __u32 dir_id, objectid, parent_dir_id = 0, parent_objectid = 0; -// unsigned long do_possibilities = 0; - - unsigned long link_count = 0; - unsigned long mode; - - dir_id = REISERFS_ROOT_PARENT_OBJECTID; - objectid = REISERFS_ROOT_OBJECTID; - - while (1) - { -#ifdef REISERDEBUG - printf ("dirname=%s\n", dirname); -#endif /* REISERDEBUG */ - - /* Search for the stat info first. */ - if (! search_stat (dir_id, objectid)) - return 0; - -#ifdef REISERDEBUG - printf ("sd_mode=%x sd_size=%d\n", - ((struct stat_data *) INFO->current_item)->sd_mode, - ((struct stat_data *) INFO->current_item)->sd_size); -#endif /* REISERDEBUG */ - - mode = ((struct stat_data *) INFO->current_item)->sd_mode; - - /* If we've got a symbolic link, then chase it. */ - if (S_ISLNK (mode)) - { - unsigned long len; - if (++link_count > MAX_LINK_COUNT) - { - errnum = ERR_SYMLINK_LOOP; - return 0; - } - - /* Get the symlink size. */ - filemax = ((struct stat_data *) INFO->current_item)->sd_size; - - /* Find out how long our remaining name is. */ - //len = 0; - //while (dirname[len] && !isspace (dirname[len])) - // len++; - for (len = 0; (ch = dirname[len]) /*&& !isspace (ch)*/; len++) - { -#if 0 - if (ch == '\\') - { - len++; - if (! (ch = dirname[len])) - break; - } -#endif - } - - if (filemax + len > PATH_MAX - 1) - { - errnum = ERR_FILELENGTH; - return 0; - } - - /* Copy the remaining name to the end of the symlink data. - Note that DIRNAME and LINKBUF may overlap! */ - grub_memmove (linkbuf + filemax, dirname, len+1); - - INFO->fileinfo.k_dir_id = dir_id; - INFO->fileinfo.k_objectid = objectid; - filepos = 0; - if (! next_key () - || reiserfs_read ((unsigned long long)(unsigned int)linkbuf, filemax, 0xedde0d90) != filemax) - { - if (! errnum) - errnum = ERR_FSYS_CORRUPT; - return 0; - } - -#ifdef REISERDEBUG - printf ("symlink=%s\n", linkbuf); -#endif /* REISERDEBUG */ - - dirname = linkbuf; - if (*dirname == '/') - { - /* It's an absolute link, so look it up in root. */ - dir_id = REISERFS_ROOT_PARENT_OBJECTID; - objectid = REISERFS_ROOT_OBJECTID; - } - else - { - /* Relative, so look it up in our parent directory. */ - dir_id = parent_dir_id; - objectid = parent_objectid; - } - - /* Now lookup the new name. */ - continue; - } - - /* if we have a real file (and we're not just printing possibilities), - then this is where we want to exit */ - - if (! *dirname || isspace (*dirname)) - { - if (! S_ISREG (mode)) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - filepos = 0; - filemax = ((struct stat_data *) INFO->current_item)->sd_size; - - /* If this is a new stat data and size is > 4GB set filemax to - * maximum - */ - if (INFO->current_ih->ih_version == ITEM_VERSION_2 - && ((struct stat_data *) INFO->current_item)->sd_size_hi > 0) - filemax = 0xffffffff; - - INFO->fileinfo.k_dir_id = dir_id; - INFO->fileinfo.k_objectid = objectid; - return next_key (); - } - - /* continue with the file/directory name interpretation */ - while (*dirname == '/') - dirname++; - if (! S_ISDIR (mode)) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - /* skip to next slash or end of filename (space) */ -// for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++); - for (rest = dirname; (ch = *rest) /*&& !isspace (ch)*/ && ch != '/'; rest++) - { -#if 0 - if (ch == '\\') - { - rest++; - if (! (ch = *rest)) - break; - } -#endif - } - - *rest = 0; - -// if (print_possibilities && ch != '/') -// do_possibilities = 1; - - while (1) - { - char *name_end; - unsigned long num_entries; - - if (! next_key ()) - return 0; -#ifdef REISERDEBUG - printf ("ih: key %d:%d:%d:%d version:%d\n", - (INFO->current_ih->ih_key.k_dir_id), - (INFO->current_ih->ih_key.k_objectid), - (INFO->current_ih->ih_key.u.v1.k_offset), - (INFO->current_ih->ih_key.u.v1.k_uniqueness), - (INFO->current_ih->ih_version)); -#endif /* REISERDEBUG */ - - if (INFO->current_ih->ih_key.k_objectid != objectid) - break; - - name_end = INFO->current_item + INFO->current_ih->ih_item_len; - de_head = (struct reiserfs_de_head *) INFO->current_item; - num_entries = INFO->current_ih->u.ih_entry_count; - while (num_entries > 0) - { - char *filename = INFO->current_item + de_head->deh_location; - //char tmp = *name_end; - int j, k; - char ch1; - //char *tmp_name = NAME_BUF; - - /* Name length = name_end - filename */ - - /* copy filename to tmp_name, and quote spaces with '\\' */ - for (j = 0, k = 0; j < name_end - filename; j++) - { - if (! (ch1 = filename[j])) - break; -#if 0 - if (ch1 == ' ') - tmp_name[k++] = '\\'; -#endif - tmp_name[k++] = ch1; - } - tmp_name[k] = 0; - - if ((de_head->deh_state & DEH_Visible)) - { - int cmp; - /* Directory names in ReiserFS are not null - * terminated. We write a temporary 0 behind it. - * NOTE: that this may overwrite the first block in - * the tree cache. That doesn't hurt as long as we - * don't call next_key () in between. - */ - //*name_end = 0; - cmp = substring (dirname, tmp_name, 0); - //*name_end = tmp; - if (print_possibilities && ch != '/') - { - if (cmp <= 0) - { - if (print_possibilities > 0) - print_possibilities = -print_possibilities; - //*name_end = 0; - print_a_completion (tmp_name, 0); - //*name_end = tmp; - } - } - else - if (cmp == 0) - goto found; - } - /* The beginning of this name marks the end of the next name. - */ - name_end = filename; - de_head++; - num_entries--; - } - } - - if (print_possibilities < 0) - return 1; - - errnum = ERR_FILE_NOT_FOUND; - *rest = ch; - return 0; - - found: - - *rest = ch; - dirname = rest; - - parent_dir_id = dir_id; - parent_objectid = objectid; - dir_id = de_head->deh_dir_id; - objectid = de_head->deh_objectid; - } -} - -unsigned long -reiserfs_embed (unsigned long *start_sector, unsigned long needed_sectors) -{ - unsigned long num_sectors; - - if (! devread (REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS, 0, - sizeof (struct reiserfs_super_block), (unsigned long long)(unsigned int)(char *) super, 0xedde0d90)) - return 0; - - *start_sector = 1; /* reserve first sector for stage1 */ - if ((substring (REISERFS_SUPER_MAGIC_STRING, super->s_magic, 0) <= 0 - || substring (REISER2FS_SUPER_MAGIC_STRING, super->s_magic, 0) <= 0 - || substring (REISER3FS_SUPER_MAGIC_STRING, super->s_magic, 0) <= 0) - && (/* check that this is not a super block copy inside - * the journal log */ - super->s_journal_block * super->s_blocksize - > REISERFS_DISK_OFFSET_IN_BYTES)) - num_sectors = (REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS) - 1; - else - num_sectors = (REISERFS_OLD_DISK_OFFSET_IN_BYTES >> SECTOR_BITS) - 1; - - return (needed_sectors <= num_sectors); -} -#endif /* FSYS_REISERFS */ diff --git a/stage2/fsys_ufs2.c b/stage2/fsys_ufs2.c deleted file mode 100644 index e9f07bab..00000000 --- a/stage2/fsys_ufs2.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2000, 2001 Free Software Foundation, Inc. - * Copyright (c) 2004 Valery Hromov - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * Elements of this file were originally from the FreeBSD "biosboot" - * bootloader file "disk.c" dated 4/12/95. - * - * The license and header comments from that file are included here. - */ - -/* - * Mach Operating System - * Copyright (c) 1992, 1991 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - * - * from: Mach, Revision 2.2 92/04/04 11:35:49 rpd - * $Id: fsys_ufs2.c,v 1.2 2004/06/19 12:17:52 okuji Exp $ - */ - -#ifdef FSYS_UFS2 - -#include "shared.h" -#include "filesys.h" - -#include "ufs2.h" - -/* used for filesystem map blocks */ -static int mapblock; -static int mapblock_offset; -static int mapblock_bsize; - -static int sblock_try[] = SBLOCKSEARCH; -static ufs2_daddr_t sblockloc; -static int type; - -/* pointer to superblock */ -#define SUPERBLOCK ((struct fs *) ( FSYS_BUF + 8192 )) - -#define INODE_UFS2 ((struct ufs2_dinode *) ( FSYS_BUF + 16384 )) - -#define MAPBUF ( FSYS_BUF + 24576 ) -#define MAPBUF_LEN 8192 -#define NAME_BUF (FSYS_BUF - 512) - -int -ufs2_mount (void) -{ - int retval = 0; - int i; - - sblockloc = -1; - type = 0; - -// if (! (((current_drive & 0x80) || (current_slice != 0)) -// && ! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_BSDFFS))) - { - for (i = 0; sblock_try[i] != -1; ++i) - { - if (! ((unsigned long)part_length < (sblock_try[i] + (SBLOCKSIZE / DEV_BSIZE)) - || ! devread (0, sblock_try[i], SBLOCKSIZE, (unsigned long long)(unsigned int)(char *) SUPERBLOCK, 0xedde0d90))) - { - if (SUPERBLOCK->fs_magic == FS_UFS2_MAGIC /* && - (SUPERBLOCK->fs_sblockloc == sblockloc || - (SUPERBLOCK->fs_old_flags & FS_FLAGS_UPDATED) == 0)*/) - { - type = 2; - } - else - { - continue; - } - - retval = 1; - sblockloc = sblock_try[i]; - break; - } - } - } - - mapblock = -1; - mapblock_offset = -1; - - return retval; -} - -static grub_int64_t -block_map (int file_block) -{ - int bnum, offset, bsize; - - if (file_block < NDADDR) - return (INODE_UFS2->di_db[file_block]); - - /* If the blockmap loaded does not include FILE_BLOCK, - load a new blockmap. */ - - if ((bnum = fsbtodb (SUPERBLOCK, INODE_UFS2->di_ib[0])) != mapblock - || (mapblock_offset <= bnum && bnum <= mapblock_offset + mapblock_bsize)) - { - if (MAPBUF_LEN < SUPERBLOCK->fs_bsize) - { - offset = ((file_block - NDADDR) % NINDIR (SUPERBLOCK)); - bsize = MAPBUF_LEN; - - if (offset + MAPBUF_LEN > SUPERBLOCK->fs_bsize) - offset = (SUPERBLOCK->fs_bsize - MAPBUF_LEN) / sizeof (int); - } - else - { - bsize = SUPERBLOCK->fs_bsize; - offset = 0; - } - - if (! devread (bnum, offset * sizeof (int), bsize, (unsigned long long)(unsigned int)(char *) MAPBUF, 0xedde0d90)) - { - mapblock = -1; - mapblock_bsize = -1; - mapblock_offset = -1; - errnum = ERR_FSYS_CORRUPT; - return -1; - } - - mapblock = bnum; - mapblock_bsize = bsize; - mapblock_offset = offset; - } - - return (((grub_int64_t *) MAPBUF)[((file_block - NDADDR) % NINDIR (SUPERBLOCK)) - - mapblock_offset]); -} - -unsigned long long -ufs2_read (unsigned long long buf, unsigned long long len, unsigned long write) -{ - unsigned long logno, off, size, ret = 0; - grub_int64_t map; - - while (len && !errnum) - { - off = blkoff (SUPERBLOCK, filepos); - logno = lblkno (SUPERBLOCK, filepos); - size = blksize (SUPERBLOCK, INODE_UFS2, logno); - - if ((map = block_map (logno)) < 0) - break; - - size -= off; - - if (size > len) - size = len; - - disk_read_func = disk_read_hook; - - devread (fsbtodb (SUPERBLOCK, map), off, size, buf, write); - - disk_read_func = NULL; - - if (buf) - buf += size; - len -= size; /* len always >= 0 */ - filepos += size; - ret += size; - } - - if (errnum) - ret = 0; - - return ret; -} - -int -ufs2_dir (char *dirname) -{ - char *rest, ch; - unsigned long block, off, loc, ino = ROOTINO; - grub_int64_t map; - struct direct *dp; - int j, k; - char ch1; - char *tmp_name = (char *)(NAME_BUF); /* MAXNAMLEN is 255, so 512 byte buffer is needed. */ - -/* main loop to find destination inode */ -loop: - - /* load current inode (defaults to the root inode) */ - - if (!devread (fsbtodb (SUPERBLOCK, ino_to_fsba (SUPERBLOCK, ino)), - ino % (SUPERBLOCK->fs_inopb) * sizeof (struct ufs2_dinode), - sizeof (struct ufs2_dinode), (unsigned long long)(unsigned int)(char *) INODE_UFS2, 0xedde0d90)) - return 0; /* XXX what return value? */ - - /* if we have a real file (and we're not just printing possibilities), - then this is where we want to exit */ - - if (!*dirname || isspace (*dirname)) - { - if ((INODE_UFS2->di_mode & IFMT) != IFREG) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - filemax = INODE_UFS2->di_size; - - /* incomplete implementation requires this! */ - fsmax = (NDADDR + NINDIR (SUPERBLOCK)) * SUPERBLOCK->fs_bsize; - return 1; - } - - /* continue with file/directory name interpretation */ - - while (*dirname == '/') - dirname++; - - if (!(INODE_UFS2->di_size) || ((INODE_UFS2->di_mode & IFMT) != IFDIR)) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - //for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++); - for (rest = dirname; (ch = *rest) /*&& !isspace (ch)*/ && ch != '/'; rest++) - { -#if 0 - if (ch == '\\') - { - rest++; - if (! (ch = *rest)) - break; - } -#endif - } - - *rest = 0; - loc = 0; - - /* loop for reading a the entries in a directory */ - - do - { - if (loc >= INODE_UFS2->di_size) - { - if (print_possibilities < 0) - return 1; - - errnum = ERR_FILE_NOT_FOUND; - *rest = ch; - return 0; - } - - if (!(off = blkoff (SUPERBLOCK, loc))) - { - block = lblkno (SUPERBLOCK, loc); - - if ((map = block_map (block)) < 0 - || !devread (fsbtodb (SUPERBLOCK, map), 0, - blksize (SUPERBLOCK, INODE_UFS2, block), - (unsigned long long)(unsigned int)(char *) FSYS_BUF, 0xedde0d90)) - { - errnum = ERR_FSYS_CORRUPT; - *rest = ch; - return 0; - } - } - - dp = (struct direct *) (FSYS_BUF + off); - loc += dp->d_reclen; - - /* copy dp->name to tmp_name, and quote the spaces with a '\\' */ - for (j = 0, k = 0; j < dp->d_namlen; j++) - { - if (! (ch1 = dp->d_name[j])) - break; -#if 0 - if (ch1 == ' ') - tmp_name[k++] = '\\'; -#endif - tmp_name[k++] = ch1; - } - tmp_name[k] = 0; - - if (dp->d_ino && print_possibilities && ch != '/' - && (!*dirname || substring (dirname, tmp_name, 0) <= 0)) - { - if (print_possibilities > 0) - print_possibilities = -print_possibilities; - - print_a_completion (tmp_name, 0); - } - } - while (!dp->d_ino || (substring (dirname, dp->d_name, 0) != 0 - || (print_possibilities && ch != '/'))); - - /* only get here if we have a matching directory entry */ - - ino = dp->d_ino; - *(dirname = rest) = ch; - - /* go back to main loop at top of function */ - goto loop; -} - -unsigned long -ufs2_embed (unsigned long *start_sector, unsigned long needed_sectors) -{ - /* XXX: I don't know if this is really correct. Someone who is - familiar with BSD should check for this. */ - if (needed_sectors > 14) - return 0; - - *start_sector = 1; -#if 1 - /* FIXME: Disable the embedding in FFS until someone checks if - the code above is correct. */ - return 0; -#else - return 1; -#endif -} - -#endif /* FSYS_UFS2 */ diff --git a/stage2/fsys_vstafs.c b/stage2/fsys_vstafs.c deleted file mode 100644 index edf51898..00000000 --- a/stage2/fsys_vstafs.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2001 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifdef FSYS_VSTAFS - -#include "shared.h" -#include "filesys.h" -#include "vstafs.h" - - -static void get_file_info (int sector); -static struct dir_entry *vstafs_readdir (long sector); -static struct dir_entry *vstafs_nextdir (void); - - -#define FIRST_SECTOR ((struct first_sector *) FSYS_BUF) -#define FILE_INFO ((struct fs_file *) (int) FIRST_SECTOR + 8192) -#define DIRECTORY_BUF ((struct dir_entry *) (int) FILE_INFO + 512) -#define NAME_BUF ((char *)((FSYS_BUF) + 8192 + 512 + 512)) - -#define ROOT_SECTOR 1 - -/* - * In f_sector we store the sector number in which the information about - * the found file is. - */ -static int f_sector; - -int -vstafs_mount (void) -{ - int retval = 1; - - if( /*(((current_drive & 0x80) || (current_slice != 0)) - && current_slice != PC_SLICE_TYPE_VSTAFS) - ||*/ ! devread (0, 0, BLOCK_SIZE, (unsigned long long)(unsigned int)(char *) FSYS_BUF, 0xedde0d90) - || FIRST_SECTOR->fs_magic != 0xDEADFACE) - retval = 0; - - return retval; -} - -static void -get_file_info (int sector) -{ - devread (sector, 0, BLOCK_SIZE, (unsigned long long)(unsigned int)(char *) FILE_INFO, 0xedde0d90); -} - -static int curr_ext, current_direntry, current_blockpos; -static struct alloc *blocks; - -static struct dir_entry * -vstafs_readdir (long sector) -{ - /* - * Get some information from the current directory - */ - get_file_info (sector); - if (FILE_INFO->type != 2) - { - errnum = ERR_FILE_NOT_FOUND; - return 0; - } - - blocks = FILE_INFO->blocks; - curr_ext = 0; - devread (blocks[curr_ext].a_start, 0, 512, (unsigned long long)(unsigned int)(char *) DIRECTORY_BUF, 0xedde0d90); - current_direntry = 11; - current_blockpos = 0; - - return &DIRECTORY_BUF[10]; -} - -static struct dir_entry * -vstafs_nextdir (void) -{ - if (current_direntry > 15) - { - current_direntry = 0; - if (++current_blockpos > (blocks[curr_ext].a_len - 1)) - { - current_blockpos = 0; - curr_ext++; - } - - if (curr_ext < FILE_INFO->extents) - { - devread (blocks[curr_ext].a_start + current_blockpos, 0, - 512, (unsigned long long)(unsigned int)(char *) DIRECTORY_BUF, 0xedde0d90); - } - else - { - /* errnum =ERR_FILE_NOT_FOUND; */ - return 0; - } - } - - return &DIRECTORY_BUF[current_direntry++]; -} - -int -vstafs_dir (char *dirname) -{ - char *fn, ch; - struct dir_entry *d; - /* int l, i, s; */ - - /* - * Read in the entries of the current directory. - */ - f_sector = ROOT_SECTOR; - do - { - if (! (d = vstafs_readdir (f_sector))) - { - return 0; - } - - /* - * Find the file in the path - */ - while (*dirname == '/') dirname++; - //fn = dirname; - //while ((ch = *fn) && ch != '/' && ! isspace (ch)) fn++; - for (fn = dirname; (ch = *fn) && ch != '/' /*&& !isspace (ch)*/; fn++) - { -#if 0 - if (ch == '\\') - { - fn++; - if (! (ch = *fn)) - break; - } -#endif - } - *fn = 0; - - do - { - int j, k; - char ch1; - char *tmp_name = NAME_BUF; /* MAXNAMLEN is 255, so 512 byte buffer is needed. */ - - if (d->name[0] == 0/* || d->name[0] & 0x80*/) - continue; - - /* copy d->name to tmp_name, and quote the spaces with a '\\' */ - for (j = 0, k = 0; j < 28/*d->namlen*/; j++) - { - if (! (ch1 = d->name[j])) - break; -#if 0 - if (ch1 == ' ') - tmp_name[k++] = '\\'; -#endif - tmp_name[k++] = ch1; - } - tmp_name[k] = 0; - - if (print_possibilities && ch != '/' - && (! *dirname || strcmp (dirname, tmp_name) <= 0)) - { - if (print_possibilities > 0) - print_possibilities = -print_possibilities; - - print_a_completion (tmp_name, 0); - } - if (! grub_strcmp (dirname, tmp_name)) - { - f_sector = d->start; - get_file_info (f_sector); - filemax = FILE_INFO->len; - break; - } - } - while ((d =vstafs_nextdir ())); - - *(dirname = fn) = ch; - - if (! d) - { - if (print_possibilities < 0) - { - putchar ('\n', 255); - return 1; - } - - errnum = ERR_FILE_NOT_FOUND; - return 0; - } - } - while (*dirname && ! isspace (ch)); - - return 1; -} - -unsigned long long -vstafs_read (unsigned long long buf, unsigned long long len, unsigned long write) -{ - //struct alloc *blocks; - unsigned long size, ret = 0, offset, curr_len = 0; - //int curr_ext; - char extent; - unsigned long ext_size; - //char *curr_pos; - - get_file_info (f_sector); - size = FILE_INFO->len-VSTAFS_START_DATA; - blocks = FILE_INFO->blocks; - - if (filepos > 0) - { - if (filepos < blocks[0].a_len * 512 - VSTAFS_START_DATA) - { - offset = filepos + VSTAFS_START_DATA; - extent = 0; - curr_len = blocks[0].a_len * 512 - offset - filepos; - } - else - { - ext_size = blocks[0].a_len * 512 - VSTAFS_START_DATA; - offset = filepos - ext_size; - extent = 1; - do - { - curr_len -= ext_size; - offset -= ext_size; - ext_size = blocks[extent+1].a_len * 512; - } - while (extent < FILE_INFO->extents && offset>ext_size); - } - } - else - { - offset = VSTAFS_START_DATA; - extent = 0; - curr_len = blocks[0].a_len * 512 - offset; - } - - //curr_pos = buf; - if (curr_len > len) - curr_len = len; - - curr_ext = extent; - while (curr_ext < FILE_INFO->extents) - { - ret += curr_len; - size -= curr_len; - if (size < 0) - { - ret += size; - curr_len += size; - } - - disk_read_func = disk_read_hook; - devread (blocks[curr_ext].a_start, offset, curr_len, buf, write); - disk_read_func = NULL; - offset = 0; - curr_len = blocks[curr_ext].a_len * 512; - if (buf) - buf += curr_len; - curr_ext++; - } - - return ret; -} - -#endif /* FSYS_VSTAFS */ diff --git a/stage2/fsys_xfs.c b/stage2/fsys_xfs.c deleted file mode 100644 index 3c01b001..00000000 --- a/stage2/fsys_xfs.c +++ /dev/null @@ -1,673 +0,0 @@ -/* fsys_xfs.c - an implementation for the SGI XFS file system */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2001,2002,2004 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifdef FSYS_XFS - -#include "shared.h" -#include "filesys.h" -#include "xfs.h" - -#define MAX_LINK_COUNT 8 - -typedef struct xad { - xfs_fileoff_t offset; - xfs_fsblock_t start; - xfs_filblks_t len; -} xad_t; - -struct xfs_info { - int bsize; - int dirbsize; - int isize; - unsigned int agblocks; - int bdlog; - int blklog; - int inopblog; - int agblklog; - int agnolog; - unsigned int nextents; - xfs_daddr_t next; - xfs_daddr_t daddr; - xfs_dablk_t forw; - xfs_dablk_t dablk; - xfs_bmbt_rec_32_t *xt; - xfs_bmbt_ptr_t ptr0; - int btnode_ptr0_off; - int i8param; - int dirpos; - int dirmax; - int blkoff; - int fpos; - xfs_ino_t rootino; -}; - -static struct xfs_info xfs; - -#define dirbuf ((char *)FSYS_BUF) -#define filebuf ((char *)FSYS_BUF + 4096) -#define inode ((xfs_dinode_t *)((char *)FSYS_BUF + 8192)) -#define icore (inode->di_core) - -#define mask32lo(n) (((xfs_uint32_t)1 << (n)) - 1) - -#define XFS_INO_MASK(k) ((xfs_uint32_t)((1ULL << (k)) - 1)) -#define XFS_INO_OFFSET_BITS xfs.inopblog -#define XFS_INO_AGBNO_BITS xfs.agblklog -#define XFS_INO_AGINO_BITS (xfs.agblklog + xfs.inopblog) -#define XFS_INO_AGNO_BITS xfs.agnolog -#define NAME_BUF ((char *)FSYS_BUF + 12288) - -static inline xfs_agblock_t -agino2agbno (xfs_agino_t agino) -{ - return agino >> XFS_INO_OFFSET_BITS; -} - -static inline xfs_agnumber_t -ino2agno (xfs_ino_t ino) -{ - return ino >> XFS_INO_AGINO_BITS; -} - -static inline xfs_agino_t -ino2agino (xfs_ino_t ino) -{ - return ino & XFS_INO_MASK(XFS_INO_AGINO_BITS); -} - -static inline int -ino2offset (xfs_ino_t ino) -{ - return ino & XFS_INO_MASK(XFS_INO_OFFSET_BITS); -} - -static inline /*__const__*/ xfs_uint16_t -le16 (xfs_uint16_t x) -{ - __asm__("xchgb %b0,%h0" \ - : "=q" (x) \ - : "0" (x)); - return x; -} - -static inline /*__const__*/ xfs_uint32_t -le32 (xfs_uint32_t x) -{ -#if 0 - /* 386 doesn't have bswap. */ - __asm__("bswap %0" : "=r" (x) : "0" (x)); -#else - /* This is slower but this works on all x86 architectures. */ - __asm__("xchgb %b0, %h0" \ - "\n\troll $16, %0" \ - "\n\txchgb %b0, %h0" \ - : "=q" (x) : "0" (x)); -#endif - return x; -} - -static inline /*__const__*/ xfs_uint64_t -le64 (xfs_uint64_t x) -{ - xfs_uint32_t h = x >> 32; - xfs_uint32_t l = x & ((1ULL<<32)-1); - return (((xfs_uint64_t)le32(l)) << 32) | ((xfs_uint64_t)(le32(h))); -} - - -static xfs_fsblock_t -xt_start (xfs_bmbt_rec_32_t *r) -{ - return (((xfs_fsblock_t)(le32 (r->l1) & mask32lo(9))) << 43) | - (((xfs_fsblock_t)le32 (r->l2)) << 11) | - (((xfs_fsblock_t)le32 (r->l3)) >> 21); -} - -static xfs_fileoff_t -xt_offset (xfs_bmbt_rec_32_t *r) -{ - return (((xfs_fileoff_t)le32 (r->l0) & - mask32lo(31)) << 23) | - (((xfs_fileoff_t)le32 (r->l1)) >> 9); -} - -static xfs_filblks_t -xt_len (xfs_bmbt_rec_32_t *r) -{ - return le32(r->l3) & mask32lo(21); -} - -static inline int -xfs_highbit32(xfs_uint32_t v) -{ - int i; - - if (--v) { - for (i = 0; i < 31; i++, v >>= 1) { - if (v == 0) - return i; - } - } - return 0; -} - -static int -isinxt (xfs_fileoff_t key, xfs_fileoff_t offset, xfs_filblks_t len) -{ - return (key >= offset) ? (key < offset + len ? 1 : 0) : 0; -} - -static xfs_daddr_t -agb2daddr (xfs_agnumber_t agno, xfs_agblock_t agbno) -{ - return ((xfs_fsblock_t)agno*xfs.agblocks + agbno) << xfs.bdlog; -} - -static xfs_daddr_t -fsb2daddr (xfs_fsblock_t fsbno) -{ - return agb2daddr ((xfs_agnumber_t)(fsbno >> xfs.agblklog), - (xfs_agblock_t)(fsbno & mask32lo(xfs.agblklog))); -} - -#undef offsetof -#define offsetof(t,m) ((int)&(((t *)0)->m)) - -static inline int -btroot_maxrecs (void) -{ - int tmp = icore.di_forkoff ? (icore.di_forkoff << 3) : xfs.isize; - - return (tmp - sizeof(xfs_bmdr_block_t) - offsetof(xfs_dinode_t, di_u)) / - (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t)); -} - -static int -di_read (xfs_ino_t ino) -{ - xfs_agino_t agino; - xfs_agnumber_t agno; - xfs_agblock_t agbno; - xfs_daddr_t daddr; - int offset; - - agno = ino2agno (ino); - agino = ino2agino (ino); - agbno = agino2agbno (agino); - offset = ino2offset (ino); - daddr = agb2daddr (agno, agbno); - - devread (daddr, offset*xfs.isize, xfs.isize, (unsigned long long)(unsigned int)(char *)inode, 0xedde0d90); - - xfs.ptr0 = *(xfs_bmbt_ptr_t *) - (inode->di_u.di_c + sizeof(xfs_bmdr_block_t) - + btroot_maxrecs ()*sizeof(xfs_bmbt_key_t)); - - return 1; -} - -static void -init_extents (void) -{ - xfs_bmbt_ptr_t ptr0; - xfs_btree_lblock_t h; - - switch (icore.di_format) { - case XFS_DINODE_FMT_EXTENTS: - xfs.xt = inode->di_u.di_bmx; - xfs.nextents = le32 (icore.di_nextents); - break; - case XFS_DINODE_FMT_BTREE: - ptr0 = xfs.ptr0; - for (;;) { - xfs.daddr = fsb2daddr (le64(ptr0)); - devread (xfs.daddr, 0, - sizeof(xfs_btree_lblock_t), (unsigned long long)(unsigned int)(char *)&h, 0xedde0d90); - if (!h.bb_level) { - xfs.nextents = le16(h.bb_numrecs); - xfs.next = fsb2daddr (le64(h.bb_rightsib)); - xfs.fpos = sizeof(xfs_btree_block_t); - return; - } - devread (xfs.daddr, xfs.btnode_ptr0_off, - sizeof(xfs_bmbt_ptr_t), (unsigned long long)(unsigned int)(char *)&ptr0, 0xedde0d90); - } - } -} - -static xad_t * -next_extent (void) -{ - static xad_t xad; - - switch (icore.di_format) { - case XFS_DINODE_FMT_EXTENTS: - if (xfs.nextents == 0) - return NULL; - break; - case XFS_DINODE_FMT_BTREE: - if (xfs.nextents == 0) { - xfs_btree_lblock_t h; - if (xfs.next == 0) - return NULL; - xfs.daddr = xfs.next; - devread (xfs.daddr, 0, sizeof(xfs_btree_lblock_t), (unsigned long long)(unsigned int)(char *)&h, 0xedde0d90); - xfs.nextents = le16(h.bb_numrecs); - xfs.next = fsb2daddr (le64(h.bb_rightsib)); - xfs.fpos = sizeof(xfs_btree_block_t); - } - /* Yeah, I know that's slow, but I really don't care */ - devread (xfs.daddr, xfs.fpos, sizeof(xfs_bmbt_rec_t), (unsigned long long)(unsigned int)filebuf, 0xedde0d90); - xfs.xt = (xfs_bmbt_rec_32_t *)filebuf; - xfs.fpos += sizeof(xfs_bmbt_rec_32_t); - } - xad.offset = xt_offset (xfs.xt); - xad.start = xt_start (xfs.xt); - xad.len = xt_len (xfs.xt); - ++xfs.xt; - --xfs.nextents; - - return &xad; -} - -/* - * Name lies - the function reads only first 100 bytes - */ -static void -xfs_dabread (void) -{ - xad_t *xad; - xfs_fileoff_t offset;; - - init_extents (); - while ((xad = next_extent ())) { - offset = xad->offset; - if (isinxt (xfs.dablk, offset, xad->len)) { - devread (fsb2daddr (xad->start + xfs.dablk - offset), - 0, 100, (unsigned long long)(unsigned int)dirbuf, 0xedde0d90); - break; - } - } -} - -static inline xfs_ino_t -sf_ino (char *sfe, int namelen) -{ - void *p = sfe + namelen + 3; - - return (xfs.i8param == 0) - ? le64(*(xfs_ino_t *)p) : le32(*(xfs_uint32_t *)p); -} - -static inline xfs_ino_t -sf_parent_ino (void) -{ - return (xfs.i8param == 0) - ? le64(*(xfs_ino_t *)(&inode->di_u.di_dir2sf.hdr.parent)) - : le32(*(xfs_uint32_t *)(&inode->di_u.di_dir2sf.hdr.parent)); -} - -static inline int -roundup8 (int n) -{ - return ((n+7)&~7); -} - -static char * -next_dentry (xfs_ino_t *ino) -{ - int namelen = 1; - int toread; - static char usual[2][3] = {".", ".."}; - static xfs_dir2_sf_entry_t *sfe; - char *name = usual[0]; - int j, k; - char ch1; - char *tmp_name = NAME_BUF; /* MAXNAMLEN is 255, so 512 byte buffer is needed. */ - - if (xfs.dirpos >= xfs.dirmax) { - if (xfs.forw == 0) - return NULL; - xfs.dablk = xfs.forw; - xfs_dabread (); -#define h ((xfs_dir2_leaf_hdr_t *)dirbuf) - xfs.dirmax = le16 (h->count) - le16 (h->stale); - xfs.forw = le32 (h->info.forw); -#undef h - xfs.dirpos = 0; - } - - switch (icore.di_format) { - case XFS_DINODE_FMT_LOCAL: - switch (xfs.dirpos) { - case -2: - *ino = 0; - break; - case -1: - *ino = sf_parent_ino (); - ++name; - ++namelen; - sfe = (xfs_dir2_sf_entry_t *) - (inode->di_u.di_c - + sizeof(xfs_dir2_sf_hdr_t) - - xfs.i8param); - break; - default: - namelen = sfe->namelen; - *ino = sf_ino ((char *)sfe, namelen); - name = (char *)(sfe->name); - sfe = (xfs_dir2_sf_entry_t *) - ((char *)sfe + namelen + 11 - xfs.i8param); - } - break; - case XFS_DINODE_FMT_BTREE: - case XFS_DINODE_FMT_EXTENTS: -#define dau ((xfs_dir2_data_union_t *)dirbuf) - for (;;) { - if (xfs.blkoff >= xfs.dirbsize) { - xfs.blkoff = sizeof(xfs_dir2_data_hdr_t); - filepos &= ~(xfs.dirbsize - 1); - filepos |= xfs.blkoff; - } - xfs_read ((unsigned long long)(unsigned int)dirbuf, 4, 0xedde0d90); - xfs.blkoff += 4; - if (dau->unused.freetag == XFS_DIR2_DATA_FREE_TAG) { - toread = roundup8 (le16(dau->unused.length)) - 4; - xfs.blkoff += toread; - filepos += toread; - continue; - } - break; - } - xfs_read ((unsigned long long)(unsigned int)(char *)dirbuf + 4, 5, 0xedde0d90); - *ino = le64 (dau->entry.inumber); - namelen = dau->entry.namelen; -#undef dau - toread = roundup8 (namelen + 11) - 9; - xfs_read ((unsigned long long)(unsigned int)dirbuf, toread, 0xedde0d90); - name = (char *)dirbuf; - xfs.blkoff += toread + 5; - } - ++xfs.dirpos; - name[namelen] = 0; - - /* copy name to tmp_name, and quote the spaces with a '\\' */ - for (j = 0, k = 0; j < namelen; j++) - { - if (! (ch1 = name[j])) - break; -#if 0 - if (ch1 == ' ') - tmp_name[k++] = '\\'; -#endif - tmp_name[k++] = ch1; - } - tmp_name[k] = 0; - return tmp_name; -} - -static char * -first_dentry (xfs_ino_t *ino) -{ - xfs.forw = 0; - switch (icore.di_format) { - case XFS_DINODE_FMT_LOCAL: - xfs.dirmax = inode->di_u.di_dir2sf.hdr.count; - xfs.i8param = inode->di_u.di_dir2sf.hdr.i8count ? 0 : 4; - xfs.dirpos = -2; - break; - case XFS_DINODE_FMT_EXTENTS: - case XFS_DINODE_FMT_BTREE: - filepos = 0; - xfs_read ((unsigned long long)(unsigned int)dirbuf, sizeof(xfs_dir2_data_hdr_t), 0xedde0d90); - if (((xfs_dir2_data_hdr_t *)dirbuf)->magic == le32(XFS_DIR2_BLOCK_MAGIC)) { -#define tail ((xfs_dir2_block_tail_t *)dirbuf) - filepos = xfs.dirbsize - sizeof(*tail); - xfs_read ((unsigned long long)(unsigned int)dirbuf, sizeof(*tail), 0xedde0d90); - xfs.dirmax = le32 (tail->count) - le32 (tail->stale); -#undef tail - } else { - xfs.dablk = (1ULL << 35) >> xfs.blklog; -#define h ((xfs_dir2_leaf_hdr_t *)dirbuf) -#define n ((xfs_da_intnode_t *)dirbuf) - for (;;) { - xfs_dabread (); - if ((n->hdr.info.magic == le16(XFS_DIR2_LEAFN_MAGIC)) - || (n->hdr.info.magic == le16(XFS_DIR2_LEAF1_MAGIC))) { - xfs.dirmax = le16 (h->count) - le16 (h->stale); - xfs.forw = le32 (h->info.forw); - break; - } - xfs.dablk = le32 (n->btree[0].before); - } -#undef n -#undef h - } - xfs.blkoff = sizeof(xfs_dir2_data_hdr_t); - filepos = xfs.blkoff; - xfs.dirpos = 0; - } - return next_dentry (ino); -} - -int -xfs_mount (void) -{ - xfs_sb_t *super = (xfs_sb_t *)0x600; - - if (!devread (0, 0, sizeof(xfs_sb_t), (unsigned long long)(unsigned int)(char *)super, 0xedde0d90) - || (le32(super->sb_magicnum) != XFS_SB_MAGIC) - || ((le16(super->sb_versionnum) - & XFS_SB_VERSION_NUMBITS) != XFS_SB_VERSION_4) ) { - return 0; - } - - xfs.bsize = le32 (super->sb_blocksize); - xfs.blklog = super->sb_blocklog; - xfs.bdlog = xfs.blklog - SECTOR_BITS; - xfs.rootino = le64 (super->sb_rootino); - xfs.isize = le16 (super->sb_inodesize); - xfs.agblocks = le32 (super->sb_agblocks); - xfs.dirbsize = xfs.bsize << super->sb_dirblklog; - - xfs.inopblog = super->sb_inopblog; - xfs.agblklog = super->sb_agblklog; - xfs.agnolog = xfs_highbit32 (le32(super->sb_agcount)); - - xfs.btnode_ptr0_off = - ((xfs.bsize - sizeof(xfs_btree_block_t)) / - (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t))) - * sizeof(xfs_bmbt_key_t) + sizeof(xfs_btree_block_t); - - return 1; -} - -unsigned long long -xfs_read (unsigned long long buf, unsigned long long len, unsigned long write) -{ - xad_t *xad; - xfs_fileoff_t endofprev, endofcur, offset; - xfs_filblks_t xadlen; - unsigned long toread, startpos, endpos; - - if (icore.di_format == XFS_DINODE_FMT_LOCAL) { - if (buf) - grub_memmove64 (buf, (unsigned long long)(unsigned int)(inode->di_u.di_c + filepos), len); - filepos += len; - return len; - } - - startpos = filepos; - endpos = filepos + len; - endofprev = (xfs_fileoff_t)-1; - init_extents (); - while (len > 0 && (xad = next_extent ())) - { - offset = xad->offset; - xadlen = xad->len; - if (isinxt (filepos >> xfs.blklog, offset, xadlen)) { - endofcur = (offset + xadlen) << xfs.blklog; - toread = (endofcur >= endpos) - ? len : (endofcur - filepos); - - disk_read_func = disk_read_hook; - devread (fsb2daddr (xad->start), - filepos - (offset << xfs.blklog), toread, buf, write); - disk_read_func = NULL; - - if (buf) - buf += toread; - len -= toread; /* len always >= 0 */ - filepos += toread; - } else if (offset > endofprev) { - if (write == 0x900ddeed) - { - grub_printf ("Fatal: Cannot write NULL blocks to file!\n"); - return !(errnum = ERR_WRITE); - } - toread = ((offset << xfs.blklog) >= endpos) - ? len : ((offset - endofprev) << xfs.blklog); - filepos += toread; -#if 0 - { - unsigned long tmp_pos = toread; - for (; tmp_pos; tmp_pos--) { - if (buf) - *buf++ = 0; - } - } -#else - if (buf) - { - grub_memset64 (buf, 0, toread); - buf += toread; - } -#endif - if (len < toread) - break; - len -= toread; - continue; - } - endofprev = offset + xadlen; - } - - return filepos - startpos; -} - -int -xfs_dir (char *dirname) -{ - xfs_ino_t ino, parent_ino, new_ino; - xfs_fsize_t di_size; - unsigned long di_mode; - int cmp; - unsigned long n, link_count; - char *rest, *name, ch; - - char *linkbuf = (char *)(FSYS_BUF - xfs.bsize); - - parent_ino = ino = xfs.rootino; - link_count = 0; - for (;;) { - di_read (ino); - di_size = le64 (icore.di_size); - di_mode = le16 (icore.di_mode); - - if ((di_mode & IFMT) == IFLNK) { - if (++link_count > MAX_LINK_COUNT) { - errnum = ERR_SYMLINK_LOOP; - return 0; - } - if (di_size < xfs.bsize - 1) { - filepos = 0; - filemax = di_size; - n = xfs_read ((unsigned long long)(unsigned int)linkbuf, filemax, 0xedde0d90); - } else { - errnum = ERR_FILELENGTH; - return 0; - } - - ino = (linkbuf[0] == '/') ? xfs.rootino : parent_ino; - while (n < (xfs.bsize - 1) && (linkbuf[n++] = *dirname++)); - linkbuf[n] = 0; - dirname = linkbuf; - continue; - } - - if (!*dirname || isspace (*dirname)) { - if ((di_mode & IFMT) != IFREG) { - errnum = ERR_BAD_FILETYPE; - return 0; - } - filepos = 0; - filemax = di_size; - return 1; - } - - if ((di_mode & IFMT) != IFDIR) { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - for (; *dirname == '/'; dirname++); - - //for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++); - for (rest = dirname; (ch = *rest) /*&& !isspace (ch)*/ && ch != '/'; rest++) - { -#if 0 - if (ch == '\\') - { - rest++; - if (! (ch = *rest)) - break; - } -#endif - } - *rest = 0; - - name = first_dentry (&new_ino); - for (;;) { - cmp = (!*dirname) ? -1 : substring (dirname, name, 0); - if (print_possibilities && ch != '/' && cmp <= 0) { - if (print_possibilities > 0) - print_possibilities = -print_possibilities; - print_a_completion (name, 0); - } else - if (cmp == 0) { - parent_ino = ino; - if (new_ino) - ino = new_ino; - *(dirname = rest) = ch; - break; - } - name = next_dentry (&new_ino); - if (name == NULL) { - if (print_possibilities < 0) - return 1; - - errnum = ERR_FILE_NOT_FOUND; - *rest = ch; - return 0; - } - } - } -} - -#endif /* FSYS_XFS */ diff --git a/stage2/graphics.c b/stage2/graphics.c index 5780f811..5b516855 100644 --- a/stage2/graphics.c +++ b/stage2/graphics.c @@ -1,6 +1,6 @@ /* graphics.c - graphics mode support for GRUB */ /* Implemented as a terminal type by Jeremy Katz based - * on a patch by Paulo Csar Pereira de Andrade + * on a patch by Paulo C閟ar Pereira de Andrade */ /* * GRUB -- GRand Unified Bootloader @@ -31,266 +31,64 @@ #include //static int saved_videomode = 0; -extern unsigned char *font8x16; +//extern unsigned char *font8x16; -int outline = 0; -extern unsigned long is_highlight; -extern unsigned long graphics_inited; -char splashimage[128]; +//int outline = 0; #define VSHADOW VSHADOW1 -#if 0 -/* 8x16 dot array, total chars = 80*30. plano size = 80*30*16 = 38400 bytes */ -/* 8x16 dot array, total chars = 100*37. plano size = 800*600/8 = 60000 bytes */ -static unsigned char *VSHADOW1 = (unsigned char *)0x3A0000; //unsigned char VSHADOW1[60000]; -static unsigned char *VSHADOW2 = (unsigned char *)0x3AEA60; //unsigned char VSHADOW2[60000]; -static unsigned char *VSHADOW4 = (unsigned char *)0x3BD4C0; //unsigned char VSHADOW4[60000]; -static unsigned char *VSHADOW8 = (unsigned char *)0x3CBF20; //unsigned char VSHADOW8[60000]; end at 0x3DA980 -/* text buffer has to be kept around so that we can write things as we - * scroll and the like */ -//static unsigned short text[80 * 30]; -static unsigned long *text = (unsigned long *)0x3FC000; // length in bytes = 100*37*4 = 0x39D0 -#endif + //extern unsigned long splashimage_loaded; /* constants to define the viewable area */ -unsigned long x1 = 80; -unsigned long y1 = 30; -unsigned long font_w = 8; -unsigned long font_h = 16; +//unsigned int x1 = 80; +//unsigned int y1 = 30; +unsigned int font_w = 8; +unsigned int font_h = 16; unsigned char num_wide = (16+7)/8; -unsigned long font_spacing = 0; -unsigned long line_spacing = 0; -unsigned long xpixels = 640; -unsigned long ypixels = 480; -unsigned long plano_size = 38400; -unsigned long graphics_mode = 3; -unsigned long current_x_resolution; -unsigned long current_y_resolution; -unsigned long current_bits_per_pixel; -unsigned long current_bytes_per_scanline; -unsigned long current_bytes_per_pixel; -unsigned long current_phys_base; -unsigned long image_pal[16]; +unsigned int font_spacing = 0; +unsigned int line_spacing = 0; +unsigned int xpixels = 640; +unsigned int ypixels = 480; +unsigned int plano_size = 38400; +unsigned int graphics_mode = 3; +//unsigned int current_x_resolution; +unsigned int current_y_resolution; +unsigned int current_bits_per_pixel; +unsigned int current_bytes_per_scanline; +unsigned int current_bytes_per_pixel; +unsigned long long current_phys_base; +unsigned int image_pal[16]; +int use_phys_base=0; /* why do these have to be kept here? */ -unsigned long foreground = 0xFFFFFF; //(63 << 16) | (63 << 8) | (63) -unsigned long background = 0; +unsigned int foreground = 0xFFFFFF; //(63 << 16) | (63 << 8) | (63) +unsigned int background = 0; /* global state so that we don't try to recursively scroll or cursor */ //static int no_scroll = 0; /* graphics local functions */ static void graphics_scroll (void); -void SetPixel (unsigned long x, unsigned long y, unsigned long color); -void XorPixel (unsigned long x, unsigned long y, unsigned long color); +void SetPixel (unsigned int x, unsigned int y, unsigned int color); +void XorPixel (unsigned int x, unsigned int y, unsigned int color); static int read_image (void); //static void graphics_cursor (int set); static void vbe_cursor (int set); void rectangle(int left, int top, int length, int width, int line); extern void (*graphics_CURSOR) (int set); -unsigned long pixel_shift(unsigned long color); +unsigned int pixel_shift(unsigned int color); /* FIXME: where do these really belong? */ -static inline void outb(unsigned short port, unsigned char val) -{ - __asm __volatile ("outb %0,%1"::"a" (val), "d" (port)); -} -#if 0 -static void MapMask(int value) { - outb(0x3c4, 2); - outb(0x3c5, value); -} -/* bit mask register */ -static void BitMask(int value) { - outb(0x3ce, 8); - outb(0x3cf, value); -} -#endif extern void memmove_forward_SSE (void *dst, const void *src, unsigned int len); -#if 0 -#if 1 -/* memmove using SSE */ -static void _memcpy_forward (void *dst, const void *src, unsigned int len) -{ -#if 0 - asm (" movl %cr0, %eax"); - asm (" orb $2, %al"); // set CR0.MP - asm (" movl %eax, %cr0"); - asm (" movl %cr4, %eax"); - asm (" orb $0x6, %ah");// set CR4.OSFXSR (bit 9) OSXMMEXCPT (bit 10) - asm (" movl %eax, %cr4"); -#endif - -#if 1 - /* this piece of code must exist! or else gcc will fail to run the asm - * code that immediately follows. So do not comment out this C code! */ - if (((int)src | (int)dst) & 0xF) - { - fontx = fonty = 0; - printf ("Unaligned!\n"); - return; - } -#endif - asm (" pushl %esi"); - asm (" pushl %edi"); - asm (" cld"); - asm (" movl %0, %%edi" : :"m"(dst)); - asm (" movl %0, %%esi" : :"m"(src)); - asm (" movl %0, %%ecx" : :"m"(len)); - asm (" shrl $7, %ecx"); // ECX = len / (16 * 8) - asm ("1:"); -#if 1 - asm (" movdqa (%esi), %xmm0"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movntps %xmm0, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movdqa (%esi), %xmm1"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movntps %xmm1, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movdqa (%esi), %xmm2"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movntps %xmm2, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movdqa (%esi), %xmm3"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movntps %xmm3, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movdqa (%esi), %xmm4"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movntps %xmm4, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movdqa (%esi), %xmm5"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movntps %xmm5, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movdqa (%esi), %xmm6"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movntps %xmm6, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movdqa (%esi), %xmm7"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movntps %xmm7, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); -#else -#if 1 - asm (" movdqa (%esi), %xmm0"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movdqa (%esi), %xmm1"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movdqa (%esi), %xmm2"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movdqa (%esi), %xmm3"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movdqa (%esi), %xmm4"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movdqa (%esi), %xmm5"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movdqa (%esi), %xmm6"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movdqa (%esi), %xmm7"); // works on PIII and up - asm (" addl $16, %esi"); -#else - asm (" movntdqa (%esi), %xmm0"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movntdqa (%esi), %xmm1"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movntdqa (%esi), %xmm2"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movntdqa (%esi), %xmm3"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movntdqa (%esi), %xmm4"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movntdqa (%esi), %xmm5"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movntdqa (%esi), %xmm6"); // works on PIII and up - asm (" addl $16, %esi"); - asm (" movntdqa (%esi), %xmm7"); // works on PIII and up - asm (" addl $16, %esi"); -#endif -#if 0 - asm (" movdqa %xmm0, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movdqa %xmm1, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movdqa %xmm2, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movdqa %xmm3, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movdqa %xmm4, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movdqa %xmm5, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movdqa %xmm6, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movdqa %xmm7, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); -#else - asm (" movntps %xmm0, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movntps %xmm1, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movntps %xmm2, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movntps %xmm3, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movntps %xmm4, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movntps %xmm5, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movntps %xmm6, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); - asm (" movntps %xmm7, (%edi)"); // works on PIII and up - asm (" addl $16, %edi"); -#endif -#endif - asm (" loop 1b"); - asm (" popl %edi"); - asm (" popl %esi"); -} - -#else - -static inline void * _memcpy_forward(void *dst, const void *src, unsigned int len) -{ - int r0, r1, r2, r3; - __asm__ __volatile__( - "movl %%ecx, %0; shrl $2, %%ecx; " // ECX=(len / 4) - "rep; movsl; " - "movl %0, %%ecx; andl $3, %%ecx; " // ECX=(len % 4) - "rep; movsb; " - : "=&r"(r0), "=&c"(r1), "=&D"(r2), "=&S"(r3) - : "1"(len), "2"((long)dst), "3"((long)src) - : "memory"); - return dst; -} -#endif -#endif -#if 0 -static inline void _memset(void *dst, unsigned char data, unsigned int len) -{ - int r0,r1,r2,r3; - __asm__ __volatile__ ( - "movb %b2, %h2; movzwl %w2, %3; shll $16, %2; orl %3, %2; " // duplicate data into all 4-bytes of EAX - "movl %0, %3; shrl $2, %0; " // ECX=(len / 4) - "rep; stosl; " - "movl %3, %0; andl $3, %0; " // ECX=(len % 4) - "rep; stosb; " - :"=&c"(r1),"=&D"(r2),"=&a"(r0),"=&r"(r3) - :"0"(len),"1"(dst),"2"(data) - :"memory"); -} -#endif -void SetPixel (unsigned long x, unsigned long y, unsigned long color) +void SetPixel (unsigned int x, unsigned int y, unsigned int color) { unsigned char *lfb; if (x < 0 || y < 0 || x >= current_x_resolution || y >= current_y_resolution) return; - lfb = (unsigned char *)(current_phys_base + (y * current_bytes_per_scanline) + (x * current_bytes_per_pixel)); + lfb = (unsigned char *)(grub_size_t)(current_phys_base + (y * current_bytes_per_scanline) + (x * current_bytes_per_pixel)); switch (current_bits_per_pixel) { case 24: @@ -298,7 +96,7 @@ void SetPixel (unsigned long x, unsigned long y, unsigned long color) lfb[2] = (unsigned char)(color >> 16); break; case 32: - *(unsigned long *)lfb = (unsigned long)color; + *(unsigned int *)lfb = (unsigned int)color; break; default: *(unsigned short *)lfb = (unsigned short)color; @@ -306,14 +104,14 @@ void SetPixel (unsigned long x, unsigned long y, unsigned long color) } } -void XorPixel (unsigned long x, unsigned long y, unsigned long color) +void XorPixel (unsigned int x, unsigned int y, unsigned int color) { unsigned char *lfb; - if (x < 0 || y < 0 || x >= current_x_resolution || y >= current_y_resolution) + if (x >= current_x_resolution || y >= current_y_resolution) return; - lfb = (unsigned char *)(current_phys_base + (y * current_bytes_per_scanline) + (x * current_bytes_per_pixel)); + lfb = (unsigned char *)(grub_size_t)(current_phys_base + (y * current_bytes_per_scanline) + (x * current_bytes_per_pixel)); switch (current_bits_per_pixel) { case 24: @@ -321,7 +119,7 @@ void XorPixel (unsigned long x, unsigned long y, unsigned long color) lfb[2] ^= (unsigned char)(color >> 16); break; case 32: - *(unsigned long *)lfb ^= (unsigned long)color; + *(unsigned int *)lfb ^= (unsigned int)color; break; default: *(unsigned short *)lfb ^= (unsigned short)color; @@ -332,172 +130,70 @@ void XorPixel (unsigned long x, unsigned long y, unsigned long color) /* Initialize a vga16 graphics display with the palette based off of * the image in splashimage. If the image doesn't exist, leave graphics * mode. */ +int graphics_init (void); int graphics_init (void) { -// if (! graphics_CURSOR) -// graphics_CURSOR = (void *)&graphics_cursor; - - if (! graphics_inited) - { + if (! graphics_inited) //如果不在图形模式 + { /* get font info before seting mode! some buggy BIOSes destroyed the * red planar of the VGA on geting font info call. So we should set * mode only after the get font info call. */ - //if (! font8x16) - // font8x16 = graphics_get_font (); - - if (graphics_mode > 0xFF) /* VBE */ - { - if (graphics_mode == 0x102) - { -// if (set_vbe_mode (graphics_mode) != 0x004F) -// { - graphics_end (); - return !(errnum = ERR_SET_VBE_MODE); -// } -// graphics_mode = 0x6A; -// goto success; - } - if (set_vbe_mode (graphics_mode | (1 << 14)) != 0x004F) - { - graphics_end (); - return !(errnum = ERR_SET_VBE_MODE); - } - - current_term->chars_per_line = x1 = current_x_resolution / (font_w + font_spacing); - current_term->max_lines = y1 = current_y_resolution / (font_h + line_spacing); + if (graphics_mode > 0xFF) /* VBE */ + { + current_term = term_table + 1; /* terminal graphics */ + current_term->chars_per_line = current_x_resolution / (font_w + font_spacing); + current_term->max_lines = current_y_resolution / (font_h + line_spacing); /* here should read splashimage. */ graphics_CURSOR = (void *)&vbe_cursor; - //graphics_inited = 1; - //return 1; - } -#if 0 - else - { - unsigned long tmp_mode; - //saved_videomode = set_videomode (graphics_mode); - /* the mode set could fail !! */ - if (graphics_mode == 0x12) - { - if (set_videomode (graphics_mode) != graphics_mode) - { - graphics_end (); - return !(errnum = ERR_SET_VGA_MODE); - } - current_term->chars_per_line = x1 = 80; - current_term->max_lines = y1 = 30; - xpixels = 640; - ypixels = 480; - plano_size = (640 * 480) / 8; - } - else /* 800x600x4 */ - { - /* first, try VBE mode 0x102 anyway */ - if (set_vbe_mode (0x102) == 0x004F) - goto success; - if (set_videomode (graphics_mode) != graphics_mode - || (*(unsigned char *)(0x8000 + 64) != 0x1B) - || (*(unsigned char *)(0x8000 + 4) != graphics_mode) - || (*(unsigned short *)(0x8000 + 5) != 100) - /* qemu bug: byte at 0x22 should be 37, but only 36 */ - || (((*(unsigned char *)(0x8000 + 0x22)) & 0xFE) != 36) - || (*(unsigned short *)(0x8000 + 0x23) != 16) - || (*(unsigned short *)(0x8000 + 0x27) != 16) - /* qemu bug: byte at 0x29 should be 1, but was 8 */ - /*|| (*(unsigned char *)(0x8000 + 0x29) != 1)*/ - ) - { - /* probe 800x600x4 modes */ - for (tmp_mode = 0x15; tmp_mode < 0x78; tmp_mode++) - { - if (set_videomode (tmp_mode) == tmp_mode - && (*(unsigned char *)(0x8000 + 64) == 0x1B) - && (*(unsigned char *)(0x8000 + 4) == tmp_mode) - && (*(unsigned short *)(0x8000 + 5) == 100) - /* qemu bug: byte at 0x22 should be 37, but only 36 */ - && (((*(unsigned char *)(0x8000 + 0x22)) & 0xFE) == 36) - && (*(unsigned short *)(0x8000 + 0x23) == 16) - && (*(unsigned short *)(0x8000 + 0x27) == 16) - /* qemu bug: byte at 0x29 should be 1, but was 8 */ - /*&& (*(unsigned char *)(0x8000 + 0x29) == 1)*/ - ) - { - /* got it! */ - graphics_mode = tmp_mode; - goto success; - } - } - graphics_end (); /* failure, go back to console. */ - return !(errnum = ERR_SET_VGA_MODE); - } -success: - current_term->chars_per_line = x1 = 100; - current_term->max_lines = y1 = 37; - xpixels = 800; - ypixels = 600; - plano_size = (800 * 600) / 8; - } - } -#endif - else - return !(errnum = ERR_SET_VBE_MODE); - menu_border.disp_ul = 0x14; - menu_border.disp_ur = 0x15; - menu_border.disp_ll = 0x16; - menu_border.disp_lr = 0x13; - menu_border.disp_horiz = 0x0F; - menu_border.disp_vert = 0x0E; } + } - if (! fill_color) + if (fill_color)//如果是满屏单色 { - if (! read_image ()) - { - //set_videomode (3/*saved_videomode*/); -// graphics_end (); - return !(errnum = ERR_LOAD_SPLASHIMAGE); - } + if (use_phys_base == 0) + { + splashimage_loaded = (unsigned int)(grub_size_t)IMAGE_BUFFER; + splashimage_loaded |= 2; + *splashimage = 1; //避免重复加载图像 + } + + vbe_fill_color(fill_color); + fill_color = 0; } else { - *splashimage = 1; - splashimage_loaded = IMAGE_BUFFER; - splashimage_loaded |= 2; + if (! read_image ()) //如果加载图像失败 + { + return !(errnum = ERR_LOAD_SPLASHIMAGE); + } } - - fontx = fonty = 0; - graphics_inited = graphics_mode; - - return 1; + + fontx = fonty = 0; + graphics_inited = graphics_mode; + return 1; } /* Leave graphics mode */ +void graphics_end (void); void graphics_end (void) -{ - current_term = term_table; /* set terminal to console */ - set_videomode (3); /* set normal 80x25 text mode. */ - set_videomode (3); /* set it once more for buggy BIOSes. */ - - menu_border.disp_ul = 218; - menu_border.disp_ur = 191; - menu_border.disp_ll = 192; - menu_border.disp_lr = 217; - menu_border.disp_horiz = 196; - menu_border.disp_vert = 179; - +{ + current_term = term_table; /* set terminal to console */ + current_term->startup(); graphics_CURSOR = 0; fontx = fonty = 0; graphics_inited = 0; } -static unsigned long pending = 0; -static unsigned long byte_SN; -static unsigned long unicode; -static unsigned long invalid; +static unsigned int pending = 0; +static unsigned int byte_SN; +static unsigned int unicode; +static unsigned int invalid; +static void check_scroll (void); static void check_scroll (void) { @@ -511,28 +207,30 @@ check_scroll (void) ++count_lines; } -unsigned long ged_unifont_simp (unsigned long unicode); -static unsigned long -print_unicode (unsigned long max_width) +int scroll_state = 0; +unsigned int ged_unifont_simp (unsigned int unicode); +static unsigned int graphics_print_unicode (unsigned int max_width); +static unsigned int +graphics_print_unicode (unsigned int max_width) { - unsigned long i, j/*, k*/; -// unsigned long pat; - unsigned long char_width; - unsigned long bgcolor; - unsigned long CursorX,CursorY; + unsigned int i, j/*, k*/; +// unsigned int pat; + unsigned int char_width; + unsigned int bgcolor; + unsigned int CursorX,CursorY; unsigned char *lfb, *pat, *p; unsigned char column; -// unsigned char tem; unsigned long long dot_matrix; -// unsigned char buf[64*64/8]; +// unsigned long long back_color_64bit; +// unsigned int back_color; CursorX = fontx * (font_w + font_spacing); CursorY = fonty * (font_h + line_spacing); - - //print triangle +; + //print triangle 打印三角形 if (unicode==0x10 || unicode==0x11) { - lfb = (unsigned char *)(current_phys_base + CursorY*current_bytes_per_scanline + CursorX*current_bytes_per_pixel); + lfb = (unsigned char *)(grub_size_t)(current_phys_base + CursorY*current_bytes_per_scanline + CursorX*current_bytes_per_pixel); for (i=0;i>16); } else if(current_bytes_per_pixel == 4) - *(unsigned long *)p = (unsigned long)current_color_64bit; + *(unsigned int *)p = (unsigned int)current_color_64bit; else - *(unsigned short *)p = (unsigned short)pixel_shift((unsigned long)current_color_64bit); + *(unsigned short *)p = (unsigned short)pixel_shift((unsigned int)current_color_64bit); p += current_bytes_per_scanline; } @@ -562,124 +260,76 @@ print_unicode (unsigned long max_width) if (unifont_simp_on) unicode = ged_unifont_simp (unicode); char_width = 2; /* wide char */ -// pat = UNIFONT_START + (unicode << 5); pat = (unsigned char *)UNIFONT_START + unicode*num_wide*font_h; -// if (*(unsigned long *)pat == narrow_char_indicator || unicode < 0x80) -// { --char_width; pat += 16; } /* narrow char */ -#if 0 - if (font_type==BIN && scan_mode==HORIZ) - { - p = pat; - //HORIZ to VERTI - for (i = 0; i < font_h; i++) - { - dot_matrix = 0; - for (j=0; j>3)+(j*num_wide)]; - if (store_mode==H_TO_L) - dot_matrix |= ((t >> ((8*num_wide-1-i) & 7)) & 1) << j; - else //store_mode==L_TO_H - dot_matrix |= ((t >> (i & 7)) & 1) << j; - } - for (j=0; j> j*8)&0xff; - } - pat = buf; - } - - p = pat; - if (font_type) //BIN,etc - { - p += num_wide*font_w; - i=0; - while (i 0x80) return (1 << 31) | invalid | (byte_SN << 8); // printed width = 0 - if (cursor_state & 1) + if (cursor_state & 1) graphics_CURSOR(0); - +//打印字符背景色 /* print CRLF and scroll if needed */ if (fontx + char_width > current_term->chars_per_line) { fontx = 0; check_scroll (); } - if (!(splashimage_loaded & 2) || !(cursor_state & 2) || (is_highlight && current_color_64bit >> 32) || (current_color_64bit & 0x1000000000000000)) +#if 0 //issue #390 steve6375提议与grub4dos相同 + if ((cursor_state & 2) && //如果在菜单界面, 并且 + (!(splashimage_loaded & 2) //没有加载背景图像. + || (is_highlight && current_color_64bit >> 32) //或者,菜单高亮并且有背景色(无论加载图像与否) + || (current_color_64bit & 0x1000000000000000))) //或者,强制背景色(无论加载图像与否) + bgcolor = current_color_64bit >> 32 | 0x1000000; //则显示字符背景色 + else if ((cursor_state < 2) || scroll_state || OnCommandLine) //如果在命令行界面, 或者滚屏状态 + { //增加OnCommandLine变量, 是为了确保在命令行, 避免胡乱使用 Fn.70 0 + back_color_64bit = current_color_64bit; + back_color = current_color; + current_term->setcolorstate (COLOR_STATE_STANDARD); //显示控制台背景色 bgcolor = current_color_64bit >> 32 | 0x1000000; - else + current_color_64bit = back_color_64bit; + current_color = back_color; + } + else //否则显示图像(背景透明) + bgcolor = 0; +#else + if (!(cursor_state & 2) //如果不在在菜单界面, + || !(splashimage_loaded & 2) //或者没有加载背景图像. + || (is_highlight && current_color_64bit >> 32) //或者菜单高亮并且有背景色(无论加载图像与否) + || (current_color_64bit & 0x1000000000000000)) //或者强制背景色(无论加载图像与否) + bgcolor = current_color_64bit >> 32 | 0x1000000; //则显示字符背景色 + else //否则显示图像(背景透明) bgcolor = 0; +#endif -// CursorX = fontx * (font_w + font_spacing); -// CursorY = fonty * (font_h + line_spacing); for (i = 0; i>1; CursorY += line_spacing>>1; -#if 0 - /* print dot matrix of the unicode char */ - for (i = 0; i < char_width * font_w; ++i) - { - unsigned long tmp_x = CursorX + i; - unsigned long column = ((unsigned short *)pat)[i]; - for (j = 0; j < font_h; ++j) - { - /* print char using foreground and background colors. */ - if ((column >> j) & 1) - { - if(current_bits_per_pixel == 24 || current_bits_per_pixel == 32) - SetPixel (tmp_x, CursorY + j,current_color_64bit); - else - SetPixel (tmp_x, CursorY + j,pixel_shift(current_color_64bit)); - } - } - } -#endif - /* print dot matrix of the unicode char */ for (i = 0; i < char_width * font_w; ++i) { - unsigned long tmp_x = CursorX + i; + unsigned int tmp_x = CursorX + i; dot_matrix = 0; for(j = 0; j < num_wide; j++) { column = *(unsigned char *)pat; pat++; -#if 0 - if (font_type==BIN && scan_mode==VERTI && store_mode==H_TO_L) - { - tem = 0; - for(k = 0; k < 8; k++) //l to h - tem |= ((column & (0x80 >> k))?(1<< k):0); - column = tem; - } -#endif + dot_matrix |= (((unsigned long long)column) << j*8); } for (j = 0; j < font_h; ++j) @@ -694,10 +344,12 @@ print_unicode (unsigned long max_width) } } } -//#endif + + if (unicode < 0x80) + char_width = 1; triangle: fontx += char_width; - if (cursor_state & 1) + if (cursor_state & 1) { if (fontx >= current_term->chars_per_line) { fontx = 0; check_scroll (); } @@ -706,12 +358,31 @@ print_unicode (unsigned long max_width) return invalid | (byte_SN << 8) | char_width; } -static unsigned long -print_invalid_pending_bytes (unsigned long max_width) +static unsigned int print_unicode (unsigned int max_width); +static unsigned int +print_unicode (unsigned int max_width) { - unsigned long tmpcode = unicode; - unsigned long ret = 0; + if (current_term != term_table) + return graphics_print_unicode (max_width); + else + { + if (unicode == 0x10) + unicode = 0x25ba; + else if (unicode == 0x11) + unicode = 0x25c4; + + console_print_unicode (unicode, max_width); + } + + return invalid | (byte_SN << 8) | (unicode < 0x80 ? 1 : 2); +} +static unsigned int print_invalid_pending_bytes (unsigned int max_width); +static unsigned int +print_invalid_pending_bytes (unsigned int max_width) +{ + unsigned int tmpcode = unicode; + unsigned int ret = 0; /* now pending is on, so byte_SN can tell the number of bytes, and * unicode can tell the value of each byte. */ @@ -720,7 +391,7 @@ print_invalid_pending_bytes (unsigned long max_width) { unicode = (unicode >> 6) | 0xDCE0; /* the 1st byte */ ret = print_unicode (max_width); - if ((long)ret < 0) + if ((int)ret < 0) return ret; max_width -= (unsigned char)ret; unicode = (tmpcode & 0x3F) | 0xDC80; /* the 2nd byte */ @@ -731,42 +402,27 @@ print_invalid_pending_bytes (unsigned long max_width) } /* Print ch on the screen. Handle any needed scrolling or the like */ +unsigned int graphics_putchar (unsigned int ch, unsigned int max_width); unsigned int graphics_putchar (unsigned int ch, unsigned int max_width) { - unsigned long ret; + unsigned int ret; + invalid = 0; + if (current_term != term_table) + { if (fontx >= current_term->chars_per_line) { fontx = 0; check_scroll (); } if (graphics_mode <= 0xFF) -// goto vga; return 0; - /* VBE */ - - invalid = 0; - - if ((unsigned char)ch > 0x7F) /* multi-byte */ - goto multibyte; - - if (pending) /* print (byte_SN) invalid bytes */ - { - ret = print_invalid_pending_bytes (max_width); - pending = 0; /* end the utf8 byte sequence */ - if ((long)ret < 0) - return ret; - max_width -= (unsigned char)ret; - } - - if (! max_width) - return (1 << 31); /* printed width = 0 */ - if (cursor_state & 1) graphics_CURSOR(0); if ((char)ch == '\n') { + fontx = 0; check_scroll (); if (cursor_state & 1) graphics_CURSOR(1); @@ -779,11 +435,28 @@ graphics_putchar (unsigned int ch, unsigned int max_width) graphics_CURSOR(1); return 1; } + } + + if ((unsigned char)ch > 0x7F) /* multi-byte */ + goto multibyte; + + if (pending) /* print (byte_SN) invalid bytes */ + { + ret = print_invalid_pending_bytes (max_width); + pending = 0; /* end the utf8 byte sequence */ + if ((int)ret < (int)0) + return ret; + max_width -= (unsigned char)ret; + } + + if (! max_width) + return (1 << 31); /* printed width = 0 */ + + /* we know that the ASCII chars are all narrow */ unicode = ch; return print_unicode (1); multibyte: - if (! (((unsigned char)ch) & 0x40)) /* continuation byte 10xxxxxx */ { if (! pending) @@ -797,11 +470,9 @@ graphics_putchar (unsigned int ch, unsigned int max_width) { pending--; byte_SN++; unicode = ((unicode << 6) | (ch & 0x3F)); - if (pending) /* pending = 1, awaiting the last continuation byte. */ return (byte_SN << 8); // succeed with printed width = 0 } - /* pending = 0, end the sequence, print the unicode char */ return print_unicode (max_width); } @@ -809,8 +480,8 @@ graphics_putchar (unsigned int ch, unsigned int max_width) { if (pending) /* print (byte_SN) invalid bytes */ { - ret = print_invalid_pending_bytes (max_width); - if ((long)ret < 0) + ret = print_invalid_pending_bytes (max_width);; + if ((int)ret < (int)0) return ret; max_width -= (unsigned char)ret; } @@ -824,7 +495,7 @@ graphics_putchar (unsigned int ch, unsigned int max_width) if (pending) /* print (byte_SN) invalid bytes */ { ret = print_invalid_pending_bytes (max_width); - if ((long)ret < 0) + if ((int)ret < (int)0) return ret; max_width -= (unsigned char)ret; } @@ -839,7 +510,7 @@ graphics_putchar (unsigned int ch, unsigned int max_width) if (pending) /* print (byte_SN) invalid bytes */ { ret = print_invalid_pending_bytes (max_width); - if ((long)ret < 0) + if ((int)ret < (int)0) return ret; max_width -= (unsigned char)ret; } @@ -849,51 +520,17 @@ graphics_putchar (unsigned int ch, unsigned int max_width) pending = 0; /* end the utf8 byte sequence */ /* print the current invalid byte */ return print_unicode (max_width); - -////////////////////////////////////////////////////////////////////////////// -#if 0 -vga: - if ((char)ch == '\n') - { - if (cursor_state & 1) - graphics_CURSOR(0); - check_scroll (); - if (cursor_state & 1) - graphics_CURSOR(1); - return 1; - } - if ((char)ch == '\r') - { - if (cursor_state & 1) - graphics_CURSOR(0); - fontx = 0; - if (cursor_state & 1) - graphics_CURSOR(1); - return 1; - } - - text[fonty * x1 + fontx] = (unsigned char)ch; - - graphics_CURSOR(0); - - fontx++; - if (cursor_state & 1) - { - if (fontx >= x1) - { fontx = 0; check_scroll (); } - graphics_CURSOR(1); - } - return 1; -#endif } /* get the current location of the cursor */ +int graphics_getxy(void); int graphics_getxy(void) { return (fonty << 8) | fontx; } +void graphics_gotoxy (int x, int y); void graphics_gotoxy (int x, int y) { @@ -907,27 +544,21 @@ graphics_gotoxy (int x, int y) graphics_CURSOR(1); } +void graphics_cls (void); void graphics_cls (void) { -// int i; -// unsigned char *mem, *s1, *s2, *s4, *s8; unsigned char *mem,*s1; - fontx = 0; fonty = 0; if (graphics_mode <= 0xFF) -// goto vga; return; /* VBE */ - #if 0 - _memset ((char *)current_phys_base, 0, current_y_resolution * current_bytes_per_scanline); - #else - s1 = (unsigned char *)current_phys_base; - unsigned long color = current_color_64bit >> 32; - unsigned long y,x,z; + s1 = (unsigned char *)(grub_size_t)current_phys_base; + unsigned int color = current_color_64bit >> 32; + unsigned int y,x,z; unsigned char *lfb; z = current_bytes_per_pixel; @@ -938,10 +569,9 @@ graphics_cls (void) { if (graphics_mode > 0xff && (splashimage_loaded & 2) && (cursor_state & 2)) { -// *(unsigned long *)mem = SPLASH_IMAGE[x+y*SPLASH_W]; lfb = (unsigned char *)SPLASH_IMAGE + x*current_bytes_per_pixel + y*current_bytes_per_scanline; if(current_bits_per_pixel == 32) - *(unsigned long *)mem = *(unsigned long *)lfb; + *(unsigned int *)mem = *(unsigned int *)lfb; else if(current_bits_per_pixel == 24) { *(unsigned short *)mem = *(unsigned short *)lfb; @@ -953,7 +583,7 @@ graphics_cls (void) else { if(current_bits_per_pixel == 32) - *(unsigned long *)mem = color; + *(unsigned int *)mem = color; else if(current_bits_per_pixel == 24) { *(unsigned short *)mem = (unsigned short)color; @@ -966,60 +596,10 @@ graphics_cls (void) } s1 += current_bytes_per_scanline; } - #endif + if (cursor_state & 1) graphics_CURSOR(1); return; -#if 0 -vga: - mem = (unsigned char*)VIDEOMEM; - - for (i = 0; i < x1 * y1; i++) - text[i] = ' '; - - if (!(cursor_state & 2)) - { - if (splashimage_loaded & 1) - { - MapMask(15); - _memset (mem, 0, plano_size); - } - else - { - for(i=1;i<16;i<<=1) - { - MapMask(i); - _memset (mem,(current_color & (i<<4))?0xff:0, plano_size); - } - } - return; - } - - s1 = (unsigned char*)VSHADOW1; - s2 = (unsigned char*)VSHADOW2; - s4 = (unsigned char*)VSHADOW4; - s8 = (unsigned char*)VSHADOW8; - - BitMask(0xff); - - /* plano 1 */ - MapMask(1); - memmove_forward_SSE (mem, s1, plano_size); - - /* plano 2 */ - MapMask(2); - memmove_forward_SSE (mem, s2, plano_size); - - /* plano 3 */ - MapMask(4); - memmove_forward_SSE (mem, s4, plano_size); - - /* plano 4 */ - MapMask(8); - memmove_forward_SSE (mem, s8, plano_size); - - MapMask(15); -#endif } void clear_entry (int x, int y, int w, int h); @@ -1033,26 +613,31 @@ clear_entry (int x, int y, int w, int h) for (i=0;i=0x30 && *p<=0x39) p--; @@ -1159,36 +744,32 @@ int animated (void) unsigned char R0,G0,B0,R1,G1,B1; int only; +static int read_image_bmp(int type); static int read_image_bmp(int type) { - //struct { /* bmfh */ - // unsigned short bfType; - // unsigned long bfSize; - // unsigned long bfReserved1; - // unsigned long bfOffBits; - // } __attribute__ ((packed)) bmfh; struct { /* bmih */ - unsigned long biSize; - unsigned long biWidth; - unsigned long biHeight; + unsigned int biSize; + unsigned int biWidth; + unsigned int biHeight; unsigned short biPlanes; unsigned short biBitCount; - unsigned long biCompression; - unsigned long biSizeImage; - unsigned long biXPelsPerMeter; - unsigned long biYPelsPerMeter; - unsigned long biClrUsed; - unsigned long biClrImportant; + unsigned int biCompression; + unsigned int biSizeImage; + unsigned int biXPelsPerMeter; + unsigned int biYPelsPerMeter; + unsigned int biClrUsed; + unsigned int biClrImportant; } __attribute__ ((packed)) bmih; - unsigned long bftmp,bfbit; + unsigned int bftmp,bfbit; int x,y; - unsigned long source = 0; + unsigned int source = 0; unsigned char R,G,B; only = 0; if (type == 0) return 0; filepos = 10; - if (!grub_read((unsigned long long)(unsigned int)(char*)&bftmp,4, GRUB_READ) || ! grub_read((unsigned long long)(unsigned int)&bmih,sizeof(bmih),GRUB_READ) || bmih.biBitCount < 24) + + if (!grub_read((unsigned long long)(grub_size_t)&bftmp,4, GRUB_READ) || ! grub_read((unsigned long long)(grub_size_t)&bmih,sizeof(bmih),GRUB_READ) || bmih.biBitCount < 24) { //return !printf("Error:Read BMP Head\n"); return !(errnum = ERR_EXEC_FORMAT); @@ -1197,18 +778,18 @@ static int read_image_bmp(int type) bfbit = bmih.biBitCount>>3; bftmp = 0; //bftmp = (bmih.biWidth*(bmih.biBitCount>>3)+3)&~3; -// SPLASH_W = bmih.biWidth; -// SPLASH_H = bmih.biHeight; -// unsigned long *bmp = SPLASH_IMAGE; + SPLASH_W = bmih.biWidth; + SPLASH_H = bmih.biHeight; unsigned char *bmp; -// if (debug > 0) -// printf("Loading splashimage...\n"); + + if (use_phys_base == 0) + splashimage_loaded = (grub_size_t)IMAGE_BUFFER; + for(y=bmih.biHeight-1;y>=0;--y) { -// bmp = SPLASH_IMAGE+y*SPLASH_W; - for(x=0;x>16; G = (bftmp & 0xff00)>>8; @@ -1259,7 +840,7 @@ static int read_image_bmp(int type) if ((R>=R0) && (R<=R1) && (G>=G0) && (G<=G1) && (B>=B0) && (B<=B1)) { if (background_transparent || (graphic_enable && (graphic_type & 0x80) && !(is_highlight && (graphic_type & 8)))) - source = *(unsigned long *)((unsigned char *)SPLASH_IMAGE+(x+X_offset)*current_bytes_per_pixel+(y+Y_offset)*current_bytes_per_scanline); + source = *(unsigned int *)((unsigned char *)SPLASH_IMAGE+(x+X_offset)*current_bytes_per_pixel+(y+Y_offset)*current_bytes_per_scanline); else if (graphic_enable && is_highlight && (graphic_type & 8)) source = current_color_64bit & 0xffffffff; else if (!graphic_enable || (graphic_enable && !(graphic_type & 0x80) && !(is_highlight && (graphic_type & 8)))) @@ -1277,7 +858,7 @@ static int read_image_bmp(int type) if(current_bits_per_pixel == 32) // bmp[x] = bftmp; // - *(unsigned long *)bmp = source; + *(unsigned int *)bmp = source; else if(current_bits_per_pixel == 24) { *(unsigned short *)bmp = (unsigned short)source; @@ -1290,7 +871,6 @@ static int read_image_bmp(int type) filepos += ((bmih.biWidth*bfbit&3)?(4-(bmih.biWidth*bfbit&3)):0); } background_transparent=0; - use_phys_base=0; return 2; } @@ -1343,10 +923,10 @@ short ycoef,ucoef,vcoef; int IntervalFlag; short interval; int Y[4*64],U[4*64],V[4*64]; -unsigned long sizei,sizej; +unsigned int sizei,sizej; short restart; -static long iclip[1024]; -static long *iclp; +static int iclip[1024]; +static int *iclp; unsigned long long size; /////////////////////////////////////////////// static void GetYUV(short flag) @@ -1384,8 +964,8 @@ static void StoreBuffer() unsigned char *lfb; unsigned char R,G,B; int y,u,v,rr,gg,bb; - unsigned long color; - unsigned long source = 0; + unsigned int color; + unsigned int source = 0; for(i=0;i=R0) && (R<=R1) && (G>=G0) && (G<=G1) && (B>=B0) && (B<=B1)) { if (background_transparent || (graphic_enable && (graphic_type & 0x80) && !(is_highlight && (graphic_type & 8)))) - source = *(unsigned long *)((unsigned char *)SPLASH_IMAGE + (sizei+i+Y_offset)*current_bytes_per_scanline + (sizej+j+X_offset)*current_bytes_per_pixel); + source = *(unsigned int *)((unsigned char *)SPLASH_IMAGE + (sizei+i+Y_offset)*current_bytes_per_scanline + (sizej+j+X_offset)*current_bytes_per_pixel); else if (graphic_enable && is_highlight && (graphic_type & 8)) source = current_color_64bit & 0xffffffff; else if (!graphic_enable || (graphic_enable && !(graphic_type & 0x80) && !(is_highlight && (graphic_type & 8)))) @@ -1487,7 +1067,7 @@ static void StoreBuffer() } if(current_bits_per_pixel == 32) - *(unsigned long *)lfb = source; + *(unsigned int *)lfb = source; else if(current_bits_per_pixel == 24) { *(unsigned short *)lfb = (unsigned short)source; @@ -1515,6 +1095,7 @@ static int DecodeMCUBlock() BitPos=0; CurByte=0; } + switch(comp_num) { case 3: @@ -1565,6 +1146,7 @@ static int DecodeMCUBlock() default: return 0; } + return 1; } @@ -1585,8 +1167,8 @@ static unsigned char ReadByte() if(size <= 16) { - grub_memmove64((unsigned long long)(int)JPG_FILE,(unsigned long long)(int)lp,(unsigned long long)size); - len=grub_read((unsigned long long)(unsigned int)(char*)JPG_FILE+size, 0x7e00, GRUB_READ); + grub_memmove64((unsigned long long)(grub_size_t)JPG_FILE,(unsigned long long)(grub_size_t)lp,size); + len=grub_read((unsigned long long)(grub_size_t)JPG_FILE+size, 0x7e00, GRUB_READ); size+=len; lp=(unsigned char*)JPG_FILE; } @@ -1640,7 +1222,7 @@ static int DecodeElement() if(codelen>16) return 0; } //while - temp=thiscode-huf_min_value[HufTabIndex][codelen-1]+code_pos_table[HufTabIndex][codelen-1],HufTabIndex; + temp=(unsigned short)(thiscode-huf_min_value[HufTabIndex][codelen-1]+code_pos_table[HufTabIndex][codelen-1]); hufexbyte=(unsigned char)code_value_table[HufTabIndex][temp]; rrun=(short)(hufexbyte>>4); runsize=hufexbyte&0x0f; @@ -1787,9 +1369,12 @@ static void Fast_IDCT(int * block) for (i=0; i<8; i++) idctrow(block+8*i); + + efi_call_1 (grub_efi_system_table->boot_services->stall, 1); //微妙 不加延时,莫名其妙的卡住了! for (i=0; i<8; i++) idctcol(block+i); + } /////////////////////////////////////////////////////////////////////// static void Initialize_Fast_IDCT() @@ -1897,7 +1482,7 @@ static void idctcol(int * blk) static int Decode() { int funcret; - size -= ((unsigned long)lp - (unsigned long)JPG_FILE); + size -= (grub_size_t)(lp - JPG_FILE); Y_in_MCU=SampRate_Y_H*SampRate_Y_V; //2*2=4 2*1=2 1*1=1 U_in_MCU=SampRate_U_H*SampRate_U_V; //1:1=1 @@ -1927,6 +1512,7 @@ static int Decode() sizej=0; sizei+=SampRate_Y_V*8; } + if ((sizej==0)&&(sizei>=SPLASH_H)) break; } @@ -2038,6 +1624,8 @@ static int InitTag() llength=MAKEWORD(*(lp+1),*lp); SPLASH_H=MAKEWORD(*(lp+4),*(lp+3)); SPLASH_W=MAKEWORD(*(lp+6),*(lp+5)); + if (use_phys_base == 0) + splashimage_loaded = (grub_size_t)IMAGE_BUFFER; comp_num=*(lp+7); if((comp_num!=1)&&(comp_num!=3)) return 0; @@ -2178,175 +1766,24 @@ read_image_jpg(int type) { filepos = 0; lp = (unsigned char*)JPG_FILE; - if (!(size=grub_read((unsigned long long)(unsigned int)(char*)lp, 0x8000, GRUB_READ))) + + if (!(size=grub_read((unsigned long long)(grub_size_t)lp, 0x8000, GRUB_READ))) return !printf("Error:Read JPG File\n"); + InitTable(); if (!(InitTag())) return 1; + Decode(); background_transparent=0; - use_phys_base=0; return 2; } -///////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -#if 0 -/* Read in the splashscreen image and set the palette up appropriately. - * Format of splashscreen is an xpm (can be gzipped) with 16 colors and - * 640x480. */ -static int -read_image_xpm (int type) -{ - char buf[32], pal[16]; - unsigned char c, base, mask; - unsigned i, len, idx, colors, x, y, width, height; - unsigned char *s1; - unsigned char *s2; - unsigned char *s4; - unsigned char *s8; - unsigned char *lfb; - - s1 = (unsigned char*)VSHADOW1; - s2 = (unsigned char*)VSHADOW2; - s4 = (unsigned char*)VSHADOW4; - s8 = (unsigned char*)VSHADOW8; - - /* parse info */ - while (grub_read((unsigned long long)(unsigned int)(char *)&c, 1, 0xedde0d90)) { - if (c == '"') - break; - } - while (grub_read((unsigned long long)(unsigned int)(char *)&c, 1, 0xedde0d90) && (c == ' ' || c == '\t')) - ; - - i = 0; - width = c - '0'; - while (grub_read((unsigned long long)(unsigned int)(char *)&c, 1, 0xedde0d90)) { - if (c >= '0' && c <= '9') - width = width * 10 + c - '0'; - else - break; - } - while (grub_read((unsigned long long)(unsigned int)(char *)&c, 1, 0xedde0d90) && (c == ' ' || c == '\t')) - ; - - height = c - '0'; - while (grub_read((unsigned long long)(unsigned int)(char *)&c, 1, 0xedde0d90)) { - if (c >= '0' && c <= '9') - height = height * 10 + c - '0'; - else - break; - } - while (grub_read((unsigned long long)(unsigned int)(char *)&c, 1, 0xedde0d90) && (c == ' ' || c == '\t')) - ; - - colors = c - '0'; - while (grub_read((unsigned long long)(unsigned int)(char *)&c, 1, 0xedde0d90)) { - if (c >= '0' && c <= '9') - colors = colors * 10 + c - '0'; - else - break; - } - - base = 0; - while (grub_read((unsigned long long)(unsigned int)(char *)&c, 1, 0xedde0d90) && c != '"') - ; - - /* palette */ - for (i = 0, idx = 1; i < colors; i++) { - len = 0; - - while (grub_read((unsigned long long)(unsigned int)(char *)&c, 1, 0xedde0d90) && c != '"') - ; - grub_read((unsigned long long)(unsigned int)(char *)&c, 1, 0xedde0d90); /* char */ - base = c; - grub_read((unsigned long long)(unsigned int)buf, 4, 0xedde0d90); /* \t c # */ - - while (grub_read((unsigned long long)(unsigned int)(char *)&c, 1, 0xedde0d90) && c != '"') { - if (len < sizeof(buf)) - buf[len++] = c; - } - - if (len == 6 && idx < 15) { - int r = (hex(buf[0]) << 4) | hex(buf[1]); - int g = (hex(buf[2]) << 4) | hex(buf[3]); - int b = (hex(buf[4]) << 4) | hex(buf[5]); - - pal[idx] = base; - image_pal[idx] = (r<<16) | (g<<8) | b; - ++idx; - } - } - - for (i = 0; i < plano_size / 4; i++) - ((long *)s1)[i] = ((long *)s2)[i] = ((long *)s4)[i] = ((long *)s8)[i] = 0; - - /* parse xpm data */ - for (y = len = 0; y < height && y < ypixels; ++y, len += x1) { - while (1) { - if (!grub_read((unsigned long long)(unsigned int)(char *)&c, 1, 0xedde0d90)) { -// grub_close(); - return 0; - } - if (c == '"') - break; - } - - for (x = 0; grub_read((unsigned long long)(unsigned int)(char *)&c, 1, 0xedde0d90) && c != '"'; ++x) - { - if (x < width && x < xpixels) - { - for (i = 1; i < 15; i++) - if (pal[i] == c) { - c = i; - break; - } - if (type == 0) - { - mask = 0x80 >> (x & 7); - if (c & 1) s1[len + (x >> 3)] |= mask; - if (c & 2) s2[len + (x >> 3)] |= mask; - if (c & 4) s4[len + (x >> 3)] |= mask; - if (c & 8) s8[len + (x >> 3)] |= mask; - } - else - { - lfb = (unsigned char *)SPLASH_IMAGE + x*current_bytes_per_pixel + y*width*current_bytes_per_scanline; - if(current_bits_per_pixel == 24 || current_bits_per_pixel == 32) -// SPLASH_IMAGE[y*width+x] = image_pal[c]; - *(unsigned long *)lfb = image_pal[c]; - else - *(unsigned short *)lfb = (unsigned short)pixel_shift(image_pal[c]); - } - } - } - } - -// grub_close(); - if (type == 1) - { - SPLASH_W = width; - SPLASH_H = height; - return 2; - } - -//set_palette: - image_pal[0] = background; - image_pal[15] = foreground; - for (i=0; i < 16;++i) - graphics_set_palette(i,image_pal[i]); - - return 1; -} -#endif //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -unsigned long rr, gg, bb; -unsigned long pixel_shift(unsigned long color) +unsigned int rr, gg, bb; +unsigned int pixel_shift(unsigned int color) { - unsigned long r,g,b; + unsigned int r,g,b; b = color & 0xff; g = (color >> 8) & 0xff; @@ -2368,83 +1805,50 @@ unsigned long pixel_shift(unsigned long color) return color; } - +static int read_image(); static int read_image() { char buf[16]; + if (*splashimage == 1) - { - if (splashimage_loaded & 1) - { - int i=0; - for (i=1 ;i<15;++i) - graphics_set_palette(i,image_pal[i]); - } return 1; - } + if (!*splashimage) { splashimage_loaded = 0; *splashimage = 1; - if (graphics_mode < 0xFF) - { - return 0; -#if 0 - unsigned char *s1; - unsigned char *s2; - unsigned char *s4; - unsigned char *s8; - unsigned i; - s1 = (unsigned char*)VSHADOW1; - s2 = (unsigned char*)VSHADOW2; - s4 = (unsigned char*)VSHADOW4; - s8 = (unsigned char*)VSHADOW8; - for (i = 0; i < plano_size / 4; i++) - ((long *)s1)[i] = ((long *)s2)[i] = ((long *)s4)[i] = ((long *)s8)[i] = 0; - graphics_set_palette( 0, background); - graphics_set_palette(15, foreground); -#endif - } return 1; } + if (! grub_open(splashimage)) { return 0; } + /* read header */ - grub_read((unsigned long long)(unsigned int)(char*)&buf, 10, 0xedde0d90); - splashimage_loaded = IMAGE_BUFFER; - if (*(unsigned short*)buf == 0x4d42) /*BMP */ + grub_read((unsigned long long)(grub_size_t)&buf, 10, 0xedde0d90); + unsigned short* a = (unsigned short*)buf; +// if (*(unsigned short*)buf == 0x4d42) /*BMP */ + if (*a == 0x4d42) /*BMP */ { splashimage_loaded |= read_image_bmp(graphics_mode > 0xFF); } -#if 0 - else if (grub_memcmp(buf, "/* XPM */\n", 10) == 0) /* XPM */ - { - splashimage_loaded |= read_image_xpm(graphics_mode > 0xFF); - } -#endif - else if (*(unsigned short*)buf == 0xD8FF) +// else if (*(unsigned short*)buf == 0xD8FF) + else if (*a == 0xD8FF) { splashimage_loaded |= read_image_jpg(graphics_mode > 0xFF); } - *splashimage = 1; + *splashimage = 1; //避免重复加载图像 grub_close(); return splashimage_loaded & 0xf; } - +#if 0 /* Convert a character which is a hex digit to the appropriate integer */ +int hex (int v); int hex (int v) { -#if 0 - if (v >= 'A' && v <= 'F') - return (v - 'A' + 10); - if (v >= 'a' && v <= 'f') - return (v - 'a' + 10); - return (v - '0'); -#else /* by chenall 2011-12-01. '0' & 0xf = 0 ... '9' & 0xf = 9; @@ -2454,44 +1858,70 @@ hex (int v) if (v >= 'A') v += 9; return v & 0xf; -#endif } - +#endif /* scroll the screen */ -void bios_scroll_up(); +//void bios_scroll_up(); static void graphics_scroll (void) { - unsigned long i; - unsigned long old_state = cursor_state; + unsigned int i; + unsigned int old_state = cursor_state; cursor_state &= ~1; - if (graphics_mode <= 0xFF) - {/* VGA */ - bios_scroll_up (); - } - else - {/* VBE */ -#if 0 - memmove_forward_SSE ((char *)current_phys_base, (char *)current_phys_base + (current_bytes_per_scanline * (font_h + line_spacing)), - (y1 - 1) * current_bytes_per_scanline * (font_h + line_spacing)); + unsigned long long clo64 = current_color_64bit; + unsigned int clo = current_color; +#if 0 //滚屏速度太慢,尤其在实体机 + grub_memcpy ((char *)(grub_size_t)current_phys_base, (char *)(grub_size_t)current_phys_base + (current_bytes_per_scanline * (font_h + line_spacing)), + (current_term->max_lines - 1) * current_bytes_per_scanline * (font_h + line_spacing)); #else - grub_memcpy ((char *)current_phys_base, (char *)current_phys_base + (current_bytes_per_scanline * (font_h + line_spacing)), - (y1 - 1) * current_bytes_per_scanline * (font_h + line_spacing)); + static grub_efi_guid_t graphics_output_guid = GRUB_EFI_GOP_GUID; + static struct grub_efi_gop *gop; + grub_efi_handle_t *handles; + grub_efi_uintn_t num_handles; + + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, + &graphics_output_guid, NULL, &num_handles); //定位手柄(通过协议) + if (!handles || num_handles == 0) //如果句柄为零, 或者句柄数为零 + return; //错误 + gop = grub_efi_open_protocol (handles[0], &graphics_output_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); //打开协议 + efi_call_10 (gop->blt, gop, (void *)(grub_size_t)current_phys_base, //没有此函数,在实体机启动时,滚动的是固件的内容! + GRUB_EFI_BLT_BUFFER_TO_VIDEO, 0, 0, 0, 0, + current_x_resolution, current_y_resolution, + 0); + efi_call_10 (gop->blt, gop, 0, + GRUB_EFI_BLT_VIDEO_TO_VIDEO, 0, font_h, 0, 0, + current_x_resolution, current_y_resolution - font_h, + 0); #endif - } - - for (i=0;ichars_per_line;++i) - graphics_putchar(' ',1); + if (old_state & 1) + scroll_state = 1; //避免空格背景杂乱无章 + if (current_term->setcolorstate) +// current_term->setcolorstate (COLOR_STATE_NORMAL); //避免图形模式时,在命令行滚屏,第24行被有其他属性的空格清屏 2022-11-28 + current_term->setcolorstate (COLOR_STATE_STANDARD); //避免图形模式时,在命令行滚屏,第24行被有其他属性的空格清屏 2022-12-15 + for (i=0;ichars_per_line;++i) + graphics_putchar(' ',1); + current_color_64bit = clo64; + current_color = clo; gotoxy(0,fonty); cursor_state = old_state; + scroll_state = 0; return; } void rectangle(int left, int top, int length, int width, int line) { unsigned char *lfb,*p; - int x,y,z,i; + int x,y,z,i,clear=0; + unsigned int source; + + if (line & 0x80000000) //清除线框及其内部区域,恢复菜单背景 + { + clear = 1; + line &= 0x7fffffff; + } + if (!graphics_inited || graphics_mode < 0xff || !line) return; @@ -2500,7 +1930,8 @@ void rectangle(int left, int top, int length, int width, int line) else y = 0; z = current_bytes_per_pixel; - lfb = (unsigned char *)(current_phys_base + top * current_bytes_per_scanline + left * z); + lfb = (unsigned char *)(grub_size_t)(current_phys_base + top * current_bytes_per_scanline + left * z); + source = current_color_64bit & 0xffffffff; if (!length) goto vert; @@ -2510,17 +1941,20 @@ void rectangle(int left, int top, int length, int width, int line) p = lfb + current_bytes_per_scanline*i; for (x=0;x>16); + *(unsigned short *)(p+y) = *(unsigned short *)p = (unsigned short)source; + *(p+y+2) = *(p+2) = (unsigned char)(source>>16); } else if(z == 4) { - *(unsigned long *)(p+y) = *(unsigned long *)p = (unsigned long)current_color_64bit; + *(unsigned int *)(p+y) = *(unsigned int *)p = (unsigned int)source; } else - *(unsigned short *)(p+y) = *(unsigned short *)p = (unsigned short)pixel_shift((unsigned long)current_color_64bit); + *(unsigned short *)(p+y) = *(unsigned short *)p = (unsigned short)pixel_shift((unsigned int)source); p += z; } } @@ -2541,17 +1975,20 @@ void rectangle(int left, int top, int length, int width, int line) p = lfb + z * i; for (x=(length ? (line*2) : 0);x>16); + *(unsigned short *)(p+y) = *(unsigned short *)p = (unsigned short)source; + *(p+y+2) = *(p+2) = (unsigned char)(source>>16); } else if(z == 4) { - *(unsigned long *)(p+y) = *(unsigned long *)p = (unsigned long)current_color_64bit; + *(unsigned int *)(p+y) = *(unsigned int *)p = (unsigned int)source; } else - *(unsigned short *)(p+y) = *(unsigned short *)p = (unsigned short)pixel_shift((unsigned long)current_color_64bit); + *(unsigned short *)(p+y) = *(unsigned short *)p = (unsigned short)pixel_shift((unsigned int)source); p += current_bytes_per_scanline; } } @@ -2559,11 +1996,10 @@ void rectangle(int left, int top, int length, int width, int line) } static void -vbe_cursor (int set) +vbe_cursor (int set) //VBE的光标 { - unsigned long x, y,j; + unsigned int x, y,j; -#if 1 x = fontx * (font_w+font_spacing); y = fonty * (font_h+line_spacing); y += line_spacing>>1; @@ -2572,122 +2008,6 @@ vbe_cursor (int set) { XorPixel (x, y + j, -1); } -#else - /* invert the beginning 2 vertical lines of the char */ - for (i = 0; i < 2; ++i) - { - for (j = 0; j < 16; ++j) - { - XorPixel (fontx * 8 + i, fonty * 16 + j, -1); - } - } -#endif } -#if 0 -static unsigned char chr[16 << 2]; -static unsigned char mask[16]; - -static void -graphics_cursor (int set) -{ - unsigned char *pat, *mem, *ptr; - int i, ch, offset; - - offset = (fonty << 4) * x1 + fontx; - - ch = text[fonty * x1 + fontx]; - - pat = font8x16 + (((unsigned long)((unsigned char)ch)) << 4); - - mem = (unsigned char*)VIDEOMEM + offset; - - if (set) - { - MapMask(15); - ptr = mem; - for (i = 0; i < 16; i++, ptr += x1) - { - *ptr = ~pat[i]; - } - return; - } - - if (outline) - for (i = 0; i < 16; i++) - { - mask[i] = pat[i]; - if (i < 15) - mask[i] |= pat[i+1]; - if (i > 0) - mask[i] |= pat[i-1]; - mask[i] |= (mask[i] << 1) | (mask[i] >> 1); - mask[i] = ~(mask[i]); - } - - for (i = 0; i < 16; i++, offset += x1) - { - unsigned char m, p, c1, c2, c4, c8; - - p = pat[i]; - - if (!(cursor_state & 2) || !(splashimage_loaded & 1)) - goto put_pattern; - if (is_highlight) - { - p = ~p; -put_pattern: - if (splashimage_loaded & 1) - { - chr[i]=chr[i+16]=chr[i+32]=chr[i+48]= p; - } - else - { - chr[i ] = (current_color & 1)?p:0; - chr[16 + i] = (current_color & 2)?p:0; - chr[32 + i] = (current_color & 4)?p:0; - chr[48 + i] = (current_color & 8)?p:0; - p = ~p; - chr[i ] |= (current_color & 0x10)?p:0; - chr[16 + i] |= (current_color & 0x20)?p:0; - chr[32 + i] |= (current_color & 0x40)?p:0; - chr[48 + i] |= (current_color & 0x80)?p:0; - } - continue; - } - - c1 = ((unsigned char*)VSHADOW1)[offset]; - c2 = ((unsigned char*)VSHADOW2)[offset]; - c4 = ((unsigned char*)VSHADOW4)[offset]; - c8 = ((unsigned char*)VSHADOW8)[offset]; - - if (outline) - { - m = mask[i]; - - c1 &= m; - c2 &= m; - c4 &= m; - c8 &= m; - } - - chr[i ] = c1 | p; - chr[16 + i] = c2 | p; - chr[32 + i] = c4 | p; - chr[48 + i] = c8 | p; - } - - offset = 0; - for (i = 1; i < 16; i <<= 1, offset += 16) - { - int j; - MapMask(i); - ptr = mem; - for (j = 0; j < 16; j++, ptr += x1) - *ptr = chr[j + offset]; - } - - MapMask(15); -} -#endif #endif /* SUPPORT_GRAPHICS */ diff --git a/stage2/graphics.h b/stage2/graphics.h index 425b80b3..4a12e50f 100644 --- a/stage2/graphics.h +++ b/stage2/graphics.h @@ -20,17 +20,19 @@ #ifndef GRAPHICS_H #define GRAPHICS_H -#define SPLASH_BASE_ADDR (splashimage_loaded & ~0xfL) -#define SPLASH_W (*(unsigned long *)SPLASH_BASE_ADDR) -#define SPLASH_H (*(unsigned long *)(SPLASH_BASE_ADDR+4)) -#define SPLASH_IMAGE ((unsigned long*)(SPLASH_BASE_ADDR+0x10)) + +unsigned int SPLASH_H; +unsigned int SPLASH_W; +#define SPLASH_IMAGE IMAGE_BUFFER #endif /* GRAPHICS_H */ -#define JPG_FILE 0x3A0000 +//#define JPG_FILE 0x3A0000 +unsigned char *JPG_FILE = 0; #define JPG_FILE_LENGTH 0x8000 -#define IMAGE_BUFFER 0x1000000 -#define IMAGE_BUFFER_LENGTH 0x753000 // 1600*1200*4 -#define MAKEWORD(a, b) (((unsigned long)((unsigned char)(a) & 0xff)) | ((unsigned long)(((unsigned char)(b) & 0xff) << 8))) +//#define IMAGE_BUFFER 0x1000000 +unsigned char *IMAGE_BUFFER = 0; +//#define IMAGE_BUFFER_LENGTH 0x753000 // 1600*1200*4 +#define MAKEWORD(a, b) (((unsigned int)((unsigned char)(a) & 0xff)) | ((unsigned int)(((unsigned char)(b) & 0xff) << 8))) #define HEX 0 #define BIN 1 #define HORIZ 0 diff --git a/stage2/grldrstart.S b/stage2/grldrstart.S deleted file mode 100644 index 59c0f1d0..00000000 --- a/stage2/grldrstart.S +++ /dev/null @@ -1,9292 +0,0 @@ -/* - * grldrstart.S -- Startup code for GRLDR - * Copyright (C) 2004-2007 Tinybit(tinybit@tom.com) - * Copyright (C) 2007 Bean(bean@windrv.net) - * Copyright (C) 2012 yaya(yaya2007_7777@126.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * This program is used to generate the GRLDR file. - * - * Use the following shell command to generate the GRLDR file: - * - * cat grldrstart pre_stage2 > grldr - * - */ - -#define ASM_FILE -#include -#define ASM_FILE - -#include - -#ifdef GRLDR_MBR - .file "mbrstart.S" -#elif defined(GRLDR_INSTALL) - .file "bootlacestart.S" -#else - .file "grldrstart.S" -#endif - -#ifdef GRLDR_INSTALL - //.data -#else - .text - .globl start, _start -start: -_start: -#endif - - - -_start1: - - - /* Tell GAS to generate 16-bit real mode instructions */ - - .code16 - -#if (! defined(GRLDR_INSTALL)) - - . = _start1 + 0x00 - - jmp 1f /* FAT32/NTFS routine comes to offset 0 */ - - . = _start1 + 0x02 - - .byte 0x90 - - /* 6 control bytes moved at offset 0x5A */ - - -#if (! defined(GRLDR_MBR)) - - /* filled in by mkisofs using the -boot-info-table option */ - -#;bi_pvd: .long 0xDEADBEEF /* LBA of primary volume descript */ -#;bi_file: .long 0xDEADBEEF /* LBA of boot file */ -#;bi_length: .long 0xDEADBEEF /* Length of boot file */ -#;bi_csum: .long 0xDEADBEEF /* Checksum of boot file */ -#;bi_reserved: .space (10*4) /* Reserved */ - - . = _start1 + 0x40 - -#else - - /* filled in with BPB in case the drive(typically USB) is treated as floppy by buggy BIOSes */ - - . = _start1 + 0x5A - -mbr_disable: - # bit0=1: disable GRLDR search on floppy - # bit1=1: disable booting previous MBR with invalid partition table - # bit2=1: disable unconditional entrance to the command-line - # bit3=1: disable geometry tune - # bit7=1: disable booting previous MBR prior to GRLDR search - - .byte 0x80 - - -mbr_time: - # time in seconds to wait, 0xFF means waiting forever - - .byte 0 // use 0 instead of 5 for grldr.mbr to work as usual. - - /* a key press to wait. if AX returned from int16 equals this word, - * the desired action will occur. */ - - -mbr_hotkey: - .word 0x3920 /* the space bar */ - - -mbr_boot_number: - .byte 0xff # preferred boot drive number, 0xff means undefined - .byte 0xff # preferred partition number, 0xff for whole drive - -#endif /* ! defined(GRLDR_MBR) */ - -1: -// cli - xorw %bx, %bx - movw %bx, %ss - movw $0x580, %sp /* temp safe stack space */ -// sti - call 1f -1: - popw %bx /* Instruction Pointer of 1b */ - subw $(1b - _start1), %bx /* CS:BX=_start1 */ - - shrw $4, %bx - movw %cs, %ax - addw %ax, %bx /* BX:0000=_start1 */ - - /* we are booted from BOOT.INI, or whole GRLDR image already loaded */ - - /* Let CS:0000=_start1 */ - pushw %bx /* BX:0000=_start1 */ - - pushw $(1f - _start1) - lret - -1: - -#if (! defined(GRLDR_MBR)) - - addw $((grldr_signature - _start1 + 4 + STAGE2_SIZE - 4) >> 4), %bx - movw %bx, %ds - cmpl $0xCE1A02B0, ((STAGE2_SIZE - 4) & 0x0F) - pushw %cs - popw %ds - je grldr_real_start /* whole image loaded. boot it! */ - - cmpb $0X80, %dl /* cdrom? */ - jbe 1f /* not */ - call cdrom_check /* cdrom_check present */ - andb $0x80, %dl - -#endif //(! defined(GRLDR_MBR)) - /* CS:0000=DS:0000=_start1 */ - - /* we are loaded by BIOS or another boot loader */ - -#define MONITOR 0x8410 /* for 4-sector NTFS boot record */ -#define GRLDR_CS 0x2000 /* grldr code segment */ -1: -// cli - pushw $GRLDR_CS - popw %ss - movw $0x9000, %sp /* SS:SP=0x9d000, keep away from EBDA data */ -// sti - - /* Extended BIOS Data Area should not take up space below 0x9d000 */ - - /* - * 0x07c00-0x07dff This sector. Another boot loader load us here - * 0x0d000-0x0d7ff partition/floppy boot track(bootsector,etc) - * 0x20000-0x27dff master boot track(MBR,etc,usually 63 sectors) - * 0x29000-0x29bff 6 sectors for stack - */ - -#define FS_BOOT 0xd00 /* segment of partition boot track */ - - cmpb $0x00, %dl - je 1f - movb $0x80, %dl -1: - pushw %ss /* SS=CS */ - popw %es /* ES=CS */ - -// movw $(((pre_stage2_start - _start1) >> 9) + 0x200), %ax - movb $((pre_stage2_start - _start1) >> 9), %al - xorb %dh, %dh - xorw %bx, %bx - call read_disk_with_reset_and_dec_di - jc read_help_err - - pushw %cs /* DS=0 */ - popw %ds /* DS=CS */ - - /* CS=DS=old segment. ES=SS=new segment. */ - - /* Move the code and error messages from DS:0000 to 9400:0000, do not - * touch the partition table - */ - xorw %si, %si - xorw %di, %di - movw $223, %cx /* 223 words = 446 bytes = 0x1be bytes */ - cld - repz movsw /* SI=DI=0x1be, CX=0 */ - - /********************************************************************/ - /* At this moment we are still not sure whether the helper is ok. */ - /********************************************************************/ - - -disk_serial_number_structure: - /********************************************************************/ - /* This piece of code is structured! It contains address 0x1FFC and */ - /* a disk serial number that can be created by grub4dos installers. */ - /********************************************************************/ - - /* if the boot loader has loaded more than one sector, we use them */ - - movw $(grldr_signature - _start1), %bx /* BX=0x1FFC */ - - /* if the boot loader has loaded more than one sector, we use them */ - - movl $0xAA555247, %eax /* "GR" 0x55 0xAA */ - -disk_serial_number_structure_end: - - cmpl %eax, (%bx) /* DS=old segment of 07C0:0000 */ - jne 1f - - /* The MOVE_HELPER code is in the old segment of 07C0:0000 */ - - call move_helper /* SI=0x1be, CX=0 */ -1: - - /* Jump to new segment! */ -#if 1 - ljmp $GRLDR_CS, $(1f - _start1) -#else - pushw %ss /* 0x9400 */ - - //pushw $(1f - _start1) - .byte 0x6A, (1f - _start1) - - lret -#endif -1: - - /* We are at the new segment. CS=ES=SS=new segment. */ - - /* But DS is still old segment. */ - - pushw %ss - popw %ds - - /* CS=DS=ES=SS=new segment. */ - - //movw $0x01be, %si - - /* check the existence of helper */ - cmpl %eax, (%bx) - je helper_call_c - - /* try to load helper from floppy/hard */ - -read_help_err: - - xorb $0x80, %dl - pushw $0x7c0 - popw %es - -// movw $(((pre_stage2_start - _start1) >> 9) + 0x200), %ax - movb $((pre_stage2_start - _start1) >> 9), %al - xorb %dh, %dh - xorw %bx, %bx /* ES:BX immediately follow this sector */ - call read_disk_with_reset_and_dec_di - jc 1f - ljmp $0x7c0, $0 -endup: -1: - movw $(message_string - _start1), %si - call print_message /* CS:SI points to message string */ -1: - jmp 1b - - -helper_call_c: - movw $0x01be, %si - -1: -helper_call: - - call helper_start /* change to jmp 6f if helper not present */ -// testb $0x80, 0x0a - testb $0x80, (help_mark - _start1) - je filesystem_boot - -6: - -add_sub_si: - - /* extended partition check routine will adjust this to - * - * 0x83, 0xEE, 0x04 for "subw $4, %si" - * - * or - * - * 0x83, 0xC6, 0xFC for "addw $-4, %si" - * - * so that SI keeps the value 0x1fe. - */ - addw $12, %si /* 0x83, 0xC6, 0x0C */ - - . = add_sub_si + 3 - - /* extended partition check routine will adjust the word 0x1fe at - * (add_sub_si + 5). The value 0x1ff or greater indicates there are - * entries need to be treated. The value 0x1fe indicates no entries - * left, and the floppy should be checked. - */ - - cmpw $0x01fe, %si /* 0x81, 0xFE, 0xfe, 0x01 */ - /* All entries checked done? */ - jb 1b /* No, check the next entry */ - ja 2f - - testb $1, (Boot_dl - _start1) - jne boot_prev_mbr - orb $1, (Boot_dl - _start1) - testb $2, (Boot_dl - _start1) - jne 1b - pushw $FS_BOOT - popw %es - movb $4, %al - xorw %dx, %dx - xorw %bx, %bx - call read_disk_with_reset_and_dec_di - jnc helper_call_c - movw $(No_floppy - _start1), %si - call print_message - jmp boot_prev_mbr -2: -try_HD: - testb $1, (Boot_dl - _start1) - jne boot_prev_mbr - orb $1, (Boot_dl - _start1) - jmp Error_modify - -int13: - pushw %ds - pushw %es -// pushw %bx - pushw %dx - pushw %si - pushw %di - pushw %bp - stc - int $0x13 - popw %bp - popw %di - popw %si - popw %dx -// popw %bx - popw %es - popw %ds - ret - -try_next_partition: - - cli - movw $GRLDR_CS, %ax - movw %ax, %ss - movw $(0x9000-36), %sp - sti - - /* restore the registers and continue */ - popal - popw %es - popw %ds - jmp add_sub_si - -read_disk_with_reset_and_dec_di: -//2: - movb $2, %ah - movw $3, %di - movw $1, %cx -2: - pushaw -//////////////////////////////////////////////////////////// - /* ES:BX=buffer */ - /* AH=2, AL=sectors */ - /* CX=sector and cylinder numbers */ - /* DH=head number, DL=drive number */ -3: - pushw %ax - pushw %bx - pushw %cx - decb %al - addb %al, %cl /* sector number */ - shlb $1, %al - addb %al, %bh /* buffer */ - movb $0x01, %al /* AH=2 untouched */ - call int13 - popw %cx - popw %bx - popw %ax - jc 3f - decb %al - jnz 3b -3: -//////////////////////////////////////////////////////////// - popaw - jnc 3f - pushaw - xorw %ax, %ax - call int13 - popaw - decw %di - jne 2b - stc -3: - ret - - /* prints string CS:SI (modifies AX BX SI) */ -3: - //xorw %bx, %bx /* video page 0 */ - movb $0x0e, %ah /* print char in AL */ - int $0x10 /* via TTY mode */ - -print_message: - - lodsb %cs:(%si), %al /* get token */ - cmpb $0, %al /* end of string? */ - jne 3b - ret - -message_string: - - .ascii "\r\nMissing helper.\0" - -help_mark: - .byte 0 - - /* helper detection flag - * bit2=1: EBIOS supported - * bit3=1: Partition Table OK - * bit7=1: Try next entry - */ - -Sectors_passed_in: - .byte 0x3f - -Heads_passed_in: - .byte 0xff - -Boot_dl: - .byte 0x00 //00/80=FD/HD - -#if (! defined(GRLDR_MBR)) - -cdrom_check: - - /* DS=CS points to the sector start. */ - - /* BX segment points to near the end of GRLDR image. */ - - /* The code must begin with 0x58, 0x8E, 0xD3, 0xBC. */ - - popw %ax /* old return IP. code: 0x58 */ - - /* set BX as the new safe stack. */ - //For compatibility Virtual PC - movw $0x6840, %bx - movw %bx, %ss - movw $0xFFF0, %sp - - pushw %ax /* old return IP */ - - /* check if DL is no-emulation-mode bootable CDROM. */ - pushw %ds - - cmpb $0x80, %dl - jb 1f /* not a valid no-emulation-mode cdrom drive number */ - - cmpw $0xAA55, 0x3FE /* 2048 bytes loaded? */ - jne 1f - - movw $0x0180, %si - movw $0x4B01, %ax - pushw $0x0040 - popw %ds - movb $0x13, (%si) - call int13 - - /* ignore CF */ -#; jc 2f /* not in emulation mode */ - xorl %eax, %eax - xorw %bp, %bp - testb $0x0F, 1(%si) /* boot media type is No Emulation? */ - jnz 2f /* no, it simulates floppy or hard disk. */ - cmpb %dl, 2(%si) /* drive number */ - jnz 2f /* invalid drive */ - - /* OK! it is no-emulation-mode cdrom drive. */ - movl 4(%si), %eax /* LBA of GRLDR */ - incw %bp - -2: - jmp cdrom_helper -1: - popw %ds - ret - -#endif //(! defined(GRLDR_MBR)) - - - /* Make sure the above code does not occupy the partition table */ - - /* offset value here must be less than or equal to 0x1b8 */ - -#if (defined(GRLDR_MBR)) -// . = . - ((. - _start1) / 0x1b9) - . = _start1 + 0x1fe /* boot signature */ - .word 0xAA55 - -#else - -#endif //(defined(GRLDR_MBR)) - . = _start1 + 0x200 - - -/* if it is in the Master Boot Track, the second sector can be used to backup - * the previously working MBR, typically, the MS MBR. if the backup copy of - * the MBR cannot boot(because, e.g., it depends on another sector of code - * that does not exist for now), then please do not set the ending signature - * to 0xAA55, that is to say, if the signature is already 0xAA55, you should - * change it to another value(for example, 0x0000). - */ - - .fill 0x6b,1,0x90 - -// . = _start1 + 0x256 - // NTLDR loads GRLDR entrance - // Have verified that at least in Windows XP SP2 (5.1.2600.2180) and SP3 (5.1.2600.5512) - - movb $0x80, %dl - jmp _start1 - -// . = _start1 + 0x270 - -#if (! defined(GRLDR_MBR)) - -cdrom_helper: - - /* IP and old_DS is on the stack. */ - - /* DS=40h */ - - /* Stack is high and safe. */ - - /* EAX is LBA. if EAX==0, LBA is unknown. */ - - /* check if the first sector is the same as the current one */ - - /* load the first sector onto the sector immediately follows */ -1: - pushw %cs - popw %bx /* BX=CS=old_DS=load_segment */ - addw $0x0080, %bx /* buffer segment */ - movw %bx, %es /* ES changed! */ - call load_cd_sector - - /* compare the two sectors */ - movw $0x200, %cx - xorw %si, %si - xorw %di, %di - cld - cs repz cmpsl - je load_the_rest /* 1st sector is ok, continue */ -not_grldr: - testw %bp, %bp - jz 2f - xorw %bp, %bp -// xorl %eax, %eax - movl $0x12, %eax -2: - incl %eax - jnz 1b /* try next */ - -cd_no_grldr: - pushw %cs - popw %ds /* DS=load_segment */ - - # Here we use error message and routine in FAT32 boot sector - # which is also inside the 2048-byte CD sector. - - movw $(msg_BootError_cd - _start1), %si -1: - lodsb (%si), %al /* get token */ - movb $0x0e, %ah /* print it */ - int $0x10 /* via TTY mode */ - cmpb $0, %al /* end of string? */ - jne 1b /* until done */ -1: - jmp 1b - - - -load_cd_sector: - /* input: EAX LBA - * BX buffer segment(buffer offset=0) - * EAX LBA lo 32 bits - * output: - * 16 bytes at DS:SI destroyed - */ - - pushaw - pushw %ds - movw $0x1A0, %si - pushw $0x40 - popw %ds - - /* disk address packet */ - movl $0x00010010, (%si) /* load 1 sector each time. */ - movw $0, 4(%si) /* buffer offset=0 */ - movw %bx, 6(%si) /* buffer segment */ - movl %eax, 8(%si) /* LBA lo 32 bits */ - movl $0, 12(%si) /* LBA hi 32 bits */ - - movb $0x42, %ah - call int13 - - popw %ds - popaw - ret - -load_the_rest: - - /* load all sectors (except the first one) */ - - /* EAX = first sector(LBA) of GRLDR */ - - pushl %eax - - pushw %cs - popw %bx /* BX=CS=old_DS=load_segment */ - pushw %bx - /* 6144 = 0x1800 = 3 sectors > 4KB, this is for the additional 4KB-preset-menu at the end of grldr */ -// movw $((grldr_signature - _start1 + 4 + STAGE2_SIZE - 1 + 6144 ) / 2048), %cx /* sectors to load */ - movw $((grldr_signature - _start1 + 4 + STAGE2_SIZE - 4) / 0x800 + 16), %cx //32KB-preset-menu -1: - incl %eax /* next sector */ - addw $0x0080, %bx /* buffer segment */ - call load_cd_sector - loop 1b - /* loading is completed. BX=segment of the last sector. */ - -// subw $0x0181, %bx /* decw %bx */ - popw %bx - addw $((grldr_signature - _start1 + 4 + STAGE2_SIZE - 4) >> 4), %bx - movw %bx, %ds - - popl %eax -// subl $((grldr_signature - _start1 + 4 + STAGE2_SIZE - 1 + 6144) / 2048), %eax - - /* check the ending signature */ -// cmpl $0xCE1A02B0, ((grldr_signature - _start1 + 4 + STAGE2_SIZE - 1) % 2048) + 13 - cmpl $0xCE1A02B0, ((STAGE2_SIZE - 4) & 0x0F) - jne not_grldr - -grldr_real_start: - cli - //xorw %ax, %ax - //movw %ax, %ss - //movw $0x0400, %sp /* tmp use real-mode IDT as stack */ - movw %cs, %bp /* save CS to BP */ - call 1f -1: - popw %bx /* BX=Instruction Pointer of 1b */ - subw $(1b - _start1), %bx - movw %bx, %cx - shrw $4, %bx - addw %bp, %bx - pushw %bx /* new CS */ - andw $0x000f, %cx - addw $(1f - _start1), %cx - pushw %cx /* new IP */ - lret -1: -// movw %ds, %cx /* CX==BP==0x7C0 for pxe enabled */ - pushw %cs - popw %ds - - /* CS=DS=BX, CS:0000 = _start1 */ - - addw $((pre_stage2_start - _start1) >> 4), %bx - - /* BX:0000 = pre_stage2_start */ - //////////////////////////////////////////////// - //old_stack 1 0x580 - //old_stack 2 0x68400 For Compatible with Virtual PC - //new_stack 0x2000 - //Buffer 0x580 - 0x59f 0x20 - //int13/AH=42 pack 0x5a0 - 0x5af 0x10 - //GRLDR head 0x5eo - 0x7df 0x200 - //pre_stage2 0x8200 - 0x681ff 0x60000 - //////////////////////////////////////////////// - -// cmpw $0x7C0, %bp -// jne 1f -// cmpw %bp, %cx -// je 2f -//1: - //orb $0x01, (pre_stage2_start - _start1 + 5) /* disable pxe */ -2: - cmpw $0x820, %bx - jb 2f - - movw $((0x8200 - (pre_stage2_start - _start1) - 0x400) >> 4), %cx //0x5e0 - - movw %cx, %es - xorw %di, %di - xorw %si, %si - - movw $0x200, %cx /* move 2 sectors */ - cld - repz movsw - - pushw %es /* ES:0000 = _start */ - pushw $(1f - _start1) - lret /* CS=ES, CS:0000 = _start1 */ -1: - - /* move BX:0000 to 0820:0000 upward since BX >= 0x820 */ - -// cld - - movw %bx, %ds //0x2200 or 0x9c0 - movw $0x820, %bx - movw %bx, %es //0x820 - - xorw %si, %si - xorw %di, %di - - movw $6, %bx /* 6*64K pages: 0x22000 - 0x81fff 6*64K = 384K */ -1: - movw $0x8000, %cx - repz movsw //(0x22000 - 0x81fff) or (0x9c00 - 0x69bff) -> (0x8200 - 0x681ff) - movw %ds, %ax - addw $0x1000, %ax - movw %ax, %ds - movw %es, %ax - addw $0x1000, %ax - movw %ax, %es - decw %bx - jnz 1b - - jmp 3f -2: - - /* move BX:0000 to 0820:0000 downward since BX < 0x820 */ - - std - - addw $0x7000, %bx - movw %bx, %ds //0x7b00 - movw $0x7820, %bx - movw %bx, %es //0x7820 - - movw $0xfffe, %si - movw %si, %di - - movw $6, %bx /* 6*64K pages: 0x0b000 - 0x6afff 6*64K = 384K */ -1: - movw $0x8000, %cx - repz movsw //(0x0b000 - 0x6afff) -> (0x8200 - 0x681ff) - movw %ds, %ax - subw $0x1000, %ax - movw %ax, %ds - movw %es, %ax - subw $0x1000, %ax - movw %ax, %es - decw %bx - jnz 1b - - cld - -3: - -#if 0 - /* put the config file name */ - xorw %ax, %ax - movw %ax, %es - movw %ax, %ds - - xorl %ebp, %ebp - - movb %dh, 0x820A /* this is the boot partition number */ - - #; clear saved_entryno so that force_cdrom_as_boot_device be cleared - #; later in common.c - - movl %ebp, 0x820C /* EBP=0, clear saved_entryno */ - - movw $0x0010, %cx /* set max length of grub version string */ - movw $0x8212, %di /* version string */ - cld - /* AL is already 0. Locate the end of version string */ - repnz scasb /* find the location of the default config file name */ - - jcxz 1f /* failed, will not use the default config file name */ - - movw $0x4e, %cx /* max length of config file name */ - - movw %cs, %si /* CS:0000 = _start1 */ - shlw $4, %si /* 0000:SI = _start1 */ - - addw $(default_config_file - _start1), %si - - //movw $(default_config_file + 0x8200 - pre_stage2_start), %si - cld - repz movsb /* move file name to the config-file field of stage2 */ -1: - cli - xorw %ax, %ax - movw %ax, %ss - movw $0x2000, %sp - sti - - movw $0x0003, %ax /* set display mode: 80*25 color text */ - int $0x10 - - ljmp $0, $0x8200 - - -default_config_file: - .ascii "/menu.lst" - - .byte 0 /* mark the end of ascii zero string */ -#else - xorl %eax, %eax - movw %ax, %es - movw %ax, %ds - //movw %ax, %ss - //movw $0x2000, %sp - - #; clear saved_entryno so that force_cdrom_as_boot_device be cleared - #; later in common.c - - movl %eax, 0x820C /* EAX=0, clear saved_entryno */ - - ljmp $0, $0x8200 -#endif - - . = _start1 + 0x3f0 - -msg_BootError_cd: - .ascii "No GRLDR\0" - - . = _start1 + 0x3fe /* boot signature */ - .word 0xAA55 - -#endif // (! defined(GRLDR_MBR)) - - . = _start1 + 0x400 - -#endif // (! defined(GRLDR_INSTALL)) - -#define ALTERNATIVE_KERNEL - -#if defined(GRLDR_INSTALL) - - .code16 - -/* ******************** fat32_dbr start ****************************** */ -/* - * The following is based on FreeDOS, modified heavily by Tinybit in Feb, 2004 - * - * Merges LBA and CHS boot sectors to ONE FAT32 boot sector! - * - * Memory layout for GRLDR FAT32 single stage boot process: - * - * ... - * |-------| 1FE0:7E00 - * |BOOTSEC| (GRUB does not use this relocation area) - * |RELOC. | (overwritten by kernel loaded) - * |-------| 1FE0:7C00 - * ... - * |-------| - * |KERNEL | (overwrites bootsec reloc.) - * |LOADED | (holds 1 sector directory buffer before kernel load) - * |-------| 2000:0000 - * ... - * |-------| 0000:7E00 - * |BOOTSEC| GRUB always run inside this sector, - * |ORIGIN | no relocation. - * |-------| 0000:7C00 - * ... - * |-------| 0060:0200 - * | FAT | (only 1 sector buffered) - * |-------| 0060:0000 - * ... - * - */ - -/* -; This is an LBA-enabled FreeDOS FAT32 boot sector (single sector!). -; You can use and copy source code and binaries under the terms of the -; GNU Public License (GPL), version 2 or newer. See www.gnu.org for more. - -; Based on earlier work by FreeDOS kernel hackers, modified heavily by -; Eric Auer and Jon Gentle in 7 / 2003. -; -; Features: Uses LBA and calculates all variables from BPB/EBPB data, -; thus making partition move / resize / image-restore easier. FreeDOS -; can boot from FAT32 partitions which start > 8 GB boundary with this -; boot sector. Disk geometry knowledge is not needed for booting. -; -; Windows uses 2-3 sectors for booting (sector stage, statistics sector, -; filesystem stage). Only using 1 sector for FreeDOS makes multi-booting -; of FreeDOS and Windows on the same filesystem easier. -; -; Requirements: LBA BIOS and 386 or better CPU. Use the older CHS-only -; boot sector if you want FAT32 on really old PCs (problems: you cannot -; boot from > 8 GB boundary, cannot move / resize / ... without applying -; SYS again if you use the CHS-only FAT32 boot sector). -; -; FAT12 / FAT16 hints: Use the older CHS-only boot sector unless you -; have to boot from > 8 GB. The LBA-and-CHS FAT12 / FAT16 boot sector -; needs applying SYS again after move / resize / ... a variant of that -; boot sector without CHS support but with better move / resize / ... -; support would be good for use on LBA harddisks. - - -; Memory layout for the FreeDOS FAT32 single stage boot process: - -; ... -; |-------| 1FE0:7E00 -; |BOOTSEC| -; |RELOC. | -; |-------| 1FE0:7C00 -; ... -; |-------| 2000:0200 -; | FAT | (only 1 sector buffered) -; |-------| 2000:0000 -; ... -; |-------| 0000:7E00 -; |BOOTSEC| overwritten by the kernel, so the -; |ORIGIN | bootsector relocates itself up... -; |-------| 0000:7C00 -; ... -; |-------| -; |KERNEL | maximum size 134k (overwrites bootsec origin) -; |LOADED | (holds 1 sector directory buffer before kernel load) -; |-------| 0060:0000 -; ... -*/ - - -#define LOADSEG 0x2000 -#define FATSEG 0x0060 - -Entry_32: - jmp 1f - - . = Entry_32 + 0x02 - - .byte 0x90 /* for CHS. Another possible value is 0x0e for LBA */ - - . = Entry_32 + 0x52 - - .ascii "FAT32 " /* filesystem ID, 8 bytes. */ - -/* -; bp is initialized to 7c00h -; %define bsOemName bp+0x03 ; OEM label (8) -%define bsBytesPerSec bp+0x0b ; bytes/sector (dw) -%define bsSecPerClust bp+0x0d ; sectors/allocation unit (db) -%define bsResSectors bp+0x0e ; # reserved sectors (dw) -%define bsFATs bp+0x10 ; # of fats (db) -; %define bsRootDirEnts bp+0x11 ; # of root dir entries (dw, 0 for FAT32) - ; (FAT32 has root dir in a cluster chain) -; %define bsSectors bp+0x13 ; # sectors total in image (dw, 0 for FAT32) - ; (if 0 use nSectorHuge even if FAT16) -; %define bsMedia bp+0x15 ; media descriptor: fd=2side9sec, etc... (db) -; %define sectPerFat bp+0x16 ; # sectors in a fat (dw, 0 for FAT32) - ; (FAT32 always uses xsectPerFat) -%define sectPerTrack bp+0x18 ; # sectors/track -; %define nHeads bp+0x1a ; # heads (dw) -%define nHidden bp+0x1c ; # hidden sectors (dd) -; %define nSectorHuge bp+0x20 ; # sectors if > 65536 (dd) -%define xsectPerFat bp+0x24 ; Sectors/Fat (dd) - ; +0x28 dw flags (for fat mirroring) - ; +0x2a dw filesystem version (usually 0) -%define xrootClst bp+0x2c ; Starting cluster of root directory (dd) - ; +0x30 dw -1 or sector number of fs.-info sector - ; +0x32 dw -1 or sector number of boot sector backup - ; (+0x34 .. +0x3f reserved) -%define drive bp+0x40 ; Drive number - bp+0x41 ; partition number for GRLDR - -%define fat_sector bp+0x44 ; last accessed FAT sector (dd) - ; (overwriting unused bytes) -%define fat_start bp+0x48 ; first FAT sector (dd) - ; (overwriting unused bytes) -%define data_start bp+0x4c ; first data sector (dd) - ; (overwriting unused bytes) - -*/ - - . = Entry_32 + 0x5a -1: - cli - cld -// testb $0x80, %dl 2014-01-26 -// jne 1f -// movb $0xff, %dh -// jmp 2f -//1: -// cmpw $0x7c00, %sp -// jne 2f -// subw $0x7be, %bp -// xchgw %bp, %ax -// shrb $4, %al -// movb %al, %dh -//2: - xorw %ax, %ax - movw $0x7c00, %bp - movw %bp, %sp - movw %ax, %ss /* stack and BP-relative moves up, too */ - sti /* after stack setup, we can use stack */ - - /* cs=ss=ds=es=0, bp=0x7C00 */ - pushw %ax - movw %dx, 0x40(%bp) /* BIOS passes drive number in DL */ - movb $0x41, %ah - movw $0x55AA, %bx - int $0x13 - popw %ds - jc 1f /* No EBIOS */ - cmpw $0xAA55, %bx - jne 1f /* No EBIOS */ - rorb $1, %cl - jnc 1f /* No EBIOS */ - /* EBIOS supported */ - movb $0x42, (ebios_32 - 1 - Entry_32 + 0x7c00) -1: -// movb (Loadusb_32 - Entry_32 + 0x7c00 +1), %al -// decb %al //al=1,When dl = 00 load -// jne 1f -// cmpb %al, %dl //dl=0? -// je 3f -//1: -// decb %al //al=2,Forced load -// jne 2f -//3: //Load the usb driver -// pushw $0x0d00 -// popw %es //read to 0d00:0000 -// movl 0x7c1c, %eax -// incl %eax -// incl %eax -// movw $0x0a, %cx -//1: -// call readDisk_32 -// loop 1b -// call $0x0d00,$0x0000 -// jc 2f -// movb %dl, 0x40(%bp) /* BIOS passes drive number in DL */ -// movb $0x42, (ebios_32 - 1 - Entry_32 + 0x7c00) -//2: - -/* figure out where FAT and DATA area starts - * (modifies EAX EDX, sets fat_start and data_start variables) - */ - xorw %bx, %bx - xorl %eax, %eax - movl %eax, 0x44(%bp) /* init buffer status */ - - /* first, find fat_start */ - movw 0x0e(%bp), %ax /* reserved sectors */ - addl 0x1c(%bp), %eax /* hidden sectors */ - movl %eax, 0x48(%bp) /* first FAT sector */ - movl %eax, 0x4c(%bp) /* first data sector, initial value */ - - /* next, find data_start */ - movl 0x10(%bp), %eax /* number of fats, no movzbl needed: the */ - /* 2 words at 0x11(%bp) are 0 for fat32. */ - mull 0x24(%bp) /* sectors per fat (EDX=0) */ - addl %eax, 0x4c(%bp) /* first DATA sector */ - -/* Searches for the file in the root directory. - * Returns: EAX = first cluster of file - */ - - movl 0x2c(%bp), %eax /* root dir cluster */ - -1: - pushl %eax /* save cluster */ - call cluster_to_lba_32 - /* EDX is sectors per cluster, EAX is sector number */ - movw $(msg_BootError_32 - Entry_32 + 0x7c00), %si - jc boot_error_32 /* EOC encountered */ - -2: -// lesw (loadseg_off_32 - Entry_32)(%bp), %bx /* load to loadseg:0 */ - pushw $LOADSEG - popw %es - pushw %es - call readDisk_32 - popw %es - xorw %di, %di - - /* Search for kernel file name, and find start cluster */ -3: - movw $11, %cx - movw $(filename_32 - Entry_32 + 0x7c00), %si - repz cmpsb - jz 1f /* note that di now is at dirent+11 */ - - addw $0x20, %di - andw $-0x20, %di /* 0xffe0 */ - cmp 0x0b(%bp), %di /* bytes per sector */ - jnz 3b /* next directory entry */ - - decw %dx /* initially DX holds sectors per cluster */ - jnz 2b /* loop over sectors in cluster */ - - popl %eax /* restore current cluster */ - call next_cluster_32 - jmp 1b /* read next cluster */ - -1: - /* kernel directory entry is found */ - pushw %es:(0x14-11)(%di) /* get cluster number HI */ - pushw %es:(0x1a-11)(%di) /* get cluster number LO */ - popl %eax /* convert to 32bit */ - - -/* read kernel */ - -2: - pushl %eax - call cluster_to_lba_32 - /* EDX is sectors per cluster, EAX is sector number */ - jnc 1f - - /* EOC encountered - done */ - - movw 0x40(%bp), %dx /* boot_drive and boot_partition */ - pushw %dx /* for loading grub.exe */ -// ljmp *(loadseg_off_32 - Entry_32)(%bp) - ljmp $LOADSEG,$0x0000 - -1: - call readDisk_32 - decw %dx /* initially DX holds sectors per cluster */ - jnz 1b /* loop over sectors in cluster */ - - popl %eax - call next_cluster_32 - jmp 2b - -/* given a cluster number, find the number of the next cluster in - * the FAT chain. Needs fat_start. - * input: EAX - cluster - * EDX = 0 - * output: EAX - next cluster - * EDX = undefined - */ - -next_cluster_32: - pushw %es - shll $2, %eax /* 32bit FAT */ - movzwl 0x0b(%bp), %ebx /* bytes per sector */ - divl %ebx /* residue is in EDX */ - addl 0x48(%bp), %eax /* add the first FAT sector number. */ - /* EAX=absolute sector number */ - movw $FATSEG, %bx - movw %bx, %es - xorw %bx, %bx - - /* is it the last accessed and already buffered FAT sector? */ - cmpl 0x44(%bp), %eax - jz 1f - movl %eax, 0x44(%bp) /* mark sector EAX as buffered */ - pushw %es - call readDisk_32 /* read sector EAX to buffer */ - popw %es -1: - andb $0x0f, %es:3(%edx) /* mask out top 4 bits */ - movl %es:(%edx), %eax /* read next cluster number */ - popw %es - ret - -/* Convert cluster number to the absolute sector number - * ... or return carry if EndOfChain! Needs data_start. - * input: EAX - target cluster - * output: EAX - absolute sector - * EDX - [bsSectPerClust] (byte) - * carry clear - * (if carry set, EAX/EDX unchanged, end of chain) - */ - -cluster_to_lba_32: - cmpl $0x0ffffff8, %eax /* check End Of Chain */ - cmc - jb 1f /* carry is stored if EOC */ - - /* sector = (cluster-2) * clustersize + data_start */ - decl %eax - decl %eax - - movzbl 0x0d(%bp), %edx /* sectors per cluster */ - pushw %dx /* only DX would change */ - mull %edx /* EDX = 0 */ - popw %dx - addl 0x4c(%bp), %eax /* data_start */ - /* here, carry is cleared (unless parameters are wrong) */ -1: - ret - -/* Read a sector from disk, using LBA or CHS - * input: EAX - 32-bit DOS sector number - * ES:0000 - destination buffer - * (will be filled with 1 sector of data) - * output: ES:0000 points one byte after the last byte read. - * EAX - next sector - */ - -readDisk_32: - pushal - xorl %edx, %edx /* EDX:EAX = LBA */ - pushl %edx /* hi 32bit of sector number */ - pushl %eax /* lo 32bit of sector number */ - pushw %es /* buffer segment */ - pushw %dx /* buffer offset */ - pushw $1 /* 1 sector to read */ - pushw $16 /* size of this parameter block */ - - xorl %ecx, %ecx - pushl 0x18(%bp) /* lo:sectors per track, hi:number of heads */ - popw %cx /* ECX = sectors per track */ - divl %ecx /* residue is in EDX */ - /* quotient is in EAX */ - incw %dx /* sector number in DL */ - popw %cx /* ECX = number of heads */ - pushw %dx /* push sector number into stack */ - xorw %dx, %dx /* EDX:EAX = cylinder * TotalHeads + head */ - divl %ecx /* residue is in EDX, head number */ - /* quotient is in EAX, cylinder number */ - xchgb %dl, %dh /* head number should be in DH */ - /* DL = 0 */ - popw %cx /* pop sector number from stack */ - xchgb %al, %ch /* lo 8bit cylinder should be in CH */ - /* AL = 0 */ - shlb $6, %ah /* hi 2bit cylinder ... */ - orb %ah, %cl /* ... should be in CL */ - - movw $0x201, %ax /* read 1 sector */ -ebios_32: - - movw %sp, %si /* DS:SI points to disk address packet */ - movb 0x40(%bp), %dl /* hard disk drive number */ - pushw %es - pushw %ds - int $0x13 - popw %ds - popw %bx - jc disk_error_32 - leaw 0x20(%bx), %bx - movw %bx, %es - popaw /* remove parameter block from stack */ - popal - incl %eax /* next sector */ - ret - - - -disk_error_32: - - movw $(msg_DiskReadError_32 - Entry_32 + 0x7c00), %si - -boot_error_32: - -/* prints string DS:SI (modifies AX BX SI) */ - -//print_32: -1: - lodsb (%si), %al /* get token */ - //xorw %bx, %bx /* video page 0 */ - movb $0x0e, %ah /* print it */ - int $0x10 /* via TTY mode */ - cmpb $0, %al /* end of string? */ - jne 1b /* until done */ -1: - jmp 1b - - . = Entry_32 + 0x1e0 - -msg_BootError_32: - .ascii "No " - -filename_32: - .ascii "GRLDR \0" - -msg_DiskReadError_32: - .ascii "Disk error\0" - - . = Entry_32 + 0x1fc - .word 0, 0xAA55 /* Win9x uses all 4 bytes as magic value here */ - - . = Entry_32 + 0x200 - -/* ******************** fat32_dbr end ****************************** */ - -/* ******************** fat12_16_dbr start ****************************** */ - - .arch i486, nojumps - -/* - * The following is based on FreeDOS, modified heavily by Tinybit in Feb, 2004 - * - * Merges FAT12 and FAT16 boot sectors to ONE FAT boot sector! - * - * Memory layout for GRLDR FAT single stage boot process: - * - * +--------+ - * | | - * |GRLDR | also used as max 128k FAT buffer - * |LOADED | before GRLDR loading starts - * |--------| 2000:0000 - * | | - * |--------| 0000:7E00 - * |BOOTSECT| - * |ORIGIN | - * |--------| 0000:7C00 - * | | - * |--------| 0000:3000 - * |CLUSTER | - * |LIST | - * |--------| 0000:2000 - * | | - * +--------+ - */ - -/* -; -; File: -; boot.asm -; Description: -; DOS-C boot -; -; Copyright (c) 1997; -; Svante Frey -; All Rights Reserved -; -; This file is part of DOS-C. -; -; DOS-C is free software; you can redistribute it and/or -; modify it under the terms of the GNU General Public License -; as published by the Free Software Foundation; either version -; 2, or (at your option) any later version. -; -; DOS-C is distributed in the hope that it will be useful, but -; WITHOUT ANY WARRANTY; without even the implied warranty of -; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -; the GNU General Public License for more details. -; -; You should have received a copy of the GNU General Public -; License along with DOS-C; see the file COPYING. If not, -; write to the Free Software Foundation, 675 Mass Ave, -; Cambridge, MA 02139, USA. -; -; -; +--------+ 1FE0:7E00 -; |BOOT SEC| -; |RELOCATE| -; |--------| 1FE0:7C00 -; | | -; |--------| 1FE0:3000 -; | CLUSTER| -; | LIST | -; |--------| 1FE0:2000 -; | | -; |--------| 0000:7E00 -; |BOOT SEC| overwritten by max 128k FAT buffer -; |ORIGIN | and later by max 134k loaded kernel -; |--------| 0000:7C00 -; | | -; |--------| -; |KERNEL | also used as max 128k FAT buffer -; |LOADED | before kernel loading starts -; |--------| 0060:0000 -; | | -; +--------+ -*/ - - -#define LOADSEG_12_16 0x2000 -#define FATBUF 0x2000 /* offset of temp buffer for FAT chain */ - -Entry_12_16: - jmp 1f - - . = Entry_12_16 + 0x02 - .byte 0x90 - - . = Entry_12_16 + 0x36 - - .ascii "FAT12/16" /* filesystem ID */ - -/* -; bp is initialized to 7c00h -%define bsOemName bp+0x03 ; OEM label -%define bsBytesPerSec bp+0x0b ; bytes/sector -%define bsSecPerClust bp+0x0d ; sectors/allocation unit -%define bsResSectors bp+0x0e ; # reserved sectors -%define bsFATs bp+0x10 ; # of fats -%define bsRootDirEnts bp+0x11 ; # of root dir entries -%define bsSectors bp+0x13 ; # sectors total in image -%define bsMedia bp+0x15 ; media descrip: fd=2side9sec, etc... -%define sectPerFat bp+0x16 ; # sectors in a fat -%define sectPerTrack bp+0x18 ; # sectors/track -%define nHeads bp+0x1a ; # heads -%define nHidden bp+0x1c ; # hidden sectors -%define nSectorHuge bp+0x20 ; # sectors if > 65536 -%define drive bp+0x24 ; drive number - bp+0x25 ; partition number for GRLDR -%define extBoot bp+0x26 ; extended boot signature -%define volid bp+0x27 -%define vollabel bp+0x2b -%define filesys bp+0x36 - -%define RootDirSecs bp+0x26 ; # of sectors root dir uses - ; (overwriting unused bytes) -%define fat_start bp+0x28 ; first FAT sector - ; (overwriting unused bytes) -%define root_dir_start bp+0x2c ; first root directory sector - ; (overwriting unused bytes) -%define data_start bp+0x30 ; first data sector - ; (overwriting unused bytes) -%define data_clusters bp+0x34 ; # of clusters in data area - ; (overwriting unused bytes) - bp+0x36 ; bytes per FAT( > 0x1800 means FAT16) - ; (overwriting unused bytes) -*/ - - . = Entry_12_16 + 0x3e -1: - cli - cld -// testb $0x80, %dl 2014-01-26 -// jne 1f -// movb $0xff, %dh -// jmp 2f -//1: -// cmpw $0x7c00, %sp -// jne 2f -// subw $0x7be, %bp -// xchgw %bp, %ax -// shrb $4, %al -// movb %al, %dh -//2: - xorw %ax, %ax - movw $0x7c00, %bp - movw %bp, %sp - movw %ax, %ss /* stack and BP-relative moves up, too */ - movw %ax, %ds - movw %ax, %es - sti /* after stack setup, we can use stack */ - - /* cs=ss=ds=es=0, bp=0x7C00 */ - - movw %dx, 0x24(%bp) /* BIOS passes drive number in DL */ - movb $0x41, %ah - movw $0x55AA, %bx - pushw %ds - pushw %es - int $0x13 - popw %es - popw %ds - jc 1f /* No EBIOS */ - cmpw $0xAA55, %bx - jne 1f /* No EBIOS */ - rorb $1, %cl - jnc 1f /* No EBIOS */ - /* EBIOS supported */ - movb $0x42, (ebios_12_16 - 1 - Entry_12_16 + 0x7c00) -1: - /* GET DRIVE PARMS: Calculate start of some disk areas */ - movzwl 0x0e(%bp), %ebx /* reserved sectors */ - addl 0x1c(%bp), %ebx /* hidden sectors */ - movl %ebx, 0x28(%bp) /* ---- FAT start */ - - movzbl 0x10(%bp), %eax /* number of FATs */ - movzwl 0x16(%bp), %ecx /* sectors per FAT */ - mull %ecx /* EDX=0, EAX=total sectors for FAT */ - addl %eax, %ebx - movl %ebx, 0x2c(%bp) /* ---- RootDir start */ - - /* Calculate how many sectors the root directory occupies */ - - movw 0x11(%bp), %ax /* max number of root dir entries */ - addw $0x0f, %ax - movw $0x10, %cx - divw %cx /* AX = sectors per root directory */ - cwde - movw %ax, %cx - addl %eax, %ebx - movl %ebx, 0x30(%bp) /* ---- DataArea start */ - - /* First, read the whole root directory into the temporary buffer */ - - movl 0x2c(%bp), %eax /* root directory starting sector(lo) */ - lesw (loadseg_off_12_16 - Entry_12_16)(%bp), %bx /* ES:BX = 0x2000:0000 */ - - /* cs=ss=ds=0 es=0x2000 */ - - call readDisk_12_16 /* CX=0, eax,ES changed */ - - lesw (loadseg_off_12_16 - Entry_12_16)(%bp), %di /* ES:DI = 0x2000:0000 */ - - - /* Search for kernel file name, and find start cluster */ - - /* BX=0, CX=0 */ - -1: - movw $(filename_12_16 - Entry_12_16 + 0x7c00), %si /* filename */ - - movb $11, %cl /* length of kernel filename */ - - pushw %di - repz cmpsb - popw %di - - jz 1f - - addw $0x20, %di /* next entry */ - jz 2f /* or jc 2f, exceeding 64K */ - - /* if the entry begins in 0, this also ends the dir. */ - - cmpb %ch, %es:(%di) /* CH=0 */ - jnz 1b -2: - movw $(msg_BootError_12_16 - Entry_12_16 + 0x7c00), %si - jmp boot_error_12_16 /* fail if not found */ - -1: - -/****************************************************************************/ - - /* BX=0, CX=0 */ - - ###################################################################### - # Reads the FAT chain and stores it in a temporary buffer in the - # first 64KB. The FAT chain is stored an array of 16-bit cluster - # numbers, ending with 0. - # - # The file must fit in conventional memory, so it can't be larger - # than 640KB. The sector size must be at least 512 bytes, so the - # FAT chain can't be larger than around 3KB. - ###################################################################### - - /********************************************************************/ - /* First, load the complete FAT into memory. The FAT can't be */ - /* larger than 128KB, so it should fit in the temporary buffer.' */ - /********************************************************************/ - - pushw %es:0x1a(%di) /* save first cluster number of file */ - movw 0x16(%bp), %cx /* sectors per FAT */ - movl 0x28(%bp), %eax /* FAT start sector(lo) */ - - pushw %es /* ES=0x2000 */ - call readDisk_12_16 /* CX=0, eax,ES changed */ - popw %ds /* DS=0x2000 */ - - /* cs=ss=0 ds=0x2000 es=x */ - - popw %ax /* restore first cluster number of file */ - - /********************************************************************/ - /* Then, extract the clusters of the file from the FAT */ - /********************************************************************/ - - /* Set ES:DI to the temporary storage for the FAT chain */ - - pushw %ds /* ES=0x2000 */ - - pushw %ss - popw %es - - /* cs=es=ss=0 ds=0x2000 */ - - movw $FATBUF, %di /* cs=ss=es=0000 ds=di=0x2000 */ - - /* BX=0, CX=0 */ -2: - stosw /* store cluster number */ - movw %ax, %si /* SI = cluster number */ - - ////////////////////////////////////////////////////////////// - // - // FAT16 can occupy 128KB, so the segment must be adjusted - // - ////////////////////////////////////////////////////////////// - - popw %dx /* DX=0x2000, segment for FAT16 */ - pushw %dx - addw %si, %si /* multiply cluster number by two */ - jnc 1f - addb $0x10, %dh /* overflow. Add 0x1000 to segment value */ -1: - cmpw $0x3231, 0x39(%bp) - jne 3f - /******** FAT12 ********/ - - addw %ax, %si /* multiply cluster number by 3 ... */ - shrw $1, %si /* ... and divide by 2 */ - lodsw - - /* If the cluster number was even, the cluster value is now in - * bits 0-11 of AX. If the cluster number was odd, the cluster - * value is in bits 4-15, and must be shifted right 4 bits. If - * the number was odd, CF was set in the last shift instruction. - */ - - jnc 1f - shrw $4, %ax -1: - andb $0x0f, %ah /* mask off the highest 4 bits */ - cmpw $0x0ff7, %ax /* check for EOF */ - jmp 4f - -3: - /******** FAT16 ********/ - - movw %dx, %ds /* DS:SI points to next cluster */ - lodsw /* AX = next cluster */ - - cmpw $0xfff7, %ax /* check for EOF */ -4: - jbe 2b /* continue if not EOF */ - - /* Mark end of FAT chain with 0, so we have a single - * EOF marker for both FAT12 and FAT16 systems. - */ - - xorw %ax, %ax - stosw - -/****************************************************************************/ - - /* Load the file into memory, one cluster at a time */ - /* cs=es=ss=0 ds=0x2000 */ - - popw %es /* ES=0x2000 */ - pushw %ss - popw %ds /* DS=SS */ - - /* cs=ds=ss=0 es=0x2000 */ - - movw $FATBUF, %si /* set DS:SI to the FAT chain */ - -1: - /* CH=0 */ - - lodsw /* AX = next cluster to read */ - subw $2, %ax /* cluster numbers start with 2 */ - jc 1f /* the cluster should be 0 for EOC */ - - movzwl %ax, %eax - movb 0x0d(%bp), %cl /* CH=0, CX=sectors per cluster */ - mull %ecx - addl 0x30(%bp), %eax /* data starting sector */ - - call readDisk_12_16 /* CX=0, eax,ES changed */ - jmp 1b /* read next cluster */ - -1: - /* EOC encountered - done */ - - movw 0x24(%bp), %dx /* boot_drive and boot_partition */ - pushw %dx /* for loading grub.exe */ - ljmp *(loadseg_off_12_16 - Entry_12_16)(%bp) /* boot it! */ - -/****************************************************************************/ - -/* Read a number of sectors into memory. - * - * Call with: DS=SS=0 - * eax = 32-bit DOS sector number - * CX = number of sectors to read - * ES:BX = destination buffer - * - * Returns: CX=0 - * ES increased, BX untouched - * ES:BX points one byte after the last byte read. - * eax = next sector number after read - * All other registers preserved - */ - -readDisk_12_16: -2: - pushal - xorl %edx, %edx - pushl %edx /* hi 32bit of sector number */ //666A00 pushd 00 - pushl %eax /* lo 32bit of sector number */ - pushw %es /* buffer segment */ - pushw %bx /* buffer offset */ - pushw $1 /* 1 sector to read */ - pushw $16 /* size of this parameter block */ - cmpb $0x42, (ebios_12_16 - 1 - Entry_12_16 + 0x7c00) - je 1f - - xorl %ecx, %ecx - pushl 0x18(%bp) /* lo:sectors per track, hi:number of heads */ - popw %cx /* ECX = sectors per track */ - divl %ecx /* residue is in EDX */ - /* quotient is in EAX */ - incw %dx /* sector number in DL */ - popw %cx /* ECX = number of heads */ - pushw %dx /* push sector number into stack */ - xorw %dx, %dx /* EDX:EAX = cylinder * TotalHeads + head */ - divl %ecx /* residue is in EDX, head number */ - /* quotient is in EAX, cylinder number */ - xchgb %dl, %dh /* head number should be in DH */ - /* DL = 0 */ - popw %cx /* pop sector number from stack */ - xchgb %al, %ch /* lo 8bit cylinder should be in CH */ - /* AL = 0 */ - shlb $6, %ah /* hi 2bit cylinder ... */ - orb %ah, %cl /* ... should be in CL */ -1: - movw $0x201, %ax /* read 1 sector */ -ebios_12_16: - - movw %sp, %si /* DS:SI points to disk address packet */ - movb 0x24(%bp), %dl /* hard disk drive number */ - pushw %ds - pushw %es - int $0x13 - popw %bx - popw %ds - jc disk_error_12_16 /* disk read error, jc 1f if caller handles */ - leaw 0x20(%bx), %bx - movw %bx, %es - popaw /* remove parameter block from stack */ - popal - incl %eax /* next sector */ - loop 2b - - ret - - -loadseg_off_12_16: .word 0 -loadseg_seg_12_16: .word LOADSEG_12_16 - - -disk_error_12_16: - - movw $(msg_DiskReadError_12_16 - Entry_12_16 + 0x7c00), %si - -boot_error_12_16: - -/* prints string DS:SI (modifies AX BX SI) */ - -//print_12_16: -1: - lodsb (%si), %al /* get token */ - movb $0x0e, %ah /* print it */ - int $0x10 /* via TTY mode */ - cmpb $0, %al /* end of string? */ - jne 1b /* until done */ -1: - jmp 1b - - . = Entry_12_16 + 0x1e0 - -msg_BootError_12_16: - .ascii "No " - -filename_12_16: - .ascii "GRLDR \0" - -msg_DiskReadError_12_16: - .ascii "Disk error\0" - - . = Entry_12_16 + 0x1fc - .word 0, 0xAA55 /* Win9x uses all 4 bytes as magic value here */ - - . = Entry_12_16 + 0x200 - - -/* ******************** fat12_16_dbr end ****************************** */ - -/* ******************** ext2_3_4_dbr start ****************************** */ - -// . = _start1 + 0x800 - - - - -// .arch i486, nojumps - -/* - #; Ext2 boot sector for GRLDR - */ - - -#define DEBUG call debug_print -#undef DEBUG - - //. = _start1 + 0x800 - -//Offset Length Description -//====== ====== ============================================================== -//00h 2 Machine code for short jump over the data. -//02h 1 0x90 -//03h 8 Partitioning message "EXT2/3/4" -//0Bh 2 Bytes per sector. Must be 512. -//0Dh 1 Sectors per block. Valid values are 2, 4, 8, 16 and 32. -//0Eh 2 Bytes per block. Valid values are 0x400, 0x800, 0x1000, 0x2000 and 0x4000. -//10h 4 Pointers in pointers-per-block blocks, that is, number of blocks covered by a double-indirect block. -// Valid values are 0x10000, 0x40000, 0x100000, 0x400000 and 0x1000000. -//14h 4 Pointers per block, that is, number of blocks covered by an indirect block. -// Valid values are 0x100, 0x200, 0x400, 0x800, 0x1000. -//18h 2 Sectors per track. -//1Ah 2 Number of heads/sides. -//1Ch 4 Number of hidden sectors (those preceding the boot sector). -// Also referred to as the starting sector of the partition. For floppies, it should be 0. -//20h 4 Total number of sectors in the filesystem(or in the partition). -//24h 1 BIOS drive number of the boot device. -// Actually this byte is ignored for read. The boot code will write DL onto this byte. -// The BIOS or the caller should set drive number in DL. -// We assume all BIOSes pass correct drive number in DL. Buggy BIOSes are not supported!! -//25h 1 Partition number of this partition on the boot drive. -// 0, 1, 2, 3 are primary partitions. -// 4, 5, 6, ... are logical partitions in the extended partition. -// 0xff is for whole drive. So for floppies, it should be 0xff. -//26h 2 inode size in bytes. (Notice! We use the formerly reserved word here for inode size!) -//28h 4 Number of inodes per group. Normally a 1.44M floppy has only one group, and the total number of inodes is 184. -// So the value should be 184 or greater. -//2Ch 4 The block number for group descriptors. Valid values are 2 for 1024-byte blocks, and 1 otherwise. -// The value here is equal to (s_first_data_block + 1). - - -Entry_ext2: - - jmp 1f - - . = Entry_ext2 + 0x02 - - /* The default mode is CHS. This is for maximum compatiblity with - * small-sized disks, e.g., floppies. - * - * Valid values are 0x02 for CHS mode, or 0x42 for LBA mode. - * - * If the BIOS int13 supports LBA, this byte can be safely set to 0x42. - * - * Some USB BIOSes might have bugs when using CHS mode, so the format - * program should set this byte to 0x42. It seems that (generally) all - * USB BIOSes have LBA support. - * - * If the format program does not know whether the BIOS has LBA - * support, it may operate this way: - * - * if (partition_start + total_sectors_in_partition) exceeds the CHS - * addressing ability(especially when it is greater than 1024*256*63), - * the caller should set this byte to 0x42, otherwise, set to 0x02. - */ - - .byte 0x90 - - . = Entry_ext2 + 0x03 - - .ascii "EXT2/3/4" - - . = Entry_ext2 + 0x30 -1: - cld /* 0xFC */ - - xorw %ax, %ax /* 0x31, 0xC0; CF=0, ZF=1 */ - movw %ax, %ss /* constant SS=0 */ - movw %ax, %ds - movw %ax, %fs - - movw $0x7c00, %sp - - movw %sp, %bp /* constant BP=0x7c00 */ - - pushw %ax /* 0x0000 at 0000:7bfe */ - movw $0x1000, %bx - pushw %bx /* 0x1000 at 0000:7bfc */ - pushw %ax /* 0x0000 at 0000:7bfa */ - /* SP=0x7bfa */ - - /* the 6 bytes in the stack are used by read_block(): - * 0000 ---- -2(%bp) - * 1000 ---- -4(%bp) - * 0000 ---- -6(%bp) - * Don't touch them!' - */ - - movb %dl, 0x24(%bp) /* BIOS passes drive number in DL */ - movw $0x200, 0xb(%bp) - - movb $0x41, %ah - movw $0x55AA, %bx - pushw %ds - int $0x13 - popw %ds - jc 1f # No EBIOS - rorb %cl # ror cl: D0 C9 - jnc 1f # No EBIOS - movb $0x42, (ebios_ext2 - 1 - Entry_ext2 + 0x7c00) -1: - pushw %dx - movb $0x08, %ah /* chs parameters obtained */ - pushw %ds - int $0x13 - popw %ds - incb %dh - movb %dh, 0x1a(%bp) - andb $0x3f, %cl - movb %cl, 0x18(%bp) - popw %dx - - xorl %eax, %eax - xorw %bx, %bx - pushw $0x0600 - popw %es - movw $1, %cx - call readDisk_ext2 /* Read MBR */ - - movw $0x61be, %si - movw $4, %cx -1: - cmpb $0x80, (%si) - je 2f - addw $0x10, %si - loop 1b - movl $0, 0x1c(%bp) - xorl %eax, %eax - jmp 1f -2: -// subw $4, %cx 2014-01-26 -// negw %cx -// movb %cl, 0x25(%bp) //Partition number -// movl 0xc(%si), %eax //The total number of sectors -// movl %eax, 0x20(%bp) - movl 8(%si), %eax /* First start logical sector */ - movl %eax, 0x1c(%bp) -1: - incl %eax /* Read from the second sector */ - pushw $0x07e0 - popw %es - movw $3, %cx /* Read 3 sectors */ - call readDisk_ext2 - cmpw $0xef53, 0x8038 /* Magic signature? */ -// je 1f /* yes */ 2014-01-26 - jne disk_error_ext2 -// addw $0x10, %si /* check the next partition table */ -// jmp 2b -//1: - movw $0x8000, %si - movw 0x58(%si), %ax /* AX=s_inode_size */ - testw %ax, %ax - jnz 1f - movw $0x80, %ax /* EXT2_GOOD_OLD_INODE_SIZE */ -1: - movw %ax, 0x26(%bp) - movb 0x18(%si), %cl /* s_log_block_size */ - movl $2, %eax - shlw %cl, %ax - movb %al, 0x0d(%bp) - shlw $9, %ax /* block size is word wide */ - movw %ax, 0x0e(%bp) - shrw $2, %ax - movl %eax, 0x14(%bp) - addb $8, %cl - shll %cl, %eax - movl %eax, 0x10(%bp) - movl 0x28(%si), %eax /* s_inodes_per_group */ - movl %eax, 0x28(%bp) - movl 4(%si), %eax - movb 0x0d(%bp), %cl - decb %cl - shll %cl, %eax - movl %eax, 0x20(%bp) - - - testb $0x80, 0x60(%si) /* 64-bit file system? */ - je 1f - orb $0x40, 2(%bp) /* 64-bit file system marked */ -1: - testb $0x10, 0x60(%si) /* metablock group? */ - je 1f /* not */ - movl 0x104(%si), %eax /* The first metablock group */ - movl %eax, 0x2c(%bp) - jmp 2f -1: - /* fix for ext2 partition: block number for group descriptors, offset 0x2c */ - /* At which block the group descriptors begin? */ - movl 0x14(%si), %eax /* s_first_data_block */ - incw %ax - movl %eax, 0x2c(%bp) -2: - xorl %ecx, %ecx - - xorl %eax, %eax /* CF=0, ZF=1 */ - - /* MOV keeps all flags untouched, so it is better than INC */ - - movb $2, %al /* EAX=2=inode number for root dir */ - - - /* CF=0, ZF=1 because MOV and PUSH do not touch Flags */ - - /* read root dir to 0000:1000, and grldr to 1000:0000 */ - - jmp 4f - -/* Read sectors from disk, using LBA or CHS - * input: EAX = 32-bit LBA sector number - * CX = number of sectors to read - * ECX high word = 0 - * ES:BX = destination buffer - * - * output: No return on error - * BX not changed - * ES = ES + 0x20 * CX - * EAX = EAX + CX - * ZF = 0 - * CF = 0 - */ - -readDisk_ext2: -2: - pushal - xorl %edx, %edx /* EDX:EAX = LBA */ - pushl %edx /* hi 32bit of sector number */ - pushl %eax /* lo 32bit of sector number */ - pushw %es /* buffer segment */ - pushw %bx /* buffer offset */ - pushw $1 /* 1 sector to read */ - pushw $16 /* size of this parameter block */ - - cmpb $0x42, (ebios_ext2 - 1 - Entry_ext2 + 0x7c00) - je 1f - - //xorl %ecx, %ecx - pushl 0x18(%bp) /* lo:sectors per track, hi:number of heads */ - popw %cx /* ECX = sectors per track */ - divl %ecx /* residue is in EDX */ - /* quotient is in EAX */ - /* EDX high=0, DH=0 */ - incw %dx /* DL=sector number */ - popw %cx /* ECX = number of heads */ - pushw %dx /* push sector number into stack */ - xorw %dx, %dx /* EDX:EAX = cylinder * TotalHeads + head */ - divl %ecx /* residue is in EDX, head number */ - /* quotient is in EAX, cylinder number */ - /* EDX high=0, EAX high=0 */ - - - xchgb %dl, %dh /* head number should be in DH */ - /* DL = 0 */ - popw %cx /* pop sector number from stack */ - xchgb %al, %ch /* lo 8bit cylinder should be in CH */ - /* AL = 0 */ - shlb $6, %ah /* hi 2bit cylinder ... */ - orb %ah, %cl /* ... should be in CL */ - - incw %ax /* AL=1, read 1 sector */ - - /* Instead of 0x0e, the LBA indicator at 2(%bp) is - * - * 0x42 for LBA - * - * and - * - * 0x02 for CHS - */ -1: - movb $0x02, %ah - /* ebios_ext2 - 1 points to 0x02 that can be changed to 0x42 */ -ebios_ext2: - - //andb 2(%bp), %ah - - movw %sp, %si /* DS:SI points to disk address packet */ - movb 0x24(%bp), %dl /* drive number */ - pushw %es - pushw %ds - int $0x13 - popw %ds - popw %bx - jc disk_error_ext2 - leaw 0x20(%bx), %bx - movw %bx, %es - popaw /* remove parameter block from stack */ - popal - incl %eax /* next sector, here ZF=0 */ - loop 2b - ret - -disk_error_ext2: - - movw $(msg_DiskReadError_ext2 - Entry_ext2 + 0x7c00), %si - -boot_error_ext2: - -/* prints string DS:SI (modifies AX BX SI) */ - -//print_ext2: -1: - lodsb (%si), %al /* get token */ - //xorw %bx, %bx /* video page 0 */ - movb $0x0e, %ah /* print it */ - int $0x10 /* via TTY mode */ - cmpb $0, %al /* end of string? */ - jne 1b /* until done */ - -1: jmp 1b - - //. = . - (. - readDisk_ext2)/74 - - . = Entry_ext2 + 0x1e0 - -msg_No_grldr_ext2: - .ascii "No " - -filename_ext2: - .ascii "GRLDR\0\0\0\0\0\0\0\0" - -msg_DiskReadError_ext2: - .ascii "Disk error\0" - - . = Entry_ext2 + 0x1fc - .word 0, 0xAA55 - -4: - /* EAX holds the inode number: for root dir or grldr */ - - /* These 3 PUSHes is intended to place 1000:0000 onto the stack for - * grldr. For root dir, the stack is not used since CF is cleared. - * Although there is no corresponding POPs, this is safe enough - * because the program comes here only twice: the first is for - * the root dir, and the second is for grldr. - * - * For root dir, CF=0 and ZF=1. For grldr, CF=1. - */ - movw $0x1000, %di - pushw %di /* 0x1000, see "jz 4b" below. */ - pushw %ss /* 0x0000 */ - pushfw - - /* SP=0x7bf4 for root dir, or 0x7bee for grldr */ - - decl %eax /* EAX=(inode - 1) */ - - /* inode numbers are far less than 0x7fffffff, so it is safe to - * initialise EDX with CDQ */ - - cdq /* let EDX=0 */ - - divl 0x28(%bp) /* s_inodes_per_group */ - /* EAX=group number */ - pushl %edx /* EDX=inode number in the group */ - - /* group numbers are far less than 0x7fffffff, so it is safe to - * initialise EDX with CDQ */ - - cdq /* let EDX=0 */ - shll $5, %eax /* EAX=relative displacement of the group descriptor */ - - testb $0x40, 02(%bp) /* filesystem 64? */ - je 1f /* no */ - shll $1, %eax /* Group Descriptor Accounted for 64 bytes */ -1: - - divl 0x0e(%bp) /* bytes per block */ - /* EAX=relative block number for the group descriptor */ - /* DX=displacement in the block */ - /* EDX high=0 */ - - pushw %dx /* we don't care about EDX high word, because it is 0 '*/ - - addl 0x2c(%bp), %eax /* EAX=absolute block number for the group descriptor */ - /* CF=0, ZF=0 */ - - call read_block /* 0000:1000 points to the block data containing the group descriptor */ - /* ES changed and > 0, BX=0x1000 */ - /* ECX=EDX=0 */ - /* CF=0, ZF=0 */ - - popw %si /* DS:[BX+SI] points to the group descriptor */ - /* DS:[BX+SI+8] points to the starting block number of the group inode table */ - - popl %eax /* inode number in the group */ - movw 0x26(%bp), %dx /* EDX=inode size */ - mull %edx /* EDX:EAX=relative displacement of the inode struct */ - - divl 0x0e(%bp) /* bytes per block */ - /* EAX=relative block number for the inode struct */ - pushw %dx /* DX=displacement of the inode struct in the block */ - /* EDX high=0 */ - - addl 8(%bx, %si), %eax /* EAX=absolute block number for the inode struct */ - /* CF=0, ZF=0 */ - - call read_block /* 0000:1000 points to the block data containing the inode struct */ - /* ES changed and > 0, BX=0x1000 */ - /* ECX=EDX=0 */ - /* CF=0, ZF=0 */ - - popw %si /* DS:[BX+SI] points to the inode struct */ - - addw %bx, %si /* DS:SI points to the inode struct */ - - testl $0x80000, 0x20(%si) /* Node using the extents way to store data, */ - /* rather than the original direct_indirect index model to store data? */ - jne extent /* yes */ - - /* Move the inode struct to a known safe area(0000:0fa8 - 0000:0fff), - * that is, 0x58 bytes immediately before 0000:1000. We care about only - * the beginning 0x58 bytes of the 0x80-byte inode struct, the last - * 0x28 bytes are ignored. The area from 0xfa8+0x28 to 0xfa8+0x57 - * stores 12 direct block pointers. - * - * - * At address Initial value Stores what? - * ========== ============= ====================================== - * 0xfa8+0x04 (const) the size of the file in bytes - * - * 0xfa8+0x08 total blocks blocks left to read - * - * 0xfa8+0x0c 0 serial number of the block to read - * - */ - - pushw %ss - popw %es /* ES=0 */ - - leaw -0x58(%bx), %di /* BX=0x1000, so DI=0x0fa8 */ - - movb $0x2c, %cl /* 0x2c words = 0x58 bytes */ - - repz movsw /* now ECX=0, BX=0x1000=DI */ - - movl %ecx, (0x0c - 0x58)(%di) /* block serial number of the file */ - /* ECX=0 means first block */ - /* DI=0x1000 */ - - movl (0x04 - 0x58)(%di), %eax /* i_size, the file size */ - decl %eax - - cdq - - divl 0x0e(%bp) /* bytes per block */ - /* EDX=various */ - incl %eax - movl %eax, (0x08 - 0x58)(%di) /* total blocks for file data */ - - /* - * 0000:1000 trebly indirect block - * 0000:8000 indirect block - * 0000:c000 double indirect block - * 1000:0000 the file data - */ - - /* now DS:SI points to indirect block number */ - - lodsl /* indirect block number */ - testl %eax, %eax - jz 1f - - movb $0x80, %bh /* ES:BX=0000:8000 */ - call read_block_c - - /* ES changed and > 0, BX=0x8000 */ - /* ECX=EDX=0 */ - /* ZF=0, CF=0 */ - - /* now DS:SI points to double indirect block number */ - - lodsl /* double indirect block number */ - testl %eax, %eax - jz 1f - - movb $0xc0, %bh /* ES:BX=0000:c000 */ - call read_block_c - - /* ES changed and > 0, BX=0xc000 */ - /* ECX=EDX=0 */ - /* ZF=0, CF=0 */ - - /* now DS:SI points to trebly indirect block number */ - - lodsl /* trebly indirect block number */ - testl %eax, %eax /* CF=0, TEST always clears CF */ - jz 1f - /* ZF=0 */ - call read_block /* 0000:1000 points to the block data */ - /* ES changed and > 0, BX=0x1000 */ - /* ECX=EDX=0 */ - /* ZF=0, CF=0 */ - - - /* the block at 0000:1000, which contains the indirect block numbers, - * is just overwritten by the trebly indirect block */ -1: - /* get absolute block number by block serial number */ - - movl (0x0c - 0x58)(%di), %ebx /* block serial number of the file */ - subl $12, %ebx - jc 3f /* direct block: block serial number < 12 */ - - pushw %bx - subl 0x14(%bp), %ebx - popw %ax - jnc 2f - - /* indirect block: 12 <= block serial number < 12 + 0x14(%bp) */ - - addb $(0x70 / 4), %ah - jmp 8f - -2: - pushl %ebx - subl 0x10(%bp), %ebx - jc 7f /* EBX on the stack is < 0x10(%bp). double indirect block: */ - /* 12 + 0x14(%bp) <= block serial number < 12 + 0x14(%bp) + 0x10(%bp) */ - - /* trebly indirect block: block serial number >= 12 + 0x14(%bp) + 0x10(%bp) */ - - popl %eax /* discard the stack */ - xchgl %eax, %ebx /* move EBX to EAX */ - /* EDX=0 */ - divl 0x10(%bp) - /* EAX=indirect block number, < 0x14(%bp) */ - /* EDX=block number, < 0x10(%bp) */ - - pushl %edx /* EDX < 0x10(%bp) */ - testl %edx, %edx - jnz 7f - - /* EDX=0, so we need to load the double indirect block */ - - shlw $2, %ax - xchgw %ax, %bx - - /* get the double indirect block number from the trebly indirect - * block data */ - - movl (%bx, %di), %eax - - movw $0xc000, %bx /* ES:BX=0000:c000 */ - - //pushw %ss - //popw %es /* ES=0 */ - //stc - call read_block_c /* 0000:c000 points to the block data */ - /* ES changed and > 0, BX=0xc000 */ - /* ECX=EDX=0 */ - /* CF=0, ZF=0 */ -7: - popl %eax /* EAX < 0x10(%bp) */ - cdq /* let EDX=0 (notice the above jc 7f and jnz 7f) */ - divl 0x14(%bp) - /* EAX=indirect block number, < 0x14(%bp) */ - /* EDX=block number, < 0x14(%bp) */ - - pushw %dx /* EDX < 0x14(%bp) */ - testw %dx, %dx - jnz 7f - - /* if DX=0, we need to load the indirect block */ - - //addb $(0xb0 / 4), %ah - shlw $2, %ax - xchgw %ax, %bx - - /* get the indirect block number from the double indirect block data */ - - movl 0xb000(%bx, %di), %eax - - movw $0x8000, %bx /* ES:BX=0000:8000 */ - - call read_block_c /* 0000:8000 points to the block data */ - /* ES changed and > 0, BX=0x8000 */ - /* ECX=EDX=0 */ - /* CF=0, ZF=0 */ -7: - popw %ax /* AX < 0x14(%bp) */ - - addb $(0x70 / 4), %ah -8: - xchgw %ax, %bx -3: - shlw $2, %bx - movl (%bx, %di), %eax - - /* got it! EAX=absolute block number */ - - /* read block data to 1000:0000. For root dir, read each block to - * 1000:0000(overwrite the previous read). For grldr, read blocks - * one by one to the area starting at 1000:0000. - */ - - popfw - popw %bx - popw %es - pushfw - - /* CF=0 and ZF=1 for reading root dir, CF=1 for reading grldr */ - - call read_block /* 1000:0000 points to the block data */ - /* ES changed and > 0x1000, BX=0 */ - /* ECX=EDX=0 */ - /* CF=0, ZF=0 */ - - popfw - pushw %es - pushw %bx - pushfw - - jc 3f /* CF=1, we are reading grldr */ - - /* We have just read a block of the root dir to 1000:0000. - * So we check all dir entries in the block to see if anyone - * matches grldr. - */ -find_grldr: - xorw %si, %si - pushw %ss - popw %es /* ES=0 */ - -2: - pushw %ds /* DS=0 */ - movw %di, %ds /* DS=0x1000 */ - movw $(filename_ext2 - Entry_ext2 + 0x7c00), %di - - pushw %di -102: - cmpb $0, %es:(%di) - je 101f - cmpb $0x41, %es:(%di) - jb 103f - cmpb $0x5a, %es:(%di) - ja 103f - orb $0x20, %es:(%di) /* Switch to lowercase */ -103: - incw %di - jmp 102b -101: - popw %di - - pushw %si - lodsl /* This is possible inode number for grldr */ - pushl %eax /* This is possible inode number for grldr */ - lodsw - xchgw %ax, %dx /* rec_len */ - lodsw /* AL=name_len, should be 5 for grldr */ - /* AH=file_type(1 for regular file) */ - xorb %ah, %ah - xchgw %ax, %cx /* CX=name_len */ - repz cmpsb - jnz 5f - xchgw %ax, %cx /* movb $0, %al */ - scasb -5: - popl %eax /* This is possible inode number for grldr */ - popw %si - - /* DS=0x1000, EAX=inode number */ - - movw %ds, %di /* DI=0x1000 */ - popw %ds /* DS=0 */ - - stc /* indicates the new inode is for grldr */ - jz 4b /* grldr is found with EAX=inode number */ - - addw %dx, %si - cmpw 0x0e(%bp), %si /* bytes per block */ - jb 2b - - - - - /* file not found in this block, continue */ - - /* We are lucky that CF=0, which indicates we are dealing with - * the root dir. - */ - movw %fs, %ax - orw %ax, %ax - jnz 1f - -3: - - /* CF=1 for grldr, CF=0 for root dir. */ - - incl (0x0c - 0x58)(%di) - decl (0x08 - 0x58)(%di) - jnz 1b -1: - movw $(msg_No_grldr_ext2 - Entry_ext2 + 0x7c00), %si - - jnc boot_error_ext2 /* grldr not found in the root dir */ - - /* All grldr blocks have been loaded to memory starting at 1000:0000, - * Before the boot, we pass boot_drive and boot_partition to grldr. - */ - - /* ES>0x1000, BX=0, ECX=EDX=0, DI=0x1000, SS=0, SI>0x7c00, DS=0 - * BP=0x7c00, SP<=0x7c00 - */ - -boot_now: - movw 0x24(%bp), %dx - - /* boot it now! */ - - pushw %dx /* for loading grub.exe */ - pushw %di /* 0x1000 */ - pushw %ss /* 0x0000 */ - lret - - - - - -extent: - addw $0x28, %si -1: - cmpw $0xf30a, (%si) /* Magic signature? */ - jne disk_error_ext2 /* Not */ - movw 02(%si), %cx /* number of effective index or leaves */ - cmpw $0, 06(%si) /* Leaf node? */ - je 2f /* yes */ - /* ext4_extent_idx */ - addw $0x0c, %si /* Each leaf or index accounted 0x0c bytes */ - movb $0x40, %ah /* cf=0,zf=1 ES:BX=0000:1000 */ - sahf /* ah->flag, ES:BX=0000:1000 */ - movl 4(%si), %eax - call read_block - movw %bx, %si - jmp 1b -2: /* ext4_extent */ - lesw -6(%bp), %bx /* ES:BX=1000:0000 */ -1: - addw $0x0c, %si /* Each leaf or index accounted 0x0c bytes */ - movl 8(%si), %eax /* Lower 32 bits of physical block */ - pushw %cx /* number of effective leaves */ - movw 4(%si), %cx /* Logic blocks */ - call read_block_e - popw %cx - loop 1b - popfw - pushfw - jc boot_now - movw %si, %fs - jmp find_grldr - -read_block_c: - - pushw %ss - popw %es /* ES=0 */ - stc - -/* read_block - read a block - * input: CF - indicator for overlap or consecution - * EAX = block number - * ES:BX - buffer - * - * output: if CF is cleared on input, ES:BX is initialized to 0000:1000 - * ES:BX - buffer filled with data - * ES, EAX - Changed - * ECX = 0 - * EDX = 0 - * ZF = 0 - * CF = 0 - */ - -read_block: - - jc 1f - - .byte 0xC4, 0x5E, 0xFC /* lesw -4(%bp), %bx */ - /* ES:BX=0000:1000 */ - jnz 1f - - //at this time, the gcc cannot generate 3 byte code - .byte 0xC4, 0x5E, 0xFA /* lesw -6(%bp), %bx */ - /* ES:BX=1000:0000 */ -1: - movw $1, %cx - -read_block_e: - - movzbl 0x0d(%bp), %edx /* sectors per block */ - imulw %dx, %cx /* Number of sectors read */ - imull %edx, %eax /* Relative to the logical sector */ - - - - addl 0x1c(%bp), %eax /* EAX=absolute sector number */ - - - call readDisk_ext2 - jb disk_error_ext2 - ret - - . = Entry_ext2 + 0x3fc - .word 0, 0xAA55 - - . = Entry_ext2 + 0x400 -/* ******************** ext2_3_4_dbr end ***************************** */ - - -/* ******************** exfat_dbr start ****************************** */ - -/* Original exFAT Volume Boot Record - * Field Name Offset(byte) Size(byte) Description/Value - * Jump Boot 0 3 0xEB7690 - * File System Name 3 8 "EXFAT " - * Must Be Zero 11 53 Must be 0x00 - * Partition Offset 64 8 Sector Address - * Volume Length 72 8 Size of total volume in sectors - * FAT Offset 80 4 Sector address of 1st FAT - * FAT Length 84 4 Size of FAT in Sectors - * Cluster Heap offset 88 4 Sector address of the Data Region - * Cluster Count 92 4 Number of clusters in the Cluster Heap - * Root Directory First Cluster 96 4 Cluster address of the Root Directory - * Volume Serial Number 100 4 Volume Serial Number - * File System Revision 104 2 VV.MM (01.00 for this release) - * Volume Flags 106 2 Field Offset bits Size bits Description - * Active FAT 0 1 0-1st 1-2nd - * Volume Dirty 1 1 0-Clean 1-Dirty - * Media Failure 2 1 0-No Failures 1-Failures - * Reported Clear to Zero 3 1 No Meaning - * Reserved 4 12 - * Bytes Per Sector 108 1 This is a power of 2. Range: min of 29 = 512 byte - * cluster size, and a max of 212 = 4096. - * Sectors Per Cluster 109 1 This is a power of 2. Range: Min of 21=512. The maximum Cluster size is 32 MiB, - * so the Values in Bytes per Sector + Sectors Per Cluster cannot exceed 25. - * Number of FATS 110 1 This number is either 1 or 2, and is only 2 if TexFAT is in use. - * Drive Select 111 1 Used by INT 13 - * Percent In Use 112 1 Percentage of Heap in use - * Reserved 113 7 - * Boot Code 120 390 The Boot Program - * Boot Signature 510 2 0xAA55 - * Excess 512 If the sector is larger than 512 bytes, extra padding may exist beyond the signature - */ - - - -/* exFAT combined - exFAT boot code provided by the Fan JianYe - - exFAT Current BPB Structure: - Offset Type Description - -------------------------------------------------------------------- - 00 Word EB 76 Jump instruction - 02 Byte 90 - 03 DWord "EXFAT " - 0b Word Bytes per sector - 0d byte Retention - 0e DWord Data start Absolute sector - 12 DWord The current cluster the absolute sector in fat table - 16 Word EIOS Mark Bit 7 EIOS - 18 Word Sectors per track - 1a Word Number of heads - 1c DWord hidden sectors - 20 DWord Retention - 24 Byte Drive number - 25 Byte Partition number - 26 Word Sectors per cluster - 28 DWord FAT table start absolute sector number - 2c DWord Retention - */ - -Entry_exfat: - jmp 1f /* cs=ds=es=0000 ss=2000 */ - - .byte 0x90 - .ascii "EXFAT " - - . = Entry_exfat + 0x78 -1: - - cli - cld -// testb $0x80, %dl 2014-01-26 -// jne 1f -// movb $0xff, %dh -// jmp 2f -//1: -// cmpw $0x7c00, %sp -// jne 2f -// subw $0x7be, %bp -// xchgw %bp, %ax -// shrb $4, %al -// movb %al, %dh -//2: - xorw %ax, %ax - movw $0x7c00, %bp /* the base address */ - movw %ax, %ss /* stack and BP-relative moves up, too */ -// movw %ax, %ds -// movw %ax, %es - movw %bp, %sp /* ss:sp=0000:7c00 */ - sti - pushw %ax - - movw %dx, 0x24(%bp) /* BIOS passes drive number in DL */ - - movb 0x6c(%bp), %cl /* Bytes per sector (power) */ - movw $1, %ax - shlw %cl, %ax - movw %ax, 0x0b(%bp) /* Bytes per sector */ - - movb $0x41, %ah - movw $0x55AA, %bx - int $0x13 - jc 1f # No EBIOS - rorb %cl # ror cl: D0 C9 - jnc 1f # No EBIOS - orb $0x80, 0x16(%bp) /* EBIOS supported */ - jmp 2f -1: - movb $0x08, %ah - int $0x13 - movb %dh, 0x1a(%bp) - andb $0x3f, %cl - movb %cl, 0x18(%bp) -2: - popw %ds - - movl 0x50(%bp), %eax - addl 0x40(%bp), %eax - testb $1, 0x6a(%bp) - je 2f - addl 0x54(%bp), %eax -2: - movl %eax, 0x28(%bp) /* FAT table start absolute sector number */ - movl 0x58(%bp), %eax - addl 0x40(%bp), %eax - movl %eax, 0x0e(%bp) /* Data start Absolute sector */ - - movb 0x6d(%bp), %cl /* Sectors per cluster (power) */ - movw $1, %ax - shlw %cl, %ax - movw %ax, 0x26(%bp) /* Sectors per cluster */ - movl 0x40(%bp), %eax /* Sector Address */ - movl %eax, 0x1c(%bp) - pushw $0x07e0 - popw %es - movw $12, %cx - call readDisk_64 - jb disk_error_64 /* Read error display 'disk error' */ - - //Calculation exfat volume boot record checksum - //si=the index entry (from 0 to cx) eax=checksum cx=volume boot record check bytes (0x1600) - xorw %si, %si //Initialize the index - xorl %eax, %eax //Initialize the checksum - movw $0x1600, %cx //Bytes volume boot record check -1: - rorl $1, %eax //"Checksum" right Cycle 1 bit - movzbl 0x7e00(%si), %ebx //Check items - addl %ebx, %eax //(("Checksum" Left Cycle 31 bit) or ("Checksum" right Cycle 1 bit)) + Check items -2: - incw %si //index+1 - cmpw $0x6a, %si //index=0x6a Exclude - je 2b - cmpw $0x6b, %si //index=0x6b Exclude - je 2b - cmpw $0x70, %si //index=0x70 Exclude - je 2b - cmpw %cx, %si //index=Maximum? - jb 1b //No, continue to - //To determine the checksum - movw $0x9400, %di - cmpl (%di), %eax - je 1f - //Filling Checksum - pushw %ds - popw %es - movw $0x80, %cx - repz stosl //0x200 byte - //Boot sector write-back - pushw $0x07e0 - popw %es - pushw %es - movb $0x03, (chs_64 + 2 - Entry_exfat + 0x7c00) - movb $0x43, (lba_64 + 1 - Entry_exfat + 0x7c00) - movl 0x40(%bp), %eax - movw $12, %cx - pushw %cx - call readDisk_64 - popw %cx - popw %es - call readDisk_64 - movb $0x02, (chs_64 + 2 - Entry_exfat + 0x7c00) - movb $0x42, (lba_64 + 1 - Entry_exfat + 0x7c00) -1: - pushw %ds - popw %es - movw $0x8000, %si - movw $0x7e00, %di - movw $0x80, %cx - repz movsl //0x200 byte - movl 0x60(%bp), %eax /* Root clusters */ - call cluster_to_lba_64 /* Calculate the absolute sector from the cluster */ - jmp exfat_next - - -/* Read a sector from disk, using LBA or CHS - * input: EAX - 32-bit DOS sector number - * ES:0000 - destination buffer - * CX - Read number of sectors - * output: ES:0000 - next destination buffer - * EAX - next sector - * warning: EAX, ES Has changed - */ -readDisk_64: -3: - pushal - xorl %edx, %edx /* EDX:EAX = LBA */ - pushl %edx /* hi 32bit of sector number */ - pushl %eax /* lo 32bit of sector number */ - pushw %es /* buffer segment */ - pushw $0 /* buffer offset */ - pushw $1 /* 1 sector to read */ - pushw $16 /* size of this parameter block */ - movw %sp, %si /* DS:SI points to disk address packet */ - testb $0x80, 0x16(%bp) /* Support the expansion of reading? */ - jne 1f /* yes */ - /* C/H/S mode read */ - movzwl 0x18(%bp), %ecx /* sectors per track */ - divl %ecx /* Tracks is in EAX,Sectors in EDX */ - incw %dx /* sector number in DL */ - pushw %dx /* push sector number into stack */ - /* quotient is in EAX, cylinder number */ - pushl %eax /* eax High 16 move to dx */ - popw %ax - popw %dx - divw 0x1a(%bp) /* ax=Tracks/Heads=cylinder number, dx=Head number */ - xchgb %dl, %dh /* head number should be in DH,DL=0 */ - popw %cx /* pop sector number from stack */ - xchgb %al, %ch /* lo 8bit cylinder should be in CH,AL=0 */ - rorb $2, %ah /* hi 2bit cylinder number moble from 0,1 to 6,7 bit */ - orb %ah, %cl /* hi 2bit cylinder number (7,6) and the sector number (5-0) are combined */ -chs_64: - movw $0x201, %ax /* read 1 sector */ - jmp 2f -lba_64: -1: - movb $0x42, %ah /* Extended Mode Read */ -2: - movb 0x24(%bp), %dl /* hard disk drive number */ - pushw %ds - pushw %es - int $0x13 - popw %bx - popw %ds - pushfw - leaw 0x20(%bx), %bx - movw %bx, %es - popfw - - popaw /* remove parameter block from stack */ - popal - jc 2f /* disk read error */ - incl %eax /* next Absolute logical sector */ - loop 3b - clc /* Read complete */ -2: ret - - . = Entry_exfat + 0x1e0 -msg_BootError_64: - .ascii "No " - -grldr_un: - .ascii "GRLDR\0\0\0\0\0\0\0\0" - -msg_DiskReadError_64: - .ascii "Disk error\0" - - . = Entry_exfat + 0x1fc - .word 0,0xAA55 - - -exfat_next: - /* Read all the root directory to 2000:0000 */ - lesw (loadseg_off_64 - Entry_exfat)(%bp), %bx /* load to loadseg:0 */ - movl %eax, %esi - jmp 2f -7: - movw $0xffe0, %di /* di initialization ffe0+20=0000 */ - -6: /* Determine the entry type */ - addw $0x20, %di /* Next Directory */ - cmpw 0x0b(%bp), %di /* Bytes per sector*/ - jb 1f -2: - call read_2_sectors /* Read all the root directory to 2000:0000 */ - jb disk_error_64 /* Read error display 'disk error' */ - jmp 7b -1: - cmpb $0, %es:(%di) /* Contents end? */ - je grldr_error_64 /* yes */ - cmpb $0xc0, %es:(%di) /* Stream Directory */ - jne 6b /* Not */ - /* Determine the length of the file name */ - movb %es:3(%di), %cl /* File name length */ - pushw %di /* Save the current directory entry */ - addw $0x22, %di /* Filename address */ - pushl %esi - movw $(grldr_un - Entry_exfat + 0x7c00), %si /*'GRLDR' First place */ -1: - cmpb $0x61, %es:(%di) - jb 101f - cmpb $0x7a, %es:(%di) - ja 101f - andb $0xdf, %es:(%di) /* lowercase to Switch */ -101: - cmpsb /* More 'grldr',Unicode file names */ - jne 1f /* NO,Restore directory entry, check the next entry */ - incw %di - loop 1b /* The same, compare the next character */ - cmpb $0, (%si) - jne 1f - /* GRLDR has been found */ - popl %esi - popw %di /* Restore directory entry */ - /* files stored continuously, Calculate the number of sectors the file */ - movl %es:0x18(%di), %eax /* 32-bit low byte file */ - movb 0x6c(%bp), %cl /* Bytes per sector (power) */ - shrl %cl, %eax /* ax = file number of sectors */ - incw %ax /* May be more than the number, file number of sectors + 1 */ - pushw %ax /* File number of sectors */ - testb $2, %es:1(%di) /* Bit 2 is equal to 1 indicates no FAT chain, files stored continuously */ - je 2f /* File storage is not continuous */ - /* Read file to 2000:0000 */ - movl %es:0x14(%di), %eax /* Starting cluster file */ - call cluster_to_lba_64 /* Calculate the absolute sector from the cluster */ - popw %cx /* File number of sectors */ - call readDisk_64 /* Read file GRLDR to 2000:0000 */ - jmp 5f -1: - /* Restore directory entry, check the next entry */ - popl %esi - popw %di /* NO,Restore directory entry */ - jmp 6b /* Check the next entry */ -2: - /* File storage is not continuous, read the file to 2000:0000 */ - popw %cx - movl %es:0x14(%di), %eax /* Starting cluster file */ - call Read_Discontinuous /* Read file GRLDR to 2000:0000 */ -5: movw 0x24(%bp), %dx /* dh=Partition number (starting from 0) dl=Drive number */ - pushw %dx /* Application just to grub.exe */ - ljmp $LOADSEG,$0 /* Go to 2000:0000 */ - - - - -/* Read 2 sectors - * First read sector from the current cluster, - * followed by reading from the cluster of sectors. - * Encountered cluster terminator stop. - * input: es:0000=Buffer esi=The first absolutely logical sector - * output: 0x60(%bp)=current cluster esi=The second absolutely logical sector - */ -read_2_sectors: - pushw %es - movl %esi, %eax - movw $1, %cx /* Number of sectors read */ - call readDisk_64 /* Read sectors */ - jb 4f - pushl %eax /* The second absolutely logical sector */ - subl 0x0e(%bp), %eax /* The first relatively logical sector */ /* Data start Absolute sector */ - xorl %edx, %edx - movzwl 0x26(%bp), %ecx /* sectors per cluster */ - divl %ecx /* eax=Cluster number edx=Sector offset */ - cmpw 0x26(%bp), %dx /* In the current cluster? */ - /* In the next cluster */ - popl %eax - jb 3f /* Yes */ - movl 0x60(%bp), %eax /* current cluster */ - call NextCluster /* Find the next cluster from the current cluster */ - movl %eax, 0x60(%bp) /* current cluster */ - jb 1f /* Not the end of the cluster */ - - xorw %ax, %ax - xorw %di, %di - xorl %esi, %esi - movw $0x100, %cx - repz stosw - jmp 2f -1: - call cluster_to_lba_64 /* Calculate the absolute sector from the cluster */ - jmp 1f -3: - /* In the current cluster */ -1: - movl %eax, %esi /* The second absolutely logical sector */ - movw $1, %cx /* Number of sectors read */ - call readDisk_64 /* Read sectors */ - jnb 2f -4: stc -2: - popw %es - ret - - -/* Read sectors from the cluster - * Input: eax=Cluster number, es:0000=buffer, cx=File number of sectors - * Warning: EAX Has changed - */ -Read_Discontinuous: - pushw %es - pushw %di - movw 0x26(%bp), %di -1: - pushl %eax /* Cluster number */ - pushw %cx - call cluster_to_lba_64 /* Calculate the absolute sector from the cluster */ - popw %cx - cmpw %di, %cx - jb 2f - subw %di, %cx - pushw %cx - movw %di, %cx /* sectors per cluster */ - jmp 3f -2: - pushw $0 -3: - call readDisk_64 /* Read Sector */ - popw %cx - popl %eax /* Cluster number */ - jb 1f /* Reading failure or end */ - orw %cx, %cx - je 1f - pushw %cx - call NextCluster /* Find the next cluster from the current cluster */ - popw %cx - jb 1b /* Not the end of the cluster, continue to read */ -1: - popw %di - popw %es - ret - - - -/* Find the next cluster from the current cluster */ -/* Input: eax=current cluster number */ -/* Otput: eax=next cluster number, Less than=Normal */ -/* [bp+2d]=The current cluster in the absolute sector fat table */ -NextCluster: - pushw %bx - pushw %es - lesw (FAT_Address - Entry_exfat)(%bp), %bx /* es:bx=0060:0000 */ - /* Computing bytes per cluster */ - shll $2, %eax /* 4 bytes per cluster */ - /* Computing cluster in the FAT table sector offset / byte offset */ - xorl %edx, %edx - movzwl 0x0b(%bp), %ecx /* Bytes per sector */ - divl %ecx /* eax=sector offset, edx=byte offset */ - /* Calculate the absolute sector of clusters */ - addl 0x28(%bp), %eax /* FAT table start absolute sector number */ - pushw %dx /* byte offset */ - /* Determine whether or not to read the fat table */ - cmpl %eax, 0x12(%bp) //The current cluster the absolute sector in fat table - je 1f /* Does not read the fat table */ - /* read the fat table */ - movl %eax, 0x12(%bp) /* Save the current address of fat table */ //The current cluster the absolute sector in fat table - movw $1, %cx /* Read 1 sector */ - pushw %es - call readDisk_64 /* Reading FAT table */ - popw %es -1: - popw %bx /* byte offset */ - movzwl %es:(%bx), %eax /* fat12/16 Next cluster number */ - cmpl $0xfffffff8, %eax - popw %es - popw %bx - ret - -/* Calculate the absolute sector from the cluster - * input: eax=Cluster number - * output: eax=Absolute sector - */ -cluster_to_lba_64: - /* sector = (cluster-2) * clustersize + data_start */ - decl %eax - decl %eax - movb 0x6d(%bp), %cl /* Sectors per cluster (power) */ - shll %cl, %eax - addl 0x0e(%bp), %eax /* Absolute sector */ /* Data start Absolute sector */ - ret - - -grldr_error_64: - movw $(msg_BootError_64 - Entry_exfat + 0x7c00), %si - jmp print_64 -disk_error_64: - movw $(msg_DiskReadError_64 - Entry_exfat + 0x7c00), %si - - -print_64: -1: - lodsb (%si), %al /* get token */ - movb $0x0e, %ah /* print it */ - int $0x10 /* via TTY mode */ - cmpb $0, %al /* end of string? */ - jne 1b /* until done */ - -1: jmp 1f - -loadseg_off_64: - .word 0 - .word LOADSEG -FAT_Address: - .word 0 - .word FATSEG - - . = Entry_exfat + 0x3fc - .word 0,0xAA55 - - . = Entry_exfat + 0x0400 - -/* ******************** exfat_dbr end ****************************** */ - -#endif /* defined(GRLDR_INSTALL) */ - -/* ******************** ntfs_dbr_mbr start ****************************** */ - - - -#define INSIDE_GRLDR - -//#include "ntfsbs.S" -//-----------------begin of "ntfsbs.S"----------------------- -/* - * GRUB Utilities -- Utilities for GRUB Legacy, GRUB2 and GRUB for DOS - * Copyright (C) 2007 Bean (bean123@126.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* NTFS boot sector for loading GRLDR , written by bean - * - * This file can be compiled as standalone boot sector, or it can be embeded in - * GRLDR.MBR at 0xA00 , right after the ext2 boot sector - * - * To compile the standalone ntfsbs.bin: - * gcc -c -o ntfsbs.o ntfsbs.S - * gcc -nostdlib -Wl,-N -Wl,-Ttext -Wl,7C00 -o ntfsbs_exec ntfsbs.o - * objcopy -O binary ntfsbs_exec ntfsbs.bin - * - * To install the standalone ntfsbs.bin: - * grubinst --restore=ntfsbs.bin DEVICE_OR_FILE - * - * Where DEVICE_OR_FILE specify a NTFS partition - * - * Limitations: - * 1. Don't support >1K MFT record size, >4K INDEX record size - * 2. Don't support encrypted file - * 3. Don't support >4K non-resident attribute list and $BITMAP ' - * - */ - -#ifndef INSIDE_GRLDR - - .text - - .code16 -#endif - -#define AT_STANDARD_INFORMATION 0x10 -#define AT_ATTRIBUTE_LIST 0x20 -#define AT_FILENAME 0x30 -#define AT_OBJECT_ID 0x40 -#define AT_SECURITY_DESCRIPTOR 0x50 -#define AT_VOLUME_NAME 0x60 -#define AT_VOLUME_INFORMATION 0x70 -#define AT_DATA 0x80 -#define AT_INDEX_ROOT 0x90 -#define AT_INDEX_ALLOCATION 0xA0 -#define AT_BITMAP 0xB0 -#define AT_SYMLINK 0xC0 -#define AT_EA_INFORMATION 0xD0 -#define AT_EA 0xE0 - -#define MAX_MFT_SIZE 1 // 1<<(1+9) = 1024 -#define MAX_IDX_SIZE 3 // 1<<(3+9) = 4096 - -#define LOADSEG_NT 0x2000 - -#define MMFT_BASE 0x2000 -#define MMFT_EMFT (MMFT_BASE + 1024) -#define MMFT_EBUF (MMFT_BASE + 2048) - -#define CMFT_BASE (MMFT_BASE + 6144) -#define CMFT_EMFT (CMFT_BASE + 1024) -#define CMFT_EBUF (CMFT_BASE + 2048) - -#define INDX_BASE (CMFT_BASE + 6144) - -#define SBUF_BASE (INDX_BASE + 4096) - -#define NTFS_Large_Structure_Error_Code 1 -#define NTFS_Corrupt_Error_Code 2 -#define NTFS_Run_Overflow_Error_Code 3 -#define NTFS_No_Data_Error_Code 4 -#define NTFS_Decompress_Error_Code 5 - -#define NT_FG_COMP 1 -#define NT_FG_MMFT 2 -#define NT_FG_ALST 4 -#define NT_FG_GPOS 8 - -#define nt_boot_drive -2(%bp) -#define nt_blocksize -4(%bp) -#define nt_spc -5(%bp) -#define nt_mft_size -6(%bp) -#define nt_idx_size -7(%bp) -#define nt_mft_start -12(%bp) -#define nt_remain_len -16(%bp) -//#define nt_file_count -18(%bp) - -#define nt_flag (%di) -#define nt_attr_cur 2(%di) -#define nt_attr_nxt 4(%di) -#define nt_attr_end 6(%di) -#define nt_curr_vcn 8(%di) -#define nt_curr_lcn 0x10(%di) -#define nt_attr_ofs 0x14(%di) -#define nt_target_vcn 0x18(%di) -#define nt_read_count 0x1C(%di) -#define nt_vcn_offset 0x20(%di) - -#define nt_emft_buf 1024(%di) -#define nt_edat_buf 2048(%di) - - .arch i586 - -Entry_nt: - jmp 1f - - . = Entry_nt + 0x02 - - .byte 0x90 /* for CHS. Another possible value is 0x0e for LBA */ - - .ascii "NTFS " - - .word 0 /* 0B - Bytes per sector */ - .byte 0 /* 0D - Sectors per cluster */ - .word 0 /* 0E - reserved sectors, unused */ - .byte 0 /* 10 - number of FATs, unused */ - .word 0 /* 11 - Max dir entries for FAT12/FAT16, unused */ - .word 0 /* 13 - total sectors for FAT12/FAT16, unused */ - .byte 0xF8 /* 15 - Media descriptor */ - .word 0 /* 16 - sectors per FAT for FAT12/FAT16, unused */ - .word 255 /* 18 - Sectors per track */ - .word 63 /* 1A - Number of heads */ -nt_part_ofs: - .long 0 /* 1C - hidden sectors */ - .long 0 /* 20 - total sectors for FAT32, unused */ - .long 0x800080 - /* 24 - Usually 80 00 80 00, A value of 80 00 00 00 has - * been seen on a USB thumb drive which is formatted - * with NTFS under Windows XP. Note this is removable - * media and is not partitioned, the drive as a whole - * is NTFS formatted. - */ - .long 0,0 /* 28 - Number of sectors in the volume */ - .long 0,0 /* 30 - LCN of VCN 0 of the $MFT */ - .long 0,0 /* 38 - LCN of VCN 0 of the $MFTMirr */ - .long 0 /* 40 - Clusters per MFT Record */ - .long 4 /* 44 - Clusters per Index Record */ - .long 0,0 /* 48 - Volume serial number */ - .long 0 /* 50 - Checksum, usually 0 */ - -1: - - . = Entry_nt + 0x54 - - cli - cld - - . = Entry_nt + 0x56 - - /* the byte at offset 0x57 stores the real partition number for read. - * the format program or the caller should set it to a correct value. - * For floppies, it should be 0xff, which stands for whole drive. - */ - - movb $0xff, %dh /* boot partition number */ - - xorw %ax, %ax - movw $0x7c00, %bp - - movw %ax, %ss /* stack and BP-relative moves up, too */ - leaw -0x20(%bp), %sp - sti - - movw %dx, nt_boot_drive - - pushw %ax /* AX=0 */ - - /* Test if your BIOS support LBA mode */ - movb $0x41, %ah - movw $0x55AA, %bx - int $0x13 - - popw %ds /* DS=0 */ - - jc 1f /* No EBIOS */ - cmpw $0xAA55, %bx - jne 1f /* No EBIOS */ -// testb $1, %cl -// jz 1f /* No EBIOS */ - rorb %cl - jnc 1f # No EBIOS - /* EBIOS supported */ - movb $0x42, (ebios_nt - 1 - Entry_nt)(%bp) -1: - - pushw %ss /* SS=0 */ - popw %es /* ES=0 */ - - cmpl $0x42555247, (nt_sector_mark - Entry_nt)(%bp) - jz 1f // Must be called from GRLDR.MBR - - movw $0x7E00, %bx - movl (nt_part_ofs - Entry_nt)(%bp), %eax - incl %eax - call readDisk_nt // Load the second sector from disk - call readDisk_nt // Load the third sector from disk - call readDisk_nt -1: - - xorl %eax, %eax - movw 0xb(%bp), %ax // Bytes per sector (blocksize) - movw %ax, nt_blocksize - - call convert_to_power_2 - movb %cl, %bl - movb 0xd(%bp), %al // Sectors per cluster - call convert_to_power_2 - movb %cl, %ch - addb %bl, %ch - subb $9, %ch // 1<0412 or ax=0783->0783 */ - cmpw $0x0ff8, %ax -4: - popw %es - popw %bx - ret - - -Entry_ext2_mbr: - - pushw %ax /* 0x0000 at 0000:7bfe */ - movw $0x1000, %bx - pushw %bx /* 0x1000 at 0000:7bfc */ - pushw %ax /* 0x0000 at 0000:7bfa */ - /* SP=0x7bfa */ - - - /* the 6 bytes in the stack are used by read_block(): - * 0000 ---- -2(%bp) - * 1000 ---- -4(%bp) - * 0000 ---- -6(%bp) - * Don't touch them!' - */ - - xorl %eax, %eax /* CF=0, ZF=1 */ - - - /* MOV keeps all flags untouched, so it is better than INC */ - movb $2, %al /* EAX=2=inode number for root dir */ - - /* CF=0, ZF=1 because MOV and PUSH do not touch Flags */ - - /* read root dir to 0000:1000, and grldr to 1000:0000 */ - -4: - /* EAX holds the inode number: for root dir or grldr */ - - /* These 3 PUSHes is intended to place 1000:0000 onto the stack for - * grldr. For root dir, the stack is not used since CF is cleared. - * Although there is no corresponding POPs, this is safe enough - * because the program comes here only twice: the first is for - * the root dir, and the second is for grldr. - * - * For root dir, CF=0 and ZF=1. For grldr, CF=1. - */ - movw $0x1000, %di - pushw %di /* 0x1000, see "jz 4b" below. */ - pushw %ss /* 0x0000 */ - pushfw - - /* SP=0x7bf4 for root dir, or 0x7bee for grldr */ - - decl %eax /* EAX=(inode - 1) */ - - /* inode numbers are far less than 0x7fffffff, so it is safe to - * initialise EDX with CDQ */ - - cdq /* let EDX=0 */ - - divl 0x28(%bp) /* s_inodes_per_group */ - /* EAX=group number */ - pushl %edx /* EDX=inode number in the group */ - - /* group numbers are far less than 0x7fffffff, so it is safe to - * initialise EDX with CDQ */ - - cdq /* let EDX=0 */ - shll $5, %eax /* EAX=relative displacement of the group descriptor */ - - testb $0x40, 02(%bp) /* filesystem 64? */ - je 1f /* no */ - shll $1, %eax /* Group Descriptor Accounted for 64 bytes */ -1: - divl 0x0e(%bp) /* bytes per block */ - /* EAX=relative block number for the group descriptor */ - /* DX=displacement in the block */ - /* EDX high=0 */ - - pushw %dx /* we don't care about EDX high word, because it is 0' */ - - addl 0x2c(%bp), %eax /* EAX=absolute block number for the group descriptor */ - /* CF=0, ZF=0 */ - - call read_block_mbr /* 0000:1000 points to the block data containing the group descriptor */ - /* ES changed and > 0, BX=0x1000 */ - /* ECX=EDX=0 */ - /* CF=0, ZF=0 */ - - popw %si /* DS:[BX+SI] points to the group descriptor */ - /* DS:[BX+SI+8] points to the starting block number of the group inode table */ - - popl %eax /* inode number in the group */ - - movw 0x26(%bp), %dx /* EDX=inode size */ - mull %edx /* EDX:EAX=relative displacement of the inode struct */ - - divl 0x0e(%bp) /* bytes per block */ - /* EAX=relative block number for the inode struct */ - pushw %dx /* DX=displacement of the inode struct in the block */ - /* EDX high=0 */ - - addl 8(%bx, %si), %eax /* EAX=absolute block number for the inode struct */ - /* CF=0, ZF=0 */ - - call read_block_mbr /* 0000:1000 points to the block data containing the inode struct */ - /* ES changed and > 0, BX=0x1000 */ - /* ECX=EDX=0 */ - /* CF=0, ZF=0 */ - - popw %si /* DS:[BX+SI] points to the inode struct */ - - addw %bx, %si /* DS:SI points to the inode struct */ - - - testl $0x80000, 0x20(%si) /* Node using the extents way to store data, */ - /* rather than the original direct_indirect index model to store data? */ - jne extent_mbr /* yes */ - - /* Move the inode struct to a known safe area(0000:0fa8 - 0000:0fff), - * that is, 0x58 bytes immediately before 0000:1000. We care about only - * the beginning 0x58 bytes of the 0x80-byte inode struct, the last - * 0x28 bytes are ignored. The area from 0xfa8+0x28 to 0xfa8+0x57 - * stores 12 direct block pointers. - * - * - * At address Initial value Stores what? - * ========== ============= ====================================== - * 0xfa8+0x04 (const) the size of the file in bytes - * - * 0xfa8+0x08 total blocks blocks left to read - * - * 0xfa8+0x0c 0 serial number of the block to read - * - */ - - pushw %ss - popw %es /* ES=0 */ - - leaw -0x58(%bx), %di /* BX=0x1000, so DI=0x0fa8 */ - movb $0x2c, %cl /* 0x2c words = 0x58 bytes */ - - repz movsw /* now ECX=0, BX=0x1000=DI */ - - movl %ecx, (0x0c - 0x58)(%di) /* block serial number of the file */ - /* ECX=0 means first block */ - /* DI=0x1000 */ - - movl (0x04 - 0x58)(%di), %eax /* i_size, the file size */ - decl %eax - - cdq - - divl 0x0e(%bp) /* bytes per block */ - /* EDX=various */ - incl %eax - movl %eax, (0x08 - 0x58)(%di) /* total blocks for file data */ - - /* - * 0000:1000 trebly indirect block - * 0000:8000 indirect block - * 0000:c000 double indirect block - * 1000:0000 the file data - */ - - /* now DS:SI points to indirect block number */ - - lodsl /* indirect block number */ - testl %eax, %eax - jz 1f - - //pushw %ss - //popw %es /* ES=0 */ -// movb $0x80, %bh /* ES:BX=0000:8000 */ - movb $0x20, %bh /* ES:BX=0000:1000 */ - - call read_block_c_mbr - /* ES changed and > 0, BX=0x8000 */ - /* ECX=EDX=0 */ - /* ZF=0, CF=0 */ - - /* now DS:SI points to double indirect block number */ - - lodsl /* double indirect block number */ - testl %eax, %eax - jz 1f - - movb $0xc0, %bh /* ES:BX=0000:c000 */ - call read_block_c_mbr - /* ES changed and > 0, BX=0xc000 */ - /* ECX=EDX=0 */ - /* ZF=0, CF=0 */ - - /* now DS:SI points to trebly indirect block number */ - - /* the block at 0000:1000, which contains the indirect block numbers, - * is just overwritten by the trebly indirect block */ - -1: - /* get absolute block number by block serial number */ - - movl (0x0c - 0x58)(%di), %ebx /* block serial number of the file */ - subl $12, %ebx - jc 3f /* direct block: block serial number < 12 */ - - pushw %bx - subl 0x14(%bp), %ebx - popw %ax - jnc 2f - - /* indirect block: 12 <= block serial number < 12 + 0x14(%bp) */ - -// addb $(0x70 / 4), %ah - addb $(0x10 / 4), %ah - //xchgw %ax, %bx - jmp 8f - -2: - pushl %ebx - subl 0x10(%bp), %ebx - -7: - popl %eax /* EAX < 0x10(%bp) */ - cdq /* let EDX=0 (notice the above jc 7f and jnz 7f) */ - divl 0x14(%bp) - /* EAX=indirect block number, < 0x14(%bp) */ - /* EDX=block number, < 0x14(%bp) */ - - pushw %dx /* EDX < 0x14(%bp) */ - testw %dx, %dx - jnz 7f - - /* if DX=0, we need to load the indirect block */ - - shlw $2, %ax - xchgw %ax, %bx - - /* get the indirect block number from the double indirect block data */ - - movl 0xb000(%bx, %di), %eax - - movw $0x2000, %bx /* ES:BX=0000:1000 */ - - call read_block_c_mbr/* 0000:8000 points to the block data */ - /* ES changed and > 0, BX=0x8000 */ - /* ECX=EDX=0 */ - /* CF=0, ZF=0 */ - -7: - popw %ax /* AX < 0x14(%bp) */ -// addb $(0x70 / 4), %ah - addb $(0x10 / 4), %ah -8: - xchgw %ax, %bx -3: - shlw $2, %bx - movl (%bx, %di), %eax - - /* got it! EAX=absolute block number */ - - /* read block data to 1000:0000. For root dir, read each block to - * 1000:0000(overwrite the previous read). For grldr, read blocks - * one by one to the area starting at 1000:0000. - */ - - popfw - popw %bx - popw %es - pushfw - - /* CF=0 and ZF=1 for reading root dir, CF=1 for reading grldr */ - - call read_block_mbr /* 1000:0000 points to the block data */ - /* ES changed and > 0x1000, BX=0 */ - /* ECX=EDX=0 */ - /* CF=0, ZF=0 */ - - popfw - pushw %es - pushw %bx - pushfw - - jc 3f /* CF=1, we are reading grldr */ - - /* We have just read a block of the root dir to 1000:0000. - * So we check all dir entries in the block to see if anyone - * matches grldr. - */ -find_grldr_mbr: - xorw %si, %si - pushw %ss - popw %es /* ES=0 */ - -2: - pushw %ds /* DS=0 */ - movw %di, %ds /* DS=0x1000 */ - movw $(filename_ext2_mbr - Entry_12_64_ext + 0x7c30), %di - - pushw %di -102: - cmpb $0, %es:(%di) - je 101f - cmpb $0x41, %es:(%di) - jb 103f - cmpb $0x5a, %es:(%di) - ja 103f - orb $0x20, %es:(%di) /* Switch to lowercase */ -103: - incw %di - jmp 102b -101: - popw %di - - pushw %si - lodsl /* This is possible inode number for grldr */ - pushl %eax /* This is possible inode number for grldr */ - lodsw - xchgw %ax, %dx /* rec_len */ - lodsw /* AL=name_len, should be 5 for grldr */ - /* AH=file_type(1 for regular file) */ - xorb %ah, %ah - xchgw %ax, %cx /* CX=name_len */ - repz cmpsb - jnz 5f - xchgw %ax, %cx /* movb $0, %al */ - scasb -5: - popl %eax /* This is possible inode number for grldr */ - popw %si - - /* DS=0x1000, EAX=inode number */ - - movw %ds, %di /* DI=0x1000 */ - popw %ds /* DS=0 */ - - stc /* indicates the new inode is for grldr */ - jz 4b /* grldr is found with EAX=inode number */ - - addw %dx, %si - cmpw 0x0e(%bp), %si /* bytes per block */ - jb 2b - - /* file not found in this block, continue */ - - /* We are lucky that CF=0, which indicates we are dealing with - * the root dir. - */ - movw %fs, %ax - orw %ax, %ax - jnz 1f - -3: - - /* CF=1 for grldr, CF=0 for root dir. */ - - incl (0x0c - 0x58)(%di) - decl (0x08 - 0x58)(%di) - jnz 1b -1: - jnc grldr_error_12_64_ext - - /* All grldr blocks have been loaded to memory starting at 1000:0000, - * Before the boot, we pass boot_drive and boot_partition to grldr. - */ - - /* ES>0x1000, BX=0, ECX=EDX=0, DI=0x1000, SS=0, SI>0x7c00, DS=0 - * BP=0x7c00, SP<=0x7c00 - */ - -boot_now_mbr: - - movw 0x24(%bp), %dx - - /* boot it now! */ - - pushw %dx /* for loading grub.exe */ - pushw %di /* 0x1000 */ - pushw %ss /* 0x0000 */ - lret - -read_block_c_mbr: - - pushw %ss - popw %es /* ES=0 */ - stc - -/* read_block - read a block - * input: CF - indicator for overlap or consecution - * EAX = block number - * ES:BX - buffer - * - * output: if CF is cleared on input, ES:BX is initialized to 0000:1000 - * ES:BX - buffer filled with data - * ES, EAX - Changed - * ECX = 0 - * EDX = 0 - * ZF = 0 - * CF = 0 - */ - -read_block_mbr: - - jc 1f - - .byte 0xC4, 0x5E, 0xFC /* lesw -4(%bp), %bx */ - /* ES:BX=0000:1000 */ - jnz 1f - - //at this time, the gcc cannot generate 3 byte code - .byte 0xC4, 0x5E, 0xFA /* lesw -6(%bp), %bx */ - /* ES:BX=1000:0000 */ - //. = . - (. - read_block) / 6 -1: - - movw $1, %cx - -read_block_e_mbr: - - movzbl 0x0d(%bp), %edx /* sectors per block */ - imulw %dx, %cx /* Number of sectors read */ - imull %edx, %eax /* Relative to the logical sector */ - addl 0x1c(%bp), %eax /* EAX=absolute sector number */ - call readDisk_12_64_ext - jb disk_error_12_64_ext - ret - - -extent_mbr: - addw $0x28, %si -1: - cmpw $0xf30a, (%si) /* Magic signature? */ - jne disk_error_12_64_ext /* Not */ - movw 02(%si), %cx /* number of effective index or leaves */ - cmpw $0, 06(%si) /* Leaf node? */ - je 2f /* yes */ - /* ext4_extent_idx */ - addw $0x0c, %si /* Each leaf or index accounted 0x0c bytes */ - movb $0x40, %ah /* cf=0,zf=1 ES:BX=0000:1000 */ - sahf - movl 4(%si), %eax /* Lower 32 bits of physical block */ - call read_block_mbr - movw %bx, %si - jmp 1b -2: /* ext4_extent */ - lesw -6(%bp), %bx /* ES:BX=1000:0000 */ -1: - addw $0x0c, %si /* Each leaf or index accounted 0x0c bytes */ - movl 8(%si), %eax /* Lower 32 bits of physical block */ - pushw %cx /* number of effective leaves */ - movw 4(%si), %cx /* Logic blocks */ - call read_block_e_mbr - popw %cx - loop 1b - popfw - pushfw - jc boot_now_mbr - movw %si, %fs - jmp find_grldr_mbr - - .align 16 - - - -msg_BootError_12_64_ext: - .ascii "No " - -grldr_un_12_64_ext: -filename_12_64_ext: -filename_ext2_mbr: - .ascii " \0\0" - -msg_DiskReadError_12_64_ext: - .ascii "Disk error\0" - - .fill 6,1,0 - -/* *************** FAT12_16_FAT32_exFAT_EXT2_3_4_mbr end ****************** */ - -// . = _start1 + 0x1200 - -end_12_64_ext: - - .arch i586, jumps - - -#ifdef DEBUG - - . = Entry_ext2 + 0x201 - -debug_print: - - pushfl - pushal - movl %eax, %ebp - call 2f -#if 0 - popal - pushal - movl %ebx, %ebp - call 2f - popal - pushal - movl %ecx, %ebp - call 2f - popal - pushal - movl %edx, %ebp - call 2f - popal - pushal - movl %esi, %ebp - call 2f - popal - pushal - movl %edi, %ebp - call 2f - popal - popfl - pushfl - pushal - pushfl - popl %ebp /* flags */ - call 2f - movw %ds, %bp - shll $16, %ebp - movw %es, %bp - call 2f - movw $0x0e0d, %ax /* print CR */ - int $0x10 /* via TTY mode */ - movw $0x0e0a, %ax /* print LF */ - int $0x10 /* via TTY mode */ -#endif - popal - popfl - ret -2: - movw $7, %cx -1: - xorw %bx, %bx /* video page 0 */ - movl %ebp, %eax - shrl %cl, %eax - shrl %cl, %eax - shrl %cl, %eax - shrl %cl, %eax - andb $0x0f, %al - addb $0x30, %al - movb $0x0e, %ah /* print char in AL */ - int $0x10 /* via TTY mode */ - - decw %cx - testw %cx, %cx - jns 1b - - movw $0x0e20, %ax /* print space */ - int $0x10 /* via TTY mode */ - ret - - -#endif - -#if 1 - /* restore GRLDR_CS */ - - /* this code is executed at 0000:MONITOR, which must be a 16-byte - * aligned address. The address 0000:MONITOR should be designed in - * a way that could avoid memory confliction with volume boot records - * (currently FAT12/16/32/NTFS/EXT2/3 are built in). - */ - - /* CS=code */ - - .align 16 - -restore_GRLDR_CS: -2: - call 1f -1: - popw %bx # instruction pointer of 1b - movw %cs, %ax - shrw $4, %bx - addw %ax, %bx # BX=segment value of this code - pushw %bx - pushw $(1f - 2b) - lret -1: - /* modify gdt base */ - xorl %eax, %eax - movw %bx, %ax - shll $4, %eax - addl $(gdt -2b), %eax - movl %eax, %cs:(gdt - 2b + 2) - - movw $GRLDR_CS, %bx - movw %bx, %es - movw %ds, %bx # save old DS to BX - - cli - lgdt %cs:(gdt - 2b) - movl %cr0, %eax - orb $1, %al - movl %eax, %cr0 - - movw $8, %si - movw %si, %ds - - xorl %esi, %esi - xorl %edi, %edi - movl $(0x9000 / 4), %ecx - - cld - repz movsl - - movw $16, %si - movw %si, %ds - - andb $0xfe, %al - movl %eax, %cr0 - - movw %bx, %ds # restore DS from BX - - ljmp $GRLDR_CS, $(try_next_partition - _start1) - - - - -#endif - -# Descriptor tables -# -# NOTE: The intel manual says gdt should be sixteen bytes aligned for -# efficiency reasons. However, there are machines which are known not -# to boot with misaligned GDTs, so alter this at your peril! If you alter -# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two -# empty GDT entries (one for NULL and one reserved). -# -# NOTE: On some CPUs, the GDT must be 8 byte aligned. This is -# true for the Voyager Quad CPU card which will not boot without -# This directive. 16 byte aligment is recommended by intel. -# - .align 16 -gdt: - /* this is the default null entry in GDT */ - .word gdt_end - gdt - 1 # gdt limit - - .long (GRLDR_CS * 16 + gdt - _start1) # linear address of gdt - - - .word 0 # pad 2 bytes - - /* real mode data segment base=0x200000 */ - .word 0xFFFF, 0 - .byte 0x20, 0x92, 0, 0 - - /* real mode data segment base=0 */ - .word 0xFFFF, 0 - .byte 0, 0x92, 0, 0 - -gdt_end: - -// =========================================================================================== - -helper_start: - //cs=ss=2000 ds=0d00/07c0 es=2000/0d00 - pushw %cs - popw %ds - pushw $FS_BOOT - popw %es - //cs=ds=ss=2000 es=0d00 - - addw $4, %si - andb $0x7f, (help_mark - _start1) - andb $0xfd, (Boot_dl - _start1) - - /* Format of partition information blocks. - * - * Offset Length in bytes Field - * 00h 1 Set to 80h if this partition is active. - * 01h 1 Partition's starting head. - * 02h 2 Partition's starting sector and track. - * 04h(SI) 1 Partition's ID number. - * 05h 1 Partition's ending head. - * 06h 2 Partition's ending sector and track. - * 08h 4 Starting LBA. - * 0Ch 4 Partition's length in sectors. - */ - - pushw %ds /* DS=0x2000 */ - pushw %es /* ES=0x0d00 */ - pushal - - cmpw $0x1c2, %si - jne 5f - movb $0, (help_mark - _start1) -#if (defined(GRLDR_MBR)) - - testb $0x0c, %cs:(mbr_disable - _start1) - jz 1f - - pushw %es /* ES=FS_BOOT */ - /* set the DUCE indicator */ - xorw %ax, %ax - movw %ax, %es - movw $0x5FC, %di - movl $0x45435544, %eax - movb %cs:(mbr_disable - _start1), %al - andb $0x0C, %al - orb $0x40, %al - stosl - popw %es -1: - call Clear_KeyboardBuffer - - testb $0x80, %cs:(mbr_disable - _start1)/* boot previous MBR first? */ - jnz 2f /* no, continue to find GRLDR */ - - /* yes, call the routine for booting the previous MBR. - * it will not return on success. - * on failure, it will return here - */ - - /* before we call the routine, we will check if the user want to - * skip this step and continue to find the GRLDR - */ - /* if timeout==0, don't display the message */ - cmpb $0, %cs:(mbr_time - _start1) - je 1f - /* Press ... to start GRUB, any other key to boot previous MBR ... */ - - movw $(press_hot_key_pre - _start1), %si - - - call print_message - - movw $(press_hot_key_name - _start1), %si - - - call print_message - - movw $(press_hot_key_sub - _start1), %si - - - call print_message -1: - call sleep_5_seconds - jc 3f /* desired hot-key pressed */ - call boot_prev_mbr //Error_modify - jmp 3f -2: - /* before we find GRLDR, give the user a chance to boot_prev_mbr. */ - /* if timeout==0, don't display the message */ - cmpb $0, %cs:(mbr_time - _start1) - je 1f - /* Press ... to boot previous MBR, any other key to start GRUB ... */ - - movw $(press_hot_key_pre - _start1), %si - - - call print_message - - movw $(press_hot_key_name - _start1), %si - - - call print_message - - movw $(press_hot_key_sub1 - _start1), %si - - - call print_message -1: - call sleep_5_seconds - jnc 3f - /* desired hot-key pressed */ - andb $0x7f, %cs:(mbr_disable - _start1) - call boot_prev_mbr //Error_modify -3: - pushw %cs - popw %ds - pushw $FS_BOOT - popw %es - /* modify code at 2b to be "jmp 4f" */ - - movw $(0xEB | ((4f - 2b - 2) << 8)), (2b - _start1) - - orb $0x80, %cs:(mbr_disable - _start1) -4: - - popal - pushal - -#endif // defined(GRLDR_MBR) - - movb $0x41, %ah /* EBIOS check existence */ - movw $0x55aa, %bx - call int13 - jc 1f /* No EBIOS */ - cmpw $0xaa55, %bx - jnz 1f /* No EBIOS */ - testb $1, %cl - jz 1f /* No EBIOS */ -// orb $0x04, 0x0a - orb $0x04, (help_mark - _start1) -1: - - /* initialize partition number and partition entries end */ - movw $0xffff, 0x1bc /* hd partition number */ - movw $0x01fe, 0x1ba /* partition entries end */ - - movw $0xFE3F, (Sectors_passed_in - _start1) /* use a default of H=255, S=63 */ - - movb $8, %ah /* read drive parameters changes DX,ES,DI,BX */ - - /* should not use "call int13", because "int13" will restore DX, - * and the DH returned by "int $0x13" thus be destroyed. - */ - pushaw /* <------ at least DL,SI need to be saved */ - pushw %ds - pushw %es - int $0x13 - popw %es - popw %ds - jc 1f /* failed */ - andb $63, %cl /* sectors per track */ - jz 1f /* failed */ - - movb %dh, %ch /* DH=Hmax */ - movw %cx, (Sectors_passed_in - _start1) /* CL=Smax, CH=Hmax */ -1: - popaw /* <------ at least DL,SI need to be restored */ - - /* geometry_tune */ - testb $0x04, (help_mark - _start1) - jne 1f /* yes, skip the tune */ - -#if defined(GRLDR_MBR) - - testb $0x08, (mbr_disable - _start1) - jnz 1f - -#endif // defined(GRLDR_MBR) - - /* check if the code is loaded completely */ - pushw %ds - pushw %es - pushaw - call geometry_tune - popaw - popw %es - popw %ds - - movw (Sectors_passed_in - _start1), %cx - movb %cl, 0x18 - incb %ch - movb %ch, 0x1a -1: - pushw %si - subw $4, %si - call Check_PartitionTable - popw %si - jc 5f - orb $8, (help_mark - _start1) - call gpt_statr -5: - xorl %eax, %eax - testb $8, (help_mark - _start1)/* Partition Table OK? */ - je 5f /* not */ - cmpw $0x1f2, %si /* is it a primary partition? */ - ja 3f /* no, it is an extended partition */ - movl 4(%si), %eax - movl %eax, 8(%si) /* parent part_start saved here */ - xorl %eax, %eax - movl %eax, 4(%si) /* current part_start(0) saved here */ - -3: - movl 4(%si), %eax - addl 8(%si), %eax /* EAX=start_LBA */ - testl %eax, %eax - je 2f - call read_lba - jnb 5f -2: - orb $0x80, (help_mark - _start1) -5: - - /*******************************************************/ - /* load partition boot track to FS_BOOT using LBA mode */ - /*******************************************************/ - - pushw %si - pushw %es -//--------------------------------------------------------- - /* print "Try (hd0,n): " or "Try (fd0): "*/ - pushw %ds - popw %es - //cs=ds=es=ss=2000 - cld /* for stosb */ - xorw %ax, %ax - testb $8, (help_mark - _start1) - je 1f /* not */ - /* hard drive */ - incw 0x1bc /* logical partition number */ - movw 0x1bc, %ax - movb %al, %dh - cmpb $4, %al - jb 1f - - movb $0xFC, (add_sub_si + 2 - _start1) -1: - /* AL=partition number, AH=0 */ - pushw %ax - - movw $(partition_message - _start1 + 7), %di /* drive type */ - - - movb %dl, %al - shrb $7, %al /* drive type: floppy=0, harddrive=1 */ - shlb $1, %al - addw $0x6466, %ax /* "fd" or "hd" */ - stosw - movb %dl, %al - andb $0x7f, %al /* drive number */ - aam /* convert binary to decimal, AH=high, AL=low */ - testb %ah, %ah - jz 1f - addb $0x30, %ah - movb %ah, (%di) - incw %di -1: - addb $0x30, %al - stosb - - popw %ax - testb $8, (help_mark - _start1) - je 2f /* not */ - /* this is a hard drive, the partition number is in AL */ - movb $0x2c, (%di) /* "," */ - incw %di - aam /* convert binary to decimal, AH=high, AL=low */ - testb %ah, %ah - jz 1f - addb $0x30, %ah - movb %ah, (%di) - incw %di -1: - addb $0x30, %al - stosb -2: - movl $0x00203a29, (%di) /* "): \0" */ - - movw $(partition_message - _start1), %si - - - call print_message /* CS:SI points to message string */ -//------------------------------------------------------------------------------------- - popw %es - //cs=ds=ss=2000 es=0d00 - testb $0x80, (help_mark - _start1) - jne invalid_or_null - - xorw %si, %si - pushw %es - popw %ds - - - //cs=ss=2000 ds=es=0d00 - - //Installation fat12/16/32/exfat/ext2/ntfs partition - /* First, check for ext2 filesystem */ - - andb $0, 0x02 /* Initialization mark */ - testb $0x04, %cs:(help_mark - _start1) - je 1f - orb $0x80, 02(%si) /* force LBA */ -1: - cmpw $0xEF53, 0x438 /* Magic signature */ - jnz fat - -/* ext2 Patch start */ - xorl %eax, %eax - cmpl %eax, 0x420 /* s_blocks_per_group */ - jz fat - cmpl %eax, 0x428 /* s_inodes_per_group */ - jz fat - - /* BX = 0 */ - /* EAX= 0 */ - - movw 0x458, %ax /* AX=s_inode_size */ - testw %ax, %ax - jnz 2f /* invalid inode size */ - movw $0x80, %ax /* EXT2_GOOD_OLD_INODE_SIZE */ - -2: - movw %ax, 0x26(%si) - - movb 0x418, %cl /* s_log_block_size */ - movl $2, %eax - shlw %cl, %ax - movb %al, 0x0d(%si) - shlw $9, %ax /* block size is word wide */ - movw %ax, 0x0e(%si) - shrw $2, %ax - movl %eax, 0x14(%si) - addb $8, %cl - shll %cl, %eax - movl %eax, 0x10(%si) - - - /* fix for ext2 partition: s_inodes_per_group, offset 0x28 */ - movl 0x428, %eax /* s_inodes_per_group */ - movl %eax, 0x28(%si) - - - testb $0x80, 0x460(%si) /* 64-bit file system? */ - je 1f /* not */ - orb $0x40, 2(%si) /* 64-bit file system marked */ -1: - testb $0x10, 0x460(%si) /* metablock group? */ - je 1f /* not */ - movl 0x504(%si), %eax /* The first metablock group */ - movl %eax, 0x2c(%si) - jmp 2f -1: - - /* fix for ext2 partition: block number for group descriptors, offset 0x2c */ - /* At which block the group descriptors begin? */ - movl 0x414, %eax /* s_first_data_block */ - incw %ax - movl %eax, 0x2c(%si) -2: - - /* fix for ext2 partition: on error go back to supervisor, offset 0x01fc */ - - movw $0x200, 0x0b(%si) /* bytes per sector */ - orb $0x10, 02(%si) /* ext2 Mark */ - -fat: - - cld - - /* ds=es=0d00 cs=ss=2000 si=0 */ - cmpl $0x5346544e, 3(%si) /* ntfs Partition? */ - je 3f /* yes */ - - //fat12/16/32/exfat/ext2 - movw %cs:(Sectors_passed_in - _start1)(%si), %ax /* SI=0 */ - movb %al, 0x18(%si) /* DS=ES */ - shrw $8, %ax - incw %ax - movw %ax, 0x1a(%si) -2: - /* BUG fix for extended FAT12/16/32/64/ext2 partition */ - popw %di /* DI points to old entry in MBR */ - pushw %di - xorl %eax, %eax /* let hidden_sectors=0 for floppy */ - testb $8, %cs:(help_mark - _start1) - je 2f /* not */ - movl %cs:4(%di), %eax - addl %cs:8(%di), %eax -2: - movl %eax, 0x1c(%si) /* adjust hidden_sectors for FAT */ - - cmpl $0x33544146, 0x52(%si) /* fat32 Partition? */ - jne 1f /* not */ - cmpl $0x20202032, 0x56(%si) /* fat32 Partition? */ - je 7f /* yes */ -1: - //fat12/16/exfat/ext2 - movw %dx, 0x24(%si) - testb $0x10, 02(%si) /* ext2 Mark */ - jne 9f /* yes */ - //fat12/16/exfat - cmpl $0x41465845, 03(%si) /* exfat Partition? */ - jne 2f /* not */ - cmpl $0x20202054, 07(%si) /* exfat Partition? */ - je 6f /* yes */ -2: - //fat12/16 - cmpl $0x31544146, 0x36(%si) /* fat12/16 Partition? */ - jne 1f /* not */ - cmpl $0x20202032, 0x3a(%si) /* fat12 Partition? */ - je 4f /* yes */ - //fat16 - cmpl $0x20202036, 0x3a(%si) /* fat16 Partition? */ - je 5f /* yes */ -3: - cmpl $0x20202020, 07(%si) /* ntfs Partition? */ - jne 1f /* not */ - - - /* NTFS */ - movl 0x20(%si), %eax /* FAT32 total sectors */ - testl %eax, %eax - jnz 1f - movw 0x0e(%si), %ax /* reserved sectors */ - testw %ax, %ax - jnz 1f - - /* fix for ntfs partition: sectors per track, offset 0x18 */ - /* fix for ntfs partition: number of heads, offset 0x1a */ - movw %cs:(Sectors_passed_in - _start1)(%si), %ax /* SI=0 */ - movb %al, 0x18(%si) /* DS=ES */ - shrw $8, %ax - incw %ax - movw %ax, 0x1a(%si) - /* BUG fix for extended NTFS partition */ - popw %si /* SI points to old entry in MBR */ - pushw %si - xorl %eax, %eax /* let hidden_sectors=0 for floppy */ - testb $8, %cs:(help_mark - _start1)/* Partition Table OK */ - je 3f /* not */ - movl %cs:4(%si), %eax - addl %cs:8(%si), %eax -3: - movl %eax, 0x1c /* adjust hidden_sectors for NTFS */ - - movb %dl, 0x24 /* adjust drive number for NTFS */ - - // Load NTFS using internal boot sector at 0xA00 - - movw $(NTFS5_message - _start1), %si - - - call print_message /* CS:SI points to message string */ - - movw $(Entry_nt - _start1), %bx - - movw $0x52, %cx - - pushw %cs - popw %ds - - /* DS=SS=0x2000 */ - /* ES=FS_BOOT */ - - movw %bx, %si - xorw %di, %di - lodsw - stosw - addw %cx, %si - addw %cx, %di - movw $0x800, %cx - subw %di, %cx - - repz movsb - - /* modify the boot partition number */ - movb %es:1, %al - addb $5, %al /* AL is less than 0x80 */ - cbw /* AH=0 */ - xchgw %ax, %di /* move AX to DI */ - movb 0x1bc, %al /* partition number */ - stosb - - /* fix for NTFS partition: on error go back to supervisor, offset 0x01fa */ - - movw $(error_go_back - Entry_nt), %di - movw %es:(%di), %ax - cmpw $0xFEEB, %ax /* EB FE is jmp back to itself(infinite loop) */ - jnz 3f - decw %ax /* AL=0xEA, ljmp */ - stosb - movw $MONITOR, %ax - stosw - xorw %ax, %ax - stosw /* DI=0x01ff */ -3: - clc - jmp move_entries_and_return - - -6: /* exFAT */ - /* Parameters calculated by the bpb */ - orb $8, 02(%si) /* exfat Mark */ - movl 0x48(%si), %eax - movl %eax, 0x20(%si) //The total number of sectors partition - movl 0x50(%si), %eax - addl 0x1c(%si), %eax - testb $1, 0x6a(%si) - je 6f - addl 0x54(%si), %eax -6: - movl %eax, 0x28(%si) /* FAT table start absolute sector number */ - movl 0x58(%si), %eax - addl 0x1c(%si), %eax - movl %eax, 0x0e(%si) /* Data start Absolute sector */ - movb 0x6c(%si), %cl /* Bytes per sector (power) */ - movw $1, %ax - pushw %ax - shlw %cl, %ax - movw %ax, 0x0b(%si) /* Bytes per sector */ - movb 0x6d(%si), %cl /* Sectors per cluster (power) */ - popw %ax - shlw %cl, %ax - movw %ax, 0x26(%si) /* Sectors per cluster */ - movl 0x60(%si), %eax - movl %eax, 0x2c(%si) /* Root clusters */ - - movw $(exfat_message - _start1), %si - jmp 3f -4: /* fat12 */ - orb $1, 02(%si) /* fat12 Mark */ -2: - pushw %dx - movzbw 0x0d(%si), %ax - movw %ax, 0x26(%si) - movzwl 0x0e(%si), %ecx /* Reserved sector */ - addl 0x1c(%si), %ecx - movl %ecx, 0x28(%si) /* FAT table start absolute sector number */ - movzbw 0x10(%si), %ax /* Number of FAT table */ - mulw 0x16(%si) - pushw %dx - pushw %ax - popl %eax /* FAT table number of sectors */ - addl %ecx, %eax - movl %eax, 0x07(%si) /* Home directory of the absolute starting sector (fat12/16) */ - pushl %eax - movw 0x0b(%si), %cx /* Bytes per sector */ - shrw $5, %cx /* (Bytes per sector)/20h=10h= Contents of each sector */ - movw 0x11(%si), %ax /* File number of Master Contents */ - addw %cx, %ax - decw %ax - divw %cx /* sectors number of the main directory */ - movzwl %ax, %eax /* sectors number of the main directory */ - popl %ecx /* Home directory of the absolute starting sector (fat12/16) */ - addl %eax, %ecx - popw %dx - movl %ecx, 0x0e(%si) /* Data start Absolute sector */ - testb $1, 02(%si) /* fat12? */ - je 8f /* not */ - - movw $(FAT12_message - _start1), %si - jmp 3f -8: - movw $(FAT16_message - _start1), %si - jmp 3f -5: /* fat16 */ - orb $2, 02(%si) /* fat16 Mark */ - jmp 2b -9: /* ext2 */ - movw $(EXT2_message - _start1), %si - - jmp 3f -7: /* fat32 */ - orb $4, 02(%si) /* fat32 Mark */ - movzwl 0x0e(%si), %ecx /* Reserved sector */ - addl 0x1c(%si), %ecx - movl %ecx, 0x28(%si) /* FAT table start absolute sector number */ - movzbl 0x10(%si), %eax - pushw %dx - mull 0x24(%si) - addl %ecx, %eax - movl %eax, 0x0e(%si) /* Data start Absolute sector */ - popw %dx - movw %dx, 0x24(%si) - movzbw 0x0d(%si), %ax - movw %ax, 0x26(%si) - movw $(FAT32_message - _start1), %si -3: - pushw %si - pushw %ds - pushw %es - pushw %di - movw $(nt_boot_image - _start1), %si - movw $(filename_12_64_ext - _start1), %di - pushw %cs - popw %es - testb $7, 02 - pushw %cs - popw %ds - jne 101f - - movw $12, %cx - repz movsb - jmp 105f -101: - pushw %di -102: - movsb -103: - cmpb $0, (%si) - je 104f - cmpb $0x2e, (%si) - jne 102b - incw %si - popw %di - pushw %di - addw $8, %di - jmp 103b -104: - popw %di -105: - popw %di - popw %es - - /* From 2000 to 0d00 move the boot code */ - /* cs=ds=ss=2000 es=0d00 */ - movw $(Entry_12_64_ext - _start1), %si /* 0a00 */ - movw $0x30, %di - movw $((end_12_64_ext - Entry_12_64_ext) / 4 +1), %cx /* move Double word */ - repz movsl /* 2000:0400->0d00:0030 */ - popw %ds - popw %si - /* cs=ss=2000 ds=es=0d00 */ - movw $0x2eeb, 0x00 /* jmp 7c30 */ - - call print_message /* CS:SI points to message string */ - jmp move_entries_and_return - /* fat12/16/32/64/ext2 Partition disposed */ - - -1: - #; It is not FAT12/16/32/NTFS. Check for extended partition. - - /* cs=ss=2000 ds=es=0d00 */ - orb $0x80, %cs:(help_mark - _start1) - pushw %cs - popw %es - - //cs=es=ss=2000 ds=0d00 - - popw %si - pushw %si - cmpb $0x05, %es:(%si) /* extended */ - je 1f - cmpb $0x0f, %es:(%si) /* Win95 extended (LBA) */ - je 1f - cmpb $0x15, %es:(%si) /* hidden extended */ - je 1f - cmpb $0x1f, %es:(%si) /* hidden win95 extended (LBA) */ - je 1f - cmpb $0x85, %es:(%si) /* Linux extended */ - je 1f - - movw $(non_MS_message - _start1), %si - -4: - call print_message /* CS:SI points to message string */ - jmp move_entries_and_return - -1: - /* extended partition entry */ - cmpw $0x1fe, %si - jb 1f - decw %es:0x1bc /* count the partitions in extended zone */ -1: - movw $(extended_message - _start1), %si - - - call print_message /* CS:SI points to message string */ - movw $0x1be, %si - call Check_PartitionTable - jb 1f - - movw $4, %cx - popw %bx /* the old SI points to extended partition ID in MBR */ - pushw %bx - pushw %dx -5: - movl (%si), %eax - cmpw 2(%si), %ax /* Is EAX high word equal to AX? */ - jnz 2f - cmpb %al, %ah /* Is AL=AH? */ - jnz 2f - - /* now all 4 bytes in EAX are equal to each other. */ - cmpl %eax, 4(%si) - jnz 2f - cmpl %eax, 8(%si) - jnz 2f - cmpl %eax, 12(%si) - jz 3f /* entry with 16 dups of a byte means empty entry */ -2: - /* now it is an acceptable entry */ - movw %es:0x1ba, %di /* partition entries end */ - - addw $16, %es:0x1ba /* increment partition entries end */ - - lodsl - stosl - lodsl - stosl - - xchgw %ax, %dx /* save AL(the partition ID)to DL */ - - lodsl - xchgl %eax, %edx /* restore AL from DL(the partition ID), */ - /* and save EAX to EDX */ - cmpb $0x05, %al - je 6f - cmpb $0x0f, %al - je 6f - cmpb $0x15, %al - je 6f - cmpb $0x1f, %al - je 6f - cmpb $0x85, %al - je 6f - /* normal partition, copied to 0x941fe-0x943fb */ - addl %es:4(%bx), %edx /* current partition start */ -6: - /* extended partition, copied to 0x941fe-0x943fb */ - xchgl %eax, %edx /* restore or update EAX from EDX */ - stosl - lodsl /* adjust SI only */ - movl %es:8(%bx), %eax /* parent partition start ... */ - stosl /* ... stored here */ - jmp 2f -3: - addw $16, %si -2: - loop 5b - - popw %dx - - /* extended partition is not a normal one, so set carry to try next */ - jmp move_entries_and_return -//cs=ss=2000 ds,es? -invalid_or_null: -1: - movw $(invalid_message - _start1), %si - call print_message /* CS:SI points to message string */ - -move_entries_and_return: - popw %si - pushw %cs - popw %ds - pushw %cs - popw %es - //cs=ds=es=ss=2000 - pushw %si - cmpw $0x202, %si - jne 1f - /* move entries backward 1 entry */ - movw $0x1fe, %di - movw $0x20e, %si - movw $0xf8, %cx /* 0x1f0 bytes = 0xf8 words */ - cld /* move upward */ - repz movsw - subw $0x10, 0x1ba -1: - popw %si - movw %sp, %bp - testb %dl, %dl - js 3f - movb $0xff, %dh /* partition # for floppy is "whole drive" */ -3: - movw $0x1fe, %ax - movw $(add_sub_si + 5 - _start1), %di - movw %ax, (%di) /* 0x1fe */ - testb $8, (help_mark - _start1) - je 4f - incw (%di) /* 0x1ff */ - cmpw %ax, 0x1ba /* AX=0x1fe */ - jne 1f - decw (%di) /* 0x1fe */ - cmpw $0x1f2, %si - ja 2f /* logical partition */ - jb 1f /* primary partition 0, 1, 2 */ - /* primary partition 3 */ - cmpw $0x0003, 0x1bc /* are there any logical partitions? */ - jne 1f -2: -inc_hard_drive: -//cs=ds=es=ss=2000 - /* all partitions on the drive have been checked, try next drive. - * - * the current stack is: - * - * SP + 36 : DS - * SP + 32 : ES - * SP + 28 : EAX - * SP + 24 : ECX - * SP + 20 : EDX - * SP + 16 : EBX - * SP + 12 : ESP_temp - * SP + 08 : EBP - * SP + 4 : ESI - * SP : EDI - * - */ - - /* get total hard drives */ - orb %dl, %dl - je 4f - xorw %ax, %ax - movw %ax, %ds - movb 0x475, %dh - pushw %cs - popw %ds - orb $0x80, %dh /* CF=0, DH=Max harddrive number + 1 */ -2: - jnc 3f - call print_message /* CS:SI points to message string */ - movw $(drive_number_string - _start1), %si - movb %dl, %al - andb $0x7f, %al - aam /* AH=high decimal, AL=low decimal */ - addw $0x3030, %ax - xchgb %al, %ah - movw %ax, 32(%si) - call print_message /* CS:SI points to message string */ -3: - incw %dx /* !!!! Next drive !!!! */ - cmpb %dh, %dl - jnb 4f /* all drives checked, try floppy finally */ -9: - pushw %dx - movb $1, %al - movw $0x7e00, %bx /* read MBR to 9400:7e00 */ - xorb %dh, %dh - call read_disk_with_reset_and_dec_di - popw %dx - movw $(Error_while_reading_string - _start1), %si - jc 2b /* read failure, try next hard drive */ - - /* The new partition table might be empty or invalid. - * Move the new partition table onto the old one while checking - */ - movw $0x7fbe, %si - call Check_PartitionTable - jb 2b - movw $0x01be, %di - movw $0x21, %cx - repz movsw - - /* Now the partition table is OK */ - - movw %dx, 8(%bp) - orb $2, (Boot_dl - _start1) - - movw $0x1b2, 4(%bp) /* adjust SI in the stack */ - - /* temp change the code: call self_modify_once - * - * "call self_modify_once" at add_sub_si is: - * - * .byte 0xE8 - * .word (self_modify_once - add_sub_si - 3) - * - */ - - movb $0xE8, (add_sub_si - _start1) - movw $(self_modify_once - add_sub_si - 3), (add_sub_si + 1 - _start1) - - /* initialize partition number and partition entries end */ - movw $0xffff, 0x1bc /* hd partition number */ - movw $0x01fe, 0x1ba /* partition entries end */ - jmp 1f -4: - - /* floppy search disabled ? */ - orb %dl, %dl - jne 1f - movw %sp, %bp - movw $0x300, 4(%bp) /* adjust SI in the stack */ -1: - popal - popw %es - popw %ds - //cs=ds=ss=2000 es=0d00 - ret - -//input eax, es:bx -read_lba: - pushw 0x02 - pushw 0x0b - pushw 0x24 - pushw %bp - xorw %bp, %bp - andb $0, 0x02 - testb $0x04, (help_mark - _start1) - je 1f - orb $0x80, 0x02 -1: - movb %dl, 0x24 - movw $0x200, 0x0b - xorw %bx, %bx - movw $4, %cx - pushw %es - call readDisk_12_64_ext /* CX=0, eax,ES changed */ - popw %es -1: - popw %bp - popw 0x24 - popw 0x0b - popw 0x02 - ret - - - -//cs=ds=ss=2000 es=0d00 -gpt_statr: - pushaw - cmpb $0xee, 0x1c2 - jne 1f - - movl $1, %eax - call read_lba - jc 1f - - cmpl $0x20494645, %es:0 //"EFI PART"? - jne 1f //no - movl %es:72, %eax - call read_lba - - movw $0x100, %cx - movw $0x1be, %di -2: - movb $0, (%di) - incw %di - loop 2b - - movw $0x1c2, %si //mbr - movw $0x20, %di //gpt - movw $16, %cx -2: - cmpl $0xe3c9e316, %es:-0x20(%di)//"microsoft reserved partition"? - je 3f //no - cmpl $0, %es:4(%di) - jne 2f - movl %es:(%di), %eax - orl %eax, %eax - je 2f - movb $0xEE, (%si) - movl %eax, 4(%si) -3: - addw $0x10, %si - addw $0x80, %di - loop 2b -2: - negw %cx - addw $16, %cx - cmpw $4, %cx - jbe 1f - subw $4, %cx - shlw $4, %cx - addw %cx, 0x1ba -1: - popaw - ret - -self_modify_once: - /* when we get here, SI should be 0x1b2, and BP high holds DL */ - addw $12, %si /* 0x83, 0xC6, 0x0C */ - movw %bp, %ax - movb %al, %dl - /* note: DS=0x9400 */ - - /* restore the original code: addw $12, %si */ - - movw $0xC683, (add_sub_si - _start1) /* 0x83, 0xC6 */ - movb $0x0C, (add_sub_si + 2 - _start1) /* 0x0C */ - ret - -Error_modify: - - /* we will do the second pass, from drive 0x80. */ - movb $0x7f, %dl /* this will become 0x80 after inc. */ - - /* pass "error" to PUSHF, simulating a load failure, in order - * to try the first entry after return from the helper function. - */ - -// orb $0x80, 0x0a - orb $0x80, (help_mark - _start1) - - pushw $(helper_call + 3 - _start1) /* return address */ - - - pushw %cs /* 0x9400, it is for DS. */ - pushw $FS_BOOT /* 0x0d00, it is for ES. */ - pushal - - pushw %cs - popw %es /* ES=0x9400 */ - movw %sp, %bp - - /* redo from start: DL will be 0x80 after inc. */ - jmp inc_hard_drive - - -1: -boot_prev_mbr: - - /* prepare to boot the previous MBR */ - - /* at this moment DS=0x9400, ES=$FS_BOOT or ES=0x9400 */ - -#if defined(GRLDR_MBR) - call Clear_KeyboardBuffer -#endif // defined(GRLDR_MBR) - - xorw %ax, %ax /* AX=0, for the segment of 0000:7c00 */ - movw %ax, %es /* ES=0x0000 */ - movw %ax, %ds /* DS=0x0000 */ -// movw $0x0202, %ax /* read 2 sectors ... */ - movw $0x0201, %ax /* read 1 sectors ... */ -// movw $0x7A00, %bx /* ... to 0000:7A00 */ - movw $0x7C00, %bx /* ... to 0000:7C00 */ -// movw $0x0001, %cx /* from the first sector ... */ - - movw $0x0002, %cx /* 0-0-2 */ - movw $0x0080, %dx /* ... of the first hard drive */ - call int13 - sti - jc 1f - testb %ah, %ah - jnz 1f - cmpw $0xAA55, 0x7dfe - jne 1f - - /* has a valid partition table ? */ - movw $0x7dbe, %si - call Check_PartitionTable - -// pushfw - - /* disable the boot of non-MBR bootsector ? */ - -// testb $2, %cs:0x02 /* test bit1 of the third byte */ - -// testb $2, %cs:(mbr_disable - _start1) -// jz 2f /* zero means non-MBR enabled */ - -// popfw - jc 1f /* invalid partition table, print "Error" */ - - /* the partition table is valid */ -// pushfw - -//2: - /* the check passed, and the boot is permitted */ -// popfw - -// jc 2f /* invalid partition table */ - - /* use partition table in MBR instead */ - - /* copy 72 bytes at 0000:7bb8 to 0000:7db8 */ - -//2: -#if defined(GRLDR_MBR) - -// testb $0x80, %cs:0x02 /* test bit 7 of the third byte */ - testb $0x80, %cs:(mbr_disable - _start1) - jz 2f /* zero means boot prev-MBR first */ - - /* Cannot find GRLDR. Press space bar to hold the screen, any other key to boot previous MBR ... */ - - movw $(Cannot_find_GRLDR_string - _start1), %si - - - call print_message /* CS:SI points to message string */ - - movw $(nt_boot_image - _start1), %si - - - call print_message /* CS:SI points to message string */ - - movw $(press_space_bar_string - _start1), %si - - -// movw $0x3920, %cs:0x04 /* reset hot-key to space bar */ - movw $0x3920, %cs:(mbr_hotkey - _start1) -// movb $15, %cs:0x03 /* reset time out to 15 seconds */ - movb $15, %cs:(mbr_time - _start1) - call print_message /* CS:SI points to message string */ - - movw $(prev_MBR_string - _start1), %si - - - call print_message /* CS:SI points to message string */ -3: - call sleep_5_seconds /* the hot-key is SPACE */ - /* if hot-key is pressed, wait forever until another key is pressed. */ -// movb $0xff, %cs:0x03 - movb $0xff, %cs:(mbr_time - _start1) - jc 3b /* desired hot-key is pressed */ - -#endif // defined(GRLDR_MBR) - -2: - /* boot the previous MBR */ - - /* clear the DUCE indicator */ - movl $0, 0x5FC /* DS=ES=0 */ - - //movb $0x80, %dl - xorb %dh, %dh - ljmp $0, $0x7c00 -1: - -#if defined(GRLDR_MBR) - - /* no previous MBR, print "Error" */ - -// testb $0x80, %cs:0x02 /* are we called prior to the GRLDR search? */ - testb $0x80, %cs:(mbr_disable - _start1) - jnz 1f /* no, it is a failure at last */ - /* yes, so return to the caller */ - /* Invalid previous MBR. Press any key to start GRUB ... */ - - movw $(continue_string - _start1), %si - call print_message /* CS:SI points to message string */ - call sleep_5_seconds - ret - -#endif // defined(GRLDR_MBR) - -1: - movw $(message_string_helper - _start1), %si - call print_message /* CS:SI points to message string */ - - movw $(nt_boot_image - _start1), %si - call print_message /* CS:SI points to message string */ - - movw $(ctrl_alt_del_string - _start1), %si - call print_message /* CS:SI points to message string */ -1: - jmp 1b /* hang */ - - -#if defined(GRLDR_MBR) - -Clear_KeyboardBuffer: - pushw %ds - xorw %ax, %ax - movw %ax, %ds - movw 0x41c, %ax - movw %ax, 0x041A - pop %ds - ret -#endif // defined(GRLDR_MBR) - -// in: ds:si -Check_PartitionTable: - pushaw - xorb %bl, %bl - movw %si, %di - addw $0x40, %di -4: - cmpw %di, %si - jnb 3f /* partition table is OK */ - pushw %si - movw $4, %cx -2: - lodsl - negl %eax - jc 2f - loop 2b - popw %ax - incb %bl - cmpb $4, %bl - jb 4b /* empty entry, check next */ - jmp 5f /* Error: empty table */ -2: - /* non-empty entry */ - popw %si - lodsw - shlb $1, %al - jnz 5f - lodsw - andb $63, %al - jz 5f - lodsw - lodsw - andb $63, %al - jz 5f - lodsl - negl %eax - jnc 5f - lodsl - negl %eax - jc 4b - jmp 5f -3: - lodsw - cmpw $0xAA55, %ax - je 1f -5: - stc /* invalid partition table */ -1: - popaw - ret - -#if defined(GRLDR_MBR) - -sleep_5_seconds: - /* sleep 5 seconds */ - - /* sleep forever if %cs:0x03 is 0xff */ - - /* calculate the timeout ticks */ - - pushw %ds - pushl %esi - pushl %edx - - movl $0xffffffff, %edx -// movzbl %cs:0x03, %eax - movzbl %cs:(mbr_time - _start1), %eax - cmpb $0xff, %al - je 1f - movl $18, %edx /* 18.2 ticks per second. We simply use 18. */ - mulw %dx /* EDX=0, EAX=ticks */ - xchgw %ax, %dx /* EAX=0, EDX=ticks */ -1: - xorw %ax, %ax - movw %ax, %ds - movl 0x46c, %eax /* initial tick */ - movl %eax, %ecx /* ECX=initial tick */ - testl %edx, %edx - js 1f - addl %edx, %eax /* EAX=timeout tick */ - pushl %eax - -// movzbl %cs:0x03, %eax - movzbl %cs:(mbr_time - _start1), %eax - orl %eax, %eax - jz 3f - - movw $(hot_key_timeout_pre - _start1), %si - - - pushl %eax - call print_message - popl %eax - - movw $(hot_key_timeout_num - _start1), %si - - - call print_decimal -3: - movl %ecx, %esi - addl $18, %esi - - popl %eax - jmp 3f -1: - movl %edx, %eax /* EAX=0xffffffff */ - movl %edx, %esi -3: - movl 0x46c, %ebx /* EBX=current tick */ - cmpl %ecx, %ebx - jnb 2f - - /* current tick is less than initial tick, this means the ticks have - * overflowed to the next day, and EBX is rather small. */ - xorl %ecx, %ecx - movl %edx, %eax - movl $18, %esi -2: - /* check if there is any key press. */ - pushl %eax - movb $1, %ah - int $0x16 - pushw %ax - pushfw - - movb $0x11, %ah - int $0x16 - jnz 1f - popfw - jnz 2f - - /* no, there is no key press. */ - - popw %ax - popl %eax - - cmpl %esi, %ebx - jb 4f - pushl %esi - pushl %eax - pushl %edx - - - subl %esi, %eax - xorl %edx, %edx - movl $18, %esi - divl %esi - - movw $(hot_key_timeout_num - _start1), %si - - - pushl %ebx - call print_decimal - popl %ebx - - popl %edx - popl %eax - popl %esi - addl $18, %esi -4: - cmpl %eax, %ebx /* timeout? */ - jbe 3b /* no, continue to wait */ - - /* timeout reached, CF=0, no key pressed. */ - popl %edx - popl %esi - popw %ds - ret -1: - popfw -2: - /* yes, there is a key press. */ -#if 0 - /* clear the keyboard buffer */ - movb $1, %ah - int $0x16 - jz 1f /* no keys, end */ - movb $0, %ah - int $0x16 /* discard the key */ - jmp 1b -1: -#endif - - /* check if it is the desired key. */ - -// xorw %cs:0x04, %ax /* CF=0 */ - xorw %cs:(mbr_hotkey - _start1), %ax - popw %ax - je 1f -// xorw %cs:0x04, %ax /* CF=0 */ - xorw %cs:(mbr_hotkey - _start1), %ax - jne 2f /* not desired, return CF=0 */ - - /* remove the desired key from the keyboard buffer. */ - - movb $0, %ah - int $0x16 /* discard the key */ - jmp 3f -1: - /* remove the desired key from the keyboard buffer. */ - - movb $0x10, %ah - int $0x16 /* discard the key */ -3: - stc /* CF=1, the desired key pressed */ -2: - popl %eax - popl %edx - popl %esi - popw %ds - ret - -out_decimal: - /* - * input: EAX = number, CS:SI = buffer - */ - - pushl %edx - pushl %ecx - pushw %bx - - movl $10, %ecx - movw %si, %bx - -1: - xorl %edx, %edx - divl %ecx - addb $'0', %dl - movb %dl, %cs:(%si) - incw %si - orl %eax, %eax - jnz 1b - - pushw %si - -1: - decw %si - cmpw %bx, %si - jbe 1f - movb %cs:(%si), %al - xchgb %al, %cs:(%bx) - movb %al, %cs:(%si) - incw %bx - jmp 1b -1: - - popw %si - - popw %bx - popl %ecx - popl %edx - ret - -print_decimal: - pushw %si - call out_decimal - -1: - cmpb $'\b', %cs:(%si) - jz 2f - movb $' ', %cs:(%si) - incw %si - jmp 1b -2: - popw %si - call print_message - ret - -#endif // defined(GRLDR_MBR) - -#if 0 -modify_NTFS_boot_record: - - /* before the call: - * AH= partition number - * AL= 0xB6 ; 0xB6 is opcode of "MOV DH,imm8" - * DL= drive number - * - * on return: CF=0 if there is NTFS boot record; - * CF=1 otherwise. - * CF of flags_orig on the stack will set if CF=1 - */ - - /* - * - * the current stack is: - * - * SP + 40 : DS - * SP + 38 : ES - * SP + 34 : EAX - * SP + 30 : ECX - * SP + 26 : EDX - * SP + 22 : EBX - * SP + 18 : ESP_temp - * SP + 14 : EBP - * SP + 10 : ESI - * SP + 6 : EDI - * SP + 4 : flags_orig - * SP + 2 : SI ; SI points to old entry in MBR - * SP : return_IP - * - */ - - /* DS=ES=FS_BOOT */ - - /* change NTLDR to GRLDR */ - - /* check GR or NT or anything else */ - - pushw %ax - - movw $0x200, %si - lodsw - cmpw $5, %ax - jne 1f /* failure */ - lodsw - testb %ah, %ah /* high byte of unicode ASCII should be 0 */ - jne 1f /* failure */ - - /* 'N' should be a capital letter */ - - cmpb $0x41, %al /* Less than 'A' */ - jb 1f /* failure */ - cmpb $0x5A, %al /* Greater than 'Z'*/ - ja 1f /* failure */ - - xchgw %ax, %cx /* save AX to CX. CL='N' */ - - lodsw - testb %ah, %ah /* high byte of unicode ASCII should be 0 */ - jne 1f /* failure */ - - /* 'T' should be a capital letter */ - - cmpb $0x41, %al /* Less than 'A' */ - jb 1f /* failure */ - cmpb $0x5A, %al /* Greater than 'Z'*/ - ja 1f /* failure */ - - movb %al, %ch /* save AL to CH. CH='T' */ - - lodsw - cmpw $0x4C, %ax /* 'L' */ - jne 1f /* failure */ - lodsw - cmpw $0x44, %ax /* 'D' */ - jne 1f /* failure */ - lodsw - cmpw $0x52, %ax /* 'R' */ - jne 1f /* failure */ - lodsw - cmpw $0x04, %ax /* length of "$I30" */ - jne 1f /* failure */ - lodsw - cmpw $0x24, %ax /* '$' */ - jne 1f /* failure */ - lodsw - cmpw $0x49, %ax /* 'I' */ - jne 1f /* failure */ - lodsw - cmpw $0x33, %ax /* '3' */ - jne 1f /* failure */ - lodsw - cmpw $0x30, %ax /* '0' */ - jne 1f /* failure */ - - - /* assume it is NT bootsector. first, find "NTLDR". CX holds "NT" */ - movw $0x0100, %di - movb %cl, %al /* AL="N" */ - movb $1, %ah /* AH=Carry for SAHF below */ - movl $0x52444c00, %ebx /* "LDR" */ - movb %ch, %bl /* 'T' */ - movw $0x00fa, %cx - - /* now AL holds 'N' and BL holds 'T' */ - - //cld /* already upward */ -3: - repnz scasb /* find "N" */ - jcxz 4f /* gets the end, exit */ - cmpl %ebx, (%di) /* is it "NTLDR"? */ - jnz 3b /* no, continue to find */ - - /* "NTLDR" is found, so we believe it is NT boot sector. */ - - movw $0x5247, -1(%di) /* change "NT" to "GR" */ - - /* CF=0 for now */ - - lahf /* Load Flags into AH */ - /* AH = SF:ZF:xx:AF:xx:PF:xx:CF */ - /* AH = binary xxxxxxx0 */ - jmp 3b -4: - sahf /* Store AH into flags SF ZF xx AF xx PF xx CF */ - - /* CF=0 means "NTLDR" is found, CF=1 means "NTLDR" is not found. */ - - jc 1f /* failure */ - - movl $0x00520047, 0x202 /* change to "G R L D R" */ - - /* check NT 4.0 */ - - movw $0x406, %si - movl (%si), %ebx /* NT 4.0 */ - cmpl $0x03E8B800, %ebx /* MOV AX, 03E8 */ - jnz 3f - - movl 0x84, %ebx - cmpl $0x680007E8, %ebx /* call 008e; push (0D00) */ - jnz 3f - - - movl 0xE8, %ebx - cmpl $0x13CD80B2, %ebx /* "B2 80"="mov DL, 80", "CD 13"="int 13" */ - jnz 3f - - popw %ax - movw %ax, 4(%si) - - movl $0x68909090, %ebx /* nop;nop;nop;push (0D00) */ - movl %ebx, 0x84 - - movb %dl, 0xE9 /* modify drive number */ - - /* modify NTFS boot record */ - movb $0xea, %al /* ljmp, hand over the control to supervisor */ - movb %al, 0x122 - - movw $MONITOR, %ax /* offset for ljmp */ - movw %ax, 0x123 - xorw %ax, %ax - movw %ax, 0x125 - - movw $(NTFS4_message - _start1), %si - - - call print_message /* CS:SI points to message string */ - clc - ret -3: - /* check NT 5.0 */ - - movw $0x44b, %si - movl (%si), %ebx /* NT 5.0 */ - cmpl $0x03E8B800, %ebx /* MOV AX, 03E8 */ - jz 2f - - movw $0x479, %si - movl (%si), %ebx /* NT 5.1 SP2 */ - cmpl $0x03E8B800, %ebx /* MOV AX, 03E8 */ - jnz 1f -2: - movl 0x71, %ebx - cmpl $0x680053E8, %ebx /* call 00C7; push (0D00) */ - jnz 1f - - //movw 0x183, %bx /* CR LF at begin of "A disk read error occurred." */ - movb 0x1F8, %bl - movb $1, %bh - movw (%bx), %bx - cmpw $0x0A0D, %bx /* CR LF */ - jnz 1f - - movb 0x1F9, %bl - movb $1, %bh - movw (%bx), %bx - cmpw $0x0A0D, %bx /* CR LF */ - jnz 1f - - movb 0x1FA, %bl - movb $1, %bh - movw (%bx), %bx - cmpw $0x0A0D, %bx /* CR LF */ - jnz 1f - - popw %ax - movw %ax, 4(%si) - - movl $0x68909090, %ebx /* nop;nop;nop;push (0D00) */ - movl %ebx, 0x71 - - /* change CRLF in NTFS error messages to spaces */ - movw $0x2020, %ax - movb 0x1F8, %bl - movb $1, %bh - movw %ax, (%bx) // 0x183 - movb 0x1F9, %bl - movb $1, %bh - movw %ax, (%bx) // 0x1A0 - movb 0x1FA, %bl - movb $1, %bh - movw %ax, (%bx) // 0x1B3 - - /* modify NTFS boot record */ - movb $0xEA, %al /* ljmp, hand over the control to supervisor */ - movb %al, 0x167 - - movw $MONITOR, %ax /* offset for ljmp */ - movw %ax, 0x168 - - xorw %ax, %ax - movw %ax, 0x16A - - cmpw $0x44b, %si - jne 2f - - movw $(NTFS5_message - _start1), %si - - - jmp 3f -2: - - movw $(NTFS5p_message - _start1), %si - - -3: - call print_message /* CS:SI points to message string */ - clc - ret -1: - /* NTFS boot record not found. */ - - movw $(NTFS_no_boot_record_message - _start1), %si - - - call print_message /* CS:SI points to message string */ - - popw %ax - popl %eax /* return_IP and SI */ - popfw - stc - pushfw - pushl %eax /* return_IP and SI */ - ret -#endif - -move_helper: - - /* called only once and only when the boot loader loaded this code */ - pushw %si - - - movw $0x200, %si /* move from the 2nd sector */ - movw %si, %di - - movw $((pre_stage2_start - _start1 - 0x200) / 2), %cx - - - cld - repz movsw - - popw %si - ret - -filesystem_boot: - /* The partition boot record successfully modified, just boot it */ - - /* - * The boot might fail, but we want to take back the control. - * So we save the registers now. - */ - pushw %ds - pushw %es - pushal - - /* DS=CS=GRLDR_CS, ES=FS_BOOT */ - - /* save GRLDR_CS */ - - movw %es, %bx # save old ES to BX - - cli - - lgdt gdt - _start1 - - - movl %cr0, %eax - orb $1, %al - movl %eax, %cr0 - - movw $8, %si - movw %si, %es - - xorl %esi, %esi - xorl %edi, %edi - movl $(0x9000 / 4), %ecx - - cld - repz movsl - - movw $16, %si - movw %si, %es - - andb $0xfe, %al - movl %eax, %cr0 - - movw %bx, %es # restore ES from BX - - /* move FS_BOOT:0000 to 0:7c00 */ -#if 0 - /* for single sector boot record */ - movw $0x0200, %cx /* move 2 sectors, the old FS_BOOT:0000 will keep untouched. */ -#else - /* for 4-sector NTFS boot record */ - movw $0x0400, %cx /* move 4 sectors, the old FS_BOOT:0000 will keep untouched. */ -#endif - xorw %si, %si - pushw %si /* SI=0, for the segment of 0000:7c00 */ - movw $0x7c00, %di - pushw %di /* DI=0x7c00, for the offset of 0000:7c00 */ - pushw %es /* ES=FS_BOOT */ - popw %ds /* DS=FS_BOOT */ - pushw %si /* SI=0 */ - popw %es /* ES=0 */ - cld - repz movsw - - movw $MONITOR, %di - - movw $(restore_GRLDR_CS - _start1), %si - - - movw $((gdt_end - restore_GRLDR_CS) / 4), %cx - cld - repz cs movsl /* CS segment override prefix(=0x2E) */ - - pushw %es /* ES=0 */ - popw %ds /* DS=0 */ - sti - lret //ljmp $0, $0x7c00 - - -press_space_bar_string: - .ascii "\r\nPress space bar\0" - -press_hot_key_pre: - .ascii "\r\nPress \0" - -press_hot_key_sub: - .ascii " to start GRUB, any other key to boot previous MBR ...\0" -press_hot_key_sub1: - .ascii " to boot previous MBR, any other key to start GRUB ...\0" - -hot_key_timeout_pre: - .ascii "\r\nTimeout: \0" - -hot_key_timeout_num: - .ascii " \b\b\b\0" - -continue_string: - .ascii "\r\nInvalid previous MBR. Press any key to start GRUB ...\0" - - -prev_MBR_string: - .ascii " to hold the screen, any other key to boot previous MBR ...\0" - -Error_while_reading_string: - .ascii "\r\nError while reading MBR of \0" - -drive_number_string: - .ascii " in partition table of drive (hd0 ) \0" - -Cannot_find_GRLDR_string: -message_string_helper: - .ascii "\r\nCannot find \0" -ctrl_alt_del_string: - .ascii " in all drives. Press Ctrl+Alt+Del to restart.\0" - -partition_message: - .ascii "\r\nTry (hd0,0 ) : \0" - -EXT2_message: - .ascii "EXT2: \0" - -NTFS5_message: - .ascii "NTFS5: \0" -exfat_message: - .ascii "EXFAT: \0" -FAT32_message: - .ascii "FAT32: \0" -FAT16_message: - .ascii "FAT16: \0" -FAT12_message: - .ascii "FAT12: \0" -non_MS_message: - .ascii "non-MS: skip \0" -extended_message: - .ascii "Extended: \0" -invalid_message: - .ascii "invalid or null \0" -No_floppy: - .ascii "\r\nNo floppy \0" - -press_hot_key_name: - - /* hot key name, the address is (grldr_signature - 16) */ - - .ascii "hot-key\0" - - /* grldr.mbr is larger than 8K. */ - - ###################################################################### - # The installer should setup the long integer at offset 0x1FFC as - # the unique disk signature. The same signature value must be also - # placed into the disk_serial_number_structure in the first sector(the - # MBR sector). You can easily locate the structure through the pointer - # at offset 0x1FF8. - # - # For GRLDR.MBR the default disk serial number is the grldr.mbr - # signature(0x93cb4d05). You should change it according to the - # date-time value just at the time when you run the installer. - ###################################################################### - -geometry_tune: - - /* on call: - * CS=DS=SS - * ES=FS_BOOT - * - * on return: - * CL max sector number - * DH max head number - * DS changed - * ES changed - * AX changed - * BX changed - * CX changed - * byte at CS:[08] updated on success(Smax) - * byte at CS:[09] updated on success(Hmax) - */ - -#define GEOMTUNE_SEG 0x5000 - /* geometry_tune uses 64KiB buffer at this segment */ -#define GEOMTUNE_BUFFERSEG 0x6000 - /* geometry_tune uses 31.5KiB buffer at this segment */ - - /* offset of variables in GEOM_TUNE_SEG */ -#define GEOMTUNE_Smax_tuned 0x0000 -#define GEOMTUNE_Hmax_tuned 0x0002 -#define GEOMTUNE_Smax_readable 0x0004 - /* upperbound of Smax, cannot read past this sector number */ -#define GEOMTUNE_Hmax_readable 0x0006 - /* upperbound of Hmax, cannot read past this head */ -#define GEOMTUNE_read_ax 0x0008 - /* byte0 = number of sectors to read */ - /* byte1 = 2 */ -#define GEOMTUNE_cmps_cx 0x000A - /* (tune Hmax) number of DWORD to compare */ -#define GEOMTUNE_next_read 0x000C - /* (tune Hmax) boolean : 1 = next cylinder head 0 is read successfully */ - /* (tune Smax) boolean : 1 = next track sector 1 is read successfully */ -#define GEOMTUNE_equal 0x0100 - /* (tune Hmax) - * [0] nonzero = There exist at least 1 track that have data equal to head 0. - * [1...254] - * bit0: 0=data from this head differ from data in head 0 same cylinder 1=no difference encountered - * bit1: 0=data from this head differ from data in head 0 next cylinder 1=no difference encountered - * [255] padding - * (tune Smax) - * [0] nonzero = There exist at least 1 sector that have data equal to sector 1. - * [1...62] - * bit0: 0=data from sector i+1 differ from data in sector 1 same track 1=no difference encountered - * bit1: 0=data from sector i+1 differ from data in sector 1 next track 1=no difference encountered - * [63] padding - */ -#define GEOMTUNE_H_buf_cch0 0x0200 - /* 0200 - 7FFF buffer current cylinder head0 (upto 63 sectors) */ -#define GEOMTUNE_H_buf_nch0 0x8000 - /* 8000 - FDFF buffer next cylinder head0 (upto 63 sectors) */ -#define GEOMTUNE_S_buf_ct 0x0200 - /* 0200 - 7FFF buffer current track */ -#define GEOMTUNE_S_buf_nt 0x8000 - /* 8000 - FDFF buffer next track */ - - /* offset of variables in BUFFERSEG */ -#define GEOMTUNE_H_buf_ct 0x0000 - /* 0000 - 7DFF buffer current track (upto 63 sectors) */ -////////////////////////////////////////////////////////////////////////////// - - /* initialize passed-in values */ - - /* print BIOS geometry */ - - movzbw %cs:(Sectors_passed_in - _start1), %cx - - pushw %cx - - movzbw %cs:(Heads_passed_in - _start1), %cx - incw %cx - - pushw %cx - movzbw %dl, %cx - pushw %cx - - pushw $(BIOS_geom_string - _start1) - - - call realmode_printf - addw $8, %sp - -#ifdef USE_OLD_GEOMETRY_TUNE -////////////////////////////////////////////////////////////////////////////// - - /* find Max sector by reading each sector on the first track. */ - - /* try the passed-in value first */ - - movzbw %cs:(Sectors_passed_in - _start1), %cx /* cylinder=0 */ - - - call check_sector_readable - jnc 1f - xorw %cx, %cx -1: - cmpw $63, %cx - jnb 2f /* this is the maximum value */ - - incw %cx - call check_sector_readable - jc 1f - cmpw $63, %cx - jb 1b - jmp 2f -1: - /* Max Sector = CX - 1 */ - decw %cx - cmpb $2, %cl - jnb 2f - movb $1, %ah /* failure */ - ret - -check_sector_readable: - movw $0x5000, %ax - movw %ax, %es - movw %ax, %ds - xorw %bx, %bx - movw $0x201, %ax /* read 1 sector */ - movb $0, %dh /* head=0 */ - pushaw - movw %bx, %si - movw %bx, %di -// int $0x13 - call int13 - popaw - ret - -2: - cmpw $63, %cx - jbe 2f - movw $63, %cx -2: - /* CX=Max Sector */ -// movw %cx, %cs:(Smax_tuned - _start1) - - movb %cl, %cs:(Smax_tuned - _start1) - - - -////////////////////////////////////////////////////////////////////////////// -#if 0 - /* check if we can read sectors across the track boundary */ - - /* first, read a track plus one sector */ - - movb $0, %cs:(cross_track - _start1) - - - - movw $1, %cx /* sector 1, cylinder 0 */ - movb $0, %dh /* head 0 */ - - movb %cs:(Smax_tuned - _start1), %al /* sectors to read */ - - - incw %ax /* read 1 more sector */ - movb $2, %ah /* READ */ - movw $0x5000, %bx - movw %bx, %es - movw %bx, %ds - xorw %bx, %bx - pushaw - movw %bx, %si - movw %bx, %di -// int $0x13 - call int13 - popaw - jc 1f /* cross-track read is not supported */ - - /* read again normally, only the track */ - - movb %cs:(Smax_tuned - _start1), %al /* sectors to read */ - - - movb $2, %ah /* READ */ - movw $0x5800, %bx - movw %bx, %es - movw %bx, %ds - xorw %bx, %bx - pushaw - movw %bx, %si - movw %bx, %di -// int $0x13 - call int13 - popaw - jc 2b /* failure */ - - /* compare the two tracks */ - - pushw %cx - pushw %si - pushw %di - - movzbw %cs:(Smax_tuned - _start1), %cx /* sectors */ - - - shlw $7, %cx /* dwords */ - movw $0x5000, %ax - movw %ax, %ds - movw $0x5800, %ax - movw %ax, %es - xorw %si, %si - xorw %di, %di - cld - repz cmpsl - popw %di - popw %si - popw %cx - jne 1f /* cross-track read is not supported */ - - movb $1, %cs:(cross_track - _start1) - - -1: -#endif -////////////////////////////////////////////////////////////////////////////// -#if 0 - /* find Max head by reading sector 1 on each track of cylinder 0. */ - - movb $0xFF, %dh /* head=Max possible */ -1: - movw $0x5000, %ax - movw %ax, %es - movw %ax, %ds - xorw %bx, %bx - movw $0x201, %ax /* read 1 sector */ - movw $1, %cx /* cylinder=0, sector=1 */ - pushaw - movw %bx, %si - movw %bx, %di -// int $0x13 - call int13 - popaw - jnc 1f /* found Max head */ - decb %dh - cmpb $0xFF, %dh - jne 1b - movb $1, %ah /* failure */ - ret -1: - - /* DH=Max head */ - - movb %dh, %cs:(Hmax_tuned - _start1) - - -#endif -////////////////////////////////////////////////////////////////////////////// - - /* tune Hmax */ - - /* First, try the passed-in value */ - movb %cs:(Heads_passed_in - _start1), %dh - incb %dh - - testb %dh, %dh - jz 1f /* the passed-in heads = 0x100 */ - - call tune_heads - jb 2f /* failure */ - ja 4f /* success */ -1: - movb $1, %dh /* Hmax: 1 - 255 */ -1: - call tune_heads - jb 2f /* failure */ - ja 4f /* success */ - -#if 0 - - cmpb %cs:(Hmax_tuned - _start1), %dh - - - ja 2f /* this should not happen */ - je 5f -#endif - - incb %dh /* Next Hmax */ - jnz 1b - - /* Hmax=0xFF */ -4: - /* got Hmax=DH-1 */ - - decb %dh - - movb %dh, %cs:(Hmax_tuned - _start1) - - -5: - /* Hmax is tuned ok. */ - - cmpb $0xFF, %dh - jne 1f - /* consider Hmax=0xFF as a failure! Use the passed-in value. */ - - movb %cs:(Heads_passed_in - _start1), %dh - incb %dh - - testb %dh, %dh - jnz 4f - decb %dh -4: - decb %dh - - movb %dh, %cs:(Hmax_tuned - _start1) - - -1: -////////////////////////////////////////////////////////////////////////////// - - /* tune Smax */ - - /* First, try the passed-in value */ - - movb %cs:(Sectors_passed_in - _start1), %cl - -4: - call tune_sectors - jb 2f /* failure */ - ja 4f /* success */ -1: - movb $8, %cl /* Smax: 8 - 63 */ -1: - call tune_sectors - jb 2f /* failure */ - ja 4f /* success */ - - incw %cx /* Next Smax */ - - - cmpb %cs:(Smax_tuned - _start1), %cl - - - jb 1b - cmpb $63, %cl - jbe 4f - movb $63, %cl - -4: - /* got Smax=CL */ - movb %cl, %cs:(Smax_tuned - _start1) - - - - /* Smax is tuned ok. */ - -////////////////////////////////////////////////////////////////////////////// - - /* print tuned geometry */ - - movzbw %cs:(Smax_tuned - _start1), %cx - - - pushw %cx - - movzbw %cs:(Hmax_tuned - _start1), %cx - - - incw %cx - pushw %cx - movzbw %dl, %cx - pushw %cx - - pushw $(TUNE_geom_string - _start1) - - - call realmode_printf - addw $8, %sp - - /* return with success */ - - movw %cx, %cs:(Sectors_passed_in - _start1) /* Smax */ - movb $0, %ah /* success */ - ret -2: - movb $1, %ah /* failure */ - ret - -////////////////////////////////////////////////////////////////////////////// - -tune_heads: - - /* input: DH = MaxHead + 1 */ - - movb $0, %ch /* cylinder: 0 - 4 */ -2: - /* read ending track of this cylinder */ - - movb $1, %cl /* sector 1=the leading sector */ - movb $2, %ah /* READ */ - - movb %cs:(Smax_tuned - _start1), %al /* sectors to read */ - - - movw $0x5000, %bx - movw %bx, %es - movw %bx, %ds - xorw %bx, %bx - pushaw - movw %bx, %si - movw %bx, %di -// int $0x13 - call int13 - popaw - //jc 2f /* failure */ - incb %ch - jc 4f /* considered OK */ - decb %ch - - /* read beginning track of this cylinder */ - - movb $1, %cl /* sector 1=the leading sector */ - movb $2, %ah /* READ */ - - movb %cs:(Smax_tuned - _start1), %al /* sectors to read */ - - - movw $0x5800, %bx - movw %bx, %es - movw %bx, %ds - xorw %bx, %bx - pushaw - movw %bx, %si - movw %bx, %di - movb $0, %dh -// int $0x13 - call int13 - popaw - jc 2f /* failure */ - - incb %ch /* next cylinder */ - - /* compare the two tracks */ - call cmp_track - je 4f /* ok, try next cylinder */ - - /* read beginning track of the next cylinder */ - - movb $1, %cl /* sector 1=the leading sector */ - movb $2, %ah /* READ */ - - movb %cs:(Smax_tuned - _start1), %al /* sectors to read */ - - - movw $0x5800, %bx - movw %bx, %es - movw %bx, %ds - xorw %bx, %bx - pushaw - movw %bx, %si - movw %bx, %di - movb $0, %dh -// int $0x13 - call int13 - popaw - jc 2f /* failure */ - - /* compare the two tracks */ - call cmp_track - jne 3f /* Next Hmax */ -4: - cmpb $5, %ch /* cylinder: 0 - 4 */ - jb 2b /* Next cylinder */ - - /* all passed, DH-1 is the final Hmax */ - cmpb $0, %dh - je 2f /* failure */ - ret /* Flag: above */ -3: - cmpb %dh, %dh /* Flag: equal */ - ret -2: - stc /* Flag: below */ - ret - -cmp_track: - pushw %cx - pushw %si - pushw %di - - movzbw %cs:(Smax_tuned - _start1), %cx /* sectors */ - - - shlw $7, %cx /* dwords */ - movw $0x5000, %ax - movw %ax, %ds - movw $0x5800, %ax - movw %ax, %es - xorw %si, %si - xorw %di, %di - cld - repz cmpsl - popw %di - popw %si - popw %cx - ret - -////////////////////////////////////////////////////////////////////////////// - -tune_sectors: - - /* input: CL = MaxSector */ - - movb $16, %cs:(Smax_count - _start1) - movb $0, %ch /* cylinder: 0 - 6 */ - movb $0, %dh /* head: 0 - Hmax */ -6: - /* read beginning sector of this track. */ - - movw $0x201, %ax /* read 1 sector */ - movw $0x5800, %bx - movw %bx, %es - movw %bx, %ds - xorw %bx, %bx - pushaw - movb $1, %cl /* beginning sector */ - movw %bx, %si - movw %bx, %di -// int $0x13 - call int13 - popaw - jc 2f /* failure */ - - /* read ending sector of this track. */ - - movw $0x202, %ax /* read 2 sectors */ - movw $0x5000, %bx - movw %bx, %es - movw %bx, %ds - xorw %bx, %bx - pushaw - movw %bx, %si - movw %bx, %di -// int $0x13 - call int13 - popaw - //jc 2f /* failure */ - - /* locate the next track. */ - - pushfw /* save CF */ - - cmpb %cs:(Hmax_tuned - _start1), %dh - - - jb 3f /* Next track */ - movb $0xFF, %dh /* head 0 of ... */ - incb %ch /* ... the next cylinder. */ -3: - incb %dh /* next track */ - popfw /* restore CF */ - jc 4f /* considered OK */ - - /* compare the 2 sectors */ - call cmp_sector - je 4f /* ok, try next track */ - - /* read beginning sector of the next track. */ - - movw $0x201, %ax /* read 1 sector */ - movw $0x5800, %bx - movw %bx, %es - movw %bx, %ds - xorw %bx, %bx - pushaw - movw %bx, %si - movw %bx, %di - movb $1, %cl /* sector 1=the leading sector */ -// int $0x13 - call int13 - popaw - jc 2f /* failure */ - - /* compare the 2 sectors */ - call cmp_sector - jne 3f /* Next Smax */ -4: - decb %cs:(Smax_count - _start1) - jz 6f - - cmpb $7, %ch /* any cylinder remains to check? */ - jb 6b /* yes, next track */ -6: - /* all passed, CL is the final Smax */ - cmpb $1, %cl - jbe 2f /* failure */ - ret /* Flag: above */ -3: - /* not Maximum sector number */ - cmpb %cl, %cl /* Flag: equal */ - ret -2: - /* I/O error, sector tune failed */ - stc /* Flag: below */ - ret - -cmp_sector: - pushw %cx - pushw %si - pushw %di - movw $0x80, %cx /* 1 sector == 0x80 dwords */ - movw $0x5020, %ax - movw %ax, %ds - movw $0x5800, %ax - movw %ax, %es - xorw %si, %si - xorw %di, %di - cld - repz cmpsl - popw %di - popw %si - popw %cx - ret - -#else /* ndef USE_OLD_GEOMETRY_TUNE */ - - ////////////////////////////////////////////////////////////////////////////// - /* find Max sector by reading each sector on the first track. */ - - movw $GEOMTUNE_SEG, %ax /* Don't use SCRATCHSEG */ - movw %ax, %es - movw %ax, %ds - - /* try the passed-in value first */ - movzbw %cs:(Sectors_passed_in - _start1), %cx /* cylinder=0 */ - xorw %ax, %ax - cmpw $63, %cx - ja 1f - call check_sector_readable - sbbw %ax, %ax - notw %ax -1: - andw %ax, %cx /* if read failure, cx=0 */ -1: - cmpb $63, %cl - jnb 2f /* this is the maximum value */ - incw %cx - call check_sector_readable - jnc 1b - - /* Max Sector = CX - 1 */ - decw %cx - cmpb $2, %cl - jnb 2f /* CX=Max Sector */ - movb $1, %ah /* failure */ - ret - -check_sector_readable: - xorw %bx, %bx - movw $0x201, %ax /* read 1 sector */ - movb $0, %dh /* head=0 */ - pushaw -// int $0x13 - call int13 - jc 1f - decb %al - addb $255, %al /* set CF if returned AL != 1 */ -1: - popaw - ret -2: - /* CX=Max Sector */ - movw %cx, GEOMTUNE_Smax_readable - - ////////////////////////////////////////////////////////////////////////////// - /* tune Hmax */ - - movw $254, GEOMTUNE_Hmax_readable - - movb $2, %ch - movw %cx, GEOMTUNE_read_ax /* number of readable sectors per track */ - shlw $7, %cx /* x128 DWORDs per sector */ - movw %cx, GEOMTUNE_cmps_cx /* number of DWORDs to compare */ - /* fill array */ - cld - movw $GEOMTUNE_equal, %di - movl $0x03030303, %eax - movw $0x40, %cx /* 0x100/4 = 0x40 */ - rep stosl - - /* cx is now 0 */ /* start with cylinder 0*/ - -10: /* cylinder loop */ - movb $1, %cl /* sector 1 */ - xorb %dh, %dh /* head 0 */ - movw GEOMTUNE_read_ax, %ax - movw %ds, %bx - movw %bx, %es /* GEOMTUNE_SEG */ - - /* read next cylinder, head 0 */ - pushaw - incb %ch /* next cylinder */ - movw $GEOMTUNE_H_buf_nch0, %bx -// int $0x13 - call int13 - setnc %ah - cmpb GEOMTUNE_read_ax, %al - sete %al - andb %ah, %al /* 1=no error and read all required sectors */ - movb %al, GEOMTUNE_next_read /* save boolean value for later use */ - popaw - - /* read current cylinder, head 0 */ - pushaw - movw $GEOMTUNE_H_buf_cch0, %bx -// int $0x13 - call int13 - setnc %ah - cmpb GEOMTUNE_read_ax, %al - sete %al - andb %ah, %al /* 1=no error and read all required sectors */ - popaw - jz 14f /* error, end cylinder loop */ - - /* read current cylinder, head 1-254 */ - movw $GEOMTUNE_BUFFERSEG, %bx - movw %bx, %es - /* DH is now 0 */ - movb %dh, GEOMTUNE_equal /* GEOMTUNE_equal[0] = 0 */ - -11: /* head loop */ - addb $1, %dh - cmp GEOMTUNE_Hmax_readable, %dh - ja 13f /* end head loop */ - - movb $(GEOMTUNE_equal >> 8), %bh - movb %dh, %bl - /* DS:BX = address of GEOMTUNE_equal[DH] */ - movb (%bx), %al - testb %al, %al /* 0=this head has already returned different data from head 0, no need to compare again */ - jz 11b /* head loop */ - - pushaw - xorw %bx, %bx /* offset GEOMTUNE_H_buf_ct is 0 */ - movw GEOMTUNE_read_ax, %ax -// int $0x13 - call int13 - setnc %ah - cmpb GEOMTUNE_read_ax, %al - sete %al - andb %ah, %al /* no error and read all required sectors */ - popaw - jz 12f /* read error head 1-254 */ - - pushaw - testb $1, %al - jz 1f - /* compare with same cylinder head 0 */ - movw GEOMTUNE_cmps_cx, %cx - movw $GEOMTUNE_H_buf_cch0, %si - xorw %di, %di /* offset GEOMTUNE_H_buf_ct is 0 */ /* ES is BUF_SEG */ - repe cmpsl - je 1f - /* different data */ - andb $(0xFF-1), %al -1: - testb $2, %al - jz 1f - /* compare with next cylinder head 0 */ - testb $1, GEOMTUNE_next_read /* skip if next cylinder head 0 has not been read successfully */ - jz 1f - movw GEOMTUNE_cmps_cx, %cx - movw $GEOMTUNE_H_buf_nch0, %si - xorw %di, %di /* offset GEOMTUNE_H_buf_ct is 0 */ /* ES is BUF_SEG */ - repe cmpsl - je 1f - /* different data */ - andb $(0xFF-2), %al -1: - movb %al, (%bx) - orb %al, GEOMTUNE_equal /* GEOMTUNE_equal[0] */ - popaw - - /* continue, next head */ - jmp 11b /* head loop */ - -12: /* read error head 1-254 */ - test %ch, %ch /* Is this cylinder 0 ? */ - /* If error on cylinder >0, end. */ - jnz 14f /* end cylinder loop */ - decb %dh /* Error on cylinder 0 = end of head. Adjust readable head number */ - movb %dh, GEOMTUNE_Hmax_readable - -13: /* end head loop */ - movb GEOMTUNE_equal, %al - test %al, %al /* 0: all readable heads(>0) differ from head0 */ - jz 14f /* end cylinder loop */ - - /* next cylinder */ - incb %ch - cmpb $5, %ch /* max number of cylinders to read */ - jb 10b /* cylinder loop */ - -14: /* end cylinder loop */ - movw %ds, %bx - movw %bx, %es /* GEOMTUNE_SEG */ - movw $(GEOMTUNE_equal +1), %di - movw GEOMTUNE_Hmax_readable, %cx - incw %cx - xorw %ax, %ax - repz scasb /* skip heads that have different data from head0 */ - subw $(GEOMTUNE_equal +2), %di - movw %di, GEOMTUNE_Hmax_tuned - - ////////////////////////////////////////////////////////////////////////////// - /* tune Smax */ - - /* DS = ES = GEOMTUNE_SEG */ - - movw $GEOMTUNE_equal, %di - movl $0x03030303, %eax - movw $(64/4), %cx - rep stosl - - /* read first track */ - movw $1, %cx /* cyl 0 sector 1 */ - xorb %dh, %dh /* head 0 */ - movw GEOMTUNE_read_ax, %ax - movw $GEOMTUNE_S_buf_ct, %bx - pushaw -// int $0x13 - call int13 - popaw - jc 2f -20: /* track loop */ - /* compare sector 1 with sectors 2-63 */ - /* AL = number of sectors read */ - - pushw %cx - pushw %dx - xorb %ah, %ah - movw $GEOMTUNE_equal, %bx - movw $GEOMTUNE_S_buf_ct, %dx -21: /* sector loop */ - incw %bx - cmpb %al, %bl - jae 22f /* end sector loop */ - addw $512, %dx - movw %dx, %di - movw $GEOMTUNE_S_buf_ct, %si - movw $(512/4), %cx - repe cmpsl - setne %cl /* eq:0 dif:1 */ - notb %cl /* eq:255 dif:255-1 */ - andb %cl, (%bx) /* clear bit0 if dif */ - setnz %cl /* dif:0 eq:1 */ - orb %cl, %ah /* AH=1 if there is some sector that has equal data to sector 1 */ - jmp 21b /* sector loop */ -22: /* end sector loop */ - popw %dx - popw %cx - - testb $0xFF, %ah /* AH=1 if there is sector that has equal data to sector 1 */ - jz 25f /* end track loop */ /* no more equal sector */ - /* next track */ - incb %dh - cmpb GEOMTUNE_Hmax_tuned, %dh - jna 1f - /* next cylinder */ - xorb %dh, %dh - incb %ch - cmpb $7, %ch /* max cylinder number to read and compare */ - ja 25f /* end track loop */ -1: /* read new track */ - movw GEOMTUNE_read_ax, %ax - movw $GEOMTUNE_S_buf_nt, %bx - pushaw -// int $0x13 - call int13 - popaw - jc 2f - /* compare sector 1 with sectors 2-63 from previous track */ - /* AL = number of sectors read */ - pushaw - movw $GEOMTUNE_equal, %bx - movw $GEOMTUNE_S_buf_ct, %dx -23: /* sector loop */ - incw %bx - cmpb %al, %bl - jae 24f /* end sector loop */ - addw $512, %dx - movw %dx, %di - movw $GEOMTUNE_S_buf_nt, %si - movw $(512/4), %cx - repe cmpsl - setne %cl /* eq=>0 dif=>1 */ - addb %cl, %cl /* eq=>0 dif=>2 */ - notb %cl /* eq=>255 dif=>255-2 */ - andb %cl, (%bx) /* clear bit1 if dif */ - jmp 23b /* sector loop */ -24: /* end sector loop */ - /* copy next track buffer to current track buffer */ - movw $GEOMTUNE_S_buf_nt, %si - movw $GEOMTUNE_S_buf_ct, %di - movw $(63*512/4), %cx - rep movsl - popaw - jmp 20b /* track loop */ -25: /* end track loop */ - movw $(GEOMTUNE_equal +1), %di - movw GEOMTUNE_Smax_readable, %cx - xorw %ax, %ax /* AL = 0 */ - repe scasb /* skip 0 */ - subw $(GEOMTUNE_equal +1), %di - movw %di, %cx - movb %cl, %cs:(Sectors_passed_in - _start1) - pushw %cx - movb GEOMTUNE_Hmax_tuned, %cl - movb %cl, %cs:(Heads_passed_in - _start1) - incb %cl - pushw %cx - movzbw %dl, %cx - pushw %cx - - pushw $(TUNE_geom_string - _start1) - - - call realmode_printf - addw $8, %sp - movb $0, %ah /* success */ - ret -2: - movb $1, %ah /* failure */ - ret -#endif /* ndef USE_OLD_GEOMETRY_TUNE */ - -////////////////////////////////////////////////////////////////////////////// - - - -#;============================================================================ - -/* void realmode_printf(const char *format, ...) - * - * input: format is offset in CS segment - * - * Usage example: - * - * pushw IntegerN - * ... ... ... ... - * pushw Integer2 - * pushw Integer1 - * pushw $format_string - _start1 - * call realmode_printf - * addw $(2*(N+1)), %sp - * - * where _start1 should be the base of the CS segment, - * and format_string like this: - * - * format_string: - * .string "Int1=%x, Int2=%x, ..., IntN=%x\r\n" - * - * Currently only %d, %x and %X are implemented. - */ - -realmode_printf: - pushaw - movw %sp, %bp - # bp+18: format - # bp+20: variables - addw $18, %bp - movw (%bp), %si # points to format string - addw $2, %bp # (%bp) is the first variable -1: - cs lodsb - testb %al, %al - jz 1f - cmpb $'%', %al - jne 2f - - #; %d, %x, %X - - cs lodsb - testb %al, %al - jz 1f - cmpb $'d', %al - movw $10, %bx # base 10 - jz 4f - cmpb $'x', %al - jz 3f - cmpb $'X', %al - jne 1b # unkown directive, continue -3: - /* print hexa number */ - movw $16, %bx # base 16 -4: - /* print decimal or hexa number */ - pushl %edi - - xorl %edi, %edi - xorw %cx, %cx # count the digits - movw (%bp), %ax -5: - xorw %dx, %dx - divw %bx # AX=quo, DX=rem - movw %dx, %di - rorl $4, %edi - incw %cx - testw %ax, %ax # end? - jnz 5b - - /* print the digits in EDI */ - xorw %bx, %bx /* video page 0 */ -5: - roll $4, %edi - movw %di, %ax # get digit in AL - andb $0x0f, %al - cmpb $9, %al - jbe 6f - addb $7, %al # A, B, C, D, E, F -6: - addb $0x30, %al - movb $0x0e, %ah /* print it */ - int $0x10 /* via TTY mode */ - loop 5b - - popl %edi - - addw $2, %bp # (%bp) is the next variable - jmp 1b # continue -2: - /* print char in AL */ - xorw %bx, %bx /* video page 0 */ - movb $0x0e, %ah /* print it */ - int $0x10 /* via TTY mode */ - jmp 1b # continue -1: - popaw - ret - -#;============================================================================ -////////////////////////////////////////////////////////////////////////////// - -BIOS_geom_string: - .string "\r\nBIOS: Drive=0x%X, H=%d, S=%d\r\n" -TUNE_geom_string: - .string "TUNE: Drive=0x%X, H=%d, S=%d\r\n" - -#ifdef USE_OLD_GEOMETRY_TUNE -Smax_tuned: - .byte 0 -Hmax_tuned: - .byte 0 -Smax_count: - .byte 0 -cross_track: - .byte 0 -#endif - -////////////////////////////////////////////////////////////////////////////// - - ###################################################################### - # External modifiers may setup a long integer at offset 0x1FFC as the - # unique disk signature. The same signature value must be also placed - # into the disk_serial_number_structure in the first sector(the MBR - # sector). You can easily locate the structure through the pointer at - # offset 0x1FF8. - # - # For GRLDR the default disk serial number is the grldr signature - # ("GR" 0x55 0xAA). Generally you needn't change it, though you are' - # allowed to change it through an external modifier. - ###################################################################### - - - . = _start1 + 0x1FF8 - - /* point to disk serial number in the first sector, i.e., the MBR - * sector. The program never access this pointer. It can be used by - * an external program to easily locate the disk serial number at MBR. - */ - - .word disk_serial_number_structure - _start1 + 5 - - - - . = _start1 + 0x1FFA - - - /* version word of grldr.mbr, the address is (grldr_signature - 2) */ - - .word 4 - -grldr_signature: - .byte 0x47, 0x52, 0x55, 0xaa /* signature for helper */ - - .align 0x200 - - . = _start1 + 0x2000 - -#endif //(! defined(GRLDR_INSTALL)) - -#if defined(GRLDR_INSTALL) - - -/* ******************** CDROM_bin start ****************************** */ - -Entry_cdrom: - - cli - xorw %bx, %bx - movw %bx, %ss - movw $0x7c00, %sp /* temp safe stack space */ - sti - call 1f -1: - popw %bx /* Instruction Pointer of 1b */ - subw $(1b - Entry_cdrom), %bx /* CS:BX=Entry_cdrom */ - shrw $4, %bx - movw %cs, %ax - addw %ax, %bx /* BX:0000=Entry_cdrom */ - /* Let CS:0000=Entry_cdrom */ - pushw %bx - pushw $(1f - Entry_cdrom) - lret -1: - movw %bx, %ds - movw %bx, %es - - //Judgment udf partition - movw $0x1000, %bx /* buffer offset */ - movl $0x10, %eax /* lba of sectors */ -1: - call load_cdrom - movw $5, %cx - leaw 1(%bx), %si - movw $(udf_tag - Entry_cdrom), %di - repz cmpsb - je 1f - incl %eax - cmpl $0x20, %eax - jae iso - jmp 1b - -1: //udf - movl $0x100, %eax //AnchorVolume - call load_cdrom - movl 0x14(%bx), %eax //MainVolume_ExtentLocation -1: - call load_cdrom - cmpw $5, (%bx) //Partition - je 1f - incl %eax - jmp 1b -1: - movl 0xbc(%bx), %eax //FileSet - movl %eax, (udf_partition_start - Entry_cdrom) - call load_cdrom - movl 0x194(%bx), %eax - addl (udf_partition_start - Entry_cdrom), %eax //RootDirectoryLocation - call load_cdrom - movw 0xa8(%bx), %si - movl 0xb4(%bx, %si), %eax - addl (udf_partition_start - Entry_cdrom), %eax //FileIdentifier - call load_cdrom -5: - testb $2, 0x12(%bx) //Directory? - jne 1f //yes - movl 0x18(%bx), %eax //lba - movw 0x24(%bx), %si //LengthofImplementationUse - movb 0x13(%bx), %cl //NameLength - orb %cl, %cl - je 1f - decb %cl - movb $0, (utf16_tag - Entry_cdrom) //utf8 - cmpb $8, 0x26(%bx, %si) //utf8? - je 2f //yes - orb $1, (utf16_tag - Entry_cdrom) //utf16 - shrb $1, %cl //NameLength/2 -2: - leaw 0x27(%bx, %si), %si //Name Address - cmpb $1, (utf16_tag - Entry_cdrom) //utf16? - jne 2f //no - incw %si -2: - movw $(cdrom_name - Entry_cdrom), %di -3: - cmpb $0, (%di) - je 2f - andb $0xdf, (%si) /* Changed to upper case */ - cmpsb - jne 1f - cmpb $1, (utf16_tag - Entry_cdrom) //utf16? - jne 3b //no - incw %si - jmp 3b -2: - - //Found files - addl (udf_partition_start - Entry_cdrom), %eax //FileEntry - movw $0x1000, %bx /* buffer offset */ - call load_cdrom - movw 0xa8(%bx), %si - movl 0xb0(%bx, %si), %ecx // ecx = File length in bytes */ - movl 0xb4(%bx, %si), %eax - addl (udf_partition_start - Entry_cdrom), %eax //lba of grldr - jmp cdrom_ok - -1: //File not found - movzbw 0x13(%bx), %cx //NameLength - addw 0x24(%bx), %cx //+LengthofImplementationUse - addw %cx, %bx //+NameBaseAddress - addw $0x26, %bx - movw $5, %cx -1: - cmpw $0x101, (%bx) //UDF_FileIdentifier - je 5b //Continue - incw %bx - loop 1b - jmp 4f - -iso: - movw $0x1000, %bx /* buffer offset */ - movl $0x10, %eax /* Read the main sector descriptor */ - call load_cdrom - movl 0x9e(%bx), %eax /* Root */ - call load_cdrom -5: - cmpb $0, (%bx) /* Record length in bytes */ - je 4f /* End */ - cmpb $0, 0x19(%bx) /* type */ - jne 3f - xorw %si, %si - movw $5, %cx /* File name length */ - cmpb $5, 0x20(%bx) /* grldr file name length */ - je 1f - cmpb $7, 0x20(%bx) - je 2f - cmpb $8, 0x20(%bx) - jne 3f - cmpb $0x2e, 0x26(%bx) - jne 3f - incw %si -2: - cmpw $0x313b, 0x26(%bx,%si) - jne 3f -1: - leaw 0x21(%bx), %si /* file name */ - movw $(cdrom_name - Entry_cdrom), %di /* "GRLDR.;1" */ -1: - andb $0xdf, (%si) /* Changed to upper case */ - cmpsb - jne 3f - loop 1b - movl 0x0a(%bx), %ecx /* File length in bytes */ - movl 2(%bx), %eax /* File logical sector */ - jmp cdrom_ok -3: - movzbw (%bx), %cx - addw %cx, %bx /* First record */ - jmp 5b - - -4: - movw $(msg_BootError_cdrom - Entry_cdrom), %si -1: - lodsb (%si), %al /* get token */ - cmpb $0, %al /* end of string? */ - je 1f - movb $0x0e, %ah /* print char in AL */ - int $0x10 /* via TTY mode */ - jmp 1b - -1: - jmp 1b - - -cdrom_ok: - /* EAX = first sector(LBA) of GRLDR */ - /* ECX = File number of byte */ - - xorw %bx, %bx - movw $0x2000, %di - movw %di, %es -1: - pushw %es - call load_cdrom - popw %di - leaw 0x80(%di), %di - movw %di, %es - incl %eax - subl $0x800, %ecx - jnl 1b - ljmp $0x2000, $0 - - -load_cdrom: - /* input: EAX LBA - * output: ES:BX - */ - pushaw - movw $0xe00, %si - movl $0x00010010, (%si) /* number of sectors */ - movw %bx, 4(%si) /* buffer offset */ - movw %es, 6(%si) /* buffer segment */ - movl %eax, 8(%si) /* LBA lo 32 bits */ - movl $0, 12(%si) /* LBA hi 32 bits */ - movb $0x42, %ah - pushw %ds - pushw %es - int $0x13 - popw %es - popw %ds - popaw - ret - - - - - . = Entry_cdrom + 0x1e0 - -msg_BootError_cdrom: - .ascii "No " - -cdrom_name: - .ascii "GRLDR\0\0\0\0\0\0\0\0" - -udf_tag: - .ascii "BEA01" - -utf16_tag: - .byte 0 - -udf_partition_start: - .long 0 - - - . = Entry_cdrom + 0x1fe - - .word 0xAA55 - - . = Entry_cdrom + 0x200 - -/* ******************** CDROM_bin end ****************************** */ - -/* ******************** HD_UDF_bin start ****************************** */ -Entry_hd_udf: - - jmp 1f - - . = Entry_hd_udf + 2 - .byte 0x90 - .ascii "UDF" - -hd_utf16_tag: - .byte 0 - -hd_udf_partition_start: - .long 0 - - . = Entry_hd_udf + 0xc -partition_start: - .ascii "hide" - -1: - cli - xorw %bx, %bx - movw %bx, %ss - movw $0x7c00, %sp /* temp safe stack space */ - sti - call 1f -1: - popw %bx /* Instruction Pointer of 1b */ - subw $(1b - Entry_hd_udf), %bx /* CS:BX=Entry_hd_udf */ - shrw $4, %bx - movw %cs, %ax - addw %ax, %bx /* BX:0000=Entry_hd_udf */ - /* Let CS:0000=Entry_hd_udf */ - pushw %bx - pushw $(1f - Entry_hd_udf) - lret -1: - movw %bx, %ds - movw %bx, %es - movw $1, %bp - movw $0x1000, %bx - - movl (partition_start - Entry_hd_udf), %eax - testl %eax, %eax - jne 1f - movb $0xff, %dh -1: - addl $0x100, %eax //AnchorVolume - call load_hd_udf - movl 0x14(%bx), %eax //MainVolume_ExtentLocation - addl (partition_start - Entry_hd_udf), %eax -1: - call load_hd_udf - cmpw $5, (%bx) //Partition - je 1f - incl %eax - jmp 1b -1: - movl 0xbc(%bx), %eax //FileSet - addl (partition_start - Entry_hd_udf), %eax - movl %eax, (hd_udf_partition_start - Entry_hd_udf) - call load_hd_udf - movl 0x194(%bx), %eax - addl (hd_udf_partition_start - Entry_hd_udf), %eax //RootDirectoryLocation - call load_hd_udf - - movw $0x09c0, %di - call read_fileEntry - jc 4f - -//(101) - movw $0x2000, %bx -5: - testb $2, 0x12(%bx) //Directory? - jne 1f //yes - movl 0x18(%bx), %eax //lba - movw 0x24(%bx), %si //LengthofImplementationUse - movb 0x13(%bx), %cl //NameLength - orb %cl, %cl - je 1f - decb %cl - movb $0, (hd_utf16_tag - Entry_hd_udf) //utf8 - cmpb $8, 0x26(%bx, %si) //utf8? - je 2f //yes - orb $1, (hd_utf16_tag - Entry_hd_udf) //utf16 - shrb $1, %cl //NameLength/2 -2: - leaw 0x27(%bx, %si), %si //Name Address - cmpb $1, (hd_utf16_tag - Entry_hd_udf) //utf16? - jne 2f //no - incw %si -2: - movw $(hd_udf_name - Entry_hd_udf), %di //"GRLDR\0" -3: - cmpb $0, (%di) - je 2f - andb $0xdf, (%si) /* Changed to upper case */ - cmpsb - jne 1f - cmpb $1, (hd_utf16_tag - Entry_hd_udf) //utf16? - jne 3b //no - incw %si - jmp 3b -1: - //File not found - movzbw 0x13(%bx), %cx //NameLength - addw 0x24(%bx), %cx //+LengthofImplementationUse - addw %cx, %bx //+NameBaseAddress - addw $0x26, %bx - movw $5, %cx -1: - cmpw $0x101, (%bx) //UDF_FileIdentifier - je 5b //Continue - incw %bx - loop 1b - jmp 4f - -2: - //Found files - addl (hd_udf_partition_start - Entry_hd_udf), %eax //FileEntry - movw $0x1000, %bx /* buffer offset */ - call load_hd_udf - movw $0x2000, %di - call read_fileEntry - jc 4f - ljmp $0x2000, $0 - - -load_hd_udf: - /* input: EAX LBA - * output: ES:BX - */ - pushaw - movw %es, %di -1: - pushl %eax - movw $0xe00, %si - movw $0x10, (%si) /* Packet length */ - movw $1, 2(%si) /* number of sectors */ - movw %bx, 4(%si) /* buffer offset */ - movw %di, 6(%si) /* buffer segment */ - movl %eax, 8(%si) /* LBA lo 32 bits */ - movl $0, 12(%si) /* LBA hi 32 bits */ - movb $0x42, %ah - pushw %ds - pushw %es - int $0x13 - popw %es - popw %ds - popl %eax - decw %bp - je 1f - leaw 0x20(%di), %di - incl %eax - jmp 1b -1: - popaw - ret - -4: - movw $(msg_BootError_hd_udf - Entry_hd_udf), %si -1: - lodsb (%si), %al /* get token */ - cmpb $0, %al /* end of string? */ - je 1f - movb $0x0e, %ah /* print char in AL */ - int $0x10 /* via TTY mode */ - jmp 1b - -1: - jmp 1b - -//(105) or (10a) -read_fileEntry: - pushw %es - cmpw $0x105, (%bx) - jne 1f - //105 - movw 0xa8(%bx), %si - movw 0xac(%bx), %cx - pushw %dx - movw $0, %dx - jmp 2f -1: - //10a - movw 0x22(%bx), %ax - andw $7, %ax - cmpw $3, %ax - jne 1f - movw 0xd0(%bx), %si - addw $0x10d8, %si - movw $0x2000, %di - movw $0x80, %cx - rep movsd - jmp 4f -1: - cmpw $0, %ax - jne 3f - pushw %dx - movw 0xd0(%bx), %si - movw 0xd4(%bx), %cx - movw $0x28, %dx -2: - addw %dx, %si - shrw $3, %cx - popw %dx -1: - movzwl 0xb4(%bx, %si), %eax - addl (hd_udf_partition_start - Entry_hd_udf), %eax //FileIdentifier - - pushl %eax - movl 0xb0(%bx, %si), %eax //File length in bytes */ - andl $0x3fffffff, %eax - addl $0x1ff, %eax - shrl $9, %eax - movw %ax, %bp - popl %eax - pushw %bx - xorw %bx, %bx - movw %di, %es - call load_hd_udf - popw %bx - leaw 0x20(%di), %di - addw $8, %bx - loop 1b - clc - jmp 4f -3: - stc -4: - popw %es - ret - - . = Entry_hd_udf + 0x1f0 - -msg_BootError_hd_udf: - .ascii "No " - -hd_udf_name: - .ascii "GRLDR\0\0\0\0\0\0" - - . = Entry_hd_udf + 0x1fe - .byte 0x55, 0xaa -/* ******************** HD_UDF_bin end ****************************** */ -#endif //defined(GRLDR_INSTALL)) - - -pre_stage2_start: - diff --git a/stage2/gunzip.c b/stage2/gunzip.c index 8fb4f518..73715e5a 100644 --- a/stage2/gunzip.c +++ b/stage2/gunzip.c @@ -148,13 +148,13 @@ static unsigned long long gzip_data_offset; static unsigned long long gzip_filepos; static unsigned long long gzip_fsmax; static unsigned long long saved_filepos; -static unsigned long gzip_crc; +static unsigned int gzip_crc; /* internal extra variables for use of inflate code */ -static unsigned long block_type; -static unsigned long block_len; -static unsigned long last_block; -static unsigned long code_state; +static unsigned int block_type; +static unsigned int block_len; +static unsigned int last_block; +static unsigned int code_state; /* Function prototypes */ @@ -164,8 +164,8 @@ static void initialize_tables (void); * Linear allocator. */ -static unsigned long linalloc_topaddr; - +static unsigned int linalloc_topaddr; +unsigned char * linalloc_buf; //static void * //linalloc (unsigned long size) //{ @@ -176,11 +176,13 @@ static unsigned long linalloc_topaddr; static void reset_linalloc (void) { - linalloc_topaddr = RAW_ADDR ((saved_mem_upper << 10) + 0x100000); +// linalloc_topaddr = RAW_ADDR ((saved_mem_upper << 10) + 0x100000); + linalloc_topaddr = (grub_size_t)linalloc_buf + 0x100000; } /* internal variable swap function */ +static void gunzip_swap_values (void); static void gunzip_swap_values (void) { @@ -204,24 +206,25 @@ gunzip_swap_values (void) /* internal function for eating variable-length header fields */ -static unsigned long -bad_field (unsigned long len) +static unsigned int bad_field (unsigned int len); +static unsigned int +bad_field (unsigned int len) { char ch = 1; - unsigned long not_retval = 1; + unsigned int not_retval = 1; do { if (len == 0) break; - if (len == -1) + if (len == (unsigned int)-1) { if (ch == 0) break; } else len--; - not_retval = grub_read ((unsigned long long)(unsigned int)&ch, 1, 0xedde0d90); + not_retval = grub_read ((unsigned long long)(grub_size_t)&ch, 1, 0xedde0d90); } while (not_retval); @@ -270,21 +273,22 @@ bad_field (unsigned long len) #define WSIZE 0x8000UL - +int gunzip_test_header (void); int gunzip_test_header (void) { - unsigned char buf[10]; - +// unsigned char buf[10]; + unsigned char *buf; + buf = dec_header; /* check lz4 */ if (dec_lz4_open ()) goto test_dec; /* check lzma */ if (dec_lzma_open ()) goto test_dec; + errnum = 0; if (dec_vhd_open()) goto test_dec; - /* "compressed_file" is already reset to zero by this point */ /* @@ -292,9 +296,9 @@ gunzip_test_header (void) * (other than a real error with the disk) then we don't think it * is a compressed file, and simply mark it as such. */ - gzip_filemax = filemax; + gzip_filemax = filemax; //返回压缩文件尺寸 if (no_decompression - || grub_read ((unsigned long long)(unsigned int)(char *)buf, 10, 0xedde0d90) != 10 +// || grub_read ((unsigned long long)(grub_size_t)(char *)buf, 10, 0xedde0d90) != 10 || ((*((unsigned short *) buf) != GZIP_HDR_LE) && (*((unsigned short *) buf) != OLD_GZIP_HDR_LE))) { @@ -307,34 +311,36 @@ gunzip_test_header (void) * problem occurs from here on, then we have corrupt or otherwise * bad data, and the error should be reported to the user. */ + + filepos = 10; if (buf[2] != DEFLATED || (buf[3] & UNSUPP_FLAGS) || ((buf[3] & EXTRA_FIELD) - && (grub_read ((unsigned long long)(unsigned int)(char *)buf, 2, 0xedde0d90) != 2 + && (grub_read ((unsigned long long)(grub_size_t)(char *)buf, 2, 0xedde0d90) != 2 || bad_field (*((unsigned short *) buf)))) || ((buf[3] & ORIG_NAME) && bad_field (-1)) || ((buf[3] & COMMENT) && bad_field (-1))) { if (! errnum) errnum = ERR_BAD_GZIP_HEADER; - return 0; } gzip_data_offset = filepos; - filepos = filemax - 8; - if (grub_read ((unsigned long long)(unsigned int)(char *)buf, 8, 0xedde0d90) != 8) + if (grub_read ((unsigned long long)(grub_size_t)(char *)buf, 8, 0xedde0d90) != 8) { if (! errnum) errnum = ERR_BAD_GZIP_HEADER; - return 0; } - gzip_crc = *((unsigned long *) buf); - gzip_fsmax = gzip_filemax = *((unsigned long *) (buf + 4)); + gzip_crc = *((unsigned int *) buf); + gzip_fsmax = gzip_filemax = *((unsigned int *) (buf + 4)); + + if (!linalloc_buf) + linalloc_buf = grub_malloc (0x100000); initialize_tables (); @@ -344,11 +350,10 @@ gunzip_test_header (void) /* * Now "gzip_*" values refer to the compressed data. */ - filepos = 0; test_dec: - if (grub_read((unsigned long long)(unsigned int)(char *)buf, 1,GRUB_READ) != 1LL) + if (grub_read((unsigned long long)(grub_size_t)(char *)buf, 1,GRUB_READ) != 1LL) { if (debug) printf("\nWarning:%s Compressed data detected but failed to decompress - using raw data!\n",decomp_table[decomp_type].name); @@ -360,9 +365,12 @@ gunzip_test_header (void) return 1; } +void gunzip_close (void); void gunzip_close (void) { + grub_free(linalloc_buf); + linalloc_buf = 0; } @@ -400,7 +408,7 @@ struct huft static unsigned char slide[WSIZE]; /* current position in slide */ -static unsigned long wp; +static unsigned int wp; /* Tables for deflate from PKZIP's appnote.txt. */ @@ -461,8 +469,8 @@ static unsigned short cpdext[] = */ -static unsigned long lbits = 9; /* bits in base literal/length lookup table */ -static unsigned long dbits = 6; /* bits in base distance lookup table */ +static unsigned int lbits = 9; /* bits in base literal/length lookup table */ +static unsigned int dbits = 6; /* bits in base distance lookup table */ /* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ @@ -470,7 +478,7 @@ static unsigned long dbits = 6; /* bits in base distance lookup table */ #define N_MAX 288 /* maximum number of codes in any set */ -static unsigned long hufts; /* track memory usage */ +static unsigned int hufts; /* track memory usage */ /* Macros for inflate() bit peeking and grabbing. @@ -503,8 +511,8 @@ static unsigned long hufts; /* track memory usage */ the stream. */ -static unsigned long bb; /* bit buffer */ -static unsigned long bk; /* bits in bit buffer */ +static unsigned int bb; /* bit buffer */ +static unsigned int bk; /* bits in bit buffer */ static unsigned short mask_bits[] = { @@ -519,15 +527,16 @@ static unsigned short mask_bits[] = #define INBUFSIZ 0x2000 static unsigned char inbuf[INBUFSIZ]; -static unsigned long bufloc = 0; +static unsigned int bufloc = 0; -static unsigned long +static unsigned int get_byte (void); +static unsigned int get_byte (void) { if (filepos == gzip_data_offset || bufloc == INBUFSIZ) { bufloc = 0; - grub_read ((unsigned long long)(unsigned int)(char *)inbuf, INBUFSIZ, 0xedde0d90); + grub_read ((unsigned long long)(grub_size_t)(char *)inbuf, INBUFSIZ, 0xedde0d90); } return inbuf[bufloc++]; @@ -536,19 +545,19 @@ get_byte (void) /* decompression global pointers */ static struct huft *tl; /* literal/length code table */ static struct huft *td; /* distance code table */ -static unsigned long bl; /* lookup bits for tl */ -static unsigned long bd; /* lookup bits for td */ +static unsigned int bl; /* lookup bits for tl */ +static unsigned int bd; /* lookup bits for td */ -static unsigned long c[BMAX + 1]; /* bit length count table */ +static unsigned int c[BMAX + 1]; /* bit length count table */ static struct huft *u[BMAX]; /* table stack */ -static unsigned long v[N_MAX]; /* values in order of bit length */ -static unsigned long x[BMAX + 1]; /* bit offsets, then code stack */ -static unsigned long lh[288]; /* length list for huft_build */ -static unsigned long ll[286 + 30]; /* literal/length and distance code lengths */ +static unsigned int v[N_MAX]; /* values in order of bit length */ +static unsigned int x[BMAX + 1]; /* bit offsets, then code stack */ +static unsigned int lh[288]; /* length list for huft_build */ +static unsigned int ll[286 + 30]; /* literal/length and distance code lengths */ /* more function prototypes */ -static unsigned long huft_build (unsigned long *, unsigned long, unsigned long, unsigned short *, unsigned short *, - struct huft **, unsigned long *); +static unsigned int huft_build (unsigned int *, unsigned int, unsigned int, unsigned short *, unsigned short *, + struct huft **, unsigned int *); static int inflate_codes_in_window (void); @@ -557,35 +566,36 @@ static int inflate_codes_in_window (void); the given code set is incomplete (the tables are still built in this case), two if the input is invalid (all zero length codes or an oversubscribed set of lengths), and three if not enough memory. */ - -static unsigned long -huft_build (unsigned long *b, /* code lengths in bits (all assumed <= BMAX) */ - unsigned long n, /* number of codes (assumed <= N_MAX) */ - unsigned long s, /* number of simple-valued codes (0..s-1) */ +static unsigned int huft_build (unsigned int *b, unsigned int n, unsigned int s, unsigned short * d, + unsigned short * e, struct huft **t, unsigned int *m); +static unsigned int +huft_build (unsigned int *b, /* code lengths in bits (all assumed <= BMAX) */ + unsigned int n, /* number of codes (assumed <= N_MAX) */ + unsigned int s, /* number of simple-valued codes (0..s-1) */ unsigned short * d, /* list of base values for non-simple codes */ unsigned short * e, /* list of extra bits for non-simple codes */ struct huft **t, /* result: starting table */ - unsigned long *m) /* maximum lookup bits, returns actual */ + unsigned int *m) /* maximum lookup bits, returns actual */ { - unsigned long a; /* counter for codes of length k */ -//unsigned long c[BMAX + 1]; /* bit length count table */ - unsigned long f; /* i repeats in table every f entries */ + unsigned int a; /* counter for codes of length k */ +//unsigned int c[BMAX + 1]; /* bit length count table */ + unsigned int f; /* i repeats in table every f entries */ int g; /* maximum code length */ int h; /* table level */ - register unsigned long i; /* counter, current code */ - register unsigned long j; /* counter */ + register unsigned int i; /* counter, current code */ + register unsigned int j; /* counter */ register int k; /* number of bits in current code */ - unsigned long l; /* bits per table (returned in m) */ - register unsigned long *p; /* pointer into c[], b[], or v[] */ + unsigned int l; /* bits per table (returned in m) */ + register unsigned int *p; /* pointer into c[], b[], or v[] */ register struct huft *q; /* points to current table */ struct huft r; /* table entry for structure assignment */ //struct huft *u[BMAX]; /* table stack */ -//unsigned long v[N_MAX]; /* values in order of bit length */ +//unsigned int v[N_MAX]; /* values in order of bit length */ register int w; /* bits before this table == (l * h) */ //unsigned long x[BMAX + 1]; /* bit offsets, then code stack */ - unsigned long *xp; /* pointer into x */ + unsigned int *xp; /* pointer into x */ int y; /* number of dummy codes added */ - unsigned long z; /* number of entries in current table */ + unsigned int z; /* number of entries in current table */ /* Generate counts for each bit length */ memset ((char *) c, 0, sizeof (c)); @@ -664,7 +674,7 @@ huft_build (unsigned long *b, /* code lengths in bits (all assumed <= BMAX) */ { /* here i is the Huffman code of length k bits for value *p */ /* make tables up to required level */ - while (k > w + l) + while (k > w + (int)l) { h++; w += l; /* previous table always l bits */ @@ -687,7 +697,7 @@ huft_build (unsigned long *b, /* code lengths in bits (all assumed <= BMAX) */ /* allocate and link in new table */ linalloc_topaddr -= (z + 1) * sizeof (struct huft); linalloc_topaddr &= ~3; - q = (struct huft *) linalloc_topaddr; + q = (struct huft *)(grub_size_t) linalloc_topaddr; hufts += z + 1; /* track memory usage */ *t = q + 1; /* link to list for huft_free() */ @@ -751,18 +761,19 @@ huft_build (unsigned long *b, /* code lengths in bits (all assumed <= BMAX) */ * Return an error code or zero if it all goes ok. */ -static unsigned long inflate_n, inflate_d; +static unsigned int inflate_n, inflate_d; +static int inflate_codes_in_window (void); static int inflate_codes_in_window (void) { - register unsigned long e; /* table entry flag/number of extra bits */ - unsigned long n, d; /* length and index for copy */ - unsigned long w; /* current window position */ + register unsigned int e; /* table entry flag/number of extra bits */ + unsigned int n, d; /* length and index for copy */ + unsigned int w; /* current window position */ struct huft *t; /* pointer to table entry */ - unsigned long ml, md; /* masks for bl and bd bits */ - register unsigned long b; /* bit buffer */ - register unsigned long k; /* number of bits in bit buffer */ + unsigned int ml, md; /* masks for bl and bd bits */ + register unsigned int b; /* bit buffer */ + register unsigned int k; /* number of bits in bit buffer */ /* make local copies of globals */ d = inflate_d; @@ -884,12 +895,12 @@ inflate_codes_in_window (void) /* get header for an inflated type 0 (stored) block. */ - +static void init_stored_block (void); static void init_stored_block (void) { - register unsigned long b; /* bit buffer */ - register unsigned long k; /* number of bits in bit buffer */ + register unsigned int b; /* bit buffer */ + register unsigned int k; /* number of bits in bit buffer */ /* make local copies of globals */ b = bb; /* initialize bit buffer */ @@ -916,12 +927,12 @@ init_stored_block (void) /* get header for an inflated type 1 (fixed Huffman codes) block. We should either replace this with a custom decoder, or at least precompute the Huffman tables. */ - +static void init_fixed_block (); static void init_fixed_block () { - unsigned long i; /* temporary variable */ -//unsigned long lh[288]; /* length list for huft_build */ + unsigned int i; /* temporary variable */ +//unsigned int lh[288]; /* length list for huft_build */ /* set up literal table */ for (i = 0; i < 144; i++) @@ -956,21 +967,21 @@ init_fixed_block () /* get header for an inflated type 2 (dynamic Huffman codes) block. */ - +static void init_dynamic_block (void); static void init_dynamic_block (void) { - unsigned long i; /* temporary variables */ - unsigned long j; - unsigned long l; /* last length */ - unsigned long m; /* mask for bit lengths table */ - unsigned long n; /* number of lengths to get */ - unsigned long nb; /* number of bit length codes */ - unsigned long na; /* number of literal/length codes */ - unsigned long nd; /* number of distance codes */ -//unsigned long ll[286 + 30]; /* literal/length and distance code lengths */ - register unsigned long b; /* bit buffer */ - register unsigned long k; /* number of bits in bit buffer */ + unsigned int i; /* temporary variables */ + unsigned int j; + unsigned int l; /* last length */ + unsigned int m; /* mask for bit lengths table */ + unsigned int n; /* number of lengths to get */ + unsigned int nb; /* number of bit length codes */ + unsigned int na; /* number of literal/length codes */ + unsigned int nd; /* number of distance codes */ +//unsigned int ll[286 + 30]; /* literal/length and distance code lengths */ + register unsigned int b; /* bit buffer */ + register unsigned int k; /* number of bits in bit buffer */ /* make local bit buffer */ b = bb; @@ -1092,12 +1103,12 @@ init_dynamic_block (void) block_len++; } - +static void get_new_block (void); static void get_new_block (void) { - register unsigned long b; /* bit buffer */ - register unsigned long k; /* number of bits in bit buffer */ + register unsigned int b; /* bit buffer */ + register unsigned int k; /* number of bits in bit buffer */ hufts = 0; @@ -1127,7 +1138,7 @@ get_new_block (void) init_dynamic_block (); } - +static void inflate_window (void); static void inflate_window (void) { @@ -1159,7 +1170,7 @@ inflate_window (void) */ if (block_type == INFLATE_STORED) { - unsigned long w = wp; + unsigned int w = wp; /* * This is basically a glorified pass-through @@ -1189,7 +1200,7 @@ inflate_window (void) /* XXX do CRC calculation here! */ } - +static void initialize_tables (void); static void initialize_tables (void) { @@ -1209,9 +1220,9 @@ initialize_tables (void) reset_linalloc (); } - +unsigned long long gunzip_read (unsigned long long buf, unsigned long long len, unsigned int write); unsigned long long -gunzip_read (unsigned long long buf, unsigned long long len, unsigned long write) +gunzip_read (unsigned long long buf, unsigned long long len, unsigned int write) { unsigned long long ret = 0; @@ -1246,7 +1257,7 @@ gunzip_read (unsigned long long buf, unsigned long long len, unsigned long write if (buf) { - grub_memmove64 (buf, (unsigned long long)(unsigned int)srcaddr, size); + grub_memmove64 (buf, (unsigned long long)(grub_size_t)srcaddr, size); buf += size; } len -= size; diff --git a/stage2/hercules.c b/stage2/hercules.c deleted file mode 100644 index 20d48435..00000000 --- a/stage2/hercules.c +++ /dev/null @@ -1,142 +0,0 @@ -/* hercules.c - hercules console interface */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2001,2002 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifdef SUPPORT_HERCULES - -#include -#include -#include - -/* Write a byte to a port. */ -static inline void -outb (unsigned short port, unsigned char value) -{ - asm volatile ("outb %b0, %w1" : : "a" (value), "Nd" (port)); -} - -static void -herc_set_cursor (void) -{ - unsigned offset = fonty * HERCULES_WIDTH + fontx; - - outb (HERCULES_INDEX_REG, 0x0f); - outb (0x80, 0); - outb (HERCULES_DATA_REG, offset & 0xFF); - outb (0x80, 0); - - outb (HERCULES_INDEX_REG, 0x0e); - outb (0x80, 0); - outb (HERCULES_DATA_REG, offset >> 8); - outb (0x80, 0); -} - -unsigned int -hercules_putchar (unsigned int c, unsigned int max_width) -{ - switch (c) - { - case '\b': - if (fontx > 0) - fontx--; - break; - - case '\n': - fonty++; - break; - - case '\r': - fontx = 0; - break; - - case '\a': - break; - - default: - { - volatile unsigned short *video - = (unsigned short *) HERCULES_VIDEO_ADDR; - - video[fonty * HERCULES_WIDTH + fontx] = (current_color << 8) | c; - fontx++; - if (fontx >= HERCULES_WIDTH) - { - fontx = 0; - fonty++; - } - } - break; - } - - if (fonty >= HERCULES_HEIGHT) - { - volatile unsigned long *video = (unsigned long *) HERCULES_VIDEO_ADDR; - int i; - - fonty = HERCULES_HEIGHT - 1; - grub_memmove ((char *) HERCULES_VIDEO_ADDR, - (char *) HERCULES_VIDEO_ADDR + HERCULES_WIDTH * 2, - HERCULES_WIDTH * (HERCULES_HEIGHT - 1) * 2); - for (i = HERCULES_WIDTH * (HERCULES_HEIGHT - 1) / 2; - i < HERCULES_WIDTH * HERCULES_HEIGHT / 2; - i++) - video[i] = 0x07200720; - } - return 1; -} - -void -hercules_cls (void) -{ - int i; - volatile unsigned long *video = (unsigned long *) HERCULES_VIDEO_ADDR; - - for (i = 0; i < HERCULES_WIDTH * HERCULES_HEIGHT / 2; i++) - video[i] = 0x07200720; - - fontx = fonty = 0; - herc_set_cursor (); -} - -int -hercules_getxy (void) -{ - return (fonty << 8) | fontx; -} - -void -hercules_gotoxy (int x, int y) -{ - fontx = x; - fonty = y; - herc_set_cursor (); -} - -void -hercules_setcursor (unsigned long on) -{ - outb (HERCULES_INDEX_REG, 0x0a); - outb (0x80, 0); - outb (HERCULES_DATA_REG, on ? 0 : (1 << 5)); - outb (0x80, 0); - - return; -} - -#endif /* SUPPORT_HERCULES */ diff --git a/stage2/hercules.h b/stage2/hercules.h deleted file mode 100644 index aaf794fa..00000000 --- a/stage2/hercules.h +++ /dev/null @@ -1,31 +0,0 @@ -/* hercules.h - hercules console interface */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2001 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef GRUB_HERCULES_HEADER -#define GRUB_HERCULES_HEADER 1 - -/* Macros. */ -#define HERCULES_VIDEO_ADDR RAW_ADDR (0xB0000) -#define HERCULES_WIDTH 80 -#define HERCULES_HEIGHT 25 -#define HERCULES_INDEX_REG 0x3b4 -#define HERCULES_DATA_REG 0x3b5 - -#endif /* ! GRUB_HERCULES_HEADER */ diff --git a/stage2/hmloadstart.S b/stage2/hmloadstart.S deleted file mode 100644 index 3be94940..00000000 --- a/stage2/hmloadstart.S +++ /dev/null @@ -1,755 +0,0 @@ -/* - * hmloadstart.S -- A DOS utility for loading a file into high memory. - * Copyright (C) 2006,2007 Tinybit(tinybit@tom.com) - * Copyright (C) 2006,2007 John Cobb (Queen Mary, University of London) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - The original source code was written by John Cobb and can be found at: - http://sysdocs.stu.qmul.ac.uk/sysdocs/Comment/GrubForDOS/code/xmsel.asm - - Transformed to AT&T syntax by Tinybit . - - The original copyright notice can be found at: - http://sysdocs.stu.qmul.ac.uk/sysdocs/Comment/GrubForDOS/code/warranty - -and here is an exact copy of the "warranty" file in August 16, 2007: - -The material is available under the usual free software rules. - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - - -/* - * This program is used to generate the hmload.com file. - * - * Use the following shell command to generate the file: - * - * cp hmloadstart hmload.com - * - */ - -/* John Cobb's Note: - * It takes two parameters -f filename -a address - * Address is in megabytes. It assumes that himem.sys - * or equivalent XMS provider is running. - */ - -/* Use the following command to compile and build: - * - * gcc -o hmloadstart.exec -nostdlib -I. -I.. -I../stage1 -Wl,-N -Wl,-s hmloadstart.S - * - */ - -#define ABS(x) (x - _start + 0x100) - -#define xmsh (bss_begin_address + 0) -#define xmsa (bss_begin_address + 256) -#define xmsl (bss_begin_address + 256 + 512) -#define buffer (bss_begin_address + 256 + 512 + 128) -#define thestack (bss_begin_address + 256 + 512 + 128 + 4096) -#define lastword (bss_begin_address + 256 + 512 + 128 + 4096 + 4096) -#define xmsh (bss_begin_address + 0) -#define xmsh (bss_begin_address + 0) -#define xmsh (bss_begin_address + 0) - - .text - .globl _start - -_start: - - /* this is real mode dos code */ - - .code16 - -# this code loads a file at a given address using the 32 bit XMS extensions. -# it makes a pretty wild assumption which is that if it -# asks for the biggest XMS memory block that block will contain the -# the address required. (on all machines I tried I got back two -# blocks, one small one and one large one. -# Obviously more sophisticated code could work round the possibility -# that you space you need straddles more than one block. -# The other assumption is that the data once loaded will stay at the -# same address, which of course it need not. A solution to that might be -# to exit terminate and stay loaded so as to hold onto the resources - -//org 100h -//section .text -//start: - - # first cut program size down to that desired - # (.com prgrams get all of memory to start) - - movw %cs, %ax - movw %ax, %es # set ES to CS - movw $ABS(lastword), %bx # desired end of program - movw %bx, %sp # set stack pointer - addw $15, %bx # round to nearest page (ok so long as not too big!) - shrw $4, %bx # pages - movb $0x4A, %ah - int $0x21 # cut program down to size - - xorw %ax, %ax - movw %ax, ABS(hand) # not ensure handle zero - movw %ax, ABS(file) - movw %ax, ABS(addr) - movw $1, ABS(xmsa20init) - movw $ABS(hallo), %dx - call chars # initial part of message about parameters - - xorw %cx, %cx - cld - movb 0x80, %cl - movw $0x81, %si - movw $ABS(buffer), %di - repz movsb # copy the parameter block to a convenient place - movb $'$', (%di) - movw $ABS(buffer), %dx - call msg # echo the parameters - movb 0x80, %al - movw $ABS(errparam), %dx - testb %al, %al - jnz startparams -paramerr: - call msg - movw $ABS(use), %dx - call msg - movw $ABS(func), %dx - call msg - jmp exiterr -nohyphen: - movw $ABS(needhyphen), %dx - jmp paramerr -noparamletter: - movw $ABS(misparam), %dx -notparam: - movb %ah, ABS(notknown) - movw $ABS(notknown), %dx - jmp paramerr -novalue: - movb %ah, ABS(misvalue+11) - movw $ABS(misvalue), %dx - jmp paramerr -nofile: - movw $ABS(misfile), %dx - jmp paramerr -noaddr: - movw $ABS(misaddr), %dx - jmp paramerr -startparams: - xorw %cx, %cx - movb 0x80, %cl # count in cx - movw $0x81, %di # point to start of buffer - cld -parameters: - movb $' ', %al - repe scasb # skip spaces nb pointer and count are left after - jcxz endparams # the character that causes the termination! - movb -1(%di), %ah # pick up the character that caused termination - cmpb $'-', %ah - jne nohyphen - jcxz noparamletter - movb (%di), %ah # the parameter identifier - incw %di - decw %cx - jcxz novalue - movb $' ', %al # skip spaces after the identifier - repe scasb - incw %cx - decw %di - orb $0x20, %ah # case insensitive - cmpb $'f', %ah - je .isfile - cmpb $'a', %ah - je .isaddr - jmp notparam -.isfile: - movw %di, ABS(file) - jmp .nextp -.isaddr: - movw %di, ABS(addr) -.nextp: - movb $' ', %al # look for space - repne scasb - cmpb $' ', -1(%di) # did we actually find a space? - jne .lastp # if not must have been last and terminated by count - movb $0, -1(%di) - jcxz endparams - jmp parameters -.lastp: - movb $0, (%di) -# check we got everything -endparams: - movw ABS(addr), %cx - jcxz noaddr - movw ABS(file), %cx - jcxz nofile - xorl %eax, %eax - movl $10, %ecx - movw ABS(addr), %si # address of addressvalue - xorl %ebx, %ebx -.dec1: - movb (%si), %bl - subb $'0', %bl - jl .dec2 - cmpb $10, %bl - jge .dec2 - mull %ecx - addl %ebx, %eax - incw %si - jmp .dec1 -.dec2: - shll $20, %eax #; shift to megabytes - movl %eax, ABS(address) - movw ABS(file), %dx - xorw %cx, %cx - movw $0x3d00, %ax #; open the file - int $0x21 - jnc opened - movw $ABS(erropen), %dx - movw ABS(file), %si - jmp errstr -opened: - movw %ax, ABS(hand) - movw $ABS(act1), %dx - call chars - movw ABS(file), %di - movb $0, %al - movw $256, %cx - repne scasb - movb $'$', (%di) - movw ABS(file), %dx - call chars - movw $ABS(act2), %dx - call chars - movw $ABS(address+3), %si - call hexl - call eol -# see if we have xms available - movw $0, ABS(xmsfull) - movw $0x4300, %ax - int $0x2F - cmpb $0x80, %al - je .xmsok - movw $ABS(noxmsmsg), %dx - call msg - jmp exiterr -.xmsok: - movw $0x4310, %ax - pushw %es - pushw %ds - int $0x2F - popw %ds - movw %es, ABS(xmsptr+2) - movw %bx, ABS(xmsptr) - popw %es - movw $ABS(xmsProc), %dx - call chars - movw $ABS(xmsptr+3), %si - call hexl - call eol -# xms version etc - movb $0, %ah - call xms - movw %ax, ABS(num) - movw %bx, ABS(num+2) - pushw %dx - movw $ABS(xmsver), %dx - call chars - movw $ABS(num+1), %si - call hexw - movw $ABS(xmsrev), %dx - call chars - movw $ABS(num+3), %si - call hexw - popw %cx # value that was in dx after the xms call - movw $ABS(xmsHMAno), %dx - jcxz .next - movw $ABS(xmsHMAyes), %dx -.next: - call msg - call checka20 # check status of the a20 line - jnc .ok - jmp exiterr -.ok: - movw %ax, ABS(xmsa20init) # save initial status of line -# a20 not needed in this version -# call xmsenable # locally enable a20 -# jnc .gota20 -# jmp xmserr -#.gota20: -# -# aquire xms memory blocks -# i am going to assume that most of xms is available as one large block -# and that will encompass the desired adress obviously I should do a sanity -# check but for now lets just stick straws in the hair -# extended xms spec found at -# http://freedos.sourceforge.net/freedos/news/press/1991-xms30.html -# aquire all full sized xms memory blocks available - movw $0, ABS(nxmsh) # zero count -.getxms: - movb $0x88, %ah - call xms # query largest xms block size - testb %bl, %bl - jz .gotms # success if BL zero - movw $ABS(xmsnomem), %dx - call msg - jmp .donemem -.gotms: - movl %eax, ABS(num) # save block size - movw $ABS(xmslargest), %dx - call chars - movw $ABS(num+3), %si - call hexl - movw $ABS(inkbmsg), %dx - call chars -# movw ABS(num), %dx -# xorw ABS(fullxmsblock), %dx -# jnz .donemem - movl ABS(num), %edx - movb $0x89, %ah - call xms # grab the block - testw %ax, %ax - jz .donemem - movw ABS(nxmsh), %si # current handle index - movb $0, ABS(xmsl)(%si) # zero the lock indicator - shlw $1, %si - movw %dx, ABS(xmsh)(%si) # store handle - pushw %dx - movw $ABS(xmsgotblock), %dx - call chars - popw %dx - movb $0x0C, %ah - call xms - testw %ax, %ax - jz .incind - movw ABS(nxmsh), %si # current handle index - movb $1, ABS(xmsl)(%si) # set the lock indicator - shlw $2, %si - movw %bx, ABS(xmsa)(%si) - movw %dx, ABS(xmsa+2)(%si) - pushw %si - movw $ABS(xmslockedblock), %dx - call chars - popw %si - addw $ABS(xmsa+3), %si - call hexl -# movw $4, %cx -# call hexstr -.incind: - call eol - movw ABS(nxmsh), %si # current handle index - incw %si - movw %si, ABS(nxmsh) - jmp .getxms -.donemem: - call eol - movw $ABS(xmsblocksgot), %dx - call chars - movw $ABS(nxmsh+1), %si - call hexw - call eol - -# start the load - movl ABS(address), %eax - subl ABS(xmsa), %eax # make relative to the first xms segment -copyin: - pushl %eax - movb $0x3f, %ah #; read file - movw ABS(hand), %bx - movw $4096, %cx - movw $ABS(buffer), %dx - int $0x21 - jc eof - testw %ax, %ax - jz eof - movw $ABS(buffer), %bx - -# setup the xms move structure - movzwl %ax, %eax - movl %eax, ABS(xmsmvlen) - movw $0, ABS(xmsmvshand) - movw %bx, ABS(xmsmvsoff) - movw %ds, ABS(xmsmvsseg) - popl %eax - movl %eax, ABS(xmsmvdoff) - addl ABS(xmsmvlen), %eax - movw ABS(xmsh), %dx - movw %dx, ABS(xmsmvdhand) - movw $ABS(xmsmove), %si - pushl %eax - movb $0x0B, %ah - call xms - popl %eax - jmp copyin -eof: - popl %eax - movw $ABS(done), %dx - call msg -# for now release the xms again -# nb this is questionable as we don't want it to move but... -.relxms: - movw ABS(nxmsh), %si # index of last handle - testw %si, %si - jz .xmsfreed - decw %si - movw %si, ABS(nxmsh) # decrement for next time - movb ABS(xmsl)(%si), %ah # check lock status - testb %ah, %ah - jz .nolock - shlw $1, %si - movw ABS(xmsh)(%si), %dx - movb $0x0D, %ah - call xms # unlock block -.nolock: - movw ABS(nxmsh), %si # index of last handle - shlw $1, %si - movw ABS(xmsh)(%si), %dx - movb $0x0A, %ah - call xms # free block - jmp .relxms -.xmsfreed: - movw ABS(xmsa20init), %ax - testw %ax, %ax - jnz .wason -# call xmsdisable # locally disable xms -# jnc .losta20 -# jmp exiterr -#.losta20: -.wason: # or possibly we never got it in the first place - movw ABS(hand), %bx - movb $0x3E, %ah # close file - int $0x21 - movw $0x4C00, %ax # return success - int $0x21 -exit: - movw $0x4C00, %ax # exit with 0 result code - int $0x21 -errstr: - pushw %si - call chars - popw %si - movw $256, %cx - movw $ABS(buffer), %di - cld -.str1: - lodsb - testb %al, %al - jz .str2 - stosb - loop .str1 -.str2: - movb $'$', (%di) - movw $ABS(buffer), %dx -err: - call msg -exiterr: - movw ABS(hand), %bx - testw %bx, %bx - jz .nofile - movb $0x3e, %ah # close file - int $0x21 -.nofile: - movw $0x4c01, %ax # return failure - int $0x21 -msg: - movb $0x09, %ah - int $0x21 -eol: - movw $ABS(eolmsg), %dx - movb $0x09, %ah - int $0x21 - ret -chars: - movb $0x09, %ah - int $0x21 - ret -hexstr: - cld - jmp hexout -hexl: - movw $4, %cx - jmp hexnum -hexw: - movw $2, %cx - jmp hexnum -hexb: - movw $1, %cx -hexnum: - std -hexout: - # expect si pointing at string or at most sig byte of num - movw $ABS(hex), %bx - lodsb - movb %al, %ah - shrb $4, %al - # andb $0x0F, %al - xlat - movb %al, ABS(tbuff+1) - pushw %cx - pushw %si - movw $ABS(tbuff), %dx - movb $0x09, %ah - int $0x21 - popw %si - popw %cx - loop hexout - ret - -checka20: - # check status of a20 line - movb $7, %ah - call xms - testb %bl, %bl - jnz .noa20 - movw $ABS(xmsa20off), %dx - pushw %ax - testw %ax, %ax - jz .next1 - movw $ABS(xmsa20on), %dx -.next1: - call msg - movb $0, %bl - popw %ax - clc - ret -.noa20: - pushw %bx - movw $ABS(xmsnoa20), %dx - call chars - popw %bx - pushw %bx - call xmserr - popw %bx - stc - ret - -xmserr: - movb %bl, ABS(num) - movw $ABS(xmserrcode), %dx - call chars - movw $ABS(num), %si - call hexb - call eol - ret -xms: - pushw %ds - lcall *ABS(xmsptr) - popw %ds - ret - -xmsenable: - movb $5, %ah - call xms - testw %ax, %ax - jnz .gota - movw $ABS(xmslocenfai), %dx - pushw %bx - call chars - popw %bx - call xmserr - stc - ret -.gota: - movw $ABS(xmslocenable), %dx - call msg - call checka20 - clc - ret - -xmsdisable: - movb $6, %ah - call xms - testw %ax, %ax - jnz .losta - movw $ABS(xmslocdisfai), %dx - pushw %bx - call chars - popw %bx - call xmserr - stc - ret -.losta: - movw $ABS(xmslocdisable), %dx - call msg - clc - ret - -//section .data - -hallo: - .ascii "Parameters: $" -//; file: db 'C:\temp\mdump',0 -erropen: - .ascii "Could not open file: $" -errparam: - .ascii "No Parameters!$" -use: - .ascii " Use: -f filename -a address (in megabytes)$" -func: - .ascii "Loads file to address$" -needhyphen: - .ascii " parameters must start with -$" -notknown: - .ascii "x is not a recognised parameter$" -misparam: - .ascii "Parameter type missing after -$" -misvalue: - .ascii "Parameter -x has no value!$" -misfile: - .ascii "-f (filename) parameter missing$" -misaddr: - .ascii "Address parameter missing$" -act1: - .ascii "Loading file: $" -act2: - .ascii " to 0x$" -done: - .ascii "file loaded$" - - .align 2 -file: - .word 0 -addr: - .word 0 -hand: - .word 0 -eolmsg: - .ascii "\r\n$" -inkbmsg: - .ascii " KB,$" -xmsnomem: - .ascii "No free XMS memory$" -xmslargest: - .ascii "Largest XMS block 0x$" -xmsgotblock: - .ascii " aquired,$" -xmslockedblock: - .ascii " locked at 0x$" -xmsblocksgot: - .ascii "number of full sized XMS blocks 0x$" -noxmsmsg: - .ascii "XMS interface not available$" -xmsnohmsg: - .ascii "XMS get handle failed$" -xmsfree: - .ascii "Free XMS$" -xmslarge: - .ascii "largest XMS$" -xmsstat: - .ascii "XMS Status$" -xmsnoa20: - .ascii "couldn't read a20 state$" -xmserrcode: - .ascii " err=0x$" -xmsa20off: - .ascii "A20 line off$" -xmsa20on: - .ascii "A20 line on$" -xmsver: - .ascii "XMS Version 0x$" -xmsrev: - .ascii " XMS Revision 0x$" -xmsHMAyes: - .ascii " HMA Exists$" -xmsHMAno: - .ascii " No HMA$" -xmsProc: - .ascii "XMS procedure address 0x$" -hex: - .ascii "0123456789ABCDEF" # String of hex numbers -tbuff: - .ascii "xx$" - - .align 2 -xmsa20init: - .word 0 -xmslocenfai: - .ascii "Failed local enable of A20$" -xmslocdisfai: - .ascii "Failed local disable of A20$" -xmslocenable: - .ascii "A 20 locally enabled$" -xmslocdisable: - .ascii "A 20 locally disabled$" -dump: - .byte 0,1,2,3 - - -//section .bss - - .align 4 -num: - .byte 0,0,0,0 -xmsptr: - .word 0,0 -xmsnext: - .word 0 -xmsfull: - .word 0 -address: - .long 0 - -xmsmove: # structure -xmsmvlen: - .long 0 -xmsmvshand: - .word 0 -xmsmvsoff: # note if shand non zero then 32 bit ofsset and no seg - .word 0 -xmsmvsseg: - .word 0 -xmsmvdhand: - .word 0 -xmsmvdoff: - .word 0 -xmsmvdseg: - .word 0 -# end of xms move structure - -nxmsh: - .word 0 - - - .align 16 -bss_begin_address: - -/* -xmsh: - .space 256 -xmsa: - .space 512 -xmsl: - .space 128 -buffer: - .space 4096 -thestack: - .space 4096 -lastword: - .word 0 -*/ - diff --git a/stage2/iamath.h b/stage2/iamath.h index 01d1cd55..e47e9f6a 100644 --- a/stage2/iamath.h +++ b/stage2/iamath.h @@ -26,7 +26,7 @@ #ifndef IAMATH_NO_ASM // return bit index of most significant 1 bit, undefined if all bits are 0. static inline __attribute__((always_inline)) -unsigned int log2_tmp(unsigned long n) +unsigned int log2_tmp(unsigned int n) { unsigned int i; asm("bsrl %1,%0":"=r"(i):"rm"(n)); @@ -34,24 +34,24 @@ unsigned int log2_tmp(unsigned long n) } static inline __attribute__((always_inline)) -unsigned long long divmodu64u32(unsigned long long num, unsigned long divisor, unsigned long *p_remainder) +unsigned long long divmodu64u32(unsigned long long num, unsigned int divisor, unsigned int *p_remainder) { - unsigned long qhi,qlo,r; + unsigned long long qhi,qlo,r; asm("divl %6; xchg %eax,%ecx; divl %6; " :"=d"(r),"=a"(qlo),"=c"(qhi) - :"0"(0),"1"((unsigned long)(num>>32)),"2"((unsigned long)num),"rm"(divisor) + :"0"(0),"1"((unsigned int)(num>>32)),"2"((unsigned int)num),"rm"(divisor) ); if (p_remainder) *p_remainder = r; return ((unsigned long long)qhi<<32)|qlo; } #else -unsigned int log2_tmp(unsigned long n); +unsigned int log2_tmp(unsigned int n); #ifdef IAMATH_NO_ASM_DEFINITION -unsigned int log2_tmp(unsigned long n) +unsigned int log2_tmp(unsigned int n) { - unsigned long a,b; + unsigned int a,b; unsigned int i; i=0; a=n; b=a>>16; if (b) { a=b; i+=16; } diff --git a/stage2/ipxe.h b/stage2/ipxe.h index 6c0a1345..62039c71 100644 --- a/stage2/ipxe.h +++ b/stage2/ipxe.h @@ -46,6 +46,7 @@ #include "pxe.h" +#if 0 /** Minimum possible opcode used within PXE FILE API */ #define PXENV_FILE_MIN 0x00e0 /** Minimum possible opcode used within PXE FILE API */ @@ -130,15 +131,15 @@ typedef struct s_PXENV_FILE_EXEC PXENV_FILE_EXEC_t; #define PXENV_FILE_API_CHECK 0x00e6 /** Parameter block for pxenv_file_api_check() */ struct s_PXENV_FILE_API_CHECK { - PXENV_STATUS_t Status; /**< PXE status code */ - grub_u16_t Size; /**< Size of structure */ - grub_u32_t Magic; /**< Magic number */ - grub_u32_t Provider; /**< Implementation identifier */ - grub_u32_t APIMask; /**< Supported API functions */ - grub_u32_t Flags; /**< Reserved for the future */ + PXENV_STATUS_t Status; /**< PXE status code */ //PXE状态码 + grub_u16_t Size; /**< Size of structure */ //结构尺寸 + grub_u32_t Magic; /**< Magic number */ //幻数 + grub_u32_t Provider; /**< Implementation identifier */ //实现标识符 + grub_u32_t APIMask; /**< Supported API functions */ //支持的API函数 + grub_u32_t Flags; /**< Reserved for the future */ //为未来保留 } __attribute__ (( packed )); -typedef struct s_PXENV_FILE_API_CHECK PXENV_FILE_API_CHECK_t; +typedef struct s_PXENV_FILE_API_CHECK PXENV_FILE_API_CHECK_t; //file检查api /** PXE API function code for pxenv_file_exit_hook() */ #define PXENV_FILE_EXIT_HOOK 0x00e7 @@ -162,22 +163,22 @@ struct s_PXENV_FILE_CMDLINE { typedef struct s_PXENV_FILE_CMDLINE PXENV_FILE_CMDLINE_t; union u_PXENV_ANY { - /* Make it easy to read status for any operation */ - PXENV_STATUS_t Status; - PXENV_GET_CACHED_INFO_t get_cached_info; - PXENV_TFTP_OPEN_t tftp_open; - PXENV_TFTP_CLOSE_t tftp_close; - PXENV_TFTP_READ_t tftp_read; - PXENV_TFTP_GET_FSIZE_t tftp_get_size; - struct s_PXENV_FILE_OPEN file_open; - struct s_PXENV_FILE_CLOSE file_close; - struct s_PXENV_FILE_SELECT file_select; - struct s_PXENV_FILE_READ file_read; - struct s_PXENV_GET_FILE_SIZE get_file_size; - struct s_PXENV_FILE_EXEC file_exec; - struct s_PXENV_FILE_API_CHECK file_api_check; - struct s_PXENV_FILE_EXIT_HOOK file_exit_hook; - struct s_PXENV_FILE_CMDLINE file_cmdline; + /* Make it easy to read status for any operation 轻松读取任何操作的状态*/ + PXENV_STATUS_t Status; //状态 + PXENV_GET_CACHED_INFO_t get_cached_info; //获取缓存的信息 + PXENV_TFTP_OPEN_t tftp_open; //tftp打开 + PXENV_TFTP_CLOSE_t tftp_close; //tftp关闭 + PXENV_TFTP_READ_t tftp_read; //tftp读 + PXENV_TFTP_GET_FSIZE_t tftp_get_size; //tftp获得尺寸 + struct s_PXENV_FILE_OPEN file_open; //file打开 + struct s_PXENV_FILE_CLOSE file_close; //file关闭 + struct s_PXENV_FILE_SELECT file_select; //file选择 + struct s_PXENV_FILE_READ file_read; //file读 + struct s_PXENV_GET_FILE_SIZE get_file_size; //获得文件尺寸 + struct s_PXENV_FILE_EXEC file_exec; //file执行 + struct s_PXENV_FILE_API_CHECK file_api_check; //file检查api + struct s_PXENV_FILE_EXIT_HOOK file_exit_hook; //file执行挂钩 + struct s_PXENV_FILE_CMDLINE file_cmdline; //file命令行 }; typedef union u_PXENV_ANY iPXENV_ANY_t; @@ -186,5 +187,7 @@ extern PXENV_ANY_t pxenv; extern grub_u32_t has_ipxe; extern s_PXE_FILE_FUNC ipxe_file_func; +#endif + #endif /* iPXE_API_H */ #endif /* ifdef FSYS_IPXE */ diff --git a/stage2/iso9660.h b/stage2/iso9660.h index 642b8d11..208cf911 100644 --- a/stage2/iso9660.h +++ b/stage2/iso9660.h @@ -32,6 +32,20 @@ #define ISO_SECTOR_BITS (11) #define ISO_SECTOR_SIZE (1<= file system block size >= PBSIZE >= DISIZE - */ -#define PBSIZE 512 /* physical block size (in byte) */ -#define DISIZE 512 /* on-disk inode size (in byte) */ -#define L2DISIZE 9 -#define INOSPERIAG 4096 /* number of disk inodes per iag */ -#define L2INOSPERIAG 12 -#define INOSPEREXT 32 /* number of disk inode per extent */ -#define L2INOSPEREXT 5 - -/* Minimum number of bytes supported for a JFS partition */ -#define MINJFS (0x1000000) - -/* - * fixed byte offset address - */ -#define SUPER1_OFF 0x8000 /* primary superblock */ - -#define AITBL_OFF (SUPER1_OFF + PSIZE + (PSIZE << 1)) - -/* - * fixed reserved inode number - */ -/* aggregate inode */ -#define AGGREGATE_I 1 /* aggregate inode map inode */ -#define FILESYSTEM_I 16 /* 1st/only fileset inode in ait: - * fileset inode map inode - */ - -/* per fileset inode */ -#define ROOT_I 2 /* fileset root inode */ - -/* - * directory configuration - */ -#define JFS_NAME_MAX 255 -#define JFS_PATH_MAX PSIZE - -typedef unsigned char u8; -typedef char s8; -typedef unsigned short u16; -typedef short s16; -typedef unsigned int u32; -typedef int s32; -typedef unsigned long long u64; -typedef long long s64; - -typedef u16 UniChar; - -/* these from jfs_btree.h */ - -/* btpaget_t flag */ -#define BT_TYPE 0x07 /* B+-tree index */ -#define BT_ROOT 0x01 /* root page */ -#define BT_LEAF 0x02 /* leaf page */ -#define BT_INTERNAL 0x04 /* internal page */ -#define BT_RIGHTMOST 0x10 /* rightmost page */ -#define BT_LEFTMOST 0x20 /* leftmost page */ - -/* those are from jfs_types.h */ - -struct timestruc_t { - u32 tv_sec; - u32 tv_nsec; -}; /* - 8 - */ - -/* - * physical xd (pxd) - */ -typedef struct pxd { - unsigned len:24; - unsigned addr1:8; - u32 addr2; -} pxd_t; /* - 8 - */ - -/* xd_t field extraction */ -#define lengthPXD(pxd) ((pxd)->len) -#define addressPXD(pxd) (((s64)((pxd)->addr1)) << 32 | ((pxd)->addr2)) - -/* - * data extent descriptor (dxd) - */ -typedef struct dxd { - unsigned flag:8; /* 1: flags */ - unsigned rsrvd:24; /* 3: */ - u32 size; /* 4: size in byte */ - unsigned len:24; /* 3: length in unit of fsblksize */ - unsigned addr1:8; /* 1: address in unit of fsblksize */ - u32 addr2; /* 4: address in unit of fsblksize */ -} dxd_t; /* - 16 - */ - -/* - * DASD limit information - stored in directory inode - */ -typedef struct dasd { - u8 thresh; /* Alert Threshold (in percent) */ - u8 delta; /* Alert Threshold delta (in percent) */ - u8 rsrvd1; - u8 limit_hi; /* DASD limit (in logical blocks) */ - u32 limit_lo; /* DASD limit (in logical blocks) */ - u8 rsrvd2[3]; - u8 used_hi; /* DASD usage (in logical blocks) */ - u32 used_lo; /* DASD usage (in logical blocks) */ -} dasd_t; /* - 16 - */ - - -/* from jfs_superblock.h */ - -#define JFS_MAGIC 0x3153464A /* "JFS1" */ - -struct jfs_superblock -{ - u32 s_magic; /* 4: magic number */ - u32 s_version; /* 4: version number */ - - s64 s_size; /* 8: aggregate size in hardware/LVM blocks; - * VFS: number of blocks - */ - s32 s_bsize; /* 4: aggregate block size in bytes; - * VFS: fragment size - */ - s16 s_l2bsize; /* 2: log2 of s_bsize */ - s16 s_l2bfactor; /* 2: log2(s_bsize/hardware block size) */ - s32 s_pbsize; /* 4: hardware/LVM block size in bytes */ - s16 s_l2pbsize; /* 2: log2 of s_pbsize */ - s16 pad; /* 2: padding necessary for alignment */ - - u32 s_agsize; /* 4: allocation group size in aggr. blocks */ - - u32 s_flag; /* 4: aggregate attributes: - * see jfs_filsys.h - */ - u32 s_state; /* 4: mount/unmount/recovery state: - * see jfs_filsys.h - */ - s32 s_compress; /* 4: > 0 if data compression */ - - pxd_t s_ait2; /* 8: first extent of secondary - * aggregate inode table - */ - - pxd_t s_aim2; /* 8: first extent of secondary - * aggregate inode map - */ - u32 s_logdev; /* 4: device address of log */ - s32 s_logserial; /* 4: log serial number at aggregate mount */ - pxd_t s_logpxd; /* 8: inline log extent */ - - pxd_t s_fsckpxd; /* 8: inline fsck work space extent */ - - struct timestruc_t s_time; /* 8: time last updated */ - - s32 s_fsckloglen; /* 4: Number of filesystem blocks reserved for - * the fsck service log. - * N.B. These blocks are divided among the - * versions kept. This is not a per - * version size. - * N.B. These blocks are included in the - * length field of s_fsckpxd. - */ - s8 s_fscklog; /* 1: which fsck service log is most recent - * 0 => no service log data yet - * 1 => the first one - * 2 => the 2nd one - */ - char s_fpack[11]; /* 11: file system volume name - * N.B. This must be 11 bytes to - * conform with the OS/2 BootSector - * requirements - */ - - /* extendfs() parameter under s_state & FM_EXTENDFS */ - s64 s_xsize; /* 8: extendfs s_size */ - pxd_t s_xfsckpxd; /* 8: extendfs fsckpxd */ - pxd_t s_xlogpxd; /* 8: extendfs logpxd */ - /* - 128 byte boundary - */ - - /* - * DFS VFS support (preliminary) - */ - char s_attach; /* 1: VFS: flag: set when aggregate is attached - */ - u8 rsrvd4[7]; /* 7: reserved - set to 0 */ - - u64 totalUsable; /* 8: VFS: total of 1K blocks which are - * available to "normal" (non-root) users. - */ - u64 minFree; /* 8: VFS: # of 1K blocks held in reserve for - * exclusive use of root. This value can be 0, - * and if it is then totalUsable will be equal - * to # of blocks in aggregate. I believe this - * means that minFree + totalUsable = # blocks. - * In that case, we don't need to store both - * totalUsable and minFree since we can compute - * one from the other. I would guess minFree - * would be the one we should store, and - * totalUsable would be the one we should - * compute. (Just a guess...) - */ - - u64 realFree; /* 8: VFS: # of free 1K blocks can be used by - * "normal" users. It may be this is something - * we should compute when asked for instead of - * storing in the superblock. I don't know how - * often this information is needed. - */ - /* - * graffiti area - */ -}; /* struct size is 160 */ - -/* from jfs_dtree.h */ - -/* - * entry segment/slot - * - * an entry consists of type dependent head/only segment/slot and - * additional segments/slots linked vi next field; - * N.B. last/only segment of entry is terminated by next = -1; - */ -/* - * directory page slot - */ -typedef struct dtslot { - s8 next; /* 1: */ - s8 cnt; /* 1: */ - UniChar name[15]; /* 30: */ -} dtslot_t; /* (32) */ - -#define DTSLOTDATALEN 15 - -/* - * internal node entry head/only segment - */ -typedef struct idtentry { - pxd_t xd; /* 8: child extent descriptor */ - - s8 next; /* 1: */ - u8 namlen; /* 1: */ - UniChar name[11]; /* 22: 2-byte aligned */ -} idtentry_t; /* (32) */ - -/* - * leaf node entry head/only segment - * - * For legacy filesystems, name contains 13 unichars -- no index field - */ -typedef struct ldtentry { - u32 inumber; /* 4: 4-byte aligned */ - s8 next; /* 1: */ - u8 namlen; /* 1: */ - UniChar name[11]; /* 22: 2-byte aligned */ - u32 index; /* 4: index into dir_table */ -} ldtentry_t; /* (32) */ - -#define DTLHDRDATALEN 11 - -/* - * dir_table used for directory traversal during readdir -*/ - -/* - * Maximum entry in inline directory table - */ - -typedef struct dir_table_slot { - u8 rsrvd; /* 1: */ - u8 flag; /* 1: 0 if free */ - u8 slot; /* 1: slot within leaf page of entry */ - u8 addr1; /* 1: upper 8 bits of leaf page address */ - u32 addr2; /* 4: lower 32 bits of leaf page address -OR- - index of next entry when this entry was deleted */ -} dir_table_slot_t; /* (8) */ - -/* - * directory root page (in-line in on-disk inode): - * - * cf. dtpage_t below. - */ -typedef union dtroot { - struct { - dasd_t DASD; /* 16: DASD limit/usage info F226941 */ - - u8 flag; /* 1: */ - s8 nextindex; /* 1: next free entry in stbl */ - s8 freecnt; /* 1: free count */ - s8 freelist; /* 1: freelist header */ - - u32 idotdot; /* 4: parent inode number */ - - s8 stbl[8]; /* 8: sorted entry index table */ - } header; /* (32) */ - - dtslot_t slot[9]; /* 288 */ -} dtroot_t; /* union size is 288 */ - -/* - * directory regular page: - * - * entry slot array of 32 byte slot - * - * sorted entry slot index table (stbl): - * contiguous slots at slot specified by stblindex, - * 1-byte per entry - * 512 byte block: 16 entry tbl (1 slot) - * 1024 byte block: 32 entry tbl (1 slot) - * 2048 byte block: 64 entry tbl (2 slot) - * 4096 byte block: 128 entry tbl (4 slot) - * - * data area: - * 512 byte block: 16 - 2 = 14 slot - * 1024 byte block: 32 - 2 = 30 slot - * 2048 byte block: 64 - 3 = 61 slot - * 4096 byte block: 128 - 5 = 123 slot - * - * N.B. index is 0-based; index fields refer to slot index - * except nextindex which refers to entry index in stbl; - * end of entry stot list or freelist is marked with -1. - */ -typedef union dtpage { - struct { - s64 next; /* 8: next sibling */ - s64 prev; /* 8: previous sibling */ - - u8 flag; /* 1: */ - s8 nextindex; /* 1: next entry index in stbl */ - s8 freecnt; /* 1: */ - s8 freelist; /* 1: slot index of head of freelist */ - - u8 maxslot; /* 1: number of slots in page slot[] */ - s8 stblindex; /* 1: slot index of start of stbl */ - u8 rsrvd[2]; /* 2: */ - - pxd_t self; /* 8: self pxd */ - } header; /* (32) */ - - dtslot_t slot[128]; /* 4096 */ -} dtpage_t; /* union size is 4096 */ - -/* from jfs_xtree.h */ - -/* - * extent allocation descriptor (xad) - */ -typedef struct xad { - unsigned flag:8; /* 1: flag */ - unsigned rsvrd:16; /* 2: reserved */ - unsigned off1:8; /* 1: offset in unit of fsblksize */ - u32 off2; /* 4: offset in unit of fsblksize */ - unsigned len:24; /* 3: length in unit of fsblksize */ - unsigned addr1:8; /* 1: address in unit of fsblksize */ - u32 addr2; /* 4: address in unit of fsblksize */ -} xad_t; /* (16) */ - -/* xad_t field extraction */ -#define offsetXAD(xad) (((s64)((xad)->off1)) << 32 | ((xad)->off2)) -#define addressXAD(xad) (((s64)((xad)->addr1)) << 32 | ((xad)->addr2)) -#define lengthXAD(xad) ((xad)->len) - -/* possible values for maxentry */ -#define XTPAGEMAXSLOT 256 -#define XTENTRYSTART 2 - -/* - * xtree page: - */ -typedef union xtpage { - struct xtheader { - s64 next; /* 8: */ - s64 prev; /* 8: */ - - u8 flag; /* 1: */ - u8 rsrvd1; /* 1: */ - s16 nextindex; /* 2: next index = number of entries */ - s16 maxentry; /* 2: max number of entries */ - s16 rsrvd2; /* 2: */ - - pxd_t self; /* 8: self */ - } header; /* (32) */ - - xad_t xad[XTPAGEMAXSLOT]; /* 16 * maxentry: xad array */ -} xtpage_t; /* union size is 16 * 256 = 4096 */ - -/* from jfs_dinode.h */ - -struct dinode { - /* - * I. base area (128 bytes) - * ------------------------ - * - * define generic/POSIX attributes - */ - u32 di_inostamp; /* 4: stamp to show inode belongs to fileset */ - s32 di_fileset; /* 4: fileset number */ - u32 di_number; /* 4: inode number, aka file serial number */ - u32 di_gen; /* 4: inode generation number */ - - pxd_t di_ixpxd; /* 8: inode extent descriptor */ - - s64 di_size; /* 8: size */ - s64 di_nblocks; /* 8: number of blocks allocated */ - - u32 di_nlink; /* 4: number of links to the object */ - - u32 di_uid; /* 4: user id of owner */ - u32 di_gid; /* 4: group id of owner */ - - u32 di_mode; /* 4: attribute, format and permission */ - - struct timestruc_t di_atime; /* 8: time last data accessed */ - struct timestruc_t di_ctime; /* 8: time last status changed */ - struct timestruc_t di_mtime; /* 8: time last data modified */ - struct timestruc_t di_otime; /* 8: time created */ - - dxd_t di_acl; /* 16: acl descriptor */ - - dxd_t di_ea; /* 16: ea descriptor */ - - s32 di_next_index; /* 4: Next available dir_table index */ - - s32 di_acltype; /* 4: Type of ACL */ - - /* - * Extension Areas. - * - * Historically, the inode was partitioned into 4 128-byte areas, - * the last 3 being defined as unions which could have multiple - * uses. The first 96 bytes had been completely unused until - * an index table was added to the directory. It is now more - * useful to describe the last 3/4 of the inode as a single - * union. We would probably be better off redesigning the - * entire structure from scratch, but we don't want to break - * commonality with OS/2's JFS at this time. - */ - union { - struct { - /* - * This table contains the information needed to - * find a directory entry from a 32-bit index. - * If the index is small enough, the table is inline, - * otherwise, an x-tree root overlays this table - */ - dir_table_slot_t _table[12]; /* 96: inline */ - - dtroot_t _dtroot; /* 288: dtree root */ - } _dir; /* (384) */ -#define di_dirtable u._dir._table -#define di_dtroot u._dir._dtroot -#define di_parent di_dtroot.header.idotdot -#define di_DASD di_dtroot.header.DASD - - struct { - union { - u8 _data[96]; /* 96: unused */ - struct { - void *_imap; /* 4: unused */ - u32 _gengen; /* 4: generator */ - } _imap; - } _u1; /* 96: */ -#define di_gengen u._file._u1._imap._gengen - - union { - xtpage_t _xtroot; /* 4096: (XXX: Is this right? Seems the type should be dtroot_t)*/ - struct { - u8 unused[16]; /* 16: */ - dxd_t _dxd; /* 16: */ - union { - u32 _rdev; /* 4: */ - u8 _fastsymlink[128]; - } _u; - u8 _inlineea[128]; - } _special; - } _u2; - } _file; -#define di_xtroot u._file._u2._xtroot -#define di_dxd u._file._u2._special._dxd -//#define di_btroot di_xtroot -#define di_inlinedata u._file._u2._special._u -#define di_rdev u._file._u2._special._u._rdev -#define di_fastsymlink u._file._u2._special._u._fastsymlink -#define di_inlineea u._file._u2._special._inlineea - } u; -}; - -typedef struct dinode dinode_t; - -/* di_mode */ -#define IFMT 0xF000 /* S_IFMT - mask of file type */ -#define IFDIR 0x4000 /* S_IFDIR - directory */ -#define IFREG 0x8000 /* S_IFREG - regular file */ -#define IFLNK 0xA000 /* S_IFLNK - symbolic link */ - -/* extended mode bits (on-disk inode di_mode) */ -#define INLINEEA 0x00040000 /* inline EA area free */ - -#if 0 -/* from jfs_imap.h */ - -#define EXTSPERIAG 128 /* number of disk inode extent per iag */ -#define SMAPSZ 4 /* number of words per summary map */ -#define MAXAG 128 /* maximum number of allocation groups */ - -/* - * inode allocation map: - * - * inode allocation map consists of - * . the inode map control page and - * . inode allocation group pages (per 4096 inodes) - * which are addressed by standard JFS xtree. - */ -/* - * inode allocation group page (per 4096 inodes of an AG) - */ -typedef struct { - s64 agstart; /* 8: starting block of ag */ - s32 iagnum; /* 4: inode allocation group number */ - s32 inofreefwd; /* 4: ag inode free list forward */ - s32 inofreeback; /* 4: ag inode free list back */ - s32 extfreefwd; /* 4: ag inode extent free list forward */ - s32 extfreeback; /* 4: ag inode extent free list back */ - s32 iagfree; /* 4: iag free list */ - - /* summary map: 1 bit per inode extent */ - s32 inosmap[SMAPSZ]; /* 16: sum map of mapwords w/ free inodes; - * note: this indicates free and backed - * inodes, if the extent is not backed the - * value will be 1. if the extent is - * backed but all inodes are being used the - * value will be 1. if the extent is - * backed but at least one of the inodes is - * free the value will be 0. - */ - s32 extsmap[SMAPSZ]; /* 16: sum map of mapwords w/ free extents */ - s32 nfreeinos; /* 4: number of free inodes */ - s32 nfreeexts; /* 4: number of free extents */ - /* (72) */ - u8 pad[1976]; /* 1976: pad to 2048 bytes */ - /* allocation bit map: 1 bit per inode (0 - free, 1 - allocated) */ - u32 wmap[EXTSPERIAG]; /* 512: working allocation map */ - u32 pmap[EXTSPERIAG]; /* 512: persistent allocation map */ - pxd_t inoext[EXTSPERIAG]; /* 1024: inode extent addresses */ -} iag_t; /* (4096) */ -#endif - -#endif /* _JFS_H_ */ diff --git a/stage2/mb_info.h b/stage2/mb_info.h index 1e1e63ba..f2256d25 100644 --- a/stage2/mb_info.h +++ b/stage2/mb_info.h @@ -24,14 +24,14 @@ struct mod_list { /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ - unsigned long mod_start; - unsigned long mod_end; + unsigned int mod_start; + unsigned int mod_end; /* Module command line */ - unsigned long cmdline; + unsigned int cmdline; /* padding to take it to 16 bytes (must be zero) */ - unsigned long pad; + unsigned int pad; }; @@ -44,10 +44,10 @@ struct mod_list struct AddrRangeDesc { - unsigned long size; + unsigned int size; unsigned long long BaseAddr; unsigned long long Length; - unsigned long Type; + unsigned int Type; /* unspecified optional padding... */ } __attribute__ ((packed)); @@ -60,7 +60,7 @@ struct AddrRangeDesc struct drive_info { /* The size of this structure. */ - unsigned long size; + unsigned int size; /* The BIOS drive number. */ unsigned char drive_number; @@ -87,7 +87,7 @@ struct apm_info { unsigned short version; unsigned short cseg; - unsigned long offset; + unsigned int offset; unsigned short cseg_16; unsigned short dseg_16; unsigned short cseg_len; @@ -106,66 +106,66 @@ struct apm_info struct multiboot_info { /* MultiBoot info version number */ - unsigned long flags; + unsigned int flags; /* Available memory from BIOS */ - unsigned long mem_lower; - unsigned long mem_upper; + unsigned int mem_lower; + unsigned int mem_upper; /* "root" partition */ - unsigned long boot_device; + unsigned int boot_device; /* Kernel command line */ - unsigned long cmdline; + unsigned int cmdline; /* Boot-Module list */ - unsigned long mods_count; - unsigned long mods_addr; + unsigned int mods_count; + unsigned int mods_addr; union { struct { /* (a.out) Kernel symbol table info */ - unsigned long tabsize; - unsigned long strsize; - unsigned long addr; - unsigned long pad; + unsigned int tabsize; + unsigned int strsize; + unsigned int addr; + unsigned int pad; } a; struct { /* (ELF) Kernel section header table */ - unsigned long num; - unsigned long size; - unsigned long addr; - unsigned long shndx; + unsigned int num; + unsigned int size; + unsigned int addr; + unsigned int shndx; } e; } syms; /* Memory Mapping buffer */ - unsigned long mmap_length; - unsigned long mmap_addr; + unsigned int mmap_length; + unsigned int mmap_addr; /* Drive Info buffer */ - unsigned long drives_length; - unsigned long drives_addr; + unsigned int drives_length; + unsigned int drives_addr; /* ROM configuration table */ - unsigned long config_table; + unsigned int config_table; /* Boot Loader Name */ - unsigned long boot_loader_name; + unsigned int boot_loader_name; /* APM table */ - unsigned long apm_table; + unsigned int apm_table; /* Video */ - unsigned long vbe_control_info; - unsigned long vbe_mode_info; + unsigned int vbe_control_info; + unsigned int vbe_mode_info; unsigned short vbe_mode; unsigned short vbe_interface_seg; unsigned short vbe_interface_off; diff --git a/stage2/mbrstart.S b/stage2/mbrstart.S deleted file mode 100644 index 27e91b47..00000000 --- a/stage2/mbrstart.S +++ /dev/null @@ -1,31 +0,0 @@ -/* - * mbrstart.S -- Master boot record code for loading GRLDR - * Copyright (C) 2005 Tinybit(tinybit@163.net) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * This program is used to generate the GRLDR.MBR file. - * - * Use the following shell command to generate the GRLDR.MBR file: - * - * cat mbrstart > grldr.mbr - * - */ - -#define GRLDR_MBR -#include "grldrstart.S" - diff --git a/stage2/md5.c b/stage2/md5.c index f0270d39..98033331 100644 --- a/stage2/md5.c +++ b/stage2/md5.c @@ -90,6 +90,7 @@ static UINT4 state[4]; static unsigned int length; static unsigned char buffer[64]; +static void md5_transform (const unsigned char block[64]); static void md5_transform (const unsigned char block[64]) { @@ -141,6 +142,7 @@ md5_transform (const unsigned char block[64]) state[3] += d; } +static void md5_init(void); static void md5_init(void) { @@ -148,6 +150,7 @@ md5_init(void) length = 0; } +static void md5_update (const char *input, int inputlen); static void md5_update (const char *input, int inputlen) { @@ -174,6 +177,7 @@ md5_update (const char *input, int inputlen) buflen = inputlen; } +static unsigned char *md5_final(); static unsigned char * md5_final() { @@ -203,6 +207,7 @@ md5_final() to strcmp. If CHECK is false, crypt KEY and save the result in CRYPTED. CRYPTED must have a salt. */ +int md5_password (const char *key, char *crypted, int check); int md5_password (const char *key, char *crypted, int check) { @@ -323,6 +328,7 @@ md5_password (const char *key, char *crypted, int check) #endif #ifdef TEST +static char *md5 (const char *input); static char * md5 (const char *input) { @@ -332,6 +338,7 @@ md5 (const char *input) return md5_final (); } +static void test (char *buffer, char *expected); static void test (char *buffer, char *expected) { @@ -348,6 +355,7 @@ test (char *buffer, char *expected) printf ("MD5(%s) OK\n", buffer); } +int main (void); int main (void) { diff --git a/stage2/pc_slice.h b/stage2/pc_slice.h index eeb204f5..3e215dee 100644 --- a/stage2/pc_slice.h +++ b/stage2/pc_slice.h @@ -32,76 +32,81 @@ #define PC_SLICE_OFFSET 446 #define PC_SLICE_MAX 4 +#define PC_DISK_SIG_OFFSET 0x1b8 + /* * Defines to guarantee structural alignment. */ #define PC_MBR_CHECK_SIG(mbr_ptr) \ - ( *( (unsigned short *) (((int) mbr_ptr) + PC_MBR_SIG_OFFSET) ) \ + ( *( (unsigned short *) (((grub_size_t) mbr_ptr) + PC_MBR_SIG_OFFSET) ) \ == PC_MBR_SIGNATURE ) #define PC_MBR_SIG(mbr_ptr) \ - ( *( (unsigned short *) (((int) mbr_ptr) + PC_MBR_SIG_OFFSET) ) ) + ( *( (unsigned short *) (((grub_size_t) mbr_ptr) + PC_MBR_SIG_OFFSET) ) ) #define PC_SLICE_FLAG(mbr_ptr, part) \ - ( *( (unsigned char *) (((int) mbr_ptr) + PC_SLICE_OFFSET \ + ( *( (unsigned char *) (((grub_size_t) mbr_ptr) + PC_SLICE_OFFSET \ + (part << 4)) ) ) #define PC_SLICE_HEAD(mbr_ptr, part) \ - ( *( (unsigned char *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 1 \ + ( *( (unsigned char *) (((grub_size_t) mbr_ptr) + PC_SLICE_OFFSET + 1 \ + (part << 4)) ) ) #define PC_SLICE_SEC(mbr_ptr, part) \ - ( *( (unsigned char *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 2 \ + ( *( (unsigned char *) (((grub_size_t) mbr_ptr) + PC_SLICE_OFFSET + 2 \ + (part << 4)) ) ) #define PC_SLICE_CYL(mbr_ptr, part) \ - ( *( (unsigned char *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 3 \ + ( *( (unsigned char *) (((grub_size_t) mbr_ptr) + PC_SLICE_OFFSET + 3 \ + (part << 4)) ) ) #define PC_SLICE_TYPE(mbr_ptr, part) \ - ( *( (unsigned char *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 4 \ + ( *( (unsigned char *) (((grub_size_t) mbr_ptr) + PC_SLICE_OFFSET + 4 \ + (part << 4)) ) ) #define PC_SLICE_EHEAD(mbr_ptr, part) \ - ( *( (unsigned char *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 5 \ + ( *( (unsigned char *) (((grub_size_t) mbr_ptr) + PC_SLICE_OFFSET + 5 \ + (part << 4)) ) ) #define PC_SLICE_ESEC(mbr_ptr, part) \ - ( *( (unsigned char *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 6 \ + ( *( (unsigned char *) (((grub_size_t) mbr_ptr) + PC_SLICE_OFFSET + 6 \ + (part << 4)) ) ) #define PC_SLICE_ECYL(mbr_ptr, part) \ - ( *( (unsigned char *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 7 \ + ( *( (unsigned char *) (((grub_size_t) mbr_ptr) + PC_SLICE_OFFSET + 7 \ + (part << 4)) ) ) #define PC_SLICE_START(mbr_ptr, part) \ - ( *( (unsigned long *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 8 \ + ( *( (unsigned int *) (((grub_size_t) mbr_ptr) + PC_SLICE_OFFSET + 8 \ + (part << 4)) ) ) #define PC_SLICE_LENGTH(mbr_ptr, part) \ - ( *( (unsigned long *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 12 \ + ( *( (unsigned int *) (((grub_size_t) mbr_ptr) + PC_SLICE_OFFSET + 12 \ + (part << 4)) ) ) #define PC_SLICE_ENTRY_IS_EMPTY(mbr_ptr, part) \ - ( ( ( *( (unsigned char *) (((int) mbr_ptr) + PC_SLICE_OFFSET \ + ( ( ( *( (unsigned char *) (((grub_size_t) mbr_ptr) + PC_SLICE_OFFSET \ + (part << 4)) ) ) == \ - ( *( (unsigned char *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 1 \ + ( *( (unsigned char *) (((grub_size_t) mbr_ptr) + PC_SLICE_OFFSET + 1 \ + (part << 4)) ) ) ) && \ - ( ( *( (unsigned short *) (((int) mbr_ptr) + PC_SLICE_OFFSET \ + ( ( *( (unsigned short *) (((grub_size_t) mbr_ptr) + PC_SLICE_OFFSET \ + (part << 4)) ) ) == \ - ( *( (unsigned short *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 2 \ + ( *( (unsigned short *) (((grub_size_t) mbr_ptr) + PC_SLICE_OFFSET + 2 \ + (part << 4)) ) ) ) && \ - ( ( *( (unsigned long *) (((int) mbr_ptr) + PC_SLICE_OFFSET \ + ( ( *( (unsigned int *) (((grub_size_t) mbr_ptr) + PC_SLICE_OFFSET \ + (part << 4)) ) ) == \ - ( *( (unsigned long *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 4 \ + ( *( (unsigned int *) (((grub_size_t) mbr_ptr) + PC_SLICE_OFFSET + 4 \ + (part << 4)) ) ) ) && \ - ( ( *( (unsigned long long *) (((int) mbr_ptr) + PC_SLICE_OFFSET \ + ( ( *( (unsigned long long *) (((grub_size_t) mbr_ptr) + PC_SLICE_OFFSET \ + (part << 4)) ) ) == \ - ( *( (unsigned long long *) (((int) mbr_ptr) + PC_SLICE_OFFSET + 8 \ + ( *( (unsigned long long *) (((grub_size_t) mbr_ptr) + PC_SLICE_OFFSET + 8 \ + (part << 4)) ) ) ) ) +//获取磁盘签名 +#define PC_DISK_SIG(mbr_ptr) \ + ( *( (unsigned int *) (((grub_size_t) mbr_ptr) + PC_DISK_SIG_OFFSET) ) ) /* * PC flag types are defined here. @@ -211,40 +216,40 @@ */ #define BSD_LABEL_CHECK_MAG(l_ptr) \ - ( *( (unsigned long *) (((int) l_ptr) + BSD_LABEL_MAG_OFFSET) ) \ - == ( (unsigned long) BSD_LABEL_MAGIC ) ) + ( *( (unsigned int *) (((grub_size_t) l_ptr) + BSD_LABEL_MAG_OFFSET) ) \ + == ( (unsigned int) BSD_LABEL_MAGIC ) ) #define BSD_LABEL_MAG(l_ptr) \ - ( *( (unsigned long *) (((int) l_ptr) + BSD_LABEL_MAG_OFFSET) ) ) + ( *( (unsigned int *) (((grub_size_t) l_ptr) + BSD_LABEL_MAG_OFFSET) ) ) #define BSD_LABEL_DTYPE(l_ptr) \ - ( *( (unsigned short *) (((int) l_ptr) + BSD_LABEL_MAG_OFFSET + 4) ) ) + ( *( (unsigned short *) (((grub_size_t) l_ptr) + BSD_LABEL_MAG_OFFSET + 4) ) ) #define BSD_LABEL_NPARTS(l_ptr) \ - ( *( (unsigned short *) (((int) l_ptr) + BSD_LABEL_NPARTS_OFFSET) ) ) + ( *( (unsigned short *) (((grub_size_t) l_ptr) + BSD_LABEL_NPARTS_OFFSET) ) ) #define BSD_PART_LENGTH(l_ptr, part) \ - ( *( (unsigned long *) (((int) l_ptr) + BSD_PART_OFFSET \ + ( *( (unsigned int *) (((grub_size_t) l_ptr) + BSD_PART_OFFSET \ + (part << 4)) ) ) #define BSD_PART_START(l_ptr, part) \ - ( *( (unsigned long *) (((int) l_ptr) + BSD_PART_OFFSET + 4 \ + ( *( (unsigned int *) (((grub_size_t) l_ptr) + BSD_PART_OFFSET + 4 \ + (part << 4)) ) ) #define BSD_PART_FRAG_SIZE(l_ptr, part) \ - ( *( (unsigned long *) (((int) l_ptr) + BSD_PART_OFFSET + 8 \ + ( *( (unsigned int *) (((grub_size_t) l_ptr) + BSD_PART_OFFSET + 8 \ + (part << 4)) ) ) #define BSD_PART_TYPE(l_ptr, part) \ - ( *( (unsigned char *) (((int) l_ptr) + BSD_PART_OFFSET + 12 \ + ( *( (unsigned char *) (((grub_size_t) l_ptr) + BSD_PART_OFFSET + 12 \ + (part << 4)) ) ) #define BSD_PART_FRAGS_PER_BLOCK(l_ptr, part) \ - ( *( (unsigned char *) (((int) l_ptr) + BSD_PART_OFFSET + 13 \ + ( *( (unsigned char *) (((grub_size_t) l_ptr) + BSD_PART_OFFSET + 13 \ + (part << 4)) ) ) #define BSD_PART_EXTRA(l_ptr, part) \ - ( *( (unsigned short *) (((int) l_ptr) + BSD_PART_OFFSET + 14 \ + ( *( (unsigned short *) (((grub_size_t) l_ptr) + BSD_PART_OFFSET + 14 \ + (part << 4)) ) ) diff --git a/stage2/pxe.h b/stage2/pxe.h index 8769d453..162e9c04 100644 --- a/stage2/pxe.h +++ b/stage2/pxe.h @@ -144,10 +144,10 @@ #define PACKED __attribute__ ((packed)) -#define SEGMENT(x) ((x) >> 4) -#define OFFSET(x) ((x) & 0xF) -#define SEGOFS(x) ((SEGMENT(x)<<16)+OFFSET(x)) -#define LINEAR(x) (void*)(((x >> 16) <<4)+(x & 0xFFFF)) +#define SEGMENT(x) ((x) >> 4) //分割 123456 -> 12345 +#define OFFSET(x) ((x) & 0xF) //偏移 123456 -> 6 +#define SEGOFS(x) ((SEGMENT(x)<<16)+OFFSET(x)) //段偏移 123450000 + 6 = 123450006 +#define LINEAR(x) (void*)(((x >> 16) <<4)+(x & 0xFFFF)) //线性 123450006 -> 123450 + 6 = 123456 //#define PXE_ERR_LEN 0xFFFFFFFF #define PXE_ERR_LEN 0 @@ -157,28 +157,28 @@ typedef grub_u32_t SEGOFS16; typedef grub_u32_t IP4; typedef grub_u16_t UDP_PORT; -#define MAC_ADDR_LEN 16 -typedef grub_u8_t MAC_ADDR[MAC_ADDR_LEN]; +#define MAC_ADDR_LEN 16 //MAC地址尺寸 +typedef grub_u8_t MAC_ADDR[MAC_ADDR_LEN]; //MAC地址 -#define PXENV_PACKET_TYPE_DHCP_DISCOVER 1 -#define PXENV_PACKET_TYPE_DHCP_ACK 2 -#define PXENV_PACKET_TYPE_CACHED_REPLY 3 +#define PXENV_PACKET_TYPE_DHCP_DISCOVER 1 //包类型 DHCP发现 +#define PXENV_PACKET_TYPE_DHCP_ACK 2 //包类型 DHCP确认 +#define PXENV_PACKET_TYPE_CACHED_REPLY 3 //包类型 回复 typedef struct { - PXENV_STATUS Status; - grub_u16_t PacketType; - grub_u16_t BufferSize; - SEGOFS16 Buffer; - grub_u16_t BufferLimit; -} PACKED PXENV_GET_CACHED_INFO_t; + PXENV_STATUS Status; //状态 grub_uint32_t state + grub_u16_t PacketType; //数据包类型 + grub_u16_t BufferSize; //缓存尺寸 grub_uint32_t nvram_size + SEGOFS16 Buffer; //缓存 + grub_u16_t BufferLimit; //缓冲限制 grub_uint32_t nvram_access_size +} PACKED PXENV_GET_CACHED_INFO_t; //获取信息 pppp -#define BOOTP_REQ 1 -#define BOOTP_REP 2 +#define BOOTP_REQ 1 //引导TP需求 +#define BOOTP_REP 2 //引导TP -#define BOOTP_BCAST 0x8000 +#define BOOTP_BCAST 0x8000 //引导 #if 1 -#define BOOTP_DHCPVEND 1024 /* DHCP extended vendor field size */ +#define BOOTP_DHCPVEND 1024 /* DHCP extended vendor field size DHCP扩展供应商字段大小*/ #else #define BOOTP_DHCPVEND 312 /* DHCP standard vendor field size */ #endif @@ -187,105 +187,206 @@ typedef struct { #define VM_RFC1048 0x63825363L #endif + + + +typedef enum grub_network_level_protocol_id //网络级协议id +{ + GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV, //DHCP_RECV + GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4, //IPV4 + GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6 //IPV6 +} grub_network_level_protocol_id_t; + +typedef struct grub_net_network_level_netaddress +{ + grub_network_level_protocol_id_t type; + union + { + struct { + grub_uint32_t base; + int masksize; + } ipv4; + struct { + grub_uint64_t base[2]; + int masksize; + } ipv6; + }; +} grub_net_network_level_netaddress_t; +#if 0 typedef struct { - grub_u8_t opcode; - grub_u8_t Hardware; /* hardware type */ - grub_u8_t Hardlen; /* hardware addr len */ - grub_u8_t Gatehops; /* zero it */ - grub_u32_t ident; /* random number chosen by client */ - grub_u16_t seconds; /* seconds since did initial bootstrap */ - grub_u16_t Flags; /* seconds since did initial bootstrap */ - IP4 cip; /* Client IP */ - IP4 yip; /* Your IP */ - IP4 sip; /* IP to use for next boot stage */ - IP4 gip; /* Relay IP ? */ - MAC_ADDR CAddr; /* Client hardware address */ - grub_u8_t Sname[64]; /* Server's hostname (Optional) */ - grub_u8_t bootfile[128]; /* boot filename */ + grub_u8_t opcode; //操作码 00 + grub_u8_t Hardware; /* hardware type 硬件类型*/ //00 + grub_u8_t Hardlen; /* hardware addr len 硬件地址长度*/ //00 + grub_u8_t Gatehops; /* zero it 归零*/ //00 + grub_u32_t ident; /* random number chosen by client 客户选择的随机数*/ //00 00 00 00 + grub_u16_t seconds; /* seconds since did initial bootstrap 自初始引导以来的秒数*/ //00 00 + grub_u16_t Flags; /* seconds since did initial bootstrap */ //00 00 + IP4 cip; /* Client IP 客户IP*/ //00 00 00 00 + IP4 yip; /* Your IP 你的IP*/ //02 01 06 00 + IP4 sip; /* IP to use for next boot stage 服务器IP*/ //f3 da 2f 8d + IP4 gip; /* Relay IP ? 网关IP*/ //00 00 80 00 + MAC_ADDR CAddr; /* Client hardware address 客户端硬件地址*/ //00 00 00 00 c0 a8 38 02 c0 a8 38 01 00 00 00 00 +// grub_u32_t CAddr[4]; + grub_u8_t Sname[64]; /* Server's hostname (Optional) 服务器的主机名(可选)*/ //00 0c 29 8d cc d9 00 00 00 00 00 00 00 00 00 00 +// grub_u32_t Sname[8]; //PC-201311212111 + grub_u8_t bootfile[128]; /* boot filename 引导文件名*/ //00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +// grub_u32_t bootfile[16]; //bootia.EFI union { - grub_u8_t d[BOOTP_DHCPVEND]; /* raw array of vendor/dhcp options */ + grub_u8_t d[BOOTP_DHCPVEND]; /* raw array of vendor/dhcp options 供应商/ dhcp选项的原始数组*/ struct { - grub_u8_t magic[4]; /* DHCP magic cookie */ - grub_u32_t flags; /* bootp flags/opcodes */ + grub_u8_t magic[4]; /* DHCP magic cookie DHCP魔术曲奇*/ + grub_u32_t flags; /* bootp flags/opcodes bootp标志/操作码*/ grub_u8_t pad[56]; } v; - } vendor; -} PACKED BOOTPLAYER; + } vendor; //供应商 +} PACKED BOOTPLAYER; //引导播放器 +#endif + +#define GRUB_NET_BOOTP_MAC_ADDR_LEN 16 + +typedef grub_uint8_t grub_net_bootp_mac_addr_t[GRUB_NET_BOOTP_MAC_ADDR_LEN]; + +#define GRUB_NET_BOOTP_RFC1048_MAGIC_0 0x63 +#define GRUB_NET_BOOTP_RFC1048_MAGIC_1 0x82 +#define GRUB_NET_BOOTP_RFC1048_MAGIC_2 0x53 +#define GRUB_NET_BOOTP_RFC1048_MAGIC_3 0x63 + +enum + { + GRUB_NET_BOOTP_PAD = 0x00, + GRUB_NET_BOOTP_NETMASK = 0x01, + GRUB_NET_BOOTP_ROUTER = 0x03, + GRUB_NET_BOOTP_DNS = 0x06, + GRUB_NET_BOOTP_HOSTNAME = 0x0c, + GRUB_NET_BOOTP_DOMAIN = 0x0f, + GRUB_NET_BOOTP_ROOT_PATH = 0x11, + GRUB_NET_BOOTP_EXTENSIONS_PATH = 0x12, + GRUB_NET_BOOTP_END = 0xff + }; + typedef struct { - PXENV_STATUS Status; - IP4 ServerIPAddress; - IP4 GatewayIPAddress; - grub_u8_t FileName[128]; - UDP_PORT TFTPPort; - grub_u16_t PacketSize; -} PACKED PXENV_TFTP_OPEN_t; + PXENV_STATUS Status; //状态 + IP4 ServerIPAddress; //服务器的IP地址 + IP4 GatewayIPAddress; //网关IP地址 + grub_u8_t FileName[128]; //文件名 + UDP_PORT TFTPPort; //TFTP端口 + grub_u16_t PacketSize; //包尺寸 +} PACKED PXENV_TFTP_OPEN_t; //TFTP打开 typedef struct { - PXENV_STATUS Status; -} PACKED PXENV_TFTP_CLOSE_t; + PXENV_STATUS Status; //状态 +} PACKED PXENV_TFTP_CLOSE_t;//TFTP关闭 typedef struct { - PXENV_STATUS Status; - grub_u16_t PacketNumber; - grub_u16_t BufferSize; - SEGOFS16 Buffer; -} PACKED PXENV_TFTP_READ_t; + PXENV_STATUS Status; //状态 + grub_u16_t PacketNumber; //包号 + grub_u16_t BufferSize; //缓存尺寸 + SEGOFS16 Buffer; //缓存地址 +} PACKED PXENV_TFTP_READ_t; //TFTP读 typedef struct { - PXENV_STATUS Status; - IP4 ServerIPAddress; - IP4 GatewayIPAddress; - grub_u8_t FileName[128]; - grub_u32_t FileSize; -} PACKED PXENV_TFTP_GET_FSIZE_t; + PXENV_STATUS Status; //状态 + IP4 ServerIPAddress; //服务器的IP地址 + IP4 GatewayIPAddress; //网关IP地址 + grub_u8_t FileName[128]; //文件名 + grub_u32_t FileSize; //文件尺寸 +} PACKED PXENV_TFTP_GET_FSIZE_t; //TFTP获得文件尺寸 typedef struct { - PXENV_STATUS Status; - IP4 src_ip; -} PACKED PXENV_UDP_OPEN_t; + PXENV_STATUS Status; //状态 + IP4 src_ip; //源ip +} PACKED PXENV_UDP_OPEN_t; //UDP 打开 typedef struct { - PXENV_STATUS Status; -} PACKED PXENV_UDP_CLOSE_t; + PXENV_STATUS Status; //状态 +} PACKED PXENV_UDP_CLOSE_t; //UDP 关闭 typedef struct { - PXENV_STATUS Status; - IP4 ip; - IP4 gw; - UDP_PORT src_port; - UDP_PORT dst_port; - grub_u16_t buffer_size; - SEGOFS16 buffer; -} PACKED PXENV_UDP_WRITE_t; + PXENV_STATUS Status; //状态 + IP4 ip; //IP4 ip + IP4 gw; //IP4 gw + UDP_PORT src_port; //源端口 + UDP_PORT dst_port; //目的端口 + grub_u16_t buffer_size; //缓存尺寸 + SEGOFS16 buffer; //缓存地址 +} PACKED PXENV_UDP_WRITE_t; //UDP 写 typedef struct { - PXENV_STATUS Status; - IP4 src_ip; - IP4 dst_ip; - UDP_PORT src_port; - UDP_PORT dst_port; - grub_u16_t buffer_size; - SEGOFS16 buffer; -} PACKED PXENV_UDP_READ_t; + PXENV_STATUS Status; //状态 + IP4 src_ip; //源ip + IP4 dst_ip; //目的ip + UDP_PORT src_port; //源端口 + UDP_PORT dst_port; //目的端口 + grub_u16_t buffer_size; //缓存尺寸 + SEGOFS16 buffer; //缓存地址 +} PACKED PXENV_UDP_READ_t; //UDP 读 typedef struct { - PXENV_STATUS Status; - grub_u8_t reserved[10]; -} PACKED PXENV_UNLOAD_STACK_t; + PXENV_STATUS Status; //状态 + grub_u8_t reserved[10]; //保留 +} PACKED PXENV_UNLOAD_STACK_t; //卸载堆栈 typedef struct { - int (*open)(const char *name); - grub_u32_t (*getsize)(void); - grub_u32_t (*readblk)(grub_u32_t buf,grub_u32_t num); - void (*close)(void); - void (*unload)(void); -} s_PXE_FILE_FUNC; + int (*open)(void); //打开 tftp_open ipxe_open +// grub_u32_t (*getsize)(void); //获得尺寸 tftp_get_size ipxe_get_size +// grub_u32_t (*readblk)(grub_u32_t buf,grub_u32_t num); //读 tftp_read_blk ipxe_read_blk + unsigned long long (*read)(char *buf,grub_u64_t num); //读 +// void (*close)(void); //关闭 tftp_close ipxe_close +// void (*unload)(void); //卸载 tftp_unload ipxe_unload +} s_PXE_FILE_FUNC; //pxe文件功能 extern s_PXE_FILE_FUNC *pxe_file_func[2]; -extern unsigned long pxe_blksize; +extern unsigned int pxe_blksize; #define PXE_FILE_TYPE_TFTP 0 -#define PXE_FILE_TYPE_IPXE 1 - +#define PXE_FILE_TYPE_HTTP 1 +//#define PXE_FILE_TYPE_IPXE 1 +///////////////////////////////////////////////////////////////////////// +extern struct grub_net_card *grub_net_cards; +#define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next) +#define FOR_NET_CARDS_SAFE(var, next) for (var = grub_net_cards, next = (var ? var->next : 0); var; var = next, next = (var ? var->next : 0)) +#define NETBUFF_ALIGN 2048 +#define NETBUFFMINLEN 64 +#define ALIGN_UP(addr, align) \ + ((addr + (typeof (addr)) align - 1) & ~((typeof (addr)) align - 1)) +#define ALIGN_UP_OVERHEAD(addr, align) ((-(addr)) & ((typeof (addr)) (align) - 1)) +#define ALIGN_DOWN(addr, align) \ + ((addr) & ~((typeof (addr)) align - 1)) +#define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0])) +#define COMPILE_TIME_ASSERT(cond) switch (0) { case 1: case !(cond): ; } + +typedef enum +{ + DNS_OPTION_IPV4, + DNS_OPTION_IPV6, + DNS_OPTION_PREFER_IPV4, + DNS_OPTION_PREFER_IPV6 +} grub_dns_option_t; + +typedef enum grub_net_interface_flags + { + GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE = 1, //网络接口硬件地址不可变 + GRUB_NET_INTERFACE_ADDRESS_IMMUTABLE = 2, //网络接口地址不可变 + GRUB_NET_INTERFACE_PERMANENT = 4 //网络接口常驻 + } grub_net_interface_flags_t; //网络接口标记 + +struct grub_env_var; +typedef const char *(*grub_env_read_hook_t) (struct grub_env_var *var, const char *val); +typedef char *(*grub_env_write_hook_t) (struct grub_env_var *var, const char *val); + +struct grub_env_var +{ + char *name; + char *value; + grub_env_read_hook_t read_hook; + grub_env_write_hook_t write_hook; + struct grub_env_var *next; + struct grub_env_var **prevp; + struct grub_env_var *sorted_next; + int global; +}; + +/////////////////////////////////////////////////////// #undef PACKED + #endif /* __PXE_H */ diff --git a/stage2/serial.c b/stage2/serial.c deleted file mode 100644 index e4d3c0a2..00000000 --- a/stage2/serial.c +++ /dev/null @@ -1,467 +0,0 @@ -/* serial.c - serial device interface */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifdef SUPPORT_SERIAL - -#include -#include -#include -#include - -/* An input buffer. */ -static char input_buf[8]; -static int npending = 0; - -static int keep_track = 1; - - -/* Hardware-dependent definitions. */ - -/* The structure for speed vs. divisor. */ -struct divisor -{ - int speed; - unsigned short div; -}; - -/* Store the port number of a serial unit. */ -static unsigned short serial_hw_port = 0; - -/* The table which lists common configurations. */ -static struct divisor divisor_tab[] = - { - { 2400, 0x0030 }, - { 4800, 0x0018 }, - { 9600, 0x000C }, - { 19200, 0x0006 }, - { 38400, 0x0003 }, - { 57600, 0x0002 }, - { 115200, 0x0001 } - }; - -/* Read a byte from a port. */ -static inline unsigned char -inb (unsigned short port) -{ - unsigned char value; - - asm volatile ("inb %w1, %0" : "=a" (value) : "Nd" (port)); - asm volatile ("outb %%al, $0x80" : : ); - - return value; -} - -/* Write a byte to a port. */ -static inline void -outb (unsigned short port, unsigned char value) -{ - asm volatile ("outb %b0, %w1" : : "a" (value), "Nd" (port)); - asm volatile ("outb %%al, $0x80" : : ); -} - -/* Fetch a key. */ -int -serial_hw_fetch (void) -{ - if (inb (serial_hw_port + UART_LSR) & UART_DATA_READY) - return inb (serial_hw_port + UART_RX); - - return -1; -} - -/* Put a chararacter. */ -void -serial_hw_put (int c) -{ - int timeout = 100000; - - /* Wait until the transmitter holding register is empty. */ - while ((inb (serial_hw_port + UART_LSR) & UART_EMPTY_TRANSMITTER) == 0) - { - if (--timeout == 0) - /* There is something wrong. But what can I do? */ - return; - } - - outb (serial_hw_port + UART_TX, c); -} - -void -serial_hw_delay (void) -{ - outb (0x80, 0); -} - -/* Return the port number for the UNITth serial device. */ -unsigned short -serial_hw_get_port (int unit) -{ - /* The BIOS data area. */ - const unsigned short *addr = (const unsigned short *) 0x0400; - - return addr[unit]; -} - -/* Initialize a serial device. PORT is the port number for a serial device. - SPEED is a DTE-DTE speed which must be one of these: 2400, 4800, 9600, - 19200, 38400, 57600 and 115200. WORD_LEN is the word length to be used - for the device. Likewise, PARITY is the type of the parity and - STOP_BIT_LEN is the length of the stop bit. The possible values for - WORD_LEN, PARITY and STOP_BIT_LEN are defined in the header file as - macros. */ -int -serial_hw_init (unsigned short port, unsigned int speed, - int word_len, int parity, int stop_bit_len) -{ - int i; - unsigned short div = 0; - unsigned char status = 0; - - /* Turn off the interrupt. */ - outb (port + UART_IER, 0); - - /* Set DLAB. */ - outb (port + UART_LCR, UART_DLAB); - - /* Set the baud rate. */ - for (i = 0; i < sizeof (divisor_tab) / sizeof (divisor_tab[0]); i++) - if (divisor_tab[i].speed == speed) - { - div = divisor_tab[i].div; - break; - } - - if (div == 0) - return 0; - - outb (port + UART_DLL, div & 0xFF); - outb (port + UART_DLH, div >> 8); - - /* Set the line status. */ - status |= parity | word_len | stop_bit_len; - outb (port + UART_LCR, status); - - /* Enable the FIFO. */ - outb (port + UART_FCR, UART_ENABLE_FIFO); - - /* Turn on DTR, RTS, and OUT2. */ - outb (port + UART_MCR, UART_ENABLE_MODEM); - - /* Store the port number. */ - serial_hw_port = port; - - /* Drain the input buffer. */ - while (serial_checkkey () != -1) - (void) serial_getkey (); - - /* Get rid of TERM_NEED_INIT from the serial terminal. */ - for (i = 0; term_table[i].name; i++) - if (grub_strcmp (term_table[i].name, "serial") == 0) - { - term_table[i].flags &= ~TERM_NEED_INIT; - break; - } - - /* FIXME: should check if the serial terminal was found. */ - - return 1; -} - - -/* Table of Serial Terminal Escape Sequences - *======================================================================= - * Key ANSI VT100 extension VT220 extension - * --------- ------- --------------- --------------- - * Up arrow [A - * Down arrow [B - * Right arrow [C - * Left arrow [D - * F1 Op - * F2 Oq - * F3 Or - * F4 Os - * F5 Ot - * F6 Ou [17~ [17~ - * F7 Ov [18~ [18~ - * F8 Ow [19~ [19~ - * F9 Ox [20~ [20~ - * F10 Oy [21~ [21~ - * F11 Oz [23~ [23~ - * F12 Oa [24~ [24~ - * Home [1~ - * End [4~ - * Insert [2~ - * Delete [3~ - * Page Up [5~ - * Page Down [6~ - * Shift-Tab [Z [0Z - */ - -/* Generic definitions. */ - -static void -serial_translate_key_sequence (void) -{ - const struct - { - short /*char*/ key; - short /*char*/ ascii; - } - three_code_table[] = - { - {'A', KEY_UP/*16*/}, /* Up arrow */ - {'B', KEY_DOWN/*14*/}, /* Down arrow */ - {'C', KEY_RIGHT/*6*/}, /* Right arrow */ - {'D', KEY_LEFT/*2*/}, /* Left arrow */ - {'F', KEY_END/*5*/}, /* End */ - {'H', KEY_HOME/*1*/}, /* Home */ - {'4', KEY_DC/*4*/} /* Delete */ - }; - - const struct - { - short key; - short /*char*/ ascii; - } - four_code_table[] = - { - {('1' | ('~' << 8)), KEY_HOME/*1*/}, /* Home */ - {('3' | ('~' << 8)), KEY_DC/*4*/}, /* Delete */ - {('5' | ('~' << 8)), KEY_PPAGE/*7*/}, /* Page Up */ - {('6' | ('~' << 8)), KEY_NPAGE/*3*/}, /* Page Down */ - }; - - /* The buffer must start with ``ESC [''. */ - if (*((unsigned short *) input_buf) != ('\e' | ('[' << 8))) - return; - - if (npending >= 3) - { - int i; - - for (i = 0; - i < sizeof (three_code_table) / sizeof (three_code_table[0]); - i++) - if (three_code_table[i].key == input_buf[2]) - { - *(short *)input_buf = three_code_table[i].ascii; - npending--;//npending -= 2; - grub_memmove (input_buf + 2/*1*/, input_buf + 3, npending - 2/*1*/); - return; - } - } - - if (npending >= 4) - { - int i; - short key = *((short *) (input_buf + 2)); - - for (i = 0; - i < sizeof (four_code_table) / sizeof (four_code_table[0]); - i++) - if (four_code_table[i].key == key) - { - *(short *)input_buf = four_code_table[i].ascii; - npending -= 2/*3*/; - grub_memmove (input_buf + 2/*1*/, input_buf + 4, npending - 2/*1*/); - return; - } - } -} - -static int -fill_input_buf (int nowait) -{ - int i; - - for (i = 0; i < 10000 && npending < sizeof (input_buf); i++) - { - int c; - - c = serial_hw_fetch (); - if (c >= 0) - { - input_buf[npending++] = c; - - /* Reset the counter to zero, to wait for the same interval. */ - i = 0; - } - - if (nowait) - break; - } - - /* Translate some key sequences. */ - serial_translate_key_sequence (); - - return npending; -} - -/* The serial version of getkey. */ -int -serial_getkey (void) -{ - int c; - - while (! fill_input_buf (0)) - ; - - npending--; - if ((c = input_buf[0])) - grub_memmove (input_buf, input_buf + 1, npending); - else - { - npending--; - c = *(unsigned short *)input_buf; - grub_memmove (input_buf, input_buf + 2, npending); - } - - return c; -} - -/* The serial version of checkkey. */ -int -serial_checkkey (void) -{ - if (fill_input_buf (1)) - return input_buf[0] ? input_buf[0] : *(unsigned short *)input_buf; - - return -1; -} - -/* The serial version of grub_putchar. */ -unsigned int -serial_putchar (unsigned int c, unsigned int max_width) -{ - /* Keep track of the cursor. */ - if (keep_track) - { -#if 0 - /* The serial terminal doesn't have VGA fonts. */ - switch (c) - { - case DISP_UL: - c = ACS_ULCORNER; - break; - case DISP_UR: - c = ACS_URCORNER; - break; - case DISP_LL: - c = ACS_LLCORNER; - break; - case DISP_LR: - c = ACS_LRCORNER; - break; - case DISP_HORIZ: - c = ACS_HLINE; - break; - case DISP_VERT: - c = ACS_VLINE; - break; - case DISP_LEFT: - c = ACS_LARROW; - break; - case DISP_RIGHT: - c = ACS_RARROW; - break; - case DISP_UP: - c = ACS_UARROW; - break; - case DISP_DOWN: - c = ACS_DARROW; - break; - default: - break; - } -#endif - - switch (c) - { - case '\r': - fontx = 0; - break; - - case '\n': - fonty++; - break; - - case '\b': - case 127: - if (fontx > 0) - fontx--; - break; - - case '\a': - break; - - default: - if (fontx >= 79) - { - serial_putchar ('\r', max_width); - serial_putchar ('\n', max_width); - } - fontx++; - break; - } - } - - serial_hw_put (c); - return 1; -} - -int -serial_getxy (void) -{ - return (fonty << 8) | fontx; -} - -void -serial_gotoxy (int x, int y) -{ - keep_track = 0; - ti_cursor_address (x, y); - keep_track = 1; - - fontx = x; - fonty = y; -} - -void -serial_cls (void) -{ - keep_track = 0; - ti_clear_screen (); - keep_track = 1; - - fontx = fonty = 0; -} - -void -serial_setcolorstate (color_state state) -{ - keep_track = 0; - if (state == COLOR_STATE_HIGHLIGHT) - ti_enter_standout_mode (); - else - ti_exit_standout_mode (); - keep_track = 1; -} - -#endif /* SUPPORT_SERIAL */ diff --git a/stage2/serial.h b/stage2/serial.h deleted file mode 100644 index 4c455495..00000000 --- a/stage2/serial.h +++ /dev/null @@ -1,87 +0,0 @@ -/* serial.h - serial device interface */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef GRUB_SERIAL_HEADER -#define GRUB_SERIAL_HEADER 1 - -/* Macros. */ - -/* The offsets of UART registers. */ -#define UART_TX 0 -#define UART_RX 0 -#define UART_DLL 0 -#define UART_IER 1 -#define UART_DLH 1 -#define UART_IIR 2 -#define UART_FCR 2 -#define UART_LCR 3 -#define UART_MCR 4 -#define UART_LSR 5 -#define UART_MSR 6 -#define UART_SR 7 - -/* For LSR bits. */ -#define UART_DATA_READY 0x01 -#define UART_EMPTY_TRANSMITTER 0x20 - -/* The type of parity. */ -#define UART_NO_PARITY 0x00 -#define UART_ODD_PARITY 0x08 -#define UART_EVEN_PARITY 0x18 - -/* The type of word length. */ -#define UART_5BITS_WORD 0x00 -#define UART_6BITS_WORD 0x01 -#define UART_7BITS_WORD 0x02 -#define UART_8BITS_WORD 0x03 - -/* The type of the length of stop bit. */ -#define UART_1_STOP_BIT 0x00 -#define UART_2_STOP_BITS 0x04 - -/* the switch of DLAB. */ -#define UART_DLAB 0x80 - -/* Enable the FIFO. */ -#define UART_ENABLE_FIFO 0xC7 - -/* Turn on DTR, RTS, and OUT2. */ -#define UART_ENABLE_MODEM 0x0B - - -/* Function prototypes. */ - -/* Fetch a key. */ -int serial_hw_fetch (void); - -/* Put a character. */ -void serial_hw_put (int c); - -/* Insert a delay. */ -void serial_hw_delay (void); - -/* Return the port number for the UNITth serial device. */ -unsigned short serial_hw_get_port (int unit); - -/* Initialize a serial device. */ -int serial_hw_init (unsigned short port, unsigned int speed, - int word_len, int parity, int stop_bit_len); - -#endif /* ! GRUB_SERIAL_HEADER */ diff --git a/stage2/shared.h b/stage2/shared.h index 3d0f232a..85ab14ca 100644 --- a/stage2/shared.h +++ b/stage2/shared.h @@ -26,6 +26,26 @@ #define GRUB_SHARED_HEADER 1 #include +/* Disable all gcc warnings */ +#if 0 //调试时设置为0,显示警告信息 +#if defined (__GNUC__) && defined (__GNUC_MINOR__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ > 8)) || (__GNUC__ >= 5)) +#pragma GCC diagnostic ignored "-Wunused-value" +#endif + +#if defined (__GNUC__) && (__GNUC__ >= 6) +#pragma GCC diagnostic ignored "-Wmisleading-indentation" +#endif + +#if defined (__GNUC__) && (__GNUC__ >= 10) +#pragma GCC diagnostic ignored "-Warray-bounds" +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#pragma GCC diagnostic ignored "-Waddress-of-packed-member" +#endif +#endif +//UEFI 编译开关 +#define GDPUP 0 //使用设备路径实用程序协议 低版本UEFI固件不支持 +#define UNMAP 1 //卸载映像 +#define VHD_DIFFERENCE 0 //使用扇区序列读,支持差分 /* Add an underscore to a C symbol in assembler code if needed. */ #ifdef HAVE_ASM_USCORE @@ -47,75 +67,36 @@ * Reserved memory by grub4dos system kernel */ -#define SYSTEM_RESERVED_MEMORY 0x2000000 #define LINUX_TMP_MEMORY 0x2600000 +#define LINUX_TMP_MEMORY_LEN 0x36000000 +#define LINUX_INITRD_MAX_ADDRESSLINUX 0x38000000 -/* unifont start at 24M */ -#define UNIFONT_START 0x1800000 -#define UNIFONT_START_SIZE 0x800000 //32*32 - -//#define narrow_char_indicator (*(unsigned long *)(UNIFONT_START + ('A' << 5))) -#define narrow_char_indicator (*(unsigned long *)(UNIFONT_START + 'A'*num_wide*font_h)) - -/* graphics video memory */ -#define VIDEOMEM 0xA0000 +//#define narrow_char_indicator (*(unsigned int *)(UNIFONT_START + 'A'*num_wide*font_h)) // /* Maximum command line size. Before you blindly increase this value, see the comment in char_io.c (get_cmdline). */ #define MAX_CMDLINE 1600 #define NEW_HEAPSIZE 1500 -/* 512-byte scratch area */ -/* more than 1 sector used! See chainloader code. */ -#define SCRATCHADDR RAW_ADDR (0x1F000) -#define SCRATCHSEG RAW_SEG (0x1F00) - /* * This is the location of the raw device buffer. It is 31.5K * in size. */ -/* BUFFERLEN must be a power of two, i.e., 2^n, or 2**n */ -/* BUFFERLEN must be 64K for now! */ #define BUFFERLEN 0x10000 -#define BUFFERADDR RAW_ADDR (0x30000) -#define BUFFERSEG RAW_SEG (0x3000) - -#define BOOT_PART_TABLE RAW_ADDR (0x07be) - -/* - * BIOS disk defines - */ -#define BIOSDISK_READ 0x0 -#define BIOSDISK_WRITE 0x1 -#define BIOSDISK_ERROR_GEOMETRY 0x100 -#define BIOSDISK_FLAG_LBA_EXTENSION 0x1 -#define BIOSDISK_FLAG_CDROM 0x2 -#define BIOSDISK_FLAG_BIFURCATE 0x4 /* accessibility acts differently between chs and lba */ -#define BIOSDISK_FLAG_GEOMETRY_OK 0x8 -#define BIOSDISK_FLAG_LBA_1_SECTOR 0x10 +#define BOOT_PART_TABLE RAW_ADDR (0x07be) /* - * This is the filesystem (not raw device) buffer. - * It is 32K in size, do not overrun! - */ - -#define FSYS_BUFLEN 0x8000 -#define FSYS_BUF RAW_ADDR (0x3E0000) - -/* Paging structure : PML4, PDPT, PD 4096-bytes each */ -/* Memory area from 0x50000 to the end of low memory is used by gfxmenu. So we - * should not use 0x60000 for page tables. And all other free room in the low - * memory is reserved. So we should use extended memory if possible. - * Currently we use the ending 16K of the first 16M. -- tinybit - * - * Big problem! Some chipset use 1M at 15M. -- tinybit 2012-11-01 + * BIOS disk defines BIOS磁盘定义 */ - -//#define PAGING_TABLES_BUF 0x60000 -//#define PAGING_TABLES_BUF 0xFFC000 -#define PAGING_TABLES_BUF 0xEFC000 -#define PAGING_TABLES_BUFLEN 0x4000 +#define BIOSDISK_READ 0x0 //读 +#define BIOSDISK_WRITE 0x1 //写 +#define BIOSDISK_ERROR_GEOMETRY 0x100 //几何错误 +#define BIOSDISK_FLAG_LBA_EXTENSION 0x1 //LBA扩展标志 +#define BIOSDISK_FLAG_CDROM 0x2 //CDROM标记 +#define BIOSDISK_FLAG_BIFURCATE 0x4 /* accessibility acts differently between chs and lba */ //分叉标记 +#define BIOSDISK_FLAG_GEOMETRY_OK 0x8 //几何ok +#define BIOSDISK_FLAG_LBA_1_SECTOR 0x10 //读1扇区标记 /* Command-line buffer for Multiboot kernels and modules. This area includes the area into which Stage 1.5 and Stage 1 are loaded, but @@ -123,60 +104,21 @@ #define MB_CMDLINE_BUF RAW_ADDR (0x7000) #define MB_CMDLINE_BUFLEN 0x1000 -//#define FSYS_BUF 0x3E0000 -//#define FSYS_BUFLEN 0x008000 - -//#define PART_TABLE_BUF 0x3E8000 -#define PART_TABLE_BUF (FSYS_BUF + FSYS_BUFLEN) -#define PART_TABLE_BUFLEN 0x001000 - -//#define PART_TABLE_TMPBUF 0x3E9000 -#define PART_TABLE_TMPBUF (PART_TABLE_BUF + PART_TABLE_BUFLEN) -#define PART_TABLE_TMPBUFLEN 0x000200 - -//#define CMDLINE_BUF 0x3E9200 -#define CMDLINE_BUF (PART_TABLE_TMPBUF + PART_TABLE_TMPBUFLEN) -#define CMDLINE_BUFLEN 0x000640 - -/* The buffer for the completion. */ -//#define COMPLETION_BUF 0x3E9840 -#define COMPLETION_BUF (CMDLINE_BUF + CMDLINE_BUFLEN) -#define COMPLETION_BUFLEN 0x000640 - -/* The buffer for the unique string. */ -//#define UNIQUE_BUF 0x3E9E80 -#define UNIQUE_BUF (COMPLETION_BUF + COMPLETION_BUFLEN) -#define UNIQUE_BUFLEN 0x000640 - /* The history buffer for the command-line. */ -//#define HISTORY_BUF 0x3EA4C0 -#define HISTORY_BUF (UNIQUE_BUF + UNIQUE_BUFLEN) #define HISTORY_SIZE 5 -//#define HISTORY_BUFLEN 0x001F40 -#define HISTORY_BUFLEN (MAX_CMDLINE * HISTORY_SIZE) - -///* THe buffer for the filename of "/boot/grub/default". */ -//#define DEFAULT_FILE_BUF (PASSWORD_BUF + PASSWORD_BUFLEN) -//#define DEFAULT_FILE_BUFLEN 0x60 - -/* graphics.c uses 0x3A0000 - 0x3DA980 and 0x3FC000 - 0x3FF9D0 */ /* The size of the drive map. */ -#define MAP_NUM_16 1 - -#if MAP_NUM_16 -#define DRIVE_MAP_SIZE 16 -#else #define DRIVE_MAP_SIZE 8 -#endif /* The size of the drive_map_slot struct. */ -#define DRIVE_MAP_SLOT_SIZE 24 +//#define DRIVE_MAP_SLOT_SIZE 0x70 /* The fragment of the drive map. */ -#define DRIVE_MAP_FRAGMENT 32 +//#define DRIVE_MAP_FRAGMENT 0x27 +#define DRIVE_MAP_FRAGMENT 0x7E -#define FRAGMENT_MAP_SLOT_SIZE 0x280 +//#define FRAGMENT_MAP_SLOT_SIZE 0x280 +#define FRAGMENT_MAP_SLOT_SIZE 0x800 /* The size of the key map. */ #define KEY_MAP_SIZE 128 @@ -185,7 +127,7 @@ * extended chainloader code address for switching to real mode */ -#define HMA_ADDR 0x2B0000 +//#define HMA_ADDR 0x2B0000 /* * Linux setup parameters @@ -382,22 +324,23 @@ #define ACS_DARROW 'v' /* Special graphics characters for IBM displays. */ -#define DISP_UL (menu_border.disp_ul) -#define DISP_UR (menu_border.disp_ur) -#define DISP_LL (menu_border.disp_ll) -#define DISP_LR (menu_border.disp_lr) -#define DISP_HORIZ (menu_border.disp_horiz) -#define DISP_VERT (menu_border.disp_vert) -#define DISP_LEFT 0x1b -#define DISP_RIGHT 0x1a -#define DISP_UP 0x18 -#define DISP_DOWN 0x19 +#define DISP_UL 0x250c +#define DISP_UR 0x2510 +#define DISP_LL 0x2514 +#define DISP_LR 0x2518 +#define DISP_HORIZ 0x2500 +#define DISP_VERT 0x2502 +#define DISP_LEFT 0x2190 //0x1b +#define DISP_RIGHT 0x2192 //0x1a +#define DISP_UP 0x2191 //0x18 +#define DISP_DOWN 0x2193 //0x19 /* Remap some libc-API-compatible function names so that we prevent circularararity. */ #ifndef WITHOUT_LIBC_STUBS #define memmove grub_memmove #define memcpy grub_memmove /* we don't need a separate memcpy */ +#define grub_memcpy grub_memmove #define memset grub_memset #define isspace grub_isspace #define printf grub_printf @@ -450,42 +393,473 @@ #define gfx_ofs_v2_args_entry_len 0x88 #define gfx_ofs_v2_timeout 0x8c +//================================================================================================================================ #ifndef ASM_FILE + +#define IMG(x) ((x) - 0x8200 + g4e_data) +//--------------------------------------------------------------------------------------------------- +//grub/term.h +#define GRUB_TERM_NO_KEY 0 + +/* Internal codes used by GRUB to represent terminal input. GRUB用来表示终端输入的内部代码 */ +/* Only for keys otherwise not having shifted modification. 仅用于键,否则没有移位修改 */ +#define GRUB_TERM_SHIFT 0x01000000 +#define GRUB_TERM_CTRL 0x02000000 +#define GRUB_TERM_ALT 0x04000000 + +/* Keys without associated character. 没有关联字符的键 */ +#define GRUB_TERM_EXTENDED 0x00800000 //扩展 +#define GRUB_TERM_KEY_MASK 0x00ffffff //多重移幅键控 + +#define GRUB_TERM_KEY_LEFT (GRUB_TERM_EXTENDED | 0x4b) +#define GRUB_TERM_KEY_RIGHT (GRUB_TERM_EXTENDED | 0x4d) +#define GRUB_TERM_KEY_UP (GRUB_TERM_EXTENDED | 0x48) +#define GRUB_TERM_KEY_DOWN (GRUB_TERM_EXTENDED | 0x50) +#define GRUB_TERM_KEY_HOME (GRUB_TERM_EXTENDED | 0x47) +#define GRUB_TERM_KEY_END (GRUB_TERM_EXTENDED | 0x4f) +#define GRUB_TERM_KEY_DC (GRUB_TERM_EXTENDED | 0x53) +#define GRUB_TERM_KEY_PPAGE (GRUB_TERM_EXTENDED | 0x49) +#define GRUB_TERM_KEY_NPAGE (GRUB_TERM_EXTENDED | 0x51) +#define GRUB_TERM_KEY_F1 (GRUB_TERM_EXTENDED | 0x3b) +#define GRUB_TERM_KEY_F2 (GRUB_TERM_EXTENDED | 0x3c) +#define GRUB_TERM_KEY_F3 (GRUB_TERM_EXTENDED | 0x3d) +#define GRUB_TERM_KEY_F4 (GRUB_TERM_EXTENDED | 0x3e) +#define GRUB_TERM_KEY_F5 (GRUB_TERM_EXTENDED | 0x3f) +#define GRUB_TERM_KEY_F6 (GRUB_TERM_EXTENDED | 0x40) +#define GRUB_TERM_KEY_F7 (GRUB_TERM_EXTENDED | 0x41) +#define GRUB_TERM_KEY_F8 (GRUB_TERM_EXTENDED | 0x42) +#define GRUB_TERM_KEY_F9 (GRUB_TERM_EXTENDED | 0x43) +#define GRUB_TERM_KEY_F10 (GRUB_TERM_EXTENDED | 0x44) +#define GRUB_TERM_KEY_F11 (GRUB_TERM_EXTENDED | 0x57) +#define GRUB_TERM_KEY_F12 (GRUB_TERM_EXTENDED | 0x58) +#define GRUB_TERM_KEY_INSERT (GRUB_TERM_EXTENDED | 0x52) +#define GRUB_TERM_KEY_CENTER (GRUB_TERM_EXTENDED | 0x4c) + +/* Hex value is used for ESC, since '\e' is nonstandard. 十六进制值用于ESC,因为“\e”是非标准的 */ +#define GRUB_TERM_ESC 0x1b +#define GRUB_TERM_TAB '\t' +#define GRUB_TERM_BACKSPACE '\b' + +#define GRUB_PROGRESS_NO_UPDATE -1 //没有进行更新 +#define GRUB_PROGRESS_FAST 0 //进展快速 +#define GRUB_PROGRESS_SLOW 2 //进展缓慢 + +//----------------------------------------------------------------------------------------------------- +//grub/types.h + + + +//#if defined(__i386__) +//# define GRUB_CPU_SIZEOF_LONG 4 +//# define GRUB_CPU_SIZEOF_VOID_P 4 +//# define GRUB_TARGET_SIZEOF_VOID_P 4 +//#else +//# define GRUB_CPU_SIZEOF_LONG 8 +//# define GRUB_CPU_SIZEOF_VOID_P 8 +//# define GRUB_TARGET_SIZEOF_VOID_P 8 +//#endif + +#define GRUB_CPU_WORDS_BIGENDIAN 0 //小端 +#define GRUB_PACKED __attribute__ ((packed)) + +typedef unsigned long long grub_uint64_t; +typedef long long grub_int64_t; +typedef int grub_int32_t; +typedef unsigned int grub_uint32_t; +typedef long long grub_s64_t; +typedef unsigned long long grub_u64_t; + +//#if GRUB_CPU_SIZEOF_LONG == 8 //8 x86_64 +#if !defined(__i386__) +typedef grub_uint64_t grub_size_t; +typedef grub_int64_t grub_ssize_t; +#else +typedef grub_uint32_t grub_size_t; +typedef grub_int32_t grub_ssize_t; +#endif + +typedef grub_size_t grub_efi_uintn_t; +typedef grub_ssize_t grub_efi_intn_t; +typedef grub_size_t grub_addr_t; + + +/* Define various wide integers. 定义各种宽度整数 */ +typedef char grub_int8_t; +typedef short grub_int16_t; +typedef unsigned char grub_uint8_t; +typedef unsigned short grub_uint16_t; +typedef grub_uint64_t grub_properly_aligned_t; +typedef grub_uint64_t grub_off_t; //表示文件偏移量的类型 +typedef grub_uint64_t grub_disk_addr_t; //表示磁盘块地址的类型 + + typedef unsigned char grub_u8_t; typedef unsigned short grub_u16_t; typedef unsigned int grub_u32_t; -typedef unsigned long long grub_u64_t; -typedef signed char grub_s8_t; -typedef short grub_s16_t; -typedef int grub_s32_t; -typedef long long grub_s64_t; +typedef char grub_s8_t; +typedef short grub_s16_t; +typedef int grub_s32_t; #define PACKED __attribute__ ((packed)) +typedef unsigned long long grub_efi_uint64_t; +typedef long long grub_efi_int64_t; +typedef unsigned int grub_efi_uint32_t; +typedef int grub_efi_int32_t; +/* Types. 类型 */ +typedef char grub_efi_boolean_t; +//#if GRUB_CPU_SIZEOF_VOID_P == 8 +//#if !defined(__i386__) +//typedef long long grub_efi_intn_t; +//typedef unsigned long long grub_efi_uintn_t; +//#else +//typedef int grub_efi_intn_t; +//typedef unsigned int grub_efi_uintn_t; +//#endif + +typedef char grub_efi_int8_t; +typedef unsigned char grub_efi_uint8_t; +typedef short grub_efi_int16_t; +typedef unsigned short grub_efi_uint16_t; +typedef unsigned char grub_efi_char8_t; +typedef unsigned short grub_efi_char16_t; + +struct grub_efi_guid +{ + grub_uint32_t data1; + grub_uint16_t data2; + grub_uint16_t data3; + grub_uint8_t data4[8]; +} __attribute__ ((aligned(8))); +typedef struct grub_efi_guid grub_efi_guid_t; + +typedef grub_efi_intn_t grub_efi_status_t; + + +typedef grub_int8_t BOOLEAN; +typedef grub_efi_intn_t INTN; +typedef grub_efi_uintn_t UINTN; +typedef grub_int8_t INT8; +typedef grub_uint8_t UINT8; +typedef grub_int16_t INT16; +typedef grub_uint16_t UINT16; +typedef int INT32; +typedef unsigned int UINT32; +typedef grub_int64_t INT64; +typedef grub_uint64_t UINT64; +typedef grub_uint8_t CHAR8; +typedef grub_uint16_t CHAR16; +typedef void VOID; +typedef grub_efi_guid_t EFI_GUID; +typedef UINTN EFI_STATUS; +typedef void* EFI_HANDLE; +typedef void* EFI_EVENT; +typedef UINT64 EFI_LBA; +typedef UINTN EFI_TPL; +typedef unsigned int EFI_MAC_ADDRESS; +typedef unsigned int EFI_IPv4_ADDRESS; +typedef grub_uint16_t EFI_IPv6_ADDRESS; +typedef grub_uint16_t EFI_IP_ADDRESS; + +#define INT128 char[128] +#define UINT128 unsigned char[128] +#define TRUE 1 +#define FALSE 0 + +/* +IN 基准传递给函数。 +OUT 从该函数返回原点。 +OPTIONAL 将数据传递给函数是可选的,如果未提供该值,则可以传递NULL。 +CONST 基准是只读的。 +EFIAPI 定义UEFI接口的调用约定。 +*/ +#define offsetof(TYPE, MEMBER) ((grub_size_t) &((TYPE *)0)->MEMBER) +//============================================================================= + +# define PRIxGRUB_UINT32_T "x" +# define PRIuGRUB_UINT32_T "u" + +//#if GRUB_CPU_SIZEOF_LONG == 8 //8 x86_64 +#if !defined(__i386__) +# define PRIxGRUB_UINT64_T "lx" +# define PRIuGRUB_UINT64_T "lu" +#else +# define PRIxGRUB_UINT64_T "llx" +# define PRIuGRUB_UINT64_T "llu" +#endif + +/* Misc types. 其他类型 */ + +//#if GRUB_CPU_SIZEOF_VOID_P == 8 //8 x86_64 +#if !defined(__i386__) +# define GRUB_SIZE_MAX 18446744073709551615UL +//# if GRUB_CPU_SIZEOF_LONG == 8 //8 x86_64 +# define PRIxGRUB_SIZE "lx" +# define PRIxGRUB_ADDR "lx" +# define PRIuGRUB_SIZE "lu" +# define PRIdGRUB_SSIZE "ld" +//# else +//# define PRIxGRUB_SIZE "llx" +//# define PRIxGRUB_ADDR "llx" +//# define PRIuGRUB_SIZE "llu" +//# define PRIdGRUB_SSIZE "lld" +//# endif +#else +# define GRUB_SIZE_MAX 4294967295UL +# define PRIxGRUB_SIZE "x" +# define PRIxGRUB_ADDR "x" +# define PRIuGRUB_SIZE "u" +# define PRIdGRUB_SSIZE "d" +#endif + +#define GRUB_UCHAR_MAX 0xFF +#define GRUB_USHRT_MAX 65535 +#define GRUB_SHRT_MAX 0x7fff +#define GRUB_UINT_MAX 4294967295U +#define GRUB_INT_MAX 0x7fffffff +#define GRUB_INT32_MIN (-2147483647 - 1) +#define GRUB_INT32_MAX 2147483647 + +//#if GRUB_CPU_SIZEOF_LONG == 8 //8 x86_64 +#if !defined(__i386__) +# define GRUB_ULONG_MAX 18446744073709551615UL +# define GRUB_LONG_MAX 9223372036854775807L +# define GRUB_LONG_MIN (-9223372036854775807L - 1) +#else +# define GRUB_ULONG_MAX 4294967295UL +# define GRUB_LONG_MAX 2147483647L +# define GRUB_LONG_MIN (-2147483647L - 1) +#endif + + + +#define GRUB_PROPERLY_ALIGNED_ARRAY(name, size) grub_properly_aligned_t name[((size) + sizeof (grub_properly_aligned_t) - 1) / sizeof (grub_properly_aligned_t)] + + + +/* Byte-orders. */ +static inline grub_uint16_t grub_swap_bytes16(grub_uint16_t _x) +{ + return (grub_uint16_t) ((_x << 8) | (_x >> 8)); +} + +#define grub_swap_bytes16_compile_time(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8)) +#define grub_swap_bytes32_compile_time(x) ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) | (((x) & 0xff0000) >> 8) | (((x) & 0xff000000UL) >> 24)) +#define grub_swap_bytes64_compile_time(x) \ +({ \ + grub_uint64_t _x = (x); \ + (grub_uint64_t) ((_x << 56) \ + | ((_x & (grub_uint64_t) 0xFF00ULL) << 40) \ + | ((_x & (grub_uint64_t) 0xFF0000ULL) << 24) \ + | ((_x & (grub_uint64_t) 0xFF000000ULL) << 8) \ + | ((_x & (grub_uint64_t) 0xFF00000000ULL) >> 8) \ + | ((_x & (grub_uint64_t) 0xFF0000000000ULL) >> 24) \ + | ((_x & (grub_uint64_t) 0xFF000000000000ULL) >> 40) \ + | (_x >> 56)); \ +}) + +#if (defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3)) || defined(__clang__) +static inline grub_uint32_t grub_swap_bytes32(grub_uint32_t x) +{ + return __builtin_bswap32(x); +} + +static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t x) +{ + return __builtin_bswap64(x); +} +#else /* not gcc 4.3 or newer */ +static inline grub_uint32_t grub_swap_bytes32(grub_uint32_t _x) +{ + return ((_x << 24) + | ((_x & (grub_uint32_t) 0xFF00UL) << 8) + | ((_x & (grub_uint32_t) 0xFF0000UL) >> 8) + | (_x >> 24)); +} + +static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t _x) +{ + return ((_x << 56) + | ((_x & (grub_uint64_t) 0xFF00ULL) << 40) + | ((_x & (grub_uint64_t) 0xFF0000ULL) << 24) + | ((_x & (grub_uint64_t) 0xFF000000ULL) << 8) + | ((_x & (grub_uint64_t) 0xFF00000000ULL) >> 8) + | ((_x & (grub_uint64_t) 0xFF0000000000ULL) >> 24) + | ((_x & (grub_uint64_t) 0xFF000000000000ULL) >> 40) + | (_x >> 56)); +} +#endif /* not gcc 4.3 or newer */ + +//#ifdef GRUB_CPU_WORDS_BIGENDIAN //大端 +#if GRUB_CPU_WORDS_BIGENDIAN //大端 +# define grub_cpu_to_le16(x) grub_swap_bytes16(x) +# define grub_cpu_to_le32(x) grub_swap_bytes32(x) +# define grub_cpu_to_le64(x) grub_swap_bytes64(x) +# define grub_le_to_cpu16(x) grub_swap_bytes16(x) +# define grub_le_to_cpu32(x) grub_swap_bytes32(x) +# define grub_le_to_cpu64(x) grub_swap_bytes64(x) +# define grub_cpu_to_be16(x) ((grub_uint16_t) (x)) +# define grub_cpu_to_be32(x) ((grub_uint32_t) (x)) +# define grub_cpu_to_be64(x) ((grub_uint64_t) (x)) +# define grub_be_to_cpu16(x) ((grub_uint16_t) (x)) +# define grub_be_to_cpu32(x) ((grub_uint32_t) (x)) +# define grub_be_to_cpu64(x) ((grub_uint64_t) (x)) +# define grub_cpu_to_be16_compile_time(x) ((grub_uint16_t) (x)) +# define grub_cpu_to_be32_compile_time(x) ((grub_uint32_t) (x)) +# define grub_cpu_to_be64_compile_time(x) ((grub_uint64_t) (x)) +# define grub_be_to_cpu64_compile_time(x) ((grub_uint64_t) (x)) +# define grub_cpu_to_le32_compile_time(x) grub_swap_bytes32_compile_time(x) +# define grub_cpu_to_le64_compile_time(x) grub_swap_bytes64_compile_time(x) +# define grub_cpu_to_le16_compile_time(x) grub_swap_bytes16_compile_time(x) +#else /* ! WORDS_BIGENDIAN */ //小端 +# define grub_cpu_to_le16(x) ((grub_uint16_t) (x)) +# define grub_cpu_to_le32(x) ((grub_uint32_t) (x)) +# define grub_cpu_to_le64(x) ((grub_uint64_t) (x)) +# define grub_le_to_cpu16(x) ((grub_uint16_t) (x)) +# define grub_le_to_cpu32(x) ((grub_uint32_t) (x)) +# define grub_le_to_cpu64(x) ((grub_uint64_t) (x)) +# define grub_cpu_to_be16(x) grub_swap_bytes16(x) +# define grub_cpu_to_be32(x) grub_swap_bytes32(x) +# define grub_cpu_to_be64(x) grub_swap_bytes64(x) +# define grub_be_to_cpu16(x) grub_swap_bytes16(x) +# define grub_be_to_cpu32(x) grub_swap_bytes32(x) +# define grub_be_to_cpu64(x) grub_swap_bytes64(x) +# define grub_cpu_to_be16_compile_time(x) grub_swap_bytes16_compile_time(x) +# define grub_cpu_to_be32_compile_time(x) grub_swap_bytes32_compile_time(x) +# define grub_cpu_to_be64_compile_time(x) grub_swap_bytes64_compile_time(x) +# define grub_be_to_cpu64_compile_time(x) grub_swap_bytes64_compile_time(x) +# define grub_cpu_to_le16_compile_time(x) ((grub_uint16_t) (x)) +# define grub_cpu_to_le32_compile_time(x) ((grub_uint32_t) (x)) +# define grub_cpu_to_le64_compile_time(x) ((grub_uint64_t) (x)) +#endif /* ! WORDS_BIGENDIAN */ + +struct grub_unaligned_uint16 +{ + grub_uint16_t val; +} GRUB_PACKED; +struct grub_unaligned_uint32 +{ + grub_uint32_t val; +} GRUB_PACKED; +struct grub_unaligned_uint64 +{ + grub_uint64_t val; +} GRUB_PACKED; + +typedef struct grub_unaligned_uint16 grub_unaligned_uint16_t; +typedef struct grub_unaligned_uint32 grub_unaligned_uint32_t; +typedef struct grub_unaligned_uint64 grub_unaligned_uint64_t; + +static inline grub_uint16_t grub_get_unaligned16 (const void *ptr) +{ + const struct grub_unaligned_uint16 *dd + = (const struct grub_unaligned_uint16 *) ptr; + return dd->val; +} + +static inline void grub_set_unaligned16 (void *ptr, grub_uint16_t val) +{ + struct grub_unaligned_uint16 *dd = (struct grub_unaligned_uint16 *) ptr; + dd->val = val; +} + +static inline grub_uint32_t grub_get_unaligned32 (const void *ptr) +{ + const struct grub_unaligned_uint32 *dd + = (const struct grub_unaligned_uint32 *) ptr; + return dd->val; +} + +static inline void grub_set_unaligned32 (void *ptr, grub_uint32_t val) +{ + struct grub_unaligned_uint32 *dd = (struct grub_unaligned_uint32 *) ptr; + dd->val = val; +} + +static inline grub_uint64_t grub_get_unaligned64 (const void *ptr) +{ + const struct grub_unaligned_uint64 *dd + = (const struct grub_unaligned_uint64 *) ptr; + return dd->val; +} + +static inline void grub_set_unaligned64 (void *ptr, grub_uint64_t val) +{ + struct grub_unaligned_uint64_t + { + grub_uint64_t d; + } GRUB_PACKED; + struct grub_unaligned_uint64_t *dd = (struct grub_unaligned_uint64_t *) ptr; + dd->d = val; +} + +//------------------------------------------------------------------------------------------------- +//UEFI 函数调用约定 只支持 GCC4.7及以上版本 +#if !defined(__i386__) +#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)))||(defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 2))) + #define EFIAPI __attribute__((ms_abi)) +#else + #error Compiler is too old for GNU_EFI_USE_MS_ABI +#endif +#endif + +#ifndef EFIAPI + #define EFIAPI // Substitute expresion to force C calling convention +#endif + +#define GRUB_CHAR_BIT 8 +//----------------------------------------------------------------------------------------------- +//#include 可变参数定义 +#ifndef _VA_LIST +typedef __builtin_va_list va_list; +#define _VA_LIST +#endif +#define va_start(ap, param) __builtin_va_start(ap, param) +#define va_end(ap) __builtin_va_end(ap) +#define va_arg(ap, type) __builtin_va_arg(ap, type) + +/* GCC always defines __va_copy, but does not define va_copy unless in c99 mode + * or -ansi is not specified, since it was not part of C90. + */ +#define __va_copy(d,s) __builtin_va_copy(d,s) +#ifndef __GNUC_VA_LIST +#define __GNUC_VA_LIST 1 +typedef __builtin_va_list __gnuc_va_list; +#endif + +//---------------------------------------------------------------------------------------------- + /* * Below this should be ONLY defines and other constructs for C code. */ /* function prototypes for asm functions */ unsigned char * graphics_get_font(); -void graphics_set_palette(int idx, int color); -unsigned long long color_8_to_64 (unsigned char color8); -unsigned long long color_4_to_32 (unsigned char color4); -extern int console_color[6]; -extern unsigned long long console_color_64bit[6]; -extern unsigned long current_color; +extern unsigned long long color_8_to_64 (unsigned char color8); +extern unsigned long long color_4_to_32 (unsigned char color4); +extern unsigned char color_64_to_8 (unsigned long long color64); +extern unsigned char color_32_to_4 (unsigned int color32); +extern unsigned int current_color; extern unsigned long long current_color_64bit; -extern unsigned long cursor_state; -extern unsigned long graphics_mode; -extern unsigned long font_w; -extern unsigned long font_h; +extern unsigned int cursor_state; +extern unsigned int OnCommandLine; +extern unsigned int graphics_mode; +extern unsigned int font_w; +extern unsigned int font_h; extern unsigned char num_wide; -extern unsigned long font_spacing; -extern unsigned long line_spacing; +extern unsigned int font_spacing; +extern unsigned int line_spacing; extern void rectangle(int left, int top, int length, int width, int line); -extern int hex (int v); -extern unsigned long splashimage_loaded; -extern unsigned long X_offset,Y_offset; +//extern int hex (int v); +extern unsigned int splashimage_loaded; +extern unsigned int X_offset,Y_offset; +extern int console_color[]; +extern unsigned long long console_color_64bit[]; +extern unsigned int console_print_unicode (unsigned int unicode, unsigned int max_width); +extern void console_putstr_utf8 (char *str); +extern void console_putstr_utf16(unsigned short *str); +extern unsigned int is_highlight; +extern unsigned int graphics_inited; struct box { unsigned char enable; @@ -494,7 +868,7 @@ struct box unsigned short horiz; unsigned short vert; unsigned char linewidth; - unsigned long color; + unsigned int color; } __attribute__ ((packed)); extern struct box DrawBox[16]; struct string @@ -509,8 +883,6 @@ struct string extern struct string* strings; extern unsigned char DateTime_enable; extern void DateTime_refresh(void); -#define MENU_TITLE 0x3A8000 -#define MENU_TITLE_LENGTH 0x800 /* The Chinese patch will begin at here */ /* multiboot stuff */ @@ -534,30 +906,251 @@ struct linux_kernel_header unsigned short root_dev; /* Default root device number */ unsigned short boot_flag; /* 0xAA55 magic number */ unsigned short jump; /* Jump instruction */ - unsigned long header; /* Magic signature "HdrS" */ - unsigned short version; /* Boot protocol version supported */ - unsigned long realmode_swtch; /* Boot loader hook */ - unsigned long start_sys; /* Points to kernel version string */ + unsigned int header; /* Magic signature "HdrS" */ + unsigned short version; /* Boot protocol version supported 支持的引导协议版本*/ + unsigned int realmode_swtch; /* Boot loader hook */ + unsigned int start_sys; /* Points to kernel version string */ unsigned char type_of_loader; /* Boot loader identifier */ unsigned char loadflags; /* Boot protocol option flags */ unsigned short setup_move_size; /* Move to high memory size */ - unsigned long code32_start; /* Boot loader hook */ - unsigned long ramdisk_image; /* initrd load address */ - unsigned long ramdisk_size; /* initrd size */ - unsigned long bootsect_kludge; /* obsolete */ + unsigned int code32_start; /* Boot loader hook */ + unsigned int ramdisk_image; /* initrd load address */ + unsigned int ramdisk_size; /* initrd size */ + unsigned int bootsect_kludge; /* obsolete */ unsigned short heap_end_ptr; /* Free memory after setup end */ unsigned short pad1; /* Unused */ - char *cmd_line_ptr; /* Points to the kernel command line */ - unsigned long initrd_addr_max; /* The highest address of initrd */ + unsigned int cmd_line_ptr; /* Points to the kernel command line */ + unsigned int initrd_addr_max; /* The highest address of initrd */ + unsigned int kernel_alignment; + unsigned char relocatable; + unsigned char min_alignment; +#define LINUX_XLF_KERNEL_64 (1<<0) //1 64位内内核 +#define LINUX_XLF_CAN_BE_LOADED_ABOVE_4G (1<<1) //2 可加载4G以上 +#define LINUX_XLF_EFI_HANDOVER_32 (1<<2) //4 支持 EFI32 Handover +#define LINUX_XLF_EFI_HANDOVER_64 (1<<3) //8 支持 EFI64 Handover +#define LINUX_XLF_EFI_KEXEC (1<<4) //16 + unsigned short xloadflags; + unsigned int cmdline_size; + unsigned int hardware_subarch; + unsigned long long hardware_subarch_data; + unsigned int payload_offset; + unsigned int payload_length; + unsigned long long setup_data; + unsigned long long pref_address; + unsigned int init_size; + unsigned int handover_offset; +} __attribute__ ((packed)); + +#define GRUB_E820_RAM 1 +#define GRUB_E820_RESERVED 2 +#define GRUB_E820_ACPI 3 +#define GRUB_E820_NVS 4 +#define GRUB_E820_BADRAM 5 + +struct grub_e820_mmap +{ + unsigned long long addr; + unsigned long long size; + unsigned int type; +} __attribute__ ((unused)); + +#define LINUX_IMAGE "BOOT_IMAGE=" + +/* Maximum number of MBR signatures to store. */ +#define EDD_MBR_SIG_MAX 16 + +#define GRUB_LINUX_I386_MAGIC_SIGNATURE 0x53726448 /* "HdrS" */ +#define GRUB_LINUX_DEFAULT_SETUP_SECTS 4 +#define GRUB_LINUX_INITRD_MAX_ADDRESS 0x37FFFFFF +#define GRUB_LINUX_MAX_SETUP_SECTS 64 +#define GRUB_LINUX_BOOT_LOADER_TYPE 0x72 +#define GRUB_LINUX_HEAP_END_OFFSET (0x9000 - 0x200) + +/* Boot parameters for Linux based on 2.6.12. This is used by the setup + sectors of Linux, and must be simulated by GRUB on EFI, because + the setup sectors depend on BIOS. */ +struct linux_kernel_params +{ + unsigned char video_cursor_x; /* 0 */ + unsigned char video_cursor_y; + + unsigned short ext_mem; /* 2 */ + + unsigned short video_page; /* 4 */ + unsigned char video_mode; /* 6 */ + unsigned char video_width; /* 7 */ + + unsigned char padding1[0xa - 0x8]; + + unsigned short video_ega_bx; /* a */ + + unsigned char padding2[0xe - 0xc]; + + unsigned char video_height; /* e */ + unsigned char have_vga; /* f */ + unsigned short font_size; /* 10 */ + + unsigned short lfb_width; /* 12 */ + unsigned short lfb_height; /* 14 */ + unsigned short lfb_depth; /* 16 */ + unsigned int lfb_base; /* 18 */ + unsigned int lfb_size; /* 1c */ + + unsigned short cl_magic; /* 20 */ + unsigned short cl_offset; + + unsigned short lfb_line_len; /* 24 */ + unsigned char red_mask_size; /* 26 */ + unsigned char red_field_pos; + unsigned char green_mask_size; + unsigned char green_field_pos; + unsigned char blue_mask_size; + unsigned char blue_field_pos; + unsigned char reserved_mask_size; + unsigned char reserved_field_pos; + unsigned short vesapm_segment; /* 2e */ + unsigned short vesapm_offset; /* 30 */ + unsigned short lfb_pages; /* 32 */ + unsigned short vesa_attrib; /* 34 */ + unsigned int capabilities; /* 36 */ + unsigned int ext_lfb_base; /* 3a */ + + unsigned char padding3[0x40 - 0x3e]; + + unsigned short apm_version; /* 40 */ + unsigned short apm_code_segment; /* 42 */ + unsigned int apm_entry; /* 44 */ + unsigned short apm_16bit_code_segment; /* 48 */ + unsigned short apm_data_segment; /* 4a */ + unsigned short apm_flags; /* 4c */ + unsigned int apm_code_len; /* 4e */ + unsigned short apm_data_len; /* 52 */ + + unsigned char padding4[0x60 - 0x54]; + + unsigned int ist_signature; /* 60 */ + unsigned int ist_command; /* 64 */ + unsigned int ist_event; /* 68 */ + unsigned int ist_perf_level; /* 6c */ + unsigned long long acpi_rsdp_addr; /* 70 */ + + unsigned char padding5[0x80 - 0x78]; + + unsigned char hd0_drive_info[0x10]; /* 80 */ + unsigned char hd1_drive_info[0x10]; /* 90 */ + unsigned short rom_config_len; /* a0 */ + + unsigned char padding6[0xb0 - 0xa2]; + + unsigned int ofw_signature; /* b0 */ + unsigned int ofw_num_items; /* b4 */ + unsigned int ofw_cif_handler; /* b8 */ + unsigned int ofw_idt; /* bc */ + + unsigned char padding7[0x1b8 - 0xc0]; + + union + { + struct + { + unsigned int efi_system_table; /* 1b8 */ + unsigned int padding7_1; /* 1bc */ + unsigned int efi_signature; /* 1c0 */ + unsigned int efi_mem_desc_size; /* 1c4 */ + unsigned int efi_mem_desc_version; /* 1c8 */ + unsigned int efi_mmap_size; /* 1cc */ + unsigned int efi_mmap; /* 1d0 */ + } v0204; + struct + { + unsigned int padding7_1; /* 1b8 */ + unsigned int padding7_2; /* 1bc */ + unsigned int efi_signature; /* 1c0 */ + unsigned int efi_system_table; /* 1c4 */ + unsigned int efi_mem_desc_size; /* 1c8 */ + unsigned int efi_mem_desc_version; /* 1cc */ + unsigned int efi_mmap; /* 1d0 */ + unsigned int efi_mmap_size; /* 1d4 */ + } v0206; + struct + { + unsigned int padding7_1; /* 1b8 */ + unsigned int padding7_2; /* 1bc */ + unsigned int efi_signature; /* 1c0 */ + unsigned int efi_system_table; /* 1c4 */ + unsigned int efi_mem_desc_size; /* 1c8 */ + unsigned int efi_mem_desc_version; /* 1cc */ + unsigned int efi_mmap; /* 1d0 */ + unsigned int efi_mmap_size; /* 1d4 */ + unsigned int efi_system_table_hi; /* 1d8 */ + unsigned int efi_mmap_hi; /* 1dc */ + } v0208; + }; + + unsigned int alt_mem; /* 1e0 */ + + unsigned char padding8[0x1e8 - 0x1e4]; + + unsigned char mmap_size; /* 1e8 */ + + unsigned char padding9[0x1f1 - 0x1e9]; + + /* Linux setup header copy - BEGIN. */ + unsigned char setup_sects; /* The size of the setup in sectors */ + unsigned short root_flags; /* If the root is mounted readonly */ + unsigned short syssize; /* obsolete */ + unsigned short swap_dev; /* obsolete */ + unsigned short ram_size; /* obsolete */ + unsigned short vid_mode; /* Video mode control */ + unsigned short root_dev; /* Default root device number */ + + unsigned char padding10; /* 1fe */ + unsigned char ps_mouse; /* 1ff */ + + unsigned short jump; /* Jump instruction */ + unsigned int header; /* Magic signature "HdrS" */ + unsigned short version; /* Boot protocol version supported */ + unsigned int realmode_swtch; /* Boot loader hook */ + unsigned short start_sys; /* The load-low segment (obsolete) */ + unsigned short kernel_version; /* Points to kernel version string */ + unsigned char type_of_loader; /* Boot loader identifier */ + unsigned char loadflags; /* Boot protocol option flags */ + unsigned short setup_move_size; /* Move to high memory size */ + unsigned int code32_start; /* Boot loader hook */ + unsigned int ramdisk_image; /* initrd load address */ + unsigned int ramdisk_size; /* initrd size */ + unsigned int bootsect_kludge; /* obsolete */ + unsigned short heap_end_ptr; /* Free memory after setup end */ + unsigned char ext_loader_ver; /* Extended loader version */ + unsigned char ext_loader_type; /* Extended loader type */ + unsigned int cmd_line_ptr; /* Points to the kernel command line */ + unsigned int initrd_addr_max; /* Maximum initrd address */ + unsigned int kernel_alignment; /* Alignment of the kernel */ + unsigned char relocatable_kernel; /* Is the kernel relocatable */ + unsigned char pad1[3]; + unsigned int cmdline_size; /* Size of the kernel command line */ + unsigned int hardware_subarch; + unsigned long long hardware_subarch_data; + unsigned int payload_offset; + unsigned int payload_length; + unsigned long long setup_data; + unsigned long long pref_address; + unsigned int init_size; + unsigned int handover_offset; //Handover 入口,没有那就不支持 Handover + /* Linux setup header copy - END. */ + + unsigned char _pad7[40]; + unsigned int edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 290 */ + struct grub_e820_mmap e820_map[(0x400 - 0x2d0) / 20]; /* 2d0 */ } __attribute__ ((packed)); /* Memory map address range descriptor used by GET_MMAP_ENTRY. */ struct mmar_desc { - unsigned long desc_len; /* Size of this descriptor. */ + unsigned int desc_len; /* Size of this descriptor. */ unsigned long long addr; /* Base address. */ unsigned long long length; /* Length in bytes. */ - unsigned long type; /* Type of address range. */ + unsigned int type; /* Type of address range. */ } __attribute__ ((packed)); /* VBE controller information. */ @@ -565,14 +1158,14 @@ struct vbe_controller { unsigned char signature[4]; unsigned short version; - unsigned long oem_string; - unsigned long capabilities; - unsigned long video_mode; + unsigned int oem_string; + unsigned int capabilities; + unsigned int video_mode; unsigned short total_memory; unsigned short oem_software_rev; - unsigned long oem_vendor_name; - unsigned long oem_product_name; - unsigned long oem_product_rev; + unsigned int oem_vendor_name; + unsigned int oem_product_name; + unsigned int oem_product_rev; unsigned char reserved[222]; unsigned char oem_data[256]; } __attribute__ ((packed)); @@ -587,7 +1180,7 @@ struct vbe_mode unsigned short win_size; unsigned short win_a_segment; unsigned short win_b_segment; - unsigned long win_func; + unsigned int win_func; unsigned short bytes_per_scanline; /* >=1.2 */ @@ -615,8 +1208,8 @@ struct vbe_mode unsigned char direct_color_mode_info; /* >=2.0 */ - unsigned long phys_base; - unsigned long reserved1; + unsigned int phys_base; + unsigned int reserved1; unsigned short reversed2; /* >=3.0 */ @@ -631,11 +1224,13 @@ struct vbe_mode unsigned char linear_blue_field_position; unsigned char linear_reserved_mask_size; unsigned char linear_reserved_field_position; - unsigned long max_pixel_clock; + unsigned int max_pixel_clock; unsigned char reserved3[189]; } __attribute__ ((packed)); +extern int graphicsmode_func (char *arg, int flags); +extern char splashimage[128]; #undef NULL #define NULL ((void *) 0) @@ -741,8 +1336,11 @@ typedef enum /* these are for batch scripts and must be > MAX_ERR_NUM */ ERR_BAT_GOTO, ERR_BAT_CALL, -} grub_error_t; + ERR_BAT_BRACE_END, +} grub_error_t; //4 +extern char *get_next_arg(char *arg); +extern int brace; struct border { unsigned char disp_ul; unsigned char disp_ur; @@ -762,28 +1360,24 @@ struct border { } __attribute__ ((packed)); extern struct border menu_border; -extern unsigned long fontx; -extern unsigned long fonty; -extern unsigned long install_partition; -extern unsigned long boot_drive; -//extern unsigned long install_second_sector; -//extern struct apm_info apm_bios_info; -extern unsigned long boot_part_addr; +extern unsigned int fontx; +extern unsigned int fonty; +extern unsigned int install_partition; +extern unsigned int boot_drive; +extern unsigned int boot_part_addr; extern int saved_entryno; extern unsigned char force_lba; extern char version_string[]; extern char config_file[]; -extern unsigned long linux_text_len; +extern unsigned int linux_text_len; extern char *linux_data_tmp_addr; extern char *linux_data_real_addr; extern char *linux_bzimage_tmp_addr; extern int quit_print; extern struct linux_kernel_header *linux_header; -extern unsigned long free_mem_start; -extern unsigned long free_mem_end; - extern unsigned char menu_tab; +extern unsigned char menu_tab_ext; extern unsigned char num_string; extern unsigned char menu_font_spacing; extern unsigned char menu_line_spacing; @@ -792,9 +1386,6 @@ extern unsigned char timeout_x; extern unsigned char timeout_y; extern unsigned long long timeout_color; extern unsigned long long keyhelp_color; -//extern unsigned char font_type; -//extern unsigned char scan_mode; -//extern unsigned char store_mode; extern unsigned char graphic_enable; extern unsigned char graphic_type; extern unsigned char graphic_row; @@ -804,16 +1395,25 @@ extern unsigned short graphic_high; extern unsigned short row_space; extern char graphic_file[128]; extern void clear_entry (int x, int y, int w, int h); -extern void vbe_fill_color (unsigned long color); +extern void vbe_fill_color (unsigned int color); +//extern int (*hotkey_func)(char *titles,int flags,int flags1); +extern int (*hotkey_func)(char *titles,int flags,int flags1,int key); //外置热键 +extern unsigned long long hotkey_color_64bit; +extern unsigned int hotkey_color; +extern int font_func (char *arg, int flags); +extern char embed_font_path[64]; +extern char *embed_font; +extern unsigned long long ext_data_0; +extern unsigned long long ext_data_1; #ifdef SUPPORT_GRAPHICS -extern unsigned long current_x_resolution; -extern unsigned long current_y_resolution; -extern unsigned long current_bits_per_pixel; -extern unsigned long current_bytes_per_scanline; -extern unsigned long current_bytes_per_pixel; -extern unsigned long current_phys_base; -extern unsigned long fill_color; +extern unsigned int current_x_resolution; +extern unsigned int current_y_resolution; +extern unsigned int current_bits_per_pixel; +extern unsigned int current_bytes_per_scanline; +extern unsigned int current_bytes_per_pixel; +extern unsigned long long current_phys_base; +extern unsigned int fill_color; extern unsigned char animated_enable; extern unsigned char animated_enable_backup; extern unsigned char animated_type; @@ -821,53 +1421,54 @@ extern unsigned short animated_delay; extern unsigned char animated_last_num; extern unsigned short animated_offset_x; extern unsigned short animated_offset_y; -extern char animated_name[57]; +extern char animated_name[128]; extern int animated (void); extern int splashimage_func(char *arg, int flags); extern int background_transparent; +extern int use_phys_base; #endif struct mem_alloc_array { - unsigned long addr; - unsigned long pid; + unsigned int addr; + unsigned int pid; }; -struct mem_alloc_array *mem_alloc_array_start; -struct mem_alloc_array *mem_alloc_array_end; -extern unsigned int prog_pid; struct malloc_array { - unsigned long addr; + unsigned int addr; struct malloc_array *next; }; -extern void *grub_malloc(unsigned long size); +extern void *grub_malloc(grub_size_t size); +extern void *grub_zalloc(grub_size_t size); +extern void * grub_memalign (grub_size_t align, grub_size_t size); extern void grub_free(void *ptr); struct malloc_array *malloc_array_start; /* If not using config file, this variable is set to zero, otherwise non-zero. */ -extern int use_config_file; -#define use_preset_menu *(unsigned long *)0x307FF8 +//extern int use_config_file; /* print debug message on startup if the DEBUG_KEY is pressed. */ -extern int debug_boot; -extern int console_checkkey (void); -extern int console_getkey (void); +//extern int debug_boot; extern int console_beep (void); -extern int beep_func(char *arg, int flags); -extern int defer(unsigned short millisecond); -extern unsigned short count_ms; -extern unsigned char beep_play; -extern unsigned char beep_enable; -extern unsigned short beep_frequency; +//extern int beep_func(char *arg, int flags); +extern void defer(unsigned short millisecond); +//extern unsigned short count_ms; +//extern unsigned char beep_play; +//extern unsigned char beep_enable; +//extern unsigned short beep_frequency; extern unsigned short beep_duration; extern unsigned long long initrd_start_sector; -extern int disable_map_info; extern int map_func (char *arg, int flags); -//#define SLEEP {unsigned long i;for (i=0;i<0xFFFFFFFF;i++);} -#define DEBUG_SLEEP {debug_sleep(debug_boot,__LINE__,__FILE__);} -extern inline void debug_sleep(int debug_boot, int line, char *file); +extern unsigned long long* map_start_sector; +extern unsigned long long* map_num_sectors; +extern unsigned int ext_num; +extern unsigned int ext_start_lba; +extern unsigned int ext_total_sectors; +extern int query_block_entries; +//#define DEBUG_SLEEP {debug_sleep(debug_boot,__LINE__,__FILE__);} +//extern inline void debug_sleep(int debug_boot, int line, char *file); #ifdef DEBUG_TIME #define PRINT_DEBUG_INFO debug_time(__LINE__,__FILE__); @@ -876,32 +1477,25 @@ extern inline void debug_time(const int line,const char*file); extern void hexdump(grub_u64_t,char*,int); extern int builtin_cmd (char *cmd, char *arg, int flags); -extern long realmode_run(long regs_ptr); +extern int realmode_run(int regs_ptr); #define MAX_USER_VARS 60 #define MAX_VARS 64 #define MAX_VAR_LEN 8 #define MAX_ENV_LEN 512 #define MAX_BUFFER (MAX_VARS * (MAX_VAR_LEN + MAX_ENV_LEN)) -//#define BASE_ADDR 0x45000 -#define VARIABLE_BASE_ADDR (*(unsigned long*)0x307FF4) -#define QUOTE_CHAR (*(char*)0x307FF0) -#define BASE_ADDR VARIABLE_BASE_ADDR typedef char VAR_NAME[MAX_VAR_LEN]; typedef char VAR_VALUE[MAX_ENV_LEN]; #define VAR ((VAR_NAME *)BASE_ADDR) #define ENVI ((VAR_VALUE *)(BASE_ADDR + MAX_VARS * MAX_VAR_LEN)) #define _WENV_ 60 -#define WENV_ENVI ((char*)0x4CA00) -#define WENV_RANDOM (*(unsigned long *)(WENV_ENVI+0x20)) -//#define QUOTE_CHAR (*(char*)(WENV_ENVI + 0x30)) -#define PATHEXT (WENV_ENVI + 0x40) -#define WENV_TMP (WENV_ENVI + 0x80) - -#define VAR_EX_TMP ((char *)(BASE_ADDR+MAX_VARS * (MAX_VAR_LEN + MAX_ENV_LEN))) +//#define VAR_EX_TMP ((char *)(BASE_ADDR+MAX_VARS * (MAX_VAR_LEN + MAX_ENV_LEN))) +/* 变量 VAR (BASE_ADDR) 需0x8200字节 + * 0x0 变量名称 8字节 64个变量 + * 0x200 变量值 512字节 64个变量值 + */ #define set_envi(var, val) envi_cmd(var, val, 0) -//#define get_env(var, val) envi_cmd(var, val, 1) #define get_env_all() envi_cmd(NULL, NULL, 2) #define reset_env_all() envi_cmd(NULL, NULL, 3) extern int envi_cmd(const char *var,char * const env,int flags); @@ -913,7 +1507,6 @@ extern int fallback_entries[MAX_FALLBACK_ENTRIES]; extern int fallback_entryno; extern int default_entry; extern int current_entryno; -extern const char *preset_menu; /* * graphics menu stuff @@ -960,7 +1553,7 @@ typedef struct #ifdef SUPPORT_GFX /* pointer to graphics image data */ extern char graphics_file[64]; -extern unsigned long gfx_drive, gfx_partition; +extern unsigned int gfx_drive, gfx_partition; int gfx_init_v1(gfx_data_v1_t *gfx_data); int gfx_done_v1(gfx_data_v1_t *gfx_data); @@ -997,22 +1590,23 @@ extern int compressed_file; #endif /* instrumentation variables */ -extern void (*disk_read_hook) (unsigned long long, unsigned long, unsigned long long); -extern void (*disk_read_func) (unsigned long long, unsigned long, unsigned long long); +extern void (*disk_read_hook) (unsigned long long, unsigned int, unsigned long long); +extern void (*disk_read_func) (unsigned long long, unsigned int, unsigned long long); /* The flag for debug mode. */ extern int debug; +extern int debug_bat; extern grub_u8_t debug_msg; -extern unsigned long current_drive; -extern unsigned long current_partition; +extern unsigned int current_drive; +extern unsigned int current_partition; extern int fsys_type; -extern unsigned int fats_type; extern char vol_name[256]; -//extern inline unsigned long log2_tmp (unsigned long word); -extern unsigned long unicode_to_utf8 (unsigned short *filename, unsigned char *utf8, unsigned long n); +extern unsigned int unicode_to_utf8 (unsigned short *filename, unsigned char *utf8, unsigned int n); +extern int utf8_to_multimode (void *to, unsigned char *from, unsigned int from_len, int mode); +//extern grub_uint8_t *grub_ucs2_to_utf8 (grub_uint8_t *dest, const grub_uint16_t *src, grub_size_t size); struct simp { @@ -1028,35 +1622,28 @@ extern unsigned char unifont_simp_on; stored in TOTAL_SECTORS. */ struct geometry { - /* The number of cylinders */ - unsigned long cylinders; - /* The number of heads */ - unsigned long heads; - /* The number of sectors */ - unsigned long sectors; /* The total number of sectors */ unsigned long long total_sectors; /* Device sector size */ - unsigned long sector_size; - /* Flags */ - unsigned long flags; + unsigned int sector_size; + /* Power of sector size 2 */ + unsigned int log2_sector_size; + unsigned char vhd_disk; //vhd磁盘 位0-1,仿真类型:1=不加载到内存 2=加载到内存 + unsigned char fill1; //填充 + unsigned short fill2; //填充 }; extern unsigned long long part_start; extern unsigned long long part_length; -extern unsigned long current_slice; -extern unsigned long dos_drive_geometry; -extern unsigned long dos_part_start; +extern unsigned int current_slice; +//extern unsigned int dos_drive_geometry; +//extern unsigned int dos_part_start; -extern unsigned long force_geometry_tune; - -extern int buf_drive; -extern int buf_track; +extern unsigned int buf_drive; +extern unsigned long long buf_track; extern struct geometry buf_geom; extern struct geometry tmp_geom; -extern struct geometry fd_geom[4]; -extern struct geometry hd_geom[8]; /* these are the current file position and maximum file position */ extern unsigned long long filepos; @@ -1064,69 +1651,73 @@ extern unsigned long long filemax; extern unsigned long long filesize; extern unsigned long long gzip_filemax; -extern unsigned long emu_iso_sector_size_2048; +extern unsigned int emu_iso_sector_size_2048; #define ISO_TYPE_9660 0 #define ISO_TYPE_udf 1 #define ISO_TYPE_Joliet 2 #define ISO_TYPE_RockRidge 3 -extern unsigned int iso_type; +//extern unsigned int iso_type; extern char iso_types; -extern unsigned long udf_BytePerSector; +extern unsigned int udf_BytePerSector; /* * Common BIOS/boot data. */ -extern char *end_of_low_16bit_code; -extern struct multiboot_info mbi; -extern unsigned long saved_drive; -extern unsigned long saved_partition; +//extern char *end_of_low_16bit_code; +//extern struct multiboot_info mbi; +extern unsigned int saved_drive; +extern unsigned int saved_partition; extern char saved_dir[256]; -extern unsigned long e820cycles; /* control how many e820 cycles will keep hooked */ -extern unsigned long int15nolow; /* unprotect int13_handler code with int15 */ -extern unsigned long memdisk_raw; /* raw mode as in memdisk */ -extern unsigned long a20_keep_on; /* keep a20 on after RAM drive sector access */ -extern unsigned long lba_cd_boot; /* LBA of no-emulation boot image, in 2048-byte sectors */ -extern unsigned long safe_mbr_hook; /* safe mbr hook flags used by Win9x */ -extern unsigned long int13_scheme; /* controls disk access methods in emulation */ +extern unsigned int e820cycles; /* control how many e820 cycles will keep hooked */ +extern unsigned int int15nolow; /* unprotect int13_handler code with int15 */ +extern unsigned int memdisk_raw; /* raw mode as in memdisk */ +extern unsigned int a20_keep_on; /* keep a20 on after RAM drive sector access */ +extern unsigned int lba_cd_boot; /* LBA of no-emulation boot image, in 2048-byte sectors */ +extern unsigned int safe_mbr_hook; /* safe mbr hook flags used by Win9x */ +extern unsigned int int13_scheme; /* controls disk access methods in emulation */ extern unsigned char atapi_dev_count; /* ATAPI CDROM DRIVE COUNT */ -extern unsigned long reg_base_addr_append; +extern unsigned int reg_base_addr_append; extern unsigned char usb_delay; extern unsigned short One_transfer; extern unsigned char usb_count_error; extern unsigned char usb_drive_num[8]; -extern unsigned long init_usb(void); -extern unsigned long init_atapi(void); +extern unsigned int init_usb(void); +extern unsigned int init_atapi(void); extern unsigned char min_cdrom_id; /* MINIMUM ATAPI CDROM DRIVE NUMBER */ -extern unsigned long cdrom_drive; -extern unsigned long force_cdrom_as_boot_device; -extern unsigned long ram_drive; +//extern unsigned int force_cdrom_as_boot_device; +extern unsigned int ram_drive; extern unsigned long long md_part_base; extern unsigned long long md_part_size; extern unsigned long long rd_base; extern unsigned long long rd_size; extern unsigned long long saved_mem_higher; -extern unsigned long saved_mem_upper; -extern unsigned long saved_mem_lower; -extern unsigned long saved_mmap_addr; -extern unsigned long saved_mmap_length; -extern unsigned long extended_memory; -extern unsigned long init_free_mem_start; +extern unsigned int saved_mem_upper; +extern unsigned int saved_mem_lower; +extern unsigned int free_mem_lower_start; +//extern unsigned int saved_mmap_addr; +//extern unsigned int saved_mmap_length; +extern unsigned int extended_memory; +//extern unsigned int init_free_mem_start; extern int config_len; extern char menu_init_script_file[32]; -extern unsigned long minimum_mem_hi_in_map; +extern unsigned int minimum_mem_hi_in_map; +extern int min_con_mem_start; +extern int min_con_mem_size; +extern int displaymem_func (char *arg, int flags); /* * Error variables. */ -extern grub_error_t errnum; +extern grub_error_t errnum; //设置错误号=0x1234,大于MAX_ERR_NUM,不打印err_list[errnum],错误信息由相应程序处理。设置错误号,可以避免死机。 extern char *err_list[]; /* Simplify declaration of entry_addr. */ typedef void (*entry_func) (int, int, int, int, int, int) __attribute__ ((noreturn)); -extern unsigned long cur_addr; +//extern unsigned long cur_addr; //???? +extern unsigned int cur_addr; extern entry_func entry_addr; /* Enter the stage1.5/stage2 C code after the stack is set up. */ @@ -1139,94 +1730,24 @@ void stop (void) __attribute__ ((noreturn)); /* Reboot the system. */ void grub_reboot (void) __attribute__ ((noreturn)); -void boot_int18 (void) __attribute__ ((noreturn)); - /* Halt the system, using APM if possible. If NO_APM is true, don't use APM even if it is available. */ -void grub_halt (int skip_flags); //__attribute__ ((noreturn)); - -struct drive_map_slot -{ - /* Remember to update DRIVE_MAP_SLOT_SIZE once this is modified. - * The struct size must be a multiple of 4. - */ - - /* X=max_sector bit 7: read only or fake write */ - /* Y=to_sector bit 6: safe boot or fake write */ - /* ------------------------------------------- */ - /* X Y: meaning of restrictions imposed on map */ - /* ------------------------------------------- */ - /* 1 1: read only=0, fake write=1, safe boot=0 */ - /* 1 0: read only=1, fake write=0, safe boot=0 */ - /* 0 1: read only=0, fake write=0, safe boot=1 */ - /* 0 0: read only=0, fake write=0, safe boot=0 */ - - unsigned char from_drive; //00 - unsigned char to_drive; /* 0xFF indicates a memdrive */ //01 - unsigned char max_head; //02 - unsigned char max_sector; /* bit 7: read only */ //03 - /* bit 6: disable lba */ - - unsigned short to_cylinder; /* max cylinder of the TO drive */ //04 - /* bit 15: TO drive support LBA */ - /* bit 14: TO drive is CDROM(with big 2048-byte sector) */ - /* bit 13: FROM drive is CDROM(with big 2048-byte sector) */ - - unsigned char to_head; /* max head of the TO drive */ //06 - unsigned char to_sector; /* max sector of the TO drive */ //07 - /* bit 7: in-situ */ - /* bit 6: fake-write or safe-boot */ - - unsigned long long start_sector; //08 - //unsigned long start_sector_hi; /* hi dword of the 64-bit value */ - unsigned long long sector_count; //16 - //unsigned long sector_count_hi; /* hi dword of the 64-bit value */ -}; +void grub_halt (void); //__attribute__ ((noreturn)); -struct fragment_map_slot +/* The key map. */ +struct key_map { - unsigned short slot_len; - unsigned char from; - unsigned char to; - unsigned char fragment_num; - unsigned long long fragment_data[0]; + unsigned int from_code; + unsigned int to_code; }; - -#if MAP_NUM_16 -struct drive_map_slot hooked_drive_map[DRIVE_MAP_SIZE + 1]; -extern struct drive_map_slot hooked_drive_map_1[DRIVE_MAP_SIZE / 2 + 1]; -extern struct drive_map_slot hooked_drive_map_2[DRIVE_MAP_SIZE / 2 + 1]; -#else -extern struct drive_map_slot hooked_drive_map[DRIVE_MAP_SIZE + 1]; -#endif -extern struct drive_map_slot bios_drive_map[DRIVE_MAP_SIZE + 1]; -extern struct fragment_map_slot hooked_fragment_map; -extern int drive_map_slot_empty (struct drive_map_slot item); - -/* Copy MAP to the drive map and set up int13_handler. */ -void set_int13_handler (struct drive_map_slot *map); - -/* Restore the original int13 handler. */ -int unset_int13_handler (int check_status_only); - -/* Set up int15_handler. */ -void set_int15_handler (void); - -/* Restore the original int15 handler. */ -void unset_int15_handler (void); - -/* Track the int13 handler to probe I/O address space. */ -void track_int13 (int drive); - -/* The key map. */ -//extern unsigned short bios_key_map[]; -extern unsigned long ascii_key_map[]; +extern struct key_map ascii_key_map[]; +extern int remap_ascii_char (int key); /* calls for direct boot-loader chaining */ -void chain_stage1 (unsigned long segment, unsigned long offset, - unsigned long part_table_addr) +void chain_stage1 (unsigned int segment, unsigned int offset, + unsigned int part_table_addr) __attribute__ ((noreturn)); -void chain_stage2 (unsigned long segment, unsigned long offset, +void chain_stage2 (unsigned int segment, unsigned int offset, int second_sector) __attribute__ ((noreturn)); @@ -1253,11 +1774,11 @@ int get_eisamemsize (void); value. DESC is a pointer to the descriptor buffer, and CONT is the previous continuation value (0 to get the first entry in the map). */ -int get_mmap_entry (struct mmar_desc *desc, int cont); +extern int get_mmap_entry (struct mmar_desc *desc, int cont); /* Get the linear address of a ROM configuration table. Return zero, if fails. */ -unsigned long get_rom_config_table (void); +unsigned int get_rom_config_table (void); /* Get APM BIOS information. */ //void get_apm_info (void); @@ -1275,72 +1796,82 @@ int set_vbe_mode (int mode_number); int get_code_end (void); /* low-level timing info */ -int getrtsecs (void); +extern int getrtsecs (void); -/* Get current date and time */ -void get_datetime(unsigned long *date, unsigned long *time); +//---------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------- +//datetime.h +struct grub_datetime +{ + unsigned short year; + unsigned char month; + unsigned char day; + unsigned char hour; + unsigned char minute; + unsigned char second; + unsigned char pad1; +}; -#define currticks() (*(unsigned long *)0x46C) +/* Get current date and time */ +extern void get_datetime (struct grub_datetime *datetime); /* Clear the screen. */ void cls (void); /* Turn on/off cursor. */ -unsigned long setcursor (unsigned long on); - -/* Get the current cursor position (where 0,0 is the top left hand - corner of the screen). Returns packed values, (RET >> 8) is x, - (RET & 0xff) is y. */ -int getxy (void); +unsigned int setcursor (unsigned int on); /* Set the cursor position. */ -void gotoxy (int x, int y); +extern void gotoxy (int x, int y); /* Displays an ASCII character. IBM displays will translate some characters to special graphical ones (see the DISP_* constants). */ -unsigned int (*grub_putchar) (unsigned int c, unsigned int max_width); +extern unsigned int grub_putchar (unsigned int c, unsigned int max_width); unsigned int _putchar (unsigned int c, unsigned int max_width); unsigned char *set_putchar_hook(unsigned char *hooked); extern unsigned char* putchar_hooked; /* Wait for a keypress, and return its packed BIOS/ASCII key code. Use ASCII_CHAR(ret) to extract the ASCII code. */ -int getkey (void); +extern int getkey (void); +#define grub_getkey() getkey() /* Like GETKEY, but doesn't block, and returns -1 if no keystroke is available. */ -int checkkey (void); +extern int checkkey (void); /* Low-level disk I/O */ extern int biosdisk_int13_extensions (unsigned ax, unsigned drive, void *dap, unsigned ssize); -int get_cdinfo (unsigned long drive, struct geometry *geometry); -int get_diskinfo (unsigned long drive, struct geometry *geometry, unsigned long lba1sector); -int biosdisk (unsigned long subfunc, unsigned long drive, struct geometry *geometry, - unsigned long long sector, unsigned long nsec, unsigned long segment); +extern int grub_map_efidisk (unsigned ax, unsigned drive, void *dap); +extern int get_diskinfo (unsigned int drive, struct geometry *geometry, unsigned int partition); +int biosdisk (unsigned int read, unsigned int drive, struct geometry *geometry, + unsigned long long sector, unsigned int nsec, unsigned int segment); void stop_floppy (void); /* Command-line interface functions. */ /* The flags for the builtins. */ -#define BUILTIN_CMDLINE 0x1 /* Run in the command-line. */ -#define BUILTIN_MENU (1 << 1)/* Run in the menu. */ -#define BUILTIN_IFTITLE (1 << 2) /* Only for the command title. */ -#define BUILTIN_SCRIPT (1 << 3)/* Run in the script. */ -#define BUILTIN_NO_ECHO (1 << 4) /* Don't print command on booting. */ -#define BUILTIN_HELP_LIST (1 << 5)/* Show help in listing. */ -#define BUILTIN_BOOTING (1 << 6) /* The command is boot-sensitive. */ -#define BUILTIN_BAT_SCRIPT (1 << 7) -#define BUILTIN_USER_PROG (1 << 8) -#define BUILTIN_NO_DECOMPRESSION (1 << 9) - -#define BAT_SIGN 0x54414221UL +#define BUILTIN_CMDLINE 0x1 /* Run in the command-line. */ +#define BUILTIN_MENU (1 << 1) /* Run in the menu. */ +#define BUILTIN_IFTITLE (1 << 2) /* Only for the command title. */ +#define BUILTIN_SCRIPT (1 << 3) /* Run in the script. */ +#define BUILTIN_NO_ECHO (1 << 4) /* Don't print command on booting. */ +#define BUILTIN_HELP_LIST (1 << 5) /* Show help in listing. */ +#define BUILTIN_BOOTING (1 << 6) /* The command is boot-sensitive. */ +#define BUILTIN_BAT_SCRIPT (1 << 7) /* 在BAT脚本中运行 */ +#define BUILTIN_USER_PROG (1 << 8) /* 在用户程序中运行 */ +#define BUILTIN_NO_DECOMPRESSION (1 << 9) /* 未减压 */ + +#define BAT_SIGN 0x54414221UL //!BAT +extern grub_size_t bat_md_start; +extern unsigned int bat_md_count; /* The table for a psp_end*/ typedef struct { - unsigned long len; - unsigned long proglen; - unsigned long arg; - unsigned long path; + unsigned int len; + unsigned int proglen; + unsigned int arg; + unsigned int path; char filename[0]; } __attribute__ ((packed)) psp_info_t; @@ -1348,15 +1879,15 @@ typedef struct { struct builtin { /* The command name. */ - char *name; + char *name; //名称 /* The callback function. */ - int (*func) (char *, int); + int (*func) (char *, int); //功能 /* The combination of the flags defined above. */ - int flags; + int flags; //标记 /* The short version of the documentation. */ - char *short_doc; + char *short_doc; //短文本 /* The long version of the documentation. */ - char *long_doc; + char *long_doc; //长文本 }; /* All the builtins are registered in this. */ @@ -1381,21 +1912,35 @@ extern int show_menu; extern int silent_hiddenmenu; extern char *mbr; extern int grub_timeout; +extern unsigned char timeout_enable; +extern void timeout_refresh(void); -char *wee_skip_to (char *cmdline, int flags); -char *skip_to (int flags, char *cmdline); +extern char *wee_skip_to (char *cmdline, int flags); +extern char *skip_to (int flags, char *cmdline); +extern char *WENV_ENVI; #define SKIP_LINE 0x100 #define SKIP_NONE 0 #define SKIP_WITH_TERMINATE 0x200 #define ADDR_RET_STR WENV_ENVI +//如果变量是字符串, 则: ADDR_RET_STR = var; +//如果变量是数值, 则: sprintf (ADDR_RET_STR,"0x%lx",var); +//#define WENV_RANDOM (*(unsigned long *)(WENV_ENVI+0x20)) +#define WENV_RANDOM (*(unsigned int *)(WENV_ENVI+0x20)) //随机数 2字节 +#define PATHEXT (WENV_ENVI + 0x40) //路径扩展 +#define WENV_TMP (WENV_ENVI + 0x80) //字符串缓存 +/* 环境参数 WENV_ENVI + * 0x0 特殊返回值 %?_UUID% %?% + * 0x20 随机数 WENV_RANDOM 只使用2字节 + * 0x40 路径扩展 PATHEXT + * 0x80 环境参数返回值 字符串缓存 WENV_TMP + */ //extern char *pre_cmdline; -#define CMD_RUN_ON_EXIT ((char *)0x4CB08) extern int expand_var(const char *str,char *out,const unsigned int len_max); -int run_line (char *heap,int flags); +extern int run_line (char *heap,int flags); struct builtin *find_command (char *command); -void print_cmdline_message (int forever); -void enter_cmdline (char *heap, int forever); +extern void print_cmdline_message (int forever); +extern void enter_cmdline (char *heap, int forever); /* C library replacement functions with identical semantics. */ //void grub_printf (const char *format,...); @@ -1405,44 +1950,44 @@ void enter_cmdline (char *heap, int forever); #define printf_debug0(...) grub_sprintf((char*)1, __VA_ARGS__) #define printf_errinfo(...) grub_sprintf((char*)3, __VA_ARGS__) #define printf_warning(...) grub_sprintf((char*)2, __VA_ARGS__) -int grub_sprintf (char *buffer, const char *format, ...); -int grub_tolower (int c); -int grub_isspace (int c); -int grub_strncat (char *s1, const char *s2, int n); -void *grub_memcpy (void *to, const void *from, unsigned int n); -void *grub_memmove (void *to, const void *from, int len); -void *grub_memset (void *start, int c, int len); -int grub_strncat (char *s1, const char *s2, int n); -char *grub_strstr (const char *s1, const char *s2); -char *grub_strtok (char *s, const char *delim); -int grub_memcmp (const char *s1, const char *s2, int n); -int grub_crc32(char *data,grub_u32_t size); -unsigned short grub_crc16(unsigned char *data, int size); -int grub_strcmp (const char *s1, const char *s2); -int strncmpx(const char *s1,const char *s2, unsigned long n, int case_insensitive); +extern int grub_sprintf (char *buffer, const char *format, ...); +extern int grub_tolower (int c); +extern int grub_isspace (int c); +extern int grub_strncat (char *s1, const char *s2, int n); +extern void *grub_memmove (void *to, const void *from, int len); +void *grub_memset (void *start, int c, grub_size_t len); +extern char *grub_strstr (const char *s1, const char *s2); +//char *grub_strtok (char *s, const char *delim); +extern int grub_memcmp (const char *s1, const char *s2, grub_size_t n); +extern int grub_crc32(char *data,grub_u32_t size); +extern unsigned short grub_crc16(unsigned char *data, int size); +extern int grub_strcmp (const char *s1, const char *s2); +extern int strncmpx(const char *s1,const char *s2, unsigned int n, int case_insensitive); #define strncmp(s1,s2,n) strncmpx(s1,s2,n,0) #define strnicmp(s1,s2,n) strncmpx(s1,s2,n,1) #define strncmpi strnicmp -int grub_strlen (const char *str); -char *grub_strcpy (char *dest, const char *src); - -unsigned long long grub_memmove64(unsigned long long dst_addr, unsigned long long src_addr, unsigned long long len); -unsigned long long grub_memset64(unsigned long long dst_addr, unsigned int data, unsigned long long len); -int grub_memcmp64(unsigned long long str1addr, unsigned long long str2addr, unsigned long long len); -//void grub_memset64 (unsigned long long start, unsigned long long c, unsigned long long len); -//int grub_memcmp64 (const unsigned long long s1, const unsigned long long s2, unsigned long long n); -//void grub_memmove64 (unsigned long long to, const unsigned long long from, unsigned long long len); +extern int grub_strlen (const char *str); +extern char *grub_strcpy (char *dest, const char *src); +extern char *grub_strncpy (char *dest, const char *src, int c); + +extern unsigned long long grub_memmove64(unsigned long long dst_addr, unsigned long long src_addr, unsigned long long len); +extern unsigned long long grub_memset64(unsigned long long dst_addr, unsigned int data, unsigned long long len); +extern int grub_memcmp64(unsigned long long str1addr, unsigned long long str2addr, unsigned long long len); int mem64 (int func, unsigned long long dest, unsigned long long src, unsigned long long len); -extern unsigned long configfile_opened; +//extern unsigned int configfile_opened; /* misc */ void init_page (void); void print_error (void); -char *convert_to_ascii (char *buf, int c, ...); +#if defined(__i386__) +extern char *convert_to_ascii (char *buf, int c, int lo, int hi); +#else +extern char *convert_to_ascii (char *buf, int c, unsigned long long lo); +#endif extern char *prompt; extern int echo_char; -extern int readline; +//extern int readline; struct get_cmdline_arg { unsigned char *cmdline; @@ -1452,17 +1997,16 @@ struct get_cmdline_arg unsigned int readline; } __attribute__ ((packed)); extern struct get_cmdline_arg get_cmdline_str; -int get_cmdline (void); -int substring (const char *s1, const char *s2, int case_insensitive); -int nul_terminate (char *str); +extern int get_cmdline (void); +extern int substring (const char *s1, const char *s2, int case_insensitive); +extern int nul_terminate (char *str); int get_based_digit (int c, int base); -int safe_parse_maxint_with_suffix (char **str_ptr, unsigned long long *myint_ptr, int unitshift); +extern int safe_parse_maxint_with_suffix (char **str_ptr, unsigned long long *myint_ptr, int unitshift); #define safe_parse_maxint(str_ptr, myint_ptr) safe_parse_maxint_with_suffix(str_ptr, myint_ptr, 0) -//int safe_parse_maxint (char **str_ptr, unsigned long long *myint_ptr); -int parse_string (char *arg); -int memcheck (unsigned long long addr, unsigned long long len); -void grub_putstr (const char *str); -unsigned int grub_sleep (unsigned int seconds); +extern int parse_string (char *arg); +extern int memcheck (unsigned long long addr, unsigned long long len); +extern void grub_putstr (char *str); +extern void grub_putstr_utf16(unsigned short *str); #ifndef NO_DECOMPRESSION /* Compression support. */ @@ -1471,7 +2015,7 @@ struct decomp_entry char *name; int (*open_func) (void); void (*close_func) (void); - unsigned long long (*read_func) (unsigned long long buf, unsigned long long len, unsigned long write); + unsigned long long (*read_func) (unsigned long long buf, unsigned long long len, unsigned int write); }; #define DECOMP_TYPE_GZ 0 @@ -1483,98 +2027,88 @@ struct decomp_entry extern struct decomp_entry decomp_table[NUM_DECOM]; extern int decomp_type; +extern unsigned char dec_header[20]; int gunzip_test_header (void); void gunzip_close (void); -unsigned long long gunzip_read (unsigned long long buf, unsigned long long len, unsigned long write); -int dec_lzma_open (void); +unsigned long long gunzip_read (unsigned long long buf, unsigned long long len, unsigned int write); +extern int dec_lzma_open (void); void dec_lzma_close (void); -unsigned long long dec_lzma_read (unsigned long long buf, unsigned long long len, unsigned long write); -int dec_lz4_open (void); +unsigned long long dec_lzma_read (unsigned long long buf, unsigned long long len, unsigned int write); +extern int dec_lz4_open (void); void dec_lz4_close (void); -unsigned long long dec_lz4_read (unsigned long long buf, unsigned long long len, unsigned long write); -int dec_vhd_open(void); +unsigned long long dec_lz4_read (unsigned long long buf, unsigned long long len, unsigned int write); +extern int dec_vhd_open(void); void dec_vhd_close(void); -unsigned long long dec_vhd_read(unsigned long long buf, unsigned long long len, unsigned long write); +unsigned long long dec_vhd_read(unsigned long long buf, unsigned long long len, unsigned int write); +extern int vhd_read; +extern unsigned long long vhd_start_sector; #endif /* NO_DECOMPRESSION */ -int rawread (unsigned long drive, unsigned long long sector, unsigned long byte_offset, unsigned long long byte_len, unsigned long long buf, unsigned long write); -int devread (unsigned long long sector, unsigned long long byte_offset, unsigned long long byte_len, unsigned long long buf, unsigned long write); -int rawwrite (unsigned long drive, unsigned long long sector, unsigned long long buf); -int devwrite (unsigned long long sector, unsigned long long sector_len, unsigned long long buf); +extern int rawread (unsigned int drive, unsigned long long sector, unsigned int byte_offset, unsigned long long byte_len, unsigned long long buf, unsigned int write); +extern int devread (unsigned long long sector, unsigned long long byte_offset, unsigned long long byte_len, unsigned long long buf, unsigned int write); +extern int rawwrite (unsigned int drive, unsigned long long sector, unsigned long long buf); /* Parse a device string and initialize the global parameters. */ char *set_device (char *device); -int open_device (void); +extern int open_device (void); //char *setup_part (char *filename); -int real_open_partition (int flags); -int open_partition (void); -int next_partition (void); -//int next_partition (unsigned long drive, unsigned long dest, -// unsigned long *partition, int *type, -// unsigned long *start, unsigned long *len, -// unsigned long *offset, int *entry, -// unsigned long *ext_offset, char *buf); - -/* Sets device to the one represented by the SAVED_* parameters. */ -//int make_saved_active (int status_only); +extern int real_open_partition (int flags); +extern int open_partition (void); +extern int next_partition (void); -/* Set or clear the current root partition's hidden flag. */ -//int set_partition_hidden_flag (int hidden); /* Open a file or directory on the active device, using GRUB's internal filesystem support. */ -int grub_open (char *filename); +extern int grub_open (char *filename); #define GRUB_READ 0xedde0d90 #define GRUB_WRITE 0x900ddeed #define GRUB_LISTBLK 0x4B42534C /* Read LEN bytes into BUF from the file that was opened with GRUB_OPEN. If LEN is -1, read all the remaining data in the file. */ -unsigned long long grub_read (unsigned long long buf, unsigned long long len, unsigned long write); - -/* Reposition a file offset. */ -//unsigned long grub_seek (unsigned long offset); +unsigned long long grub_read (unsigned long long buf, unsigned long long len, unsigned int write); /* Close a file. */ void grub_close (void); -/* List the contents of the directory that was opened with GRUB_OPEN, - printing all completions. */ -//int dir (char *dirname); - -int set_bootdev (int hdbias); +extern int set_bootdev (int hdbias); /* Display statistics on the current active device. */ void print_fsys_type (void); /* Print the root device information.*/ -void print_root_device (char *buffer,int flag); +extern void print_root_device (char *buffer,int flag); /* Display device and filename completions. */ -void print_a_completion (char *filename, int case_insensitive); -int print_completions (int is_filename, int is_completion); +extern void print_a_completion (char *filename, int case_insensitive); +extern int print_completions (int is_filename, int is_completion); /* Copies the current partition data to the desired address. */ void copy_current_part_entry (char *buf); -void bsd_boot (kernel_t type, int bootdev, char *arg) - __attribute__ ((noreturn)); +//extern void bsd_boot (kernel_t type, int bootdev, char *arg) +// __attribute__ ((noreturn)); +extern void bsd_boot (kernel_t type, int bootdev, char *arg); /* Define flags for load_image here. */ /* Don't pass a Linux's mem option automatically. */ #define KERNEL_LOAD_NO_MEM_OPTION (1 << 0) kernel_t load_image (char *kernel, char *arg, kernel_t suggested_type, - unsigned long load_flags); + unsigned int load_flags); -int load_module (char *module, char *arg); -int load_initrd (char *initrd); +extern int load_module (char *module, char *arg); +extern int load_initrd (char *initrd); -int check_password(char* expected, password_t type); +extern int check_password(char* expected, password_t type); extern int biosdisk_standard (unsigned ah, unsigned drive, unsigned coff, unsigned hoff, unsigned soff, unsigned nsec, unsigned segment); void init_bios_info (void); +#define EFI_PARTITION 0xef +#define GRUB_PC_PARTITION_TYPE_GPT_DISK 0xee +#define ACTIVE_PARTITION 0x80 + struct master_and_dos_boot_sector { /* 00 */ char dummy1[0x0b]; /* at offset 0, normally there is a short JMP instuction(opcode is 0xEB) */ /* 0B */ unsigned short bytes_per_sector __attribute__ ((packed));/* seems always to be 512, so we just use 512 */ @@ -1587,11 +2121,14 @@ struct master_and_dos_boot_sector { /* 16 */ unsigned short sectors_per_fat __attribute__ ((packed));/* FAT32=0, NTFS=0, FAT12/16=non-zero */ /* 18 */ unsigned short sectors_per_track __attribute__ ((packed));/* range from 1 to 63 */ /* 1A */ unsigned short total_heads __attribute__ ((packed));/* range from 1 to 256 */ -/* 1C */ unsigned long hidden_sectors __attribute__ ((packed));/* any value */ -/* 20 */ unsigned long total_sectors_long __attribute__ ((packed));/* FAT32=non-zero, NTFS=0, FAT12/16=any */ -/* 24 */ unsigned long sectors_per_fat32 __attribute__ ((packed));/* FAT32=non-zero, NTFS=any, FAT12/16=any */ +/* 1C */ unsigned int hidden_sectors __attribute__ ((packed));/* any value */ +/* 20 */ unsigned int total_sectors_long __attribute__ ((packed));/* FAT32=non-zero, NTFS=0, FAT12/16=any */ +/* 24 */ unsigned int sectors_per_fat32 __attribute__ ((packed));/* FAT32=non-zero, NTFS=any, FAT12/16=any */ /* 28 */ unsigned long long total_sectors_long_long __attribute__ ((packed));/* NTFS=non-zero, FAT12/16/32=any */ -/* 30 */ char dummy2[0x18e]; +///* 30 */ char dummy2[0x18e]; +/* 30 */ char dummy2[0x188]; +/* 0x1B8 */unsigned char unique_signature[4]; +/* 0x1BC */unsigned char unknown[2]; /* Partition Table, starting at offset 0x1BE */ /* 1BE */ struct { @@ -1601,51 +2138,23 @@ struct master_and_dos_boot_sector { /* +04 */ unsigned char system_indicator; /* +05 */ unsigned char end_head; /* +06 */ unsigned short end_sector_cylinder __attribute__ ((packed)); - /* +08 */ unsigned long start_lba __attribute__ ((packed)); - /* +0C */ unsigned long total_sectors __attribute__ ((packed)); + /* +08 */ unsigned int start_lba __attribute__ ((packed)); + /* +0C */ unsigned int total_sectors __attribute__ ((packed)); /* +10 */ } P[4]; /* 1FE */ unsigned short boot_signature __attribute__ ((packed));/* 0xAA55 */ -#if 0 - /* This starts at offset 0x200 */ -/* 200 */ unsigned long probed_total_sectors __attribute__ ((packed)); -/* 204 */ unsigned long probed_heads __attribute__ ((packed)); -/* 208 */ unsigned long probed_sectors_per_track __attribute__ ((packed)); -/* 20C */ unsigned long probed_cylinders __attribute__ ((packed)); -/* 210 */ unsigned long sectors_per_cylinder __attribute__ ((packed)); -/* 214 */ char dummy3[0x0c] __attribute__ ((packed)); - - /* matrix of coefficients of linear equations - * - * C[n] * (H_count * S_count) + H[n] * S_count = LBA[n] - S[n] + 1 - * - * where n = 1, 2, 3, 4, 5, 6, 7, 8 - */ - /* This starts at offset 0x130 */ -/* 220 */ long long L[9] __attribute__ ((packed)); /* L[n] == LBA[n] - S[n] + 1 */ -/* 268 */ long H[9] __attribute__ ((packed)); -/* 28C */ short C[9] __attribute__ ((packed)); -/* 29E */ short X __attribute__ ((packed)); -/* 2A0 */ short Y __attribute__ ((packed)); -/* 2A2 */ short Cmax __attribute__ ((packed)); -/* 2A4 */ long Hmax __attribute__ ((packed)); -/* 2A8 */ unsigned long Z __attribute__ ((packed)); -/* 2AC */ short Smax __attribute__ ((packed)); -/* 2AE */ -#endif }; -extern unsigned long probed_total_sectors; -extern unsigned long probed_heads; -extern unsigned long probed_sectors_per_track; -extern unsigned long probed_cylinders; -extern unsigned long sectors_per_cylinder; +extern unsigned int probed_total_sectors; +extern unsigned int probed_heads; +extern unsigned int probed_sectors_per_track; +extern unsigned int probed_cylinders; +extern unsigned int sectors_per_cylinder; extern int filesystem_type; -extern unsigned long bios_id; /* 1 for bochs, 0 for unknown. */ -int probe_bpb (struct master_and_dos_boot_sector *BS); -int probe_mbr (struct master_and_dos_boot_sector *BS, unsigned long start_sector1, unsigned long sector_count1, unsigned long part_start1); +extern int probe_bpb (struct master_and_dos_boot_sector *BS); +extern int probe_mbr (struct master_and_dos_boot_sector *BS, unsigned int start_sector1, unsigned int sector_count1, unsigned int part_start1); extern int check_int13_extensions (unsigned drive, unsigned lba1sector); @@ -1653,13 +2162,13 @@ struct drive_parameters { unsigned short size; unsigned short flags; - unsigned long cylinders; - unsigned long heads; - unsigned long sectors; + unsigned int cylinders; + unsigned int heads; + unsigned int sectors; unsigned long long total_sectors; unsigned short bytes_per_sector; /* ver 2.0 or higher */ - unsigned long EDD_configuration_parameters; + unsigned int EDD_configuration_parameters; /* ver 3.0 or higher */ unsigned short signature_dpi; unsigned char length_dpi; @@ -1695,75 +2204,81 @@ typedef struct { } PACKED GUID; //GPT_HDR_SIG "EFI PART" -#define GPT_HDR_SIG 0x5452415020494645LL +#define GPT_HDR_SIG 0x5452415020494645LL //gpt磁盘签名 typedef struct { - grub_u64_t hdr_sig; - grub_u32_t hdr_revision; - grub_u32_t hdr_size; - grub_u32_t hdr_crc_self; - grub_u32_t __reserved; - grub_u64_t hdr_lba_self; - grub_u64_t hdr_lba_alt; - grub_u64_t hdr_lba_start; - grub_u64_t hdr_lba_end; - GUID hdr_uuid; - grub_u64_t hdr_lba_table; - grub_u32_t hdr_entries; - grub_u32_t hdr_entsz; - grub_u32_t hdr_crc_table; - grub_u32_t padding; + grub_u64_t hdr_sig; //签名 + grub_u32_t hdr_revision; //版本 + grub_u32_t hdr_size; //分区表头尺寸 + grub_u32_t hdr_crc_self; //分区表头crc32(第0-91字节) + grub_u32_t __reserved; //保留(必须是0) + grub_u64_t hdr_lba_self; //当前分区表头lba(这个分区表头的位置) + grub_u64_t hdr_lba_alt; //备用分区表头lba(另一个分区表头的位置) + grub_u64_t hdr_lba_start;//可用分区起始lba + grub_u64_t hdr_lba_end; //可用分区结束lba + GUID hdr_uuid; //硬盘GUID + grub_u64_t hdr_lba_table;//分区表起始lba + grub_u32_t hdr_entries; //分区表数量(入口数) + grub_u32_t hdr_entsz; //单个分区表尺寸 + grub_u32_t hdr_crc_table;//分区crc32 + grub_u32_t padding; //填充(必须是0) } PACKED GPT_HDR; -typedef GPT_HDR* P_GPT_HDR; +typedef GPT_HDR* P_GPT_HDR; //gpt_标题 typedef struct { - GUID type; - GUID uid; - grub_u64_t starting_lba; - grub_u64_t ending_lba; + GUID type; //分区类型GUID + GUID uid; //分区GUID + grub_u64_t starting_lba; //分区起始 + grub_u64_t ending_lba; //分区尺寸 union{ - grub_u64_t attributes; + grub_u64_t attributes; //属性 struct { grub_u16_t unused[3]; grub_u16_t gpt_att; } PACKED ms_attr; }; - char name[72]; + char name[72]; //名称 } PACKED GPT_ENT; -typedef GPT_ENT* P_GPT_ENT; +typedef GPT_ENT* P_GPT_ENT; //gpt_分区入口 + int check_64bit (void); -int check_64bit_and_PAE (void); +#if defined(__i386__) +extern int check_64bit_and_PAE (void); +#endif extern int is64bit; -// mask for is64bit bits #define IS64BIT_PAE 1 #define IS64BIT_AMD64 2 extern int errorcheck; -extern unsigned long pxe_restart_config; - -extern unsigned long saved_pxe_ip; +//extern unsigned int pxe_restart_config; +extern char *efi_pxe_buf; //2023-11-28 +extern unsigned int saved_pxe_ip; extern unsigned char saved_pxe_mac[6]; +extern grub_u32_t cur_pxe_type; +extern grub_u32_t http_feature; +extern grub_u32_t pxe_http_type; +extern grub_u32_t gbk; +extern int map_pd; #ifdef FSYS_PXE #include "pxe.h" extern grub_u8_t pxe_mac_len, pxe_mac_type; extern MAC_ADDR pxe_mac; -extern IP4 pxe_yip, pxe_sip, pxe_gip; -extern unsigned long pxe_keep; -extern BOOTPLAYER *discover_reply; +extern grub_u32_t pxe_yip, pxe_sip, pxe_gip; +extern unsigned int pxe_keep; +//extern grub_efi_pxe_dhcpv4_packet_t *discover_reply; extern unsigned short pxe_basemem, pxe_freemem; -extern unsigned long pxe_entry; -extern unsigned long pxe_inited; -extern unsigned long pxe_scan(void); +extern struct grub_efi_pxe *pxe_entry; +extern unsigned int pxe_inited; +extern unsigned int pxe_scan(void); extern int pxe_detect(int, char *); extern void pxe_unload(void); -extern int pxe_call(int func,void* data); -#if PXE_FAST_READ -extern int pxe_fast_read(void* data,int num); -#endif -int pxe_func(char* arg,int flags); +extern int pxe_init (void); +extern int only_tftp; +extern int pxe_func (char *arg, int flags); +extern unsigned long long pxe_read (unsigned long long buf, unsigned long long len, unsigned int write); #ifdef FSYS_IPXE extern grub_u32_t has_ipxe; int ipxe_func(char* arg,int flags); @@ -1775,17 +2290,15763 @@ void ipxe_init(void); #endif /* FSYS_PXE */ -extern unsigned long fb_status; -extern unsigned long next_partition_drive; -extern unsigned long next_partition_dest; -extern unsigned long *next_partition_partition; -extern unsigned long *next_partition_type; -extern unsigned long long *next_partition_start; -extern unsigned long long *next_partition_len; -extern unsigned long long *next_partition_offset; -extern unsigned long *next_partition_entry; -extern unsigned long *next_partition_ext_offset; -extern char *next_partition_buf; -#endif /* ! ASM_FILE */ +extern unsigned int fb_status; +/* backup of original BIOS floppy-count byte in 0x410 */ +extern char floppies_orig; +/* backup of original BIOS harddrive-count byte in 0x475 */ +extern char harddrives_orig; +extern char cdrom_orig; +//extern char first_boot; +typedef void *grub_efi_handle_t; +extern struct grub_disk_data *get_device_by_drive (unsigned int drive, unsigned int map); +extern struct grub_disk_data *disk_data; //磁盘数据 +extern int big_to_little (char *filename, unsigned int n); +extern void uninstall (unsigned int drive, struct grub_disk_data *d); +extern int (*ext_timer)(char *arg, int flags); + +//########################################################################################################################################## + +#define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0])) +#define EXPORT_FUNC(x) x +#define EXPORT_VAR(x) x + +//---------------------------------------------------------------------------------------------------- +//grub/efi/api.h +/* For consistency and safety, we name the EFI-defined types differently. 为了一致性和安全性,我们对EFI定义的类型进行了不同的命名。 + All names are transformed into lower case, _t appended, and 所有的名字都被转换成小写字母,附加_t和预置grub_efi_ + grub_efi_ prepended. */ + +/* Constants. 常量 */ +//事件的类型 +#define GRUB_EFI_EVT_TIMER 0x80000000 //计时器 +#define GRUB_EFI_EVT_RUNTIME 0x40000000 //运行 +#define GRUB_EFI_EVT_RUNTIME_CONTEXT 0x20000000 //运行环境 +#define GRUB_EFI_EVT_NOTIFY_WAIT 0x00000100 //通知等待 +#define GRUB_EFI_EVT_NOTIFY_SIGNAL 0x00000200 //通知信号 +#define GRUB_EFI_EVT_SIGNAL_EXIT_BOOT_SERVICES 0x00000201 //信号出口启动服务 +#define GRUB_EFI_EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202 //信号虚拟地址变更 +//事件的优先级 +#define GRUB_EFI_TPL_APPLICATION 4 //应用 +#define GRUB_EFI_TPL_CALLBACK 8 //回调 +#define GRUB_EFI_TPL_NOTIFY 16 //通知 +#define GRUB_EFI_TPL_HIGH_LEVEL 31 //高电平 + +#define GRUB_EFI_MEMORY_UC 0x0000000000000001LL //存储器UC +#define GRUB_EFI_MEMORY_WC 0x0000000000000002LL //存储器 +#define GRUB_EFI_MEMORY_WT 0x0000000000000004LL //存储器 +#define GRUB_EFI_MEMORY_WB 0x0000000000000008LL //存储器 +#define GRUB_EFI_MEMORY_UCE 0x0000000000000010LL //存储器 +#define GRUB_EFI_MEMORY_WP 0x0000000000001000LL //存储器 +#define GRUB_EFI_MEMORY_RP 0x0000000000002000LL //存储器 +#define GRUB_EFI_MEMORY_XP 0x0000000000004000LL //存储器 +#define GRUB_EFI_MEMORY_NV 0x0000000000008000LL //存储器 +#define GRUB_EFI_MEMORY_MORE_RELIABLE 0x0000000000010000LL //存储器更可靠 +#define GRUB_EFI_MEMORY_RO 0x0000000000020000LL //存储器 +#define GRUB_EFI_MEMORY_RUNTIME 0x8000000000000000LL //存储器运行 + +#define GRUB_EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001 //打开协议 通过句柄 +#define GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002 //打开协议 获得协议 +#define GRUB_EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x00000004 //打开协议 测试协议 +#define GRUB_EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008 //打开协议 通过子控制器 +#define GRUB_EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010 //打开协议 通过驱动器 +#define GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE 0x00000020 //打开协议 通过专用的 + +#define GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001ULL //OS指示启动到FW UI + +#define GRUB_EFI_VARIABLE_NON_VOLATILE 0x0000000000000001 //变量不易变 +#define GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002 //变量启动服务访问 +#define GRUB_EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004 //变量运行时访问 + +#define GRUB_EFI_TIME_ADJUST_DAYLIGHT 0x01 //时间调节日光 +#define GRUB_EFI_TIME_IN_DAYLIGHT 0x02 //时间白昼 + +#define GRUB_EFI_UNSPECIFIED_TIMEZONE 0x07FF //未指定时区 + +#define GRUB_EFI_OPTIONAL_PTR 0x00000001 //可选PTR + +//加载映像GUID +#define GRUB_EFI_LOADED_IMAGE_GUID \ + { 0x5b1b31a1, 0x9562, 0x11d2, \ + { 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } +//磁盘IO_GUID +#define GRUB_EFI_DISK_IO_GUID \ + { 0xce345171, 0xba0b, 0x11d2, \ + { 0x8e, 0x4f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } +//块IO_GUID +#define GRUB_EFI_BLOCK_IO_GUID \ + { 0x964e5b21, 0x6459, 0x11d2, \ + { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } +//连续IO_GUID +#define GRUB_EFI_SERIAL_IO_GUID \ + { 0xbb25cf6f, 0xf1d4, 0x11d2, \ + { 0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0xfd } \ + } +//简单网络GUID +#define GRUB_EFI_SIMPLE_NETWORK_GUID \ + { 0xa19832b9, 0xac25, 0x11d3, \ + { 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } +//PXE GUID +#define GRUB_EFI_PXE_GUID \ + { 0x03c4e603, 0xac28, 0x11d3, \ + { 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } +//设备路径GUID +#define GRUB_EFI_DEVICE_PATH_GUID \ + { 0x09576e91, 0x6d3f, 0x11d2, \ + { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } +//简单文本输入协议GUID +#define GRUB_EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID \ + { 0x387477c1, 0x69c7, 0x11d2, \ + { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } +//简单文本输入扩展协议GUID +#define GRUB_EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \ + { 0xdd9e7534, 0x7762, 0x4698, \ + { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } \ + } +//简单文本输出协议GUID +#define GRUB_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID \ + { 0x387477c2, 0x69c7, 0x11d2, \ + { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } +//简单指针协议GUID +#define GRUB_EFI_SIMPLE_POINTER_PROTOCOL_GUID \ + { 0x31878c87, 0xb75, 0x11d5, \ + { 0x9a, 0x4f, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } +//绝对指针协议GUID +#define GRUB_EFI_ABSOLUTE_POINTER_PROTOCOL_GUID \ + { 0x8D59D32B, 0xC655, 0x4AE9, \ + { 0x9B, 0x15, 0xF2, 0x59, 0x04, 0x99, 0x2A, 0x43 } \ + } +//驱动程序绑定协议GUID +#define GRUB_EFI_DRIVER_BINDING_PROTOCOL_GUID \ + { 0x18A031AB, 0xB443, 0x4D1A, \ + { 0xA5, 0xC0, 0x0C, 0x09, 0x26, 0x1E, 0x9F, 0x71 } \ + } +//加载映像协议GUID +#define GRUB_EFI_LOADED_IMAGE_PROTOCOL_GUID \ + { 0x5B1B31A1, 0x9562, 0x11d2, \ + { 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } \ + } +//加载文件协议GUID +#define GRUB_EFI_LOAD_FILE_PROTOCOL_GUID \ + { 0x56EC3091, 0x954C, 0x11d2, \ + { 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } \ + } +//LoadFile2 协议 https://github.com/u-boot/u-boot/commit/ec80b4735a593961fe701cc3a5d717d4739b0fd0 +#define GRUB_EFI_LOAD_FILE2_PROTOCOL_GUID \ + { 0x4006c0c1, 0xfcb3, 0x403e, \ + { 0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d } \ + } +//简单文件系统协议GUID +#define GRUB_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \ + { 0x0964e5b22, 0x6459, 0x11d2, \ + { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } +//磁带IO协议GUID +#define GRUB_EFI_TAPE_IO_PROTOCOL_GUID \ + { 0x1e93e633, 0xd65a, 0x459e, \ + { 0xab, 0x84, 0x93, 0xd9, 0xec, 0x26, 0x6d, 0x18 } \ + } +//Unicode排序协议GUID +#define GRUB_EFI_UNICODE_COLLATION_PROTOCOL_GUID \ + { 0x1d85cd7f, 0xf43d, 0x11d2, \ + { 0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } +//SCSI IO协议GUID +#define GRUB_EFI_SCSI_IO_PROTOCOL_GUID \ + { 0x932f47e6, 0x2362, 0x4002, \ + { 0x80, 0x3e, 0x3c, 0xd5, 0x4b, 0x13, 0x8f, 0x85 } \ + } +//USB2 HC协议GUID +#define GRUB_EFI_USB2_HC_PROTOCOL_GUID \ + { 0x3e745226, 0x9818, 0x45b6, \ + { 0xa2, 0xac, 0xd7, 0xcd, 0x0e, 0x8b, 0xa2, 0xbc } \ + } +//调试支持协议GUID +#define GRUB_EFI_DEBUG_SUPPORT_PROTOCOL_GUID \ + { 0x2755590C, 0x6F3C, 0x42FA, \ + { 0x9E, 0xA4, 0xA3, 0xBA, 0x54, 0x3C, 0xDA, 0x25 } \ + } +//调试端口协议GUID +#define GRUB_EFI_DEBUGPORT_PROTOCOL_GUID \ + { 0xEBA4E8D2, 0x3858, 0x41EC, \ + { 0xA2, 0x81, 0x26, 0x47, 0xBA, 0x96, 0x60, 0xD0 } \ + } +//解压协议GUID +#define GRUB_EFI_DECOMPRESS_PROTOCOL_GUID \ + { 0xd8117cfe, 0x94a6, 0x11d4, \ + { 0x9a, 0x3a, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } +//设备路径文本协议 GUID +#define GRUB_EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID \ + { 0x8b843e20, 0x8132, 0x4852, \ + { 0x90, 0xcc, 0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c } \ + } +//设备路径实用程序协议GUID +#define GRUB_EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID \ + { 0x379be4e, 0xd706, 0x437d, \ + { 0xb0, 0x37, 0xed, 0xb8, 0x2f, 0xb7, 0x72, 0xa4 } \ + } +//文本协议的设备路径GUID +#define GRUB_EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID \ + { 0x5c99a21, 0xc70f, 0x4ad2, \ + { 0x8a, 0x5f, 0x35, 0xdf, 0x33, 0x43, 0xf5, 0x1e } \ + } +//ACPI表协议GUID +#define GRUB_EFI_ACPI_TABLE_PROTOCOL_GUID \ + { 0xffe06bdd, 0x6107, 0x46a6, \ + { 0x7b, 0xb2, 0x5a, 0x9c, 0x7e, 0xc5, 0x27, 0x5c} \ + } +//HII配置路由协议GUID +#define GRUB_EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID \ + { 0x587e72d7, 0xcc50, 0x4f79, \ + { 0x82, 0x09, 0xca, 0x29, 0x1f, 0xc1, 0xa1, 0x0f } \ + } +//HII数据库协议GUID +#define GRUB_EFI_HII_DATABASE_PROTOCOL_GUID \ + { 0xef9fc172, 0xa1b2, 0x4693, \ + { 0xb3, 0x27, 0x6d, 0x32, 0xfc, 0x41, 0x60, 0x42 } \ + } +//HII字符串协议GUID +#define GRUB_EFI_HII_STRING_PROTOCOL_GUID \ + { 0xfd96974, 0x23aa, 0x4cdc, \ + { 0xb9, 0xcb, 0x98, 0xd1, 0x77, 0x50, 0x32, 0x2a } \ + } +//HII映像协议GUID +#define GRUB_EFI_HII_IMAGE_PROTOCOL_GUID \ + { 0x31a6406a, 0x6bdf, 0x4e46, \ + { 0xb2, 0xa2, 0xeb, 0xaa, 0x89, 0xc4, 0x9, 0x20 } \ + } +//HII字体协议GUID +#define GRUB_EFI_HII_FONT_PROTOCOL_GUID \ + { 0xe9ca4775, 0x8657, 0x47fc, \ + { 0x97, 0xe7, 0x7e, 0xd6, 0x5a, 0x8, 0x43, 0x24 } \ + } +//HII配置访问协议 GUID +#define GRUB_EFI_HII_CONFIGURATION_ACCESS_PROTOCOL_GUID \ + { 0x330d4706, 0xf2a0, 0x4e4f, \ + { 0xa3, 0x69, 0xb6, 0x6f, 0xa8, 0xd5, 0x43, 0x85 } \ + } +//组件名称协议GUID +#define GRUB_EFI_COMPONENT_NAME_PROTOCOL_GUID \ + { 0x107a772c, 0xd5e1, 0x11d4, \ + { 0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } +//组件名称2协议GUID +#define GRUB_EFI_COMPONENT_NAME2_PROTOCOL_GUID \ + { 0x6a7a5cff, 0xe8d9, 0x4f70, \ + { 0xba, 0xda, 0x75, 0xab, 0x30, 0x25, 0xce, 0x14} \ + } +//USB IO协议GUID +#define GRUB_EFI_USB_IO_PROTOCOL_GUID \ + { 0x2B2F68D6, 0x0CD2, 0x44cf, \ + { 0x8E, 0x8B, 0xBB, 0xA2, 0x0B, 0x1B, 0x5B, 0x75 } \ + } +//天奴定制减压GUID +#define GRUB_EFI_TIANO_CUSTOM_DECOMPRESS_GUID \ + { 0xa31280ad, 0x481e, 0x41b6, \ + { 0x95, 0xe8, 0x12, 0x7f, 0x4c, 0x98, 0x47, 0x79 } \ + } +//CRC32制导剖面提取 GUID +#define GRUB_EFI_CRC32_GUIDED_SECTION_EXTRACTION_GUID \ + { 0xfc1bcdb0, 0x7d31, 0x49aa, \ + { 0x93, 0x6a, 0xa4, 0x60, 0x0d, 0x9d, 0xd0, 0x83 } \ + } +//LZMA自定义解压缩 GUID +#define GRUB_EFI_LZMA_CUSTOM_DECOMPRESS_GUID \ + { 0xee4e5898, 0x3914, 0x4259, \ + { 0x9d, 0x6e, 0xdc, 0x7b, 0xd7, 0x94, 0x03, 0xcf } \ + } +//TSC频率GUID +#define GRUB_EFI_TSC_FREQUENCY_GUID \ + { 0xdba6a7e3, 0xbb57, 0x4be7, \ + { 0x8a, 0xf8, 0xd5, 0x78, 0xdb, 0x7e, 0x56, 0x87 } \ + } +//系统资源表GUID +#define GRUB_EFI_SYSTEM_RESOURCE_TABLE_GUID \ + { 0xb122a263, 0x3661, 0x4f68, \ + { 0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80 } \ + } +//DXE服务表 GUID +#define GRUB_EFI_DXE_SERVICES_TABLE_GUID \ + { 0x05ad34ba, 0x6f02, 0x4214, \ + { 0x95, 0x2e, 0x4d, 0xa0, 0x39, 0x8e, 0x2b, 0xb9 } \ + } +//HOB表GUID +#define GRUB_EFI_HOB_LIST_GUID \ + { 0x7739f24c, 0x93d7, 0x11d4, \ + { 0x9a, 0x3a, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } +//内存类型信息GUID +#define GRUB_EFI_MEMORY_TYPE_INFORMATION_GUID \ + { 0x4c19049f, 0x4137, 0x4dd3, \ + { 0x9c, 0x10, 0x8b, 0x97, 0xa8, 0x3f, 0xfd, 0xfa } \ + } +//调试映像信息表GUID +#define GRUB_EFI_DEBUG_IMAGE_INFO_TABLE_GUID \ + { 0x49152e77, 0x1ada, 0x4764, \ + { 0xb7, 0xa2, 0x7a, 0xfe, 0xfe, 0xd9, 0x5e, 0x8b } \ + } +//MPS表GUID +#define GRUB_EFI_MPS_TABLE_GUID \ + { 0xeb9d2d2f, 0x2d88, 0x11d3, \ + { 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } +//ACPI表GUID +#define GRUB_EFI_ACPI_TABLE_GUID \ + { 0xeb9d2d30, 0x2d88, 0x11d3, \ + { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } +//ACPI_20表GUID +#define GRUB_EFI_ACPI_20_TABLE_GUID \ + { 0x8868e871, 0xe4f1, 0x11d3, \ + { 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } +//SMBIOS表GUID +#define GRUB_EFI_SMBIOS_TABLE_GUID \ + { 0xeb9d2d31, 0x2d88, 0x11d3, \ + { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } +//SAL表GUID +#define GRUB_EFI_SAL_TABLE_GUID \ + { 0xeb9d2d32, 0x2d88, 0x11d3, \ + { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } +//HCDP表GUID +#define GRUB_EFI_HCDP_TABLE_GUID \ + { 0xf951938d, 0x620b, 0x42ef, \ + { 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 } \ + } +//设备树GUID +#define GRUB_EFI_DEVICE_TREE_GUID \ + { 0xb1b621d5, 0xf19c, 0x41a5, \ + { 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 } \ + } +//供应商APPLE GUID +#define GRUB_EFI_VENDOR_APPLE_GUID \ + { 0x2B0585EB, 0xD8B8, 0x49A9, \ + { 0x8B, 0x8C, 0xE2, 0x1B, 0x01, 0xAE, 0xF2, 0xB7 } \ + } + +#define GRUB_EFI_GRUB_VARIABLE_GUID \ + { 0x91376aff, 0xcba6, 0x42be, \ + { 0x94, 0x9d, 0x06, 0xfd, 0xe8, 0x11, 0x28, 0xe8 } \ + } + +#define GRUB_EFI_SECURITY_PROTOCOL_GUID \ + { 0xa46423e3, 0x4617, 0x49f1, \ + { 0xb9, 0xff, 0xd1, 0xbf, 0xa9, 0x11, 0x58, 0x39 } \ + } + +#define GRUB_EFI_SECURITY2_PROTOCOL_GUID \ + { 0x94ab2f58, 0x1438, 0x4ef1, \ + { 0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } \ + } + +#define GRUB_EFI_SHIM_LOCK_GUID \ + { 0x605dab50, 0xe046, 0x4300, \ + { 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } \ + } + +#define GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID \ + { 0x5b446ed1, 0xe30b, 0x4faa, \ + { 0x87, 0x1a, 0x36, 0x54, 0xec, 0xa3, 0x60, 0x80 } \ + } + +#define GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID \ + { 0x937fe521, 0x95ae, 0x4d1a, \ + { 0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } \ + } + +#define GRUB_EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID \ + { 0x9d9a39d8, 0xbd42, 0x4a73, \ + { 0xa4, 0xd5, 0x8e, 0xe9, 0x4b, 0xe1, 0x13, 0x80 } \ + } + +#define GRUB_EFI_DHCP4_PROTOCOL_GUID \ + { 0x8a219718, 0x4ef5, 0x4761, \ + { 0x91, 0xc8, 0xc0, 0xf0, 0x4b, 0xda, 0x9e, 0x56 } \ + } + +#define GRUB_EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID \ + { 0x9fb9a8a1, 0x2f4a, 0x43a6, \ + { 0x88, 0x9c, 0xd0, 0xf7, 0xb6, 0xc4 ,0x7a, 0xd5 } \ + } + +#define GRUB_EFI_DHCP6_PROTOCOL_GUID \ + { 0x87c8bad7, 0x595, 0x4053, \ + { 0x82, 0x97, 0xde, 0xde, 0x39, 0x5f, 0x5d, 0x5b } \ + } +//HTTP服务绑定协议GUID +#define GRUB_EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID \ + { 0xbdc8e6af, 0xd9bc, 0x4379, \ + { 0xa7, 0x2a, 0xe0, 0xc4, 0xe7, 0x5d, 0xae, 0x1c } \ + } +//HTTP协议GUID +#define GRUB_EFI_HTTP_PROTOCOL_GUID \ + { 0x7A59B29B, 0x910B, 0x4171, \ + { 0x82, 0x42, 0xA8, 0x5A, 0x0D, 0xF2, 0x5B, 0x5B } \ + } + +//IP4服务绑定协议GUID +#define GRUB_EFI_IP4_SERVICE_BINDING_PROTOCOL_GUID \ + { 0xc51711e7,0xb4bf,0x404a, \ + { 0xbf,0xb8,0x0a,0x04,0x8e,0xf1,0xff,0xe4} \ + } + +//IP4协议GUID +#define GRUB_EFI_IP4_PROTOCOL_GUID \ + { 0x41d94cd2,0x35b6,0x455a,\ + { 0x82,0x58,0xd4,0xe5,0x13,0x34,0xaa,0xdd} \ + } + +//IP4配置协议GUID +#define GRUB_EFI_IP4_CONFIG_PROTOCOL_GUID \ + { 0x3b95aa31,0x3793,0x434b, \ + { 0x86,0x67,0xc8,0x07,0x08,0x92,0xe0,0x5e} \ + } + +//SAL系统表 //签名 +struct grub_efi_sal_system_table +{ + unsigned int signature; + unsigned int total_table_len; //总表尺寸 + unsigned short sal_rev; + unsigned short entry_count; //入口计数 + unsigned char checksum; //校验和 + unsigned char reserved1[7]; //保留 + unsigned short sal_a_version; //version + unsigned short sal_b_version; //version + unsigned char oem_id[32]; //oem标识 + unsigned char product_id[32]; //产品标识 + unsigned char reserved2[8]; //保留 + unsigned char entries[0]; //条目 +}; + +enum //SAL系统表类型 + { + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_ENTRYPOINT_DESCRIPTOR = 0, //入口描述符 + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_MEMORY_DESCRIPTOR = 1, //存储描述符 + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_PLATFORM_FEATURES = 2, //平台特征 + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_TRANSLATION_REGISTER_DESCRIPTOR = 3, //转换寄存器描述符 + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_PURGE_TRANSLATION_COHERENCE = 4, //清除转换连接 + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_AP_WAKEUP = 5 //AP唤醒 + }; + +struct grub_efi_sal_system_table_entrypoint_descriptor //SAL系统表入口描述符 +{ + unsigned char type; + unsigned char pad[7]; + unsigned long long pal_proc_addr; + unsigned long long sal_proc_addr; + unsigned long long global_data_ptr; + unsigned long long reserved[2]; +}; + +struct grub_efi_sal_system_table_memory_descriptor //SAL系统表存储描述符 +{ + unsigned char type; //类型 + unsigned char sal_used; //使用 + unsigned char attr; //属性 + unsigned char ar; + unsigned char attr_mask; //屏蔽掩膜 + unsigned char mem_type; //内存类型 + unsigned char usage; //用法 + unsigned char unknown; //未知的 + unsigned long long addr; //地址 + unsigned long long len; //长度 + unsigned long long unknown2; //未知的 +}; + +struct grub_efi_sal_system_table_platform_features //SAL系统表平台特征 +{ + unsigned char type; //类型 + unsigned char flags; //标记 + unsigned char reserved[14];//保留 +}; + +struct grub_efi_sal_system_table_translation_register_descriptor //SAL系统表转换寄存器描述符 +{ + unsigned char type; //类型 + unsigned char register_type; //寄存器类型 + unsigned char register_number; //寄存器号 + unsigned char reserved[5]; //保留 + unsigned long long addr; //地址 + unsigned long long page_size; //页尺寸 + unsigned long long reserver; //保留 +}; + +struct grub_efi_sal_system_table_purge_translation_coherence //SAL系统表清除转换连接 +{ + unsigned char type; //类型 + unsigned char reserved[3]; //保留 + unsigned int ndomains; //N域 + unsigned long long coherence; //一致性 +}; + +struct grub_efi_sal_system_table_ap_wakeup //SAL系统表AP唤醒 +{ + unsigned char type; //类型 + unsigned char mechanism; //机制 + unsigned char reserved[6]; //保留 + unsigned long long vector; //矢量 +}; + +enum //SAL系统表平台特征 + { + GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_BUSLOCK = 1, //总线锁 + GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_IRQREDIRECT = 2, //IRQ重定向 + GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_IPIREDIRECT = 4, //IPI重定向 + GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_ITCDRIFT = 8, //斜纹 + }; + +typedef enum grub_efi_parity_type //校验方式 + { + GRUB_EFI_SERIAL_DEFAULT_PARITY, //缺省校验 + GRUB_EFI_SERIAL_NO_PARITY, //无校验 + GRUB_EFI_SERIAL_EVEN_PARITY, //偶校验 + GRUB_EFI_SERIAL_ODD_PARITY //奇校验 + } +grub_efi_parity_type_t; //4 + +typedef enum grub_efi_stop_bits //停止位 + { + GRUB_EFI_SERIAL_DEFAULT_STOP_BITS, //缺省停止位 + GRUB_EFI_SERIAL_1_STOP_BIT, //1停止位 + GRUB_EFI_SERIAL_1_5_STOP_BITS, //1.5停止位 + GRUB_EFI_SERIAL_2_STOP_BITS //2停止位 + } +grub_efi_stop_bits_t; + +/* Enumerations. 枚举 */ +enum grub_efi_timer_delay //计时器延迟 + { + GRUB_EFI_TIMER_CANCEL, //计时器取消 + GRUB_EFI_TIMER_PERIODIC, //计时器周期性 + GRUB_EFI_TIMER_RELATIVE //计时器相对 + }; +typedef enum grub_efi_timer_delay grub_efi_timer_delay_t; + +enum grub_efi_allocate_type //分配类型 + { + GRUB_EFI_ALLOCATE_ANY_PAGES, //任意页面 0 分配请求分配满足该请求的任何可用页面范围。输入时,忽略内存指向的地址 + GRUB_EFI_ALLOCATE_MAX_ADDRESS, //最大地址 1 分配请求分配任何可用的页范围,这些页的最上面地址小于或等于输入时内存指向的地址。 + GRUB_EFI_ALLOCATE_ADDRESS, //指定地址 2 分配请求在输入时由内存指向的地址分配页。 + GRUB_EFI_MAX_ALLOCATION_TYPE //最大分配类型 3 + }; +typedef enum grub_efi_allocate_type grub_efi_allocate_type_t; + +enum grub_efi_memory_type //存储器类型 + { + GRUB_EFI_RESERVED_MEMORY_TYPE, //保留内存类型 0 + GRUB_EFI_LOADER_CODE, //装载程序代码 1 + GRUB_EFI_LOADER_DATA, //装载数据 2 + GRUB_EFI_BOOT_SERVICES_CODE, //启动服务代码 3 + GRUB_EFI_BOOT_SERVICES_DATA, //启动服务数据 4 + GRUB_EFI_RUNTIME_SERVICES_CODE, //运行服务代码 5 + GRUB_EFI_RUNTIME_SERVICES_DATA, //运行服务数据 6 + GRUB_EFI_CONVENTIONAL_MEMORY, //常规存储器 7 + GRUB_EFI_UNUSABLE_MEMORY, //不可用内存 8 + GRUB_EFI_ACPI_RECLAIM_MEMORY, //ACPI回收内存 9 + GRUB_EFI_ACPI_MEMORY_NVS, //ACPI存储器NVS a + GRUB_EFI_MEMORY_MAPPED_IO, //内存映射IO b + GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE, //内存映射IO端口空间 c + GRUB_EFI_PAL_CODE, //PAL代码 d + GRUB_EFI_PERSISTENT_MEMORY, //持久记忆 e + GRUB_EFI_MAX_MEMORY_TYPE //最大内存类型 f + }; +typedef enum grub_efi_memory_type grub_efi_memory_type_t; //4 + +enum grub_efi_interface_type //接口类型 + { + GRUB_EFI_NATIVE_INTERFACE //本机接口 + }; +typedef enum grub_efi_interface_type grub_efi_interface_type_t; + +enum grub_efi_locate_search_type //定位搜索类型 + { + GRUB_EFI_ALL_HANDLES, //所有句柄 + GRUB_EFI_BY_REGISTER_NOTIFY, //通过寄存器通知 + GRUB_EFI_BY_PROTOCOL //通过协议 + }; +typedef enum grub_efi_locate_search_type grub_efi_locate_search_type_t; + +enum grub_efi_reset_type //复位类型 + { + GRUB_EFI_RESET_COLD, //冷复位 + GRUB_EFI_RESET_WARM, //热复位 + GRUB_EFI_RESET_SHUTDOWN //关机 + }; +typedef enum grub_efi_reset_type grub_efi_reset_type_t; + + + +#define GRUB_EFI_ERROR_CODE(value) \ + ((((grub_efi_status_t) 1) << (sizeof (grub_efi_status_t) * 8 - 1)) | (value)) //32位: 1<<31 | value +//uefi错误代码值 error +#define GRUB_EFI_WARNING_CODE(value) (value) + +#define GRUB_EFI_SUCCESS 0 //正常 + +#define GRUB_EFI_LOAD_ERROR GRUB_EFI_ERROR_CODE (1) //加载错误 +#define GRUB_EFI_INVALID_PARAMETER GRUB_EFI_ERROR_CODE (2) //无效参数 +#define GRUB_EFI_UNSUPPORTED GRUB_EFI_ERROR_CODE (3) //不支持 +#define GRUB_EFI_BAD_BUFFER_SIZE GRUB_EFI_ERROR_CODE (4) //参数不是设备固有块大小的倍数 +#define GRUB_EFI_BUFFER_TOO_SMALL GRUB_EFI_ERROR_CODE (5) //缓存太小 +#define GRUB_EFI_NOT_READY GRUB_EFI_ERROR_CODE (6) //还没准备好 +#define GRUB_EFI_DEVICE_ERROR GRUB_EFI_ERROR_CODE (7) //设备错误 +#define GRUB_EFI_WRITE_PROTECTED GRUB_EFI_ERROR_CODE (8) //写保护 +#define GRUB_EFI_OUT_OF_RESOURCES GRUB_EFI_ERROR_CODE (9) //资源不足 +#define GRUB_EFI_VOLUME_CORRUPTED GRUB_EFI_ERROR_CODE (10) //卷损坏 +#define GRUB_EFI_VOLUME_FULL GRUB_EFI_ERROR_CODE (11) //卷已满 +#define GRUB_EFI_NO_MEDIA GRUB_EFI_ERROR_CODE (12) //没有媒体 +#define GRUB_EFI_MEDIA_CHANGED GRUB_EFI_ERROR_CODE (13) //媒体变更 +#define GRUB_EFI_NOT_FOUND GRUB_EFI_ERROR_CODE (14) //没有找到 +#define GRUB_EFI_ACCESS_DENIED GRUB_EFI_ERROR_CODE (15) //拒绝访问 +#define GRUB_EFI_NO_RESPONSE GRUB_EFI_ERROR_CODE (16) //没有反应 +#define GRUB_EFI_NO_MAPPING GRUB_EFI_ERROR_CODE (17) //没有映射 到设备的映射不存在 +#define GRUB_EFI_TIMEOUT GRUB_EFI_ERROR_CODE (18) //超时 +#define GRUB_EFI_NOT_STARTED GRUB_EFI_ERROR_CODE (19) //没有开始 +#define GRUB_EFI_ALREADY_STARTED GRUB_EFI_ERROR_CODE (20) //已经开始 +#define GRUB_EFI_ABORTED GRUB_EFI_ERROR_CODE (21) //已中止 +#define GRUB_EFI_ICMP_ERROR GRUB_EFI_ERROR_CODE (22) //ICMP错误 +#define GRUB_EFI_TFTP_ERROR GRUB_EFI_ERROR_CODE (23) //TFTP错误 +#define GRUB_EFI_PROTOCOL_ERROR GRUB_EFI_ERROR_CODE (24) //协议错误 +#define GRUB_EFI_INCOMPATIBLE_VERSION GRUB_EFI_ERROR_CODE (25)//不兼容的版本 +#define GRUB_EFI_SECURITY_VIOLATION GRUB_EFI_ERROR_CODE (26) //安全违规 +#define GRUB_EFI_CRC_ERROR GRUB_EFI_ERROR_CODE (27) //CRC错误 +#define GRUB_EFI_END_OF_MEDIA GRUB_EFI_ERROR_CODE (28) //已到达媒体的开始或结束 +#define GRUB_EFI_END_OF_FILE GRUB_EFI_ERROR_CODE (31) //已到达文件的末尾 +#define GRUB_EFI_INVALID_LANGUAGE GRUB_EFI_ERROR_CODE (32) //指定的语言无效 +#define GRUB_EFI_COMPROMISED_DATA GRUB_EFI_ERROR_CODE (33) //数据的安全状态未知或已损坏,必须更新或替换数据才能恢复有效的安全状态。 +#define GRUB_EFI_IP_ADDRESS_CONFLICT GRUB_EFI_ERROR_CODE (34)//存在地址冲突地址分配 +#define GRUB_EFI_HTTP_ERROR GRUB_EFI_ERROR_CODE (35) //网络操作过程中发生HTTP错误 + +#define GRUB_EFI_NETWORK_UNREACHABLE GRUB_EFI_ERROR_CODE (100) //网络不可访问 +#define GRUB_EFI_HOST_UNREACHABLE GRUB_EFI_ERROR_CODE (101) //主机无法访问 +#define GRUB_EFI_PROTOCOL_UNREACHABLE GRUB_EFI_ERROR_CODE (102) //协议不可访问 +#define GRUB_EFI_PORT_UNREACHABLE GRUB_EFI_ERROR_CODE (103) //端口无法访问 +#define GRUB_EFI_CONNECTION_FIN GRUB_EFI_ERROR_CODE (104) //接收操作失败,因为通信对等体已关闭连接,并且实例的接收缓冲区中没有更多数据。 +#define GRUB_EFI_CONNECTION_RESET GRUB_EFI_ERROR_CODE (105) //接收或传输操作失败,因为此连接被实例本身或通信对等体重置。 +#define GRUB_EFI_CONNECTION_REFUSED GRUB_EFI_ERROR_CODE (106) //此连接被拒绝,接收或传输操作失败。 + +#define GRUB_EFI_WARN_UNKNOWN_GLYPH GRUB_EFI_WARNING_CODE (1) //警告 未知字形 +#define GRUB_EFI_WARN_DELETE_FAILURE GRUB_EFI_WARNING_CODE (2) //警告 删除失败 +#define GRUB_EFI_WARN_WRITE_FAILURE GRUB_EFI_WARNING_CODE (3) //警告 写失败 +#define GRUB_EFI_WARN_BUFFER_TOO_SMALL GRUB_EFI_WARNING_CODE (4) //警告 缓存太小 +#define GRUB_EFI_WARN_STALE_DATA GRUB_EFI_WARNING_CODE (5) //警告 过期数据 +#define GRUB_EFI_WARN_FILE_SYSTEM GRUB_EFI_WARNING_CODE (6) //警告 文件系统 + + +typedef void *grub_efi_event_t; +typedef grub_efi_uint64_t grub_efi_lba_t; +typedef grub_efi_uintn_t grub_efi_tpl_t; +typedef grub_uint8_t grub_efi_mac_address_t[32]; +typedef grub_uint8_t grub_efi_ipv4_address_t[4]; +typedef grub_uint16_t grub_efi_ipv6_address_t[8]; +//typedef grub_uint8_t grub_efi_ip_address_t[8] __attribute__ ((aligned(4))); +typedef union +{ + grub_efi_uint32_t addr[4]; + grub_efi_ipv4_address_t v4; + grub_efi_ipv6_address_t v6; +} grub_efi_ip_address_t __attribute__ ((aligned(4))); +typedef grub_efi_uint64_t grub_efi_physical_address_t; +typedef grub_efi_uint64_t grub_efi_virtual_address_t; + +struct grub_efi_packed_guid //efi包 +{ + unsigned int data1; + unsigned short data2; + unsigned short data3; + unsigned char data4[8]; +} __attribute__ ((packed)); +typedef struct grub_efi_packed_guid grub_efi_packed_guid_t; + +/* XXX although the spec does not specify the padding, this actually 虽然规格没有指定填充,这一定要有填充物! + must have the padding! */ +struct grub_efi_memory_descriptor //内存描述符 +{ + unsigned int type; //类型 07 + unsigned int padding; //填充 00 + unsigned long long physical_start; //物理地址起始 0 + unsigned long long virtual_start; //虚拟地址起始 0 + unsigned long long num_pages; //页数 a0 + unsigned long long attribute; //属性 0f +} __attribute__ ((packed)); +typedef struct grub_efi_memory_descriptor grub_efi_memory_descriptor_t; //28(按指定) + +#define NEXT_MEMORY_DESCRIPTOR(desc, size) \ + ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) //下一个内存描述符(描述符,尺寸) + +/* Device Path definitions. 设备路径定义 */ +struct grub_efi_device_path +{ + unsigned char type; //类型 04 7f结束 + unsigned char subtype; //子类型 04 ff结束 01结束设备路径的此实例并启动新的设备路径 + unsigned short length; //长度 0030 \EFI\BOOT\BOOTX64.EFI 此结构的长度(字节)。长度为4字节。 +} __attribute__ ((packed)); +typedef struct grub_efi_device_path grub_efi_device_path_t; +/* XXX EFI does not define EFI_DEVICE_PATH_PROTOCOL but uses it. EFI不定义EFI_DEVICE_PATH_PROTOCOL协议,而是使用它. 这似乎相同于EFI_DEVICE_PATH. + It seems to be identical to EFI_DEVICE_PATH. */ +typedef struct grub_efi_device_path grub_efi_device_path_protocol_t; + +#define GRUB_EFI_DEVICE_PATH_TYPE(dp) ((dp)->type & 0x7f) //路径类型 +#define GRUB_EFI_DEVICE_PATH_SUBTYPE(dp) ((dp)->subtype) //路径子类型 +#define GRUB_EFI_DEVICE_PATH_LENGTH(dp) ((dp)->length) //路径尺寸 +#define GRUB_EFI_DEVICE_PATH_VALID(dp) ((dp) != NULL && GRUB_EFI_DEVICE_PATH_LENGTH (dp) >= 4) //路径有效 不为零并且尺寸>=4 + +/* The End of Device Path nodes. 设备路径节点的结束 */ +#define GRUB_EFI_END_DEVICE_PATH_TYPE (0xff & 0x7f) //结束设备路径类型 + +#define GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff //结束整个设备路径子类型 +#define GRUB_EFI_END_THIS_DEVICE_PATH_SUBTYPE 0x01 //结束这个设备路径子类型 + +#define GRUB_EFI_END_ENTIRE_DEVICE_PATH(dp) \ + (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_END_DEVICE_PATH_TYPE \ + && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) \ + == GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE)) //判断是不是结束设备路径 + +#define GRUB_EFI_NEXT_DEVICE_PATH(dp) \ + ((grub_efi_device_path_t *) ((char *) (dp) \ + + GRUB_EFI_DEVICE_PATH_LENGTH (dp))) //获得下一设备路径 + +typedef struct { + grub_uint8_t addr[4]; +} grub_efi_pxe_ipv4_address_t; + +typedef struct { + grub_uint8_t addr[16]; +} grub_efi_pxe_ipv6_address_t; + +typedef struct { + grub_uint8_t addr[32]; +} grub_efi_pxe_mac_address_t; + +typedef union { + grub_uint32_t addr[4]; + grub_efi_pxe_ipv4_address_t v4; + grub_efi_pxe_ipv6_address_t v6; +} grub_efi_pxe_ip_address_t; + +/* Hardware Device Path. 硬件设备路径类型 */ +#define GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE 1 +//此设备路径定义设备如何连接到系统的资源域,其中资源域只是系统的共享内存、内存映射I/O和I/O空间。可以有多个级别的硬件设备路径,例如连接到PCCARD PCI控制器的PCCARD设备。 + +//PCI设备路径子类型 +#define GRUB_EFI_PCI_DEVICE_PATH_SUBTYPE 1 +//PCI的设备路径定义PCI设备的PCI配置空间地址的路径。每个设备和函数号都有一个PCI设备路径条目,用于定义从根PCI总线到设备的路径。由于设备的PCI总线号可能会更改,因此无法使用单个PCI设备路径项的平面编码。例如,当PCI设备位于网桥后面时,会发生以下事件之一: +//?操作系统执行PCI总线的即插即用配置。 +//?执行PCI设备的热插拔。 +//?系统配置在重新启动之间更改。 +//PCI设备路径条目前面必须有唯一标识PCI根总线的ACPI设备路径条目。根PCI桥的编程没有由任何PCI规范定义,这就是为什么需要ACPI设备路径条目的原因。 + +struct grub_efi_pci_device_path //pci设备路径 +{ + grub_efi_device_path_t header; //设备路径表头 + unsigned char function; //功能 + unsigned char device; //设备 +} __attribute__ ((packed)); +typedef struct grub_efi_pci_device_path grub_efi_pci_device_path_t; +//PC卡设备路径子类型 +#define GRUB_EFI_PCCARD_DEVICE_PATH_SUBTYPE 2 + +struct grub_efi_pccard_device_path //PC卡设备路径 +{ + grub_efi_device_path_t header; //设备路径表头 + unsigned char function; //功能 +} __attribute__ ((packed)); +typedef struct grub_efi_pccard_device_path grub_efi_pccard_device_path_t; +//内存映射设备路径子类型 +#define GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE 3 + +struct grub_efi_memory_mapped_device_path //内存映射设备路径 +{ + grub_efi_device_path_t header; + unsigned int memory_type; //内存类型 + unsigned long long start_address;//物理起始地址 + unsigned long long end_address; //物理结束地址 +} __attribute__ ((packed)); +typedef struct grub_efi_memory_mapped_device_path grub_efi_memory_mapped_device_path_t; +//供应商设备路径子类型 +#define GRUB_EFI_VENDOR_DEVICE_PATH_SUBTYPE 4 + +struct grub_efi_vendor_device_path //供应商设备路径 +{ + grub_efi_device_path_t header; //句柄 + grub_efi_packed_guid_t vendor_guid; //供应商guid + unsigned char vendor_defined_data[0]; //供应商定义的数据 +} __attribute__ ((packed)); +typedef struct grub_efi_vendor_device_path grub_efi_vendor_device_path_t; +//控制器设备路径子类型 +#define GRUB_EFI_CONTROLLER_DEVICE_PATH_SUBTYPE 5 + +struct grub_efi_controller_device_path //控制器设备路径 +{ + grub_efi_device_path_t header; //设备路径表头 + unsigned int controller_number; //控制器号 +} __attribute__ ((packed)); +typedef struct grub_efi_controller_device_path grub_efi_controller_device_path_t; + +//ACPI设备路径类型 +#define GRUB_EFI_ACPI_DEVICE_PATH_TYPE 2 //类型 +//此设备路径包含表示设备的即插即用硬件ID及其对应的唯一持久ID的ACPI设备ID。ACPI ID存储在与设备关联的ACPI HID、CID和UID设备标识对象中。ACPI设备路径包含的值必须与平台固件提供给操作系统的ACPI名称空间完全匹配。有关HID、CID和UID设备标识对象的完整说明,请参阅ACPI规范。 +//HID和CID值是出现在ACPI名称空间中的可选设备标识对象。如果只存在HID,则必须使用HID来描述将由ACPI驱动程序枚举的任何设备。如果存在,则CID包含对操作系统附加通用驱动程序(例如,PCI总线驱动程序)重要的信息,而HID包含对操作系统附加设备特定驱动程序重要的信息。ACPI总线驱动仅在设备没有标准总线枚举器的情况下枚举设备。 +//UID对象为操作系统提供一个序列号样式的ID,用于在重新启动时不会更改的设备。对象是可选的,但当系统包含两个报告相同HID的设备时,该对象是必需的。UID只需在具有相同HID值的所有设备对象中唯一。如果在一个yHID的APCI名称空间中不存在UIID,则必须在ACPI设备路径的UID字段中存储零的值。 +//ACPI设备路径仅用于描述不由硬件设备路径定义的设备。由于PCI规范没有定义PCI根桥的编程模型,因此需要一个HID(如果存在,还需要一个CID)来表示PCI根桥。ACPI设备路径有两个子类型:一个简单的子类型,仅包含HID和UID字段,另一个扩展的子类型,包含HID、CID和UID字段。 +//ACPI设备路径节点仅支持用于HID和UID值的32位数值。扩展的ACPI设备路径节点支持HID、UID和CID值的数值和字符串值。结果,ACPI设备路径节点较小,如果可能的话,应该使用它来减小可能存储在非易失性存储器中的设备路径的大小。如果HID字段需要字符串值,或者UID字段需要字符串值,或者CID字段需要字符串值,则必须使用扩展的ACPI设备路径节点。如果扩展的ACPI设备路径节点的字符串字段存在,则忽略相应的数值字段。 +//ACPI设备路径节点和扩展的ACPI设备路径节点中的HID和CID字段存储为32位压缩EISA类型id。以下宏可用于从即插即用硬件ID计算这些EISA类型ID。用于计算EFI设备路径节点中的HID和CID字段的即插即用硬件ID必须与用于在ACPI表中生成匹配项的即插即用硬件ID匹配。此宏生成的压缩EISA类型ID与存储在ACPI表中的压缩EISA类型ID不同。因此,来自ACPI设备路径节点的压缩EISA类型id不能直接与来自ACPI表的压缩EISA类型id进行比较。 + +//ACPI设备路径子类型 +#define GRUB_EFI_ACPI_DEVICE_PATH_SUBTYPE 1 //子类型 + +struct grub_efi_acpi_device_path //ACPI设备路径 +{ + grub_efi_device_path_t header; //设备路径表头 + unsigned int hid; + unsigned int uid; +} __attribute__ ((packed)); +typedef struct grub_efi_acpi_device_path grub_efi_acpi_device_path_t; +//扩展的ACPI设备路径子类型 +#define GRUB_EFI_EXPANDED_ACPI_DEVICE_PATH_SUBTYPE 2 + +struct grub_efi_expanded_acpi_device_path //扩展的ACPI设备路径 +{ + grub_efi_device_path_t header; //设备路径表头 + unsigned int hid; + unsigned int uid; + unsigned int cid; + char hidstr[0]; +} __attribute__ ((packed)); +typedef struct grub_efi_expanded_acpi_device_path grub_efi_expanded_acpi_device_path_t; + +#define GRUB_EFI_EXPANDED_ACPI_HIDSTR(dp) \ + (((grub_efi_expanded_acpi_device_path_t *) dp)->hidstr) +#define GRUB_EFI_EXPANDED_ACPI_UIDSTR(dp) \ + (GRUB_EFI_EXPANDED_ACPI_HIDSTR(dp) \ + + grub_strlen (GRUB_EFI_EXPANDED_ACPI_HIDSTR(dp)) + 1) +#define GRUB_EFI_EXPANDED_ACPI_CIDSTR(dp) \ + (GRUB_EFI_EXPANDED_ACPI_UIDSTR(dp) \ + + grub_strlen (GRUB_EFI_EXPANDED_ACPI_UIDSTR(dp)) + 1) + +//消息传递设备路径类型 +#define GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE 3 +//ATAPI设备路径子类型 +#define GRUB_EFI_ATAPI_DEVICE_PATH_SUBTYPE 1 + +struct grub_efi_atapi_device_path //ATAPI设备路径 +{ + grub_efi_device_path_t header; //设备路径表头 + unsigned char primary_secondary; //主次 + unsigned char slave_master; //从主 + unsigned short lun; //逻辑单元 +} __attribute__ ((packed)); +typedef struct grub_efi_atapi_device_path grub_efi_atapi_device_path_t; +//SCSI设备路径子类型 +#define GRUB_EFI_SCSI_DEVICE_PATH_SUBTYPE 2 + +struct grub_efi_scsi_device_path //scsi设备路径 +{ + grub_efi_device_path_t header; //设备路径表头 + unsigned short pun; + unsigned short lun; +} __attribute__ ((packed)); +typedef struct grub_efi_scsi_device_path grub_efi_scsi_device_path_t; +//光纤通道设备路径子类型 +#define GRUB_EFI_FIBRE_CHANNEL_DEVICE_PATH_SUBTYPE 3 + +struct grub_efi_fibre_channel_device_path //光纤通道设备路径 +{ + grub_efi_device_path_t header; //设备路径表头 + unsigned int reserved; + unsigned long long wwn; + unsigned long long lun; +} __attribute__ ((packed)); +typedef struct grub_efi_fibre_channel_device_path grub_efi_fibre_channel_device_path_t; +//1394设备路径子类型 +#define GRUB_EFI_1394_DEVICE_PATH_SUBTYPE 4 + +struct grub_efi_1394_device_path //1394设备路径 +{ + grub_efi_device_path_t header; //设备路径表头 + unsigned int reserved; + unsigned long long guid; +} __attribute__ ((packed)); +typedef struct grub_efi_1394_device_path grub_efi_1394_device_path_t; +//usb设备路径子类型 +#define GRUB_EFI_USB_DEVICE_PATH_SUBTYPE 5 + +struct grub_efi_usb_device_path //usb设备路径 +{ + grub_efi_device_path_t header; //设备路径表头 + unsigned char parent_port_number; //父端口号 + unsigned char usb_interface; //接口 +} __attribute__ ((packed)); +typedef struct grub_efi_usb_device_path grub_efi_usb_device_path_t; +//I2O设备路径子类型 +#define GRUB_EFI_I2O_DEVICE_PATH_SUBTYPE 6 + +struct grub_efi_i2o_device_path //i2o设备路径 +{ + grub_efi_device_path_t header; + unsigned int tid; +} __attribute__ ((packed)); +typedef struct grub_efi_i2o_device_path grub_efi_i2o_device_path_t; +//无限宽带设备路径子类型 +#define GRUB_EFI_INFINIBAND_DEVICE_PATH_SUBTYPE 9 + +struct grub_efi_infiniband_device_path //无限宽带设备路径 +{ + grub_efi_device_path_t header; + unsigned int resource_flags; + unsigned char port_gid[16]; + unsigned long long remote_id; + unsigned long long target_port_id; + unsigned long long device_id; +} __attribute__ ((packed)); +typedef struct grub_efi_infiniband_device_path grub_efi_infiniband_device_path_t; +//MAC地址设备路径子类型 +#define GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE 11 + +struct grub_efi_mac_address_device_path //MAC地址设备路径 +{ + grub_efi_device_path_t header; + grub_efi_mac_address_t mac_address; //mac地址 + unsigned char if_type; //网络接口类型(即802.3、FDDI) See RFC 3232 +} __attribute__ ((packed)); +typedef struct grub_efi_mac_address_device_path grub_efi_mac_address_device_path_t; +//IPV4设备路径子类型 +#define GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE 12 + +struct grub_efi_ipv4_device_path //ipv4设备路径 +{ + grub_efi_device_path_t header; //标头 + grub_efi_ipv4_address_t local_ip_address; //本地ip地址 + grub_efi_ipv4_address_t remote_ip_address; //远程ip地址 + grub_efi_uint16_t local_port; //本地端口 + grub_efi_uint16_t remote_port; //远程端口 + grub_efi_uint16_t protocol; //网络协议(即UDP、TCP) + grub_efi_uint8_t static_ip_address; //静态ip地址 0x00-源IP地址是通过DHCP分配的;0x01-源IP地址被静态绑定 + grub_efi_ipv4_address_t gateway_ip_address; //网关ip地址 + grub_efi_ipv4_address_t subnet_mask; //子网掩码 +} GRUB_PACKED; +typedef struct grub_efi_ipv4_device_path grub_efi_ipv4_device_path_t; +//IPV6设备路径子类型 +#define GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE 13 + +struct grub_efi_ipv6_device_path //ipv6设备路径 +{ + grub_efi_device_path_t header; //标头 + grub_efi_ipv6_address_t local_ip_address; //本地ip地址 + grub_efi_ipv6_address_t remote_ip_address; //远程ip地址 + grub_efi_uint16_t local_port; //本地端口 + grub_efi_uint16_t remote_port; //远程端口 + grub_efi_uint16_t protocol; //网络协议(即UDP、TCP) + grub_efi_uint8_t static_ip_address; //静态ip地址 0x00-本地IP地址已手动配置;0x01-本地IP地址是通过IPv6无状态自动配置分配的;0x02-本地IP地址是通过IPv6状态配置分配的 + grub_efi_uint8_t prefix_length; //前缀长度 + grub_efi_ipv6_address_t gateway_ip_address; //网关ip地址 +} GRUB_PACKED; +typedef struct grub_efi_ipv6_device_path grub_efi_ipv6_device_path_t; +//UART设备路径子类型 +#define GRUB_EFI_UART_DEVICE_PATH_SUBTYPE 14 + +struct grub_efi_uart_device_path //uart设备路径 +{ + grub_efi_device_path_t header; + unsigned int reserved; + unsigned long long baud_rate; + unsigned char data_bits; + unsigned char parity; + unsigned char stop_bits; +} __attribute__ ((packed)); +typedef struct grub_efi_uart_device_path grub_efi_uart_device_path_t; +//USB类设备路径子类型 +#define GRUB_EFI_USB_CLASS_DEVICE_PATH_SUBTYPE 15 + +struct grub_efi_usb_class_device_path //USB类设备路径 +{ + grub_efi_device_path_t header; //设备路径表头 + unsigned short vendor_id; //厂商标识 + unsigned short product_id; //产品标识 + unsigned char device_class; //设备类 + unsigned char device_subclass; //设备子类 + unsigned char device_protocol; //设备协议 +} __attribute__ ((packed)); +typedef struct grub_efi_usb_class_device_path grub_efi_usb_class_device_path_t; +#define GRUB_EFI_USB_LOGICAL_UNIT_DEVICE_PATH_SUBTYPE 17 + +struct grub_efi_usb_logical_unit_device_path //USB逻辑单元设备路径 +{ + grub_efi_device_path_t header; //设备路径表头 + unsigned char LUN; //接口的逻辑单元号 +} __attribute__ ((packed)); +typedef struct grub_efi_usb_logical_unit_device_path grub_efi_usb_logical_unit_device_path_t; +//SATA设备路径子类型 +#define GRUB_EFI_SATA_DEVICE_PATH_SUBTYPE 18 + +struct grub_efi_sata_device_path //sata设备路径 +{ + grub_efi_device_path_t header; + unsigned short hba_port; + unsigned short multiplier_port; + unsigned short lun; +} __attribute__ ((packed)); +typedef struct grub_efi_sata_device_path grub_efi_sata_device_path_t; +#if 1 +#define GRUB_EFI_URI_DEVICE_PATH_SUBTYPE 24 + +struct grub_efi_uri_device_path +{ + grub_efi_device_path_t header; + grub_efi_uint8_t uri[0]; +} GRUB_PACKED; +typedef struct grub_efi_uri_device_path grub_efi_uri_device_path_t; + +#define GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE 31 +struct grub_efi_dns_device_path +{ + grub_efi_device_path_t header; + grub_efi_uint8_t is_ipv6; + grub_efi_pxe_ip_address_t dns_server_ip[0]; +} GRUB_PACKED; +typedef struct grub_efi_dns_device_path grub_efi_dns_device_path_t; +#endif +//供应商信息设备路径子类型 +#define GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE 10 + +//媒体设备路径类型 +#define GRUB_EFI_MEDIA_DEVICE_PATH_TYPE 4 +//此设备路径用于描述由引导服务抽象的介质部分。媒体设备路径的一个例子是定义硬盘上正在使用的分区。 + +//硬盘驱动器设备路径子类型 +#define GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE 1 +//硬盘驱动器媒体设备路径用于表示硬盘驱动器上的分区。每个分区至少有一个硬盘驱动器设备路径节点,每个节点描述分区表中的一个条目。EFI支持MBR和GPT分区格式。分区根据它们在各自分区表中的条目进行编号,从1开始。分区从lba0开始在EFI中寻址。分区号为零可用于表示原始硬盘驱动器或原始扩展分区。 +//分区格式存储在设备路径中,以便将来支持新的分区格式。硬盘驱动器设备路径还包含磁盘签名和磁盘签名类型。磁盘签名由操作系统维护,并且仅由EFI用于分区设备路径节点。磁盘签名使操作系统能够查找磁盘,即使磁盘已在系统中物理移动。 +//第3.1.2节定义了处理硬盘驱动器媒体设备路径的特殊规则。这些特殊规则允许磁盘的位置更改,并且系统仍然可以从磁盘启动。 + +struct grub_efi_hard_drive_device_path //硬盘驱动器路径 +{ + grub_efi_device_path_t header; //设备路径表头 + unsigned int partition_number; //分区号 描述分区表中的条目,从条目1开始。分区号0表示整个设备。MBR分区的有效分区号是[1-4],但是并不对应主分区号。GPT分区的有效分区号为[1,NumberOfPartitionEntries]。 + unsigned long long partition_start; //分区起始 启动硬盘上分区的LBA + unsigned long long partition_size; //分区尺寸 以逻辑块为单位的分区大小 + unsigned char partition_signature[16]; //分区签名 此分区唯一的签名:如果SignatureType为0,则必须用16个零初始化此字段。 + // 如果SignatureType为1,则MBR签名存储在此字段的前4个字节中。其他12个字节用零初始化。 签名是1b8处的4字节. + // 如果SignatureType为2,则此字段包含16字节签名。签名是分区GUID. + unsigned char partmap_type; //分区格式类型 分区格式(保留未使用的值) 0x01–PC-AT兼容的传统MBR(见第5.2.1节)。分区开始和分区大小来自分区的PartitionStartingLBA和PartitionSizeInLBA。 + // 0x02–GUID分区表(请参阅第5.3.2节)。 + unsigned char signature_type; //签名类型 磁盘签名类型:(保留未使用的值) 0x00–没有磁盘签名。0x01–来自0x01 MBR类型的地址0x1b8的32位签名. 0x02–GUID签名。 +} __attribute__ ((packed)); +typedef struct grub_efi_hard_drive_device_path grub_efi_hard_drive_device_path_t; +//光盘驱动器路径子类型 +#define GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE 2 + +struct grub_efi_cdrom_device_path //光盘驱动器路径 +{ + grub_efi_device_path_t header; //设备路径表头 + unsigned int boot_entry; //引导入口 引导目录中的引导条目号。初始/默认项定义为零。 0 + unsigned long long boot_start; //引导起始 引导映像文件的扇区地址。 12b + unsigned long long boot_size; //引导尺寸 引导时装入内存的映像文件扇区数(每扇区按0x200字节) 4 +} __attribute__ ((packed)); +typedef struct grub_efi_cdrom_device_path grub_efi_cdrom_device_path_t; +//多媒体设备路径子类型 +#define GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE 3 + +struct grub_efi_vendor_media_device_path //多媒体设备路径 +{ + grub_efi_device_path_t header; + grub_efi_packed_guid_t vendor_guid; + unsigned char vendor_defined_data[0]; +} __attribute__ ((packed)); +typedef struct grub_efi_vendor_media_device_path grub_efi_vendor_media_device_path_t; +//文件路径设备路径子类型 +#define GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE 4 + +struct grub_efi_file_path_device_path //文件路径设备路径 +{ + grub_efi_device_path_t header; //设备路径表头 + unsigned short path_name[0]; //路径名称 +} __attribute__ ((packed)); +typedef struct grub_efi_file_path_device_path grub_efi_file_path_device_path_t; +//协议设备路径子类型 +#define GRUB_EFI_PROTOCOL_DEVICE_PATH_SUBTYPE 5 + +struct grub_efi_protocol_device_path //协议设备路径 +{ + grub_efi_device_path_t header; + grub_efi_packed_guid_t guid; +} __attribute__ ((packed)); +typedef struct grub_efi_protocol_device_path grub_efi_protocol_device_path_t; +//PIWG设备路径子类型 +#define GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE 6 + +struct grub_efi_piwg_device_path //PIWG设备路径 +{ + grub_efi_device_path_t header; + grub_efi_packed_guid_t guid; +} __attribute__ ((packed)); +typedef struct grub_efi_piwg_device_path grub_efi_piwg_device_path_t; + + +//BIOS设备路径类型 +#define GRUB_EFI_BIOS_DEVICE_PATH_TYPE 5 +//BIOS设备路径子类型 +#define GRUB_EFI_BIOS_DEVICE_PATH_SUBTYPE 1 + +struct grub_efi_bios_device_path //BIOS设备路径 +{ + grub_efi_device_path_t header; //设备路径表头 + unsigned short device_type; //设备类型 + unsigned short status_flags; //状态标志 + char description[0]; +} __attribute__ ((packed)); +typedef struct grub_efi_bios_device_path grub_efi_bios_device_path_t; + +//设备路径转文本协议 +//struct EFI_DEVICE_PATH_TO_TEXT_PROTOCOL +struct grub_efi_device_to_text_protocol +{ + //创建设备节点到文本 + unsigned short* EFIAPI + (*ConvertDeviceNodeToText)( //PciRoot(0x0) + grub_efi_device_path_protocol_t *DeviceNode, //设备节点 + grub_int8_t DisplayOnly, //仅显示 + grub_int8_t AllowShortcuts); //允许快捷方式 + + //创建设备路径到文本 + unsigned short* EFIAPI + (*ConvertDevicePathToText)( //PciRoot(0x0)/Pci(0x1,0x1)/Ata(Primary,Master,0x0)/HD(1,MBR,0x12efcdab,0x3f,0x7cfc1) + grub_efi_device_path_protocol_t *DevicePath, //设备路径 + grub_int8_t DisplayOnly, //仅显示 + grub_int8_t AllowShortcuts); //允许快捷方式 +}; +typedef struct grub_efi_device_to_text_protocol grub_efi_device_to_text_protocol_t; + +//文本转设备路径协议 +//将其转换为一个分配给它的二进制表示的缓冲区。 +//内存是从EFI引导服务内存分配的。调用者有责任释放分配的内存。 +//struct EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL +struct grub_efi_device_pate_from_text_protocol +{ + //将文本转换为设备节点的二进制表示形式。 + grub_efi_device_path_protocol_t *EFIAPI (*ConvertTextToDeviceNode)( + const unsigned short *TextDeviceNode); //指向设备节点的文本表示形式。转换从第一个字符开始,一直持续到第一个非设备节点字符。 + + //将文本转换为设备路径的二进制表示形式。 + grub_efi_device_path_protocol_t *EFIAPI (*ConvertTextToDevicePath)( + const unsigned short *TextDevicePath); //指向设备路径的文本表示形式。转换从第一个字符开始,一直持续到第一个非设备路径字符。 +}; + +//设备路径实用程序协议 +//struct EFI_DEVICE_PATH_UTILITIES_PROTOCOL +struct grub_efi_device_pate_utilities_protocol +{ + //获得设备路径尺寸 + //此函数返回指定设备路径的尺寸(以字节为单位),包括路径结束标记。如果DevicePath为NULL,则返回零。 + grub_efi_uintn_t *EFIAPI (* GetDevicePathSize)( + grub_efi_device_path_protocol_t *DevicePath); //指向EFI设备路径的起点。 + + //创建指定路径的副本 + //此函数用于创建指定设备路径的副本。内存是从EFI引导服务内存分配的。调用者有责任释放分配的内存。如果DevicePath为NULL,则返回NULL,并且不分配内存。 + //此函数返回指向重复设备路径的指针,如果内存不足,则返回NULL。 + grub_efi_device_path_protocol_t *EFIAPI (* DuplicateDevicePath)( + grub_efi_device_path_protocol_t *DevicePath); //指向源设备路径 + + //附加设备路径 通过将第二个设备路径附加到第一个设备路径来创建新路径。 + //此函数通过将第二个设备路径的副本附加到新分配的缓冲区中第一个设备路径的副本来创建新的设备路径。只保留第二个设备路径中的设备路径末端设备节点。 + //如果Src1为NULL而Src2为非NULL,则返回Src2的副本。如果Src1为非NULL且Src2为NULL,则返回Src1的副本。如果Src1和Src2都为NULL,则返回设备结束路径的副本。 + //内存是从EFI引导服务内存分配的。调用者有责任释放分配的内存。 + //此函数返回指向新创建的设备路径的指针,如果无法分配内存,则返回NULL。 + grub_efi_device_path_protocol_t *EFIAPI (* AppendDevicePath)( + const grub_efi_device_path_protocol_t *Src1, //指向第一个设备路径。 + const grub_efi_device_path_protocol_t *Src2); //指向第二个设备路径。 + + //附加设备节点 通过将设备节点附加到设备路径来创建新路径。 + //函数通过将指定设备节点的副本附加到分配的缓冲区中指定设备路径的副本来创建新的设备路径。设备路径末端设备节点移动到附加设备节点的末尾之后。 + //如果DeviceNode为空,则返回DevicePath的副本。如果DevicePath为空,则返回DeviceNode的副本,后跟设备路径的末尾device节点。 + //如果DeviceNode和DevicePath都为NULL,则返回设备路径末端设备节点的副本。 + //内存是从EFI引导服务内存分配的。调用者有责任释放分配的内存。 + //此函数返回指向分配的设备路径的指针,如果内存不足,则返回NULL。 + grub_efi_device_path_protocol_t *EFIAPI (* AppendDeviceNode)( + const grub_efi_device_path_protocol_t *DevicePath, //指向设备路径。 + const grub_efi_device_path_protocol_t *DeviceNode); //指向设备节点。 + + //附加设备路径实例 通过将指定的设备路径实例附加到指定的设备路径来创建新路径。 + //此函数通过将指定设备路径实例的副本附加到已分配缓冲区中指定设备路径的副本来创建新的设备路径。设备路径末端设备节点移动到附加设备节点的末尾之后, + //并在两者之间插入新的设备路径结束实例节点。如果DevicePath为NULL,则返回一个如果DevicePath实例的副本. + //内存是从EFI引导服务内存分配的。调用者有责任释放分配的内存。 + //此函数返回一个指向新创建的设备路径的指针,如果devicepathnance为NULL或内存不足,则返回NULL + grub_efi_device_path_protocol_t *EFIAPI (* AppendDevicePathInstance)( + const grub_efi_device_path_protocol_t *DevicePath, //指向设备路径。如果为空,则忽略 + const grub_efi_device_path_protocol_t *DevicePathInstance); //指向设备路径实例 + + //获得下一个设备路径实例 创建当前设备路径实例的副本,并返回指向下一个设备路径实例的指针。 + //此函数用于创建当前设备路径实例的副本。它还将更新devicepathnistance以指向设备路径中的下一个设备路径实例(如果不再存在,则为NULL), + //并更新DevicePathInstanceSize以保留设备路径实例副本的大小。 + //内存是从EFI引导服务内存分配的。调用者有责任释放分配的内存。 + //此函数返回指向当前设备路径实例副本的指针,如果条目上的DevicePathInstance为NULL或内存不足,则返回NULL。 + grub_efi_device_path_protocol_t *EFIAPI (* GetNextDevicePathInstance)( + grub_efi_device_path_protocol_t **DevicePathInstance, //设备路径实例 在输入时,它保存指向当前设备路径实例的指针。在输出时,它保留指向下一个设备路径实例的指针,如果设备路径中没有更多的设备路径实例,则为空。 + grub_efi_uintn_t *DevicePathInstanceSize); //设备路径实例尺寸(可选) 在输出时,如果DevicePathInstance为NULL,它将保存设备路径实例的大小(以字节为单位)或零。如果为空,则不输出实例大小。 + + //返回设备路径是否为多实例。 此函数返回指定的设备路径是否具有多个路径实例。 + //如果设备路径有多个实例,则此函数返回TRUE;如果设备路径为空或仅包含单个实例,则此函数返回FALSE。 + grub_int8_t *(* IsDevicePathMultiInstance)( + const grub_efi_device_path_protocol_t *DevicePath); //指向设备路径。如果为空,则忽略. + + //创建设备节点 + //此函数用于在新分配的缓冲区中创建新的设备节点。 内存是从EFI引导服务内存分配的。调用者有责任释放分配的内存。 + //此函数返回指向创建的设备节点的指针,如果NodeLength小于头的大小或内存不足,则返回NULL。 + grub_efi_device_path_protocol_t *EFIAPI (* CreateDeviceNode)( + unsigned char NodeType, //节点类型 + unsigned char NodeSubType, //节点子类型 + unsigned short NodeLength); //节点尺寸 +}; +typedef struct grub_efi_device_pate_utilities_protocol grub_efi_device_pate_utilities_protocol_t; + + +struct grub_efi_open_protocol_information_entry //打开协议信息入口 +{ + void * agent_handle; //代理句柄 + void * controller_handle; //控制器句柄 + unsigned int attributes; //属性 + unsigned int open_count; //打开计数 +}; +typedef struct grub_efi_open_protocol_information_entry grub_efi_open_protocol_information_entry_t; + +struct grub_efi_time //时间 +{ + unsigned short year; //年 1900-9999 + unsigned char month; //月 1-12 + unsigned char day; //日 1-31 + unsigned char hour; //时 0-23 + unsigned char minute; //分 0-59 + unsigned char second; //秒 0-59 + unsigned char pad1; + unsigned int nanosecond; //毫微秒 0-999999999 1秒=10^9=1000000000毫微秒 1毫秒=10^6=1000000毫微秒 有些主板不支持,返回0!!! + short time_zone; //时区 -1440 到 1440 UTC - TimeZone + unsigned char daylight; //夏令时 + unsigned char pad2; +} __attribute__ ((packed)); +typedef struct grub_efi_time grub_efi_time_t; + +struct grub_efi_time_capabilities //时间能力 +{ + unsigned int resolution; //分辨率 + unsigned int accuracy; //精度 + char sets_to_zero; //设置为零 +}; +typedef struct grub_efi_time_capabilities grub_efi_time_capabilities_t; + +struct grub_efi_input_key //输入键 +{ + unsigned short scan_code; //扫描码 + unsigned short unicode_char; //unicode字符 +}; +typedef struct grub_efi_input_key grub_efi_input_key_t; //4(按指定) + +typedef unsigned char grub_efi_key_toggle_state_t; +struct grub_efi_key_state //键状态 +{ + unsigned int key_shift_state; //键移位状态 反映输入设备当前按下的移位修饰符。仅当已设置高阶位时,返回值才有效。 + grub_efi_key_toggle_state_t key_toggle_state; //键切换状态 反映各种切换属性的当前内部状态。仅当已设置高阶位时,返回值才有效。 +}; +typedef struct grub_efi_key_state grub_efi_key_state_t; + +//EFI键移位状态 +#define GRUB_EFI_SHIFT_STATE_VALID 0x80000000 //键移位状态有效 +#define GRUB_EFI_RIGHT_SHIFT_PRESSED 0x00000001 //右SHIFT +#define GRUB_EFI_LEFT_SHIFT_PRESSED 0x00000002 //左SHIFT +#define GRUB_EFI_RIGHT_CONTROL_PRESSED 0x00000004 //右CONTROL +#define GRUB_EFI_LEFT_CONTROL_PRESSED 0x00000008 //左CONTROL +#define GRUB_EFI_RIGHT_ALT_PRESSED 0x00000010 //右ALT +#define GRUB_EFI_LEFT_ALT_PRESSED 0x00000020 //左ALT +#define GRUB_EFI_RIGHT_LOGO_PRESSED 0x00000040 //右LOGO +#define GRUB_EFI_LEFT_LOGO_PRESSED 0x00000080 //左LOGO +#define GRUB_EFI_MENU_KEY_PRESSED 0x00000100 //菜单键 +#define GRUB_EFI_SYS_REQ_PRESSED 0x00000200 //系统键 +//EFI键切换状态 +#define GRUB_EFI_TOGGLE_STATE_VALID 0x80 //键切换状态有效 +#define GRUB_EFI_KEY_STATE_EXPOSED 0x40 //按键状态曝光 +#define GRUB_EFI_SCROLL_LOCK_ACTIVE 0x01 //滚动锁定有效 +#define GRUB_EFI_NUM_LOCK_ACTIVE 0x02 //数字锁定有效 +#define GRUB_EFI_CAPS_LOCK_ACTIVE 0x04 //大写锁定有效 + +struct grub_efi_simple_text_output_mode //简单文本输出模式 +{ + grub_efi_int32_t max_mode; //最大模式 + grub_efi_int32_t mode; //模式 + grub_efi_int32_t attribute; //属性 + grub_efi_int32_t cursor_column; //光标列 + grub_efi_int32_t cursor_row; //光标行 + grub_efi_boolean_t cursor_visible; //光标可见属性 +}; +typedef struct grub_efi_simple_text_output_mode grub_efi_simple_text_output_mode_t; //18(long按4,最后一行char按4对齐) + +/* Tables. */ +struct grub_efi_table_header //表头 +{ + unsigned long long signature; //签名 IBI SYST + unsigned int revision; //修订 020028 + unsigned int header_size; //标题大小 78 + unsigned int crc32; //crc32 7D66830F + unsigned int reserved; //保留 0 +}; +typedef struct grub_efi_table_header grub_efi_table_header_t; + +struct grub_efi_block_io_media //块输入输出介质 +{ + grub_efi_uint32_t media_id; //媒体标识 1 1f 1f 当前媒体ID。如果媒体更改,则此值将更改 + grub_efi_boolean_t removable_media; //可移动媒体 0 0 0 如果媒体是可移动的,则为TRUE;否则为FALSE + grub_efi_boolean_t media_present; //媒体目前 1 1 1 如果设备中当前存在媒体,则为TRUE;否则为FALSE。此字段显示最近一次ReadBlocks()或WriteBlocks()调用时的媒体当前状态 + grub_efi_boolean_t logical_partition; //逻辑分区 0 0 0 如果生成EFI_BLOCK_IO_协议以抽象磁盘上的分区结构,则为TRUE。如果生成块IO协议以提取硬件设备上的逻辑块,则为FALSE。 + grub_efi_boolean_t read_only; //只读 0 0 0 如果媒体标记为只读,则为TRUE;否则为FALSE。此字段显示最近一次WriteBlocks()调用的只读状态。 + grub_efi_boolean_t write_caching; //写缓存 0 0 0 如果WriteBlocks()函数缓存写入数据,则为TRUE。 + grub_efi_uint8_t pad[3]; //填充 + grub_efi_uint32_t block_size; //块尺寸 200 200 200 设备的内部块大小。如果媒体更改,则更新此字段。返回每个逻辑块的字节数。 + grub_efi_uint32_t io_align; //IO对齐 4 4 0 提供数据传输中使用的任何缓冲区的对齐要求。IoAlign值为0和1意味着缓冲区可以放在内存中的任何位置。否则,IoAlign必须是2的幂,并且要求缓冲区的起始地址必须可以被IoAlign均匀地整除,并且不能有余数。 + grub_efi_uint8_t pad2[4]; //填充 + grub_efi_lba_t last_block; //最后块 1fffff(1G) 3a38602f(465G) 1e45ff(968M) 设备上的最后一个LBA,加1等于总扇区数 这是指分区(卷)的尺寸 +}; +typedef struct grub_efi_block_io_media grub_efi_block_io_media_t; //20(按指定) + +struct block_io_protocol //块io协议 +{ + grub_efi_uint64_t revision; //修订 + grub_efi_block_io_media_t *media; //媒体 + grub_efi_status_t (EFIAPI *reset) (struct block_io_protocol *this, + grub_efi_boolean_t extended_verification); //复位 + grub_efi_status_t (EFIAPI *read_blocks) (struct block_io_protocol *this, + grub_efi_uint32_t media_id, + grub_efi_lba_t lba, + grub_efi_uintn_t buffer_size, + void *buffer); //读块 + grub_efi_status_t (EFIAPI *write_blocks) (struct block_io_protocol *this, + grub_efi_uint32_t media_id, + grub_efi_lba_t lba, + grub_efi_uintn_t buffer_size, + void *buffer); //写块 + grub_efi_status_t (EFIAPI *flush_blocks) (struct block_io_protocol *this); //填充 +}; +typedef struct block_io_protocol block_io_protocol_t; + +struct grub_efi_boot_services //引导服务 +{ + grub_efi_table_header_t hdr; //表头 + + grub_efi_tpl_t EFIAPI + (*raise_tpl) (grub_efi_tpl_t new_tpl); //枚举 + + void EFIAPI + (*restore_tpl) (grub_efi_tpl_t old_tpl); //恢复 + + grub_efi_status_t EFIAPI + (*allocate_pages) (grub_efi_allocate_type_t type, + grub_efi_memory_type_t memory_type, + grub_efi_uintn_t pages, + grub_efi_physical_address_t *memory); //分配页 + + grub_efi_status_t EFIAPI + (*free_pages) (grub_efi_physical_address_t memory, + grub_efi_uintn_t pages); //释放页 + + grub_efi_status_t EFIAPI + (*get_memory_map) (grub_efi_uintn_t *memory_map_size, + grub_efi_memory_descriptor_t *memory_map, + grub_efi_uintn_t *map_key, + grub_efi_uintn_t *descriptor_size, + grub_efi_uint32_t *descriptor_version); //获得内存映射 + + grub_efi_status_t EFIAPI + (*allocate_pool) (grub_efi_memory_type_t pool_type, + grub_efi_uintn_t size, + void **buffer); //分配池 + + grub_efi_status_t EFIAPI + (*free_pool) (void *buffer); //释放池 + + //创建事件 + grub_efi_status_t EFIAPI + (*create_event) (grub_efi_uint32_t type, //事件的类型 + grub_efi_tpl_t notify_tpl, //事件的优先级 + void (*notify_function) (grub_efi_event_t event, + void *context), //事件处理函数 + void *notify_context, //传递给事件处理函数的参数 + grub_efi_event_t *event); //创建的事件 + + grub_efi_status_t EFIAPI + (*set_timer) (grub_efi_event_t event, + grub_efi_timer_delay_t type, + grub_efi_uint64_t trigger_time); //设置时间 + + //等待事件 + grub_efi_status_t EFIAPI + (*wait_for_event) (grub_efi_uintn_t num_events, //第二个参数Event中的事件数量 + grub_efi_event_t *event, //所要等待的事件数组 + grub_efi_uintn_t *index); //指向满足等待条件的事件索引的指针 + + grub_efi_status_t EFIAPI + (*signal_event) (grub_efi_event_t event); //信号事件 + + grub_efi_status_t EFIAPI + (*close_event) (grub_efi_event_t event); //关闭事件 +/* +函数检查事件是否处于信号状态。如果Event的类型为EVT_NOTIFY_SIGNAL,则返回EFI_INVALID_PARAMETER。否则,有三种可能性: +•如果事件处于信号状态,则清除它并返回EFI_SUCCESS。 +•如果Event未处于信号状态且没有通知功能,则返回EFI_not_READY。 +•如果事件未处于信号状态,但具有通知功能,则通知功能将按事件的通知任务优先级排队。如果通知函数的执行导致事件被发出信号, + 则信号状态被清除,并返回EFI_SUCCESS;如果事件未发出信号,则返回EFI_not_READY。 + 返回状态代码 + EFI_SUCCESS 事件处于信号状态(0正常)。 + EFI_NOT_READY 事件未处于信号状态(6还没准备好)。 + EFI_INVALID_PARAMETER 事件的类型为EVT_NOTIFY_SIGNAL(2无效参数) +*/ + grub_efi_status_t EFIAPI + (*check_event) (grub_efi_event_t event); //检查事件 + + grub_efi_status_t EFIAPI + (*install_protocol_interface) (grub_efi_handle_t *handle, + grub_efi_guid_t *protocol, + grub_efi_interface_type_t protocol_interface_type, + void *protocol_interface); //安装协议接口 + + grub_efi_status_t EFIAPI + (*reinstall_protocol_interface) (grub_efi_handle_t handle, + grub_efi_guid_t *protocol, + void *old_interface, + void *new_interface); //重新安装协议接口 + + grub_efi_status_t EFIAPI + (*uninstall_protocol_interface) (grub_efi_handle_t handle, + grub_efi_guid_t *protocol, + void *protocol_interface); //卸载协议接口 + + grub_efi_status_t EFIAPI + (*handle_protocol) (grub_efi_handle_t handle, + grub_efi_guid_t *protocol, + void **protocol_interface); //句柄协议 + + void *reserved; + + grub_efi_status_t EFIAPI + (*register_protocol_notify) (grub_efi_guid_t *protocol, + grub_efi_event_t event, + void **registration); //注册协议通知 + + grub_efi_status_t EFIAPI + (*locate_handle) (grub_efi_locate_search_type_t search_type, + grub_efi_guid_t *protocol, + void *search_key, + grub_efi_uintn_t *buffer_size, + grub_efi_handle_t *buffer); //定位句柄 + + grub_efi_status_t EFIAPI + (*locate_device_path) (grub_efi_guid_t *protocol, + grub_efi_device_path_t **device_path, + grub_efi_handle_t *device); //定位设备路径 + + grub_efi_status_t EFIAPI + (*install_configuration_table) (grub_efi_guid_t *guid, void *table); //安装配置表 + + grub_efi_status_t EFIAPI + (*load_image) (grub_efi_boolean_t boot_policy, + grub_efi_handle_t parent_image_handle, + grub_efi_device_path_t *file_path, + void *source_buffer, + grub_efi_uintn_t source_size, + grub_efi_handle_t *image_handle); //加载映像 + + grub_efi_status_t EFIAPI + (*start_image) (grub_efi_handle_t image_handle, + grub_efi_uintn_t *exit_data_size, + grub_efi_char16_t **exit_data); //启动映像 + + grub_efi_status_t EFIAPI + (*exit) (grub_efi_handle_t image_handle, + grub_efi_status_t exit_status, + grub_efi_uintn_t exit_data_size, + grub_efi_char16_t *exit_data) __attribute__((noreturn)); //退出 + + grub_efi_status_t EFIAPI + (*unload_image) (grub_efi_handle_t image_handle); //卸载映像 + + grub_efi_status_t EFIAPI + (*exit_boot_services) (grub_efi_handle_t image_handle, + grub_efi_uintn_t map_key); //退出引导服务 + + grub_efi_status_t EFIAPI + (*get_next_monotonic_count) (grub_efi_uint64_t *count); //获得下一单调计数 + + grub_efi_status_t EFIAPI + (*stall) (grub_efi_uintn_t microseconds); //失速 + + grub_efi_status_t EFIAPI + (*set_watchdog_timer) (grub_efi_uintn_t timeout, + grub_efi_uint64_t watchdog_code, + grub_efi_uintn_t data_size, + grub_efi_char16_t *watchdog_data); //设置看门狗定时器 + + //连接控制器 将一个或多个驱动程序连接到控制器 + grub_efi_status_t EFIAPI + (*connect_controller) (grub_efi_handle_t controller_handle, //要连接驱动程序的控制器的句柄 + grub_efi_handle_t *driver_image_handle, //指向支持EFI驱动程序绑定协议的有序列表句柄的指针。列表以空句柄值终止。这些句柄是驱动程序绑定协议的候选者,该协议将管理由ControllerHandle指定的控制器。 + grub_efi_device_path_protocol_t *remaining_device_path, //指向设备路径的指针,指定由ControllerHandle指定的控制器的子级。 + grub_efi_boolean_t recursive); //如果为true,则递归调用ConnectController(),直到ControllerHandle指定的控制器下的整个控制器树都已创建。如果为false,则控制器树仅展开一个级别。 + + //断开控制器 从控制器断开一个或多个驱动程序 + grub_efi_status_t EFIAPI + (*disconnect_controller) (grub_efi_handle_t controller_handle, //要连接驱动程序的控制器的句柄 + grub_efi_handle_t driver_image_handle, //从控制器手柄上断开的驱动程序。如果DriverImageHandle为空,则当前管理ControllerHandle的所有驱动程序都与ControllerHandle断开连接。 + grub_efi_handle_t child_handle); //要摧毁子级的句柄。如果child_handle为空,则在驱动程序与controllerhandle断开连接之前,controllerhandle的所有子级都将被销毁。 + + //打开协议 + grub_efi_status_t EFIAPI + (*open_protocol) (grub_efi_handle_t handle, //句柄 + grub_efi_guid_t *protocol, //协议guid + void **protocol_interface, //协议接口 + grub_efi_handle_t agent_handle, //代理句柄 + grub_efi_handle_t controller_handle, //控制句柄 + grub_efi_uint32_t attributes); //属性 + + grub_efi_status_t EFIAPI + (*close_protocol) (grub_efi_handle_t handle, + grub_efi_guid_t *protocol, + grub_efi_handle_t agent_handle, + grub_efi_handle_t controller_handle); //关闭协议 + + grub_efi_status_t EFIAPI + (*open_protocol_information) (grub_efi_handle_t handle, + grub_efi_guid_t *protocol, + grub_efi_open_protocol_information_entry_t **entry_buffer, + grub_efi_uintn_t *entry_count); //打开协议信息 + + grub_efi_status_t EFIAPI + (*protocols_per_handle) (grub_efi_handle_t handle, + grub_efi_packed_guid_t ***protocol_buffer, + grub_efi_uintn_t *protocol_buffer_count); //每个句柄协议 + + grub_efi_status_t EFIAPI + (*locate_handle_buffer) (grub_efi_locate_search_type_t search_type, + grub_efi_guid_t *protocol, + void *search_key, + grub_efi_uintn_t *no_handles, + grub_efi_handle_t **buffer); //定位句柄缓冲 + + grub_efi_status_t EFIAPI + (*locate_protocol) (grub_efi_guid_t *protocol, + void *registration, + void **protocol_interface); //定位协议 + + //安装多协议接口 将一个或多个协议接口安装到启动服务环境中 + grub_efi_status_t EFIAPI + (*install_multiple_protocol_interfaces) (grub_efi_handle_t *handle, //指向协议接口的指针 + ...); + + grub_efi_status_t EFIAPI + (*uninstall_multiple_protocol_interfaces)(grub_efi_handle_t *handle, //指向协议接口的指针 + ...); + + grub_efi_status_t EFIAPI + (*calculate_crc32) (void *data, + grub_efi_uintn_t data_size, + grub_efi_uint32_t *crc32); //计算crc32 + + void EFIAPI + (*copy_mem) (void *destination, void *source, grub_efi_uintn_t length); //复制内存(目的,源,长度) + + void EFIAPI + (*set_mem) (void *buffer, grub_efi_uintn_t size, grub_efi_uint8_t value);//设置内存(缓存,尺寸,值) +}; +typedef struct grub_efi_boot_services grub_efi_boot_services_t; //170(表头按18,结构及void按8,其余按指定) + //g4d:占c4(结构按指定,其余不论'long long'或者'void'均按4) + +struct grub_efi_runtime_services //运行时服务 +{ + grub_efi_table_header_t hdr; + +/*获得时间 返回硬件平台的当前时间和日期信息以及时间保持功能。 +getTime()函数返回在调用函数期间某个时间有效的时间。虽然返回的EFI U时间结构包含时区和夏令时信息,但实际时钟不维护这些值。getTime()返回的当前时区和夏令时信息是最后通过setTime()设置的值。 +getTime()函数在每次调用时读取时间的时间应该大致相同。所有报告的设备功能都要进行四舍五入。 +在运行时,如果平台中存在PC-AT CMOS设备,则调用方必须在调用GetTime()之前同步对该设备的访问。 +*/ + grub_efi_status_t EFIAPI + (*get_time) (grub_efi_time_t *time, //指向存储的指针,用于接收当前时间的快照。 + grub_efi_time_capabilities_t *capabilities); //指向缓冲区的可选指针,用于接收实时时钟设备的功能。 + + grub_efi_status_t EFIAPI + (*set_time) (grub_efi_time_t *time); //设置时间 + + grub_efi_status_t EFIAPI + (*get_wakeup_time) (grub_efi_boolean_t *enabled, + grub_efi_boolean_t *pending, + grub_efi_time_t *time); //获得唤醒时间 + + grub_efi_status_t EFIAPI + (*set_wakeup_time) (grub_efi_boolean_t enabled, + grub_efi_time_t *time); //设置唤醒时间 + + grub_efi_status_t EFIAPI + (*set_virtual_address_map) (grub_efi_uintn_t memory_map_size, + grub_efi_uintn_t descriptor_size, + grub_efi_uint32_t descriptor_version, + grub_efi_memory_descriptor_t *virtual_map); //设置虚拟地址MA (内存映射尺寸,描述符尺寸,描述符版本,虚拟映射) + + grub_efi_status_t EFIAPI + (*convert_pointer) (grub_efi_uintn_t debug_disposition, void **address); //转换指针 + +#define GRUB_EFI_GLOBAL_VARIABLE_GUID \ + { 0x8BE4DF61, 0x93CA, 0x11d2, { 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B,0x8C }} //全局变量GUID + + + grub_efi_status_t EFIAPI + (*get_variable) (grub_efi_char16_t *variable_name, + const grub_efi_guid_t *vendor_guid, + grub_efi_uint32_t *attributes, + grub_efi_uintn_t *data_size, + void *data); //获取变量 + + grub_efi_status_t EFIAPI + (*get_next_variable_name) (grub_efi_uintn_t *variable_name_size, + grub_efi_char16_t *variable_name, + grub_efi_guid_t *vendor_guid); //获取下一个变量名 + + grub_efi_status_t EFIAPI + (*set_variable) (grub_efi_char16_t *variable_name, + const grub_efi_guid_t *vendor_guid, + grub_efi_uint32_t attributes, + grub_efi_uintn_t data_size, + void *data); //设置变量 + + grub_efi_status_t EFIAPI + (*get_next_high_monotonic_count) (grub_efi_uint32_t *high_count); + + void EFIAPI + (*reset_system) (grub_efi_reset_type_t reset_type, + grub_efi_status_t reset_status, + grub_efi_uintn_t data_size, + grub_efi_char16_t *reset_data); //求下一个高单调数 重置系统 +}; +typedef struct grub_efi_runtime_services grub_efi_runtime_services_t; //g4d:占44 + +struct grub_efi_configuration_table //配置表 +{ + grub_efi_packed_guid_t vendor_guid; //占10 g4d + void *vendor_table; //占4 +} GRUB_PACKED; +typedef struct grub_efi_configuration_table grub_efi_configuration_table_t; //g4d:占14 + +#define GRUB_EFIEMU_SYSTEM_TABLE_SIGNATURE 0x5453595320494249LL +#define GRUB_EFIEMU_RUNTIME_SERVICES_SIGNATURE 0x56524553544e5552LL + +struct grub_efi_serial_io_interface //串行IO接口 +{ + grub_efi_uint32_t revision; + void (*reset) (void); + grub_efi_status_t EFIAPI (*set_attributes) (struct grub_efi_serial_io_interface *this, + grub_efi_uint64_t speed, + grub_efi_uint32_t fifo_depth, + grub_efi_uint32_t timeout, + grub_efi_parity_type_t parity, + grub_uint8_t word_len, + grub_efi_stop_bits_t stop_bits); + grub_efi_status_t EFIAPI (*set_control_bits) (struct grub_efi_serial_io_interface *this, + grub_efi_uint32_t flags); + void (*get_control_bits) (void); + grub_efi_status_t EFIAPI (*write) (struct grub_efi_serial_io_interface *this, + grub_efi_uintn_t *buf_size, + void *buffer); + grub_efi_status_t EFIAPI (*read) (struct grub_efi_serial_io_interface *this, + grub_efi_uintn_t *buf_size, + void *buffer); +}; + +//函数的作用是:从输入设备中读取下一次击键。如果没有挂起的击键,则函数返回EFI_NOT_READY。如果存在挂起的击键,则扫描代码是表107中定义的EFI扫描代码。 +//Unicode字符是实际的可打印字符,如果键不代表可打印字符(控制键、功能键等),则为零。 +struct grub_efi_simple_input_interface //简单输入接口 +{ + //重置 重置输入设备硬件 + grub_efi_status_t EFIAPI + (*reset) (struct grub_efi_simple_input_interface *this, + grub_efi_boolean_t extended_verification); //值=1,扩展验证. 指示在重置期间,驱动程序可以对设备执行更彻底的验证操作。 + + grub_efi_status_t EFIAPI + (*read_key_stroke) (struct grub_efi_simple_input_interface *this, + grub_efi_input_key_t *key); //读击键 从输入设备读取下一次击键. key是指向缓冲区的指针,该缓冲区中填充了所按键的击键信息。 + + grub_efi_event_t wait_for_key; //等待键 事件与EFI_BOOT_SERVICES.WaitForEvent()一起使用,以等待键可用。 +}; +typedef struct grub_efi_simple_input_interface grub_efi_simple_input_interface_t; //grub2:18(全部按8) g4d:c(全部按4)? + +struct grub_efi_key_data { //键数据 + grub_efi_input_key_t key; //键信息 从输入设备返回的EFI扫描代码和Unicode值。32位 + grub_efi_key_state_t key_state; //键状态 各种切换属性以及输入修改器值的当前状态。40位 +}; +typedef struct grub_efi_key_data grub_efi_key_data_t; + +typedef long long (*grub_efi_key_notify_function_t) ( //状态 + grub_efi_key_data_t *key_data //键数据 + ); + +struct grub_efi_simple_text_input_ex_interface //简单文本输入扩展接口 +{ + //重置 重置输入设备硬件 + grub_efi_status_t EFIAPI + (*reset) (struct grub_efi_simple_text_input_ex_interface *this, + grub_efi_boolean_t extended_verification); //值=1,扩展验证. 指示在重置期间,驱动程序可以对设备执行更彻底的验证操作。 + + grub_efi_status_t EFIAPI + (*read_key_stroke) (struct grub_efi_simple_text_input_ex_interface *this, + grub_efi_key_data_t *key_data); //读击键 从输入设备读取下一次击键。 + + grub_efi_event_t wait_for_key; //等待键 事件与WaitForEvent()一起使用,以等待按键可用。只有KeyData.Key中包含信息时,才会触发事件。 + +//函数的作用是:允许输入设备硬件调整状态设置。通过调用SetState()函数,使KeyToggleState参数中的EFI_KEY_STATE_EXPOSED位处于活动状态,这将使readkeystrookex函数返回不完整的击键,例如在没有键数据时按住某些键,这些键表示为KeyState的一部分。 + grub_efi_status_t EFIAPI + (*set_state) (struct grub_efi_simple_text_input_ex_interface *this, + grub_efi_key_toggle_state_t *key_toggle_state); //设置状态 设置输入设备的特定状态 + +//注册一个函数,当指定的击键发生时将调用该函数。指定的击键可以是KeyData.Key或KeyData.KeyState信息的任意组合。 +//用来将特定按键输入事件和事件处理函数绑定的函数 + grub_efi_status_t EFIAPI + (*register_key_notify) (struct grub_efi_simple_text_input_ex_interface *this, + grub_efi_key_data_t *key_data, //要绑定的按键事件 + grub_efi_key_notify_function_t key_notification_function, //指向要绑定的函数的指针 + void **NotifyHandle); //返回的句柄,它的值唯一,在取消绑定时要用到 + +//注销键通知 +//解绑按键事件 + grub_efi_status_t EFIAPI + (*unregister_key_notify) (struct grub_efi_simple_text_input_ex_interface *this, + void *notification_handle); +}; +typedef struct grub_efi_simple_text_input_ex_interface grub_efi_simple_text_input_ex_interface_t; + +/* +绑定按键事件 +展示一个使用RegisterKeyNotify() 的例子。 +#include "efi.h" +#include "common.h" +unsigned char is_exit = FALSE; +unsigned long long key_notice( +struct EFI_KEY_DATA *KeyData __attribute__ ((unused))) +{ + is_exit = TRUE; + return EFI_SUCCESS; +} +void efi_main(void *ImageHandle __attribute__ ((unused)), +struct EFI_SYSTEM_TABLE *SystemTable) +{ + unsigned long long status; + struct EFI_KEY_DATA key_data = {{0, L'q'}, {0, 0}}; + void *notify_handle; + efi_init(SystemTable); + ST->ConOut->ClearScreen(ST->ConOut); + puts(L"Waiting for the 'q' key input...\r\n"); + status = STIEP->RegisterKeyNotify(STIEP, &key_data, key_notice, ¬ify_handle); + assert(status, L"RegisterKeyNotify"); + while (!is_exit); + puts(L"exit.\r\n"); + while (TRUE); +} +上面这段代码实现了按下"q"键来退出efi_main() 中的一个循环的功能。这里要处理的事件是“按下q键”,因此我们先将key_data.Key.UnicodeChar 设置为"q", +并将key_data 中的其它属性设为0。然后,我们使用RegisterKeyNotify() 函数,将“按下q键”这一事件与事件处理函数key_notice() 绑定。在key_notice() 函数中, +我们把全局变量is_exit 设置为TRUE ,这样就实现了按下q键跳出efi_main()中while (!is_exit); 这个循环的功能, +*/ + + + +struct grub_efi_simple_text_output_interface //简单文本输出接口 +{ +//重置 重置控制台设备 + grub_efi_status_t EFIAPI + (*reset) (struct grub_efi_simple_text_output_interface *this, + grub_efi_boolean_t extended_verification); //值=1,扩展验证. 指示在重置期间,驱动程序可以对设备执行更彻底的验证操作 + +//输出字符串 在当前光标位置显示设备上的字符串 +//将字符串写入输出设备。要在输出设备上显示的以空结尾的字符串。所有输出设备还必须支持“相关定义”中定义的Unicode绘图字符代码 + grub_efi_status_t EFIAPI + (*output_string) (struct grub_efi_simple_text_output_interface *this, + grub_efi_char16_t *string); + +//测试字符串 测试ConsoleOut设备是否支持此字符串。 +//函数的作用是:验证字符串中的所有字符都可以输出到目标设备。此函数提供了一种方法,可以知道输出设备上是否支持渲染所需的字符代码。 +//这允许安装过程(或EFI映像)至少选择输出设备能够显示的字符代码。由于输出设备可能在引导之间发生更改,如果加载程序无法适应这些更改, +//建议加载程序调用OutputString(),并忽略任何“不受支持”的错误代码。能够显示Unicode字符代码的设备将这样做。 + grub_efi_status_t EFIAPI + (*test_string) (struct grub_efi_simple_text_output_interface *this, + grub_efi_char16_t *string); + +//查询模式 查询有关输出设备支持的文本模式的信息 + grub_efi_status_t EFIAPI + (*query_mode) (struct grub_efi_simple_text_output_interface *this, + grub_efi_uintn_t mode_number, + grub_efi_uintn_t *columns, + grub_efi_uintn_t *rows); + +//设置模式 设置输出设备的当前模式 + grub_efi_status_t EFIAPI + (*set_mode) (struct grub_efi_simple_text_output_interface *this, + grub_efi_uintn_t mode_number); + +//设置属性 设置输出文本的前景色和背景色 + grub_efi_status_t EFIAPI + (*set_attributes) (struct grub_efi_simple_text_output_interface *this, + grub_efi_uintn_t attribute); + +//清除屏幕 清除当前设置背景色的屏幕 +//在调用清屏函数前先输出了一个空格,这是为了适配部分计算机的UEFI固件。某些UEFI固件,例如作者的联想笔记本的固件, +//在启动后不输出任何内容的情况下直接调用ClearScreen() 进行清屏似乎会被忽略。即使这里我们先调用SetAttribute() 设置背景色, +//再调用ClearScreen() 清屏,屏幕的背景色也不会被设为我们指定的颜色。 + grub_efi_status_t EFIAPI + (*clear_screen) (struct grub_efi_simple_text_output_interface *this); + +//设置光标位置 设置当前光标位置 + grub_efi_status_t EFIAPI + (*set_cursor_position) (struct grub_efi_simple_text_output_interface *this, + grub_efi_uintn_t column, + grub_efi_uintn_t row); + +//使能光标 打开/关闭光标的可见性 + grub_efi_status_t EFIAPI + (*enable_cursor) (struct grub_efi_simple_text_output_interface *this, + grub_efi_boolean_t visible); + +//输出模式 指向简单文本输出模式数据的指针。 + grub_efi_simple_text_output_mode_t *mode; +}; +typedef struct grub_efi_simple_text_output_interface grub_efi_simple_text_output_interface_t; //g4d:占28 + + +typedef struct grub_efi_pxe_dhcpv4_packet //引导播放器 备注: 在 ipxe->bootia32.efi 时, pxe_reply与dhcp_ack相同; bootp_yi_addr = c0 a8 38 06 +{ // dhcp_discover dhcp_ack dhcp_offer dhcp_request proxy同dhcp + grub_efi_uint8_t bootp_opcode; //00 操作码 01 02 02 01 + grub_efi_uint8_t bootp_hwtype; //01 硬件类型 01 + grub_efi_uint8_t bootp_hwaddr_len; //02 硬件地址长度 06 + grub_efi_uint8_t bootp_gate_hops; //03 + grub_efi_uint32_t bootp_ident; //04 随机数 59 6b 5d 13 07 6c 4a a1 + grub_efi_uint16_t bootp_seconds; //08 引导以来秒数 00 00 + grub_efi_uint16_t bootp_flags; //0a 标记 80 00 + grub_u32_t bootp_ci_addr; //0c 客户IP 00 00 00 00 + grub_u32_t bootp_yi_addr; //10 你的IP 00 00 00 00 c0 a8 38 02 + grub_u32_t bootp_si_addr; //14 服务器IP 00 00 00 00 c0 a8 38 01 + grub_u32_t bootp_gi_addr; //18 网关IP 00 00 00 00 + grub_efi_uint8_t bootp_hw_addr[16]; //1c 客户硬件地址 00 0c 29 8d cc d9 + grub_efi_uint8_t bootp_srv_name[64]; //2c 服务器的主机名 PC-201311212111 + grub_efi_uint8_t bootp_boot_file[128]; //6c 引导文件件名 0 bootia32.EFI + grub_efi_uint32_t dhcp_magik; //ec 魔术 63 82 53 63 + grub_efi_uint8_t dhcp_options[56]; //f0 选项 35 01 01 39 02 05 c0 37 - 23 01 02 03 04 05 06 0c - 0d 0f 11 12 16 17 1c 28 - 29 2a 2b 32 33 36 3a 3b + // 3c 42 43 61 80 81 82 83 - 84 85 86 87 61 11 00 56 - 4d dc 4a a9 a8 2f 94 73 - 61 65 d5 98 8d cc d9 5e + // 03 01 03 10 5d 02 00 06 - 3c 20 50 58 45 43 6c 69 - 65 6e 74 3a 41 72 63 68 - 3a 30 30 30 30 36 3a 55 + // 4e 44 49 3a 30 30 33 30 - 31 36 ff 00 +} grub_efi_pxe_dhcpv4_packet_t; + +extern grub_efi_pxe_dhcpv4_packet_t *discover_reply; + +struct grub_efi_pxe_dhcpv6_packet +{ + grub_efi_uint32_t message_type:8; //消息类型 + grub_efi_uint32_t transaction_id:24; //交易id + grub_efi_uint8_t dhcp_options[1024]; //dhcp选项 +} GRUB_PACKED; +typedef struct grub_efi_pxe_dhcpv6_packet grub_efi_pxe_dhcpv6_packet_t; + +typedef union +{ + grub_efi_uint8_t raw[1472]; + grub_efi_pxe_dhcpv4_packet_t dhcpv4; + grub_efi_pxe_dhcpv6_packet_t dhcpv6; +} grub_efi_pxe_packet_t; + +typedef struct grub_efi_pxe_icmp_error +{ + grub_efi_uint8_t type; + grub_efi_uint8_t code; + grub_efi_uint16_t checksum; + union + { + grub_efi_uint32_t reserved; + grub_efi_uint32_t mtu; + grub_efi_uint32_t pointer; + struct + { + grub_efi_uint16_t identifier; + grub_efi_uint16_t sequence; + } echo; + } u; + grub_efi_uint8_t data[494]; +} grub_efi_pxe_icmp_error_t; + +typedef struct grub_efi_pxe_tftp_error //TFTP错误 +{ + grub_efi_uint8_t error_code; //错误代码 + grub_efi_char8_t error_string[127]; //错误信息 +} grub_efi_pxe_tftp_error_t; + +typedef grub_efi_uint16_t grub_efi_pxe_base_code_udp_port_t; + +typedef enum { + GRUB_EFI_PXE_BASE_CODE_TFTP_FIRST, //TFTP首先 + GRUB_EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE, //TFTP获得文件尺寸 + GRUB_EFI_PXE_BASE_CODE_TFTP_READ_FILE, //TFTP读文件 + GRUB_EFI_PXE_BASE_CODE_TFTP_WRITE_FILE, //TFTP写文件 + GRUB_EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY, //TFTP读目录 + GRUB_EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE, + GRUB_EFI_PXE_BASE_CODE_MTFTP_READ_FILE, + GRUB_EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY, + GRUB_EFI_PXE_BASE_CODE_MTFTP_LAST +} grub_efi_pxe_base_code_tftp_opcode_t; //pxe基本代码tftp操作 + +typedef struct { + grub_efi_ip_address_t mcast_ip; + grub_efi_pxe_base_code_udp_port_t c_port; + grub_efi_pxe_base_code_udp_port_t s_port; + grub_efi_uint16_t listen_timeout; + grub_efi_uint16_t transmit_timeout; +} grub_efi_pxe_base_code_mtftp_info_t; + +#define GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT 8 +typedef struct grub_efi_pxe_ip_filter +{ + grub_efi_uint8_t filters; //过滤器 01; 0f + grub_efi_uint8_t ip_count; //ip计数 00 + grub_efi_uint16_t reserved; //保留 0000 + grub_efi_ip_address_t ip_list[GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT]; +} grub_efi_pxe_ip_filter_t; + +typedef struct { + grub_efi_pxe_ip_address_t ip_addr; + grub_efi_pxe_mac_address_t mac_addr; +} grub_efi_pxe_arp_entry_t; + +typedef struct { + grub_efi_pxe_ip_address_t ip_addr; //c0 a8 38 00 + grub_efi_pxe_ip_address_t subnet_mask; //00 00 00 00 + grub_efi_pxe_ip_address_t gw_addr; //ff ff ff 00 +} grub_efi_pxe_route_entry_t; + + +#define GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES 8 +#define GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES 8 + +typedef struct grub_efi_pxe_mode //pxe模式 尺寸=0x28b8 +{ // bootia32.efi ipxe->bootia32.efi + grub_efi_boolean_t started; //开始了 01 - + grub_efi_boolean_t ipv6_available; //ipv6可用 00 + grub_efi_boolean_t ipv6_supported; //ipv6支持 00 + grub_efi_boolean_t using_ipv6; //使用ipv6 00 + grub_efi_boolean_t bis_supported; //bis支持 00 + grub_efi_boolean_t bis_detected; //bis检测到 00 + grub_efi_boolean_t auto_arp; //自动ARP 01 + grub_efi_boolean_t send_guid; //发送引导 00 + grub_efi_boolean_t dhcp_discover_valid; //dhcp发现有效 01 - + grub_efi_boolean_t dhcp_ack_received; //收到dhcp ack 01 + grub_efi_boolean_t proxy_offer_received; //收到代理报文 00 + grub_efi_boolean_t pxe_discover_valid; //pxe发现有效 00 + grub_efi_boolean_t pxe_reply_received; //pxe收到回复 00 01 + grub_efi_boolean_t pxe_bis_reply_received;//pxe bis收到答复 00 + grub_efi_boolean_t icmp_error_received; //icmp收到错误 00 + grub_efi_boolean_t tftp_error_received; //tftp收到错误 00 + grub_efi_boolean_t make_callbacks; //进行回调 00 - + grub_efi_uint8_t ttl; //ttl 10 + grub_efi_uint8_t tos; //tos 00 + grub_efi_ip_address_t station_ip; //站IP c0 a8 38 02 c0 a8 38 06 + grub_efi_ip_address_t subnet_mask; //子网掩码 ff ff ff 00 + grub_efi_pxe_packet_t dhcp_discover; //dhcp发现 + grub_efi_pxe_packet_t dhcp_ack; //dhcp_ack + grub_efi_pxe_packet_t proxy_offer; //代理提供 + grub_efi_pxe_packet_t pxe_discover; //pxe发现 + grub_efi_pxe_packet_t pxe_reply; //pxe回复 + grub_efi_pxe_packet_t pxe_bis_reply; //pxe_bis回复 + grub_efi_pxe_ip_filter_t ip_filter; //ip过滤器 01 00 00 00 0f 00 00 00 + grub_efi_uint32_t arp_cache_entries; //arp缓存条目 01 00 00 00 00 00 00 00 + grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES]; //ARP缓存 c0 a8 38 01, 0a 00 27 00 00 14; 0 + grub_efi_uint32_t route_table_entries;//路由表条目 01 00 00 00 00 00 00 00 + grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES]; //路线表 0 + grub_efi_pxe_icmp_error_t icmp_error; //icmp错误 + grub_efi_pxe_tftp_error_t tftp_error; //tftp错误 +} grub_efi_pxe_mode_t; + + +//******************************************************* +// Bootstrap Types 引导类型 +//******************************************************* +#define EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP 0 //自举 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_MS_WINNT_RIS 1 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_INTEL_LCM 2 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_DOSUNDI 3 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_NEC_ESMPRO 4 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_IBM_WSoD 5 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_IBM_LCCM 6 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_CA_UNICENTER_TNG 7 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_HP_OPENVIEW 8 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_ALTIRIS_9 9 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_ALTIRIS_10 10 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_ALTIRIS_11 11 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_NOT_USED_12 12 //未使用 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_REDHAT_INSTALL 13 //红帽安装 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_REDHAT_BOOT 14 //红帽引导 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_REMBO 15 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_BEOBOOT 16 +// +// Values 17 through 32767 are reserved. 保留值17到32767 +// Values 32768 through 65279 are for vendor use. 值32768到65279供供应商使用 +// Values 65280 through 65534 are reserved. 保留值65280到65534 +// +#define EFI_PXE_BASE_CODE_BOOT_TYPE_PXETEST 65535 //PXE试验 +#define EFI_PXE_BASE_CODE_BOOT_LAYER_MASK 0x7FFF //层蒙版 +#define EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL 0x0000 //层初始 + +//******************************************************* +// EFI_PXE_BASE_CODE_SRVLIST Ip列表 +//******************************************************* +typedef struct grub_efi_srvlist +{ + grub_u16_t Type; + grub_int8_t AcceptAnyResponse; + grub_int8_t reserved; + grub_uint16_t IpAddr; +} grub_efi_srvlist_t; + +//******************************************************* +// EFI_PXE_BASE_CODE_DISCOVER_INFO 发现信息 +//******************************************************* +typedef struct grub_efi_discover_info +{ + grub_int8_t UseMCast; //使用MCast 通过多播进行发现 + grub_int8_t UseBCast; //使用BCast 通过广播进行发现,但仅适用于IPv4 + grub_int8_t UseUCast; //使用UCast 通过单播进行发现 + grub_int8_t MustUseList; //必须使用列表 + grub_uint16_t ServerMCastIp; //服务器MCastIp + grub_uint16_t IpCnt; //Ip计数 + grub_efi_srvlist_t SrvList[8]; //Ip列表 +} grub_efi_discover_info_t; + +typedef struct grub_efi_pxe +{ + grub_uint64_t rev; //版本 + grub_efi_status_t (*start) (struct grub_efi_pxe *this, grub_efi_boolean_t use_ipv6); //开始 启动PXE基本代码协议。 + //在启动基本代码之前,模式结构信息无效,其他基本代码协议功能将无法运行。 + void (*stop) (void); //停止 停止PXE基本代码协议。 该功能不会改变模式结构信息。 在重新启动基本代码之前,不会运行任何基本代码协议功能。 + grub_efi_status_t (*dhcp) (struct grub_efi_pxe *this, + grub_efi_boolean_t sort_offers); //dhcp 尝试完成DHCPv4 D.O.R.A. (发现/提供/请求/确认)或DHCPv6 S.A.R.R(请求/发布/请求/回复)序列。 + grub_efi_status_t (*discover) (struct grub_efi_pxe *this, //发现 尝试完成PXE引导服务器和/或引导映像发现序列。 + grub_u16_t type, + grub_u16_t *layer, + char usebis, + grub_efi_discover_info_t *Info); + //执行TFTP和MTFTP服务。 + grub_efi_status_t (*mtftp) (struct grub_efi_pxe *this, //指向EFI_PXE_BASE_CODE_PROTOCOL实例的指针 + grub_efi_pxe_base_code_tftp_opcode_t operation, //运作方式 要执行的操作类型。 + char *buffer_ptr, //指向数据缓冲区的指针。 如果dont_use_buffer为TRUE,则忽略读取文件。 + grub_efi_boolean_t overwrite, //覆盖,仅用于写文件操作。 如果可以覆盖远程服务器上的文件,则为TRUE。 + grub_efi_uint64_t *buffer_size, //缓冲区尺寸 对于获取文件尺寸操作,*buffer_size返回所请求文件的尺寸。对于读文件和写文件操作, + //此参数设置为指定的缓冲区尺寸。 对于读取文件操作,如果返回EFI_BUFFER_TOO_SMALL,则*buffer_size返回所请求文件的尺寸。 + grub_efi_uintn_t *block_size, //块尺寸 在TFTP传输期间要使用的请求块尺寸。 该字段必须至少为512。 + //如果此字段为NULL,则将使用实现支持的最大块大小。 + grub_u32_t *server_ip, //TFTP/MTFTP服务器IP地址 + char *filename, //文件名 以Null结尾的ASCII字符串,用于指定目录名称或文件名。 MTFTP读取目录会忽略此内容。 + grub_efi_pxe_base_code_mtftp_info_t *info, //指向MTFTP信息的指针。 启动或加入多播TFTP会话需要此信息。 + grub_efi_boolean_t dont_use_buffer); //对于正常的TFTP和MTFTP读取文件操作,设置为FALSE。 +//TFTP读取目录操作返回的数据格式是一个以null结尾的文件名,后跟一个以null结尾的信息字符串,格式为“尺寸 年-月-日 时:分:秒” +//(即%d%d-%d-%d:%d:%f-注意秒字段可以是十进制数字),其中日期和时间为UTC。 + void (*udpwrite) (void); //udp写 将UDP数据包写入网络接口。 + void (*udpread) (void); //udp读 从网络接口读取UDP数据包。 + void (*setipfilter) (void); //设置过滤器 更新网络设备的IP接收筛选器。 + void (*arp) (void); //arp 使用ARP协议解析MAC地址。 + void (*setparams) (void); //设定参数 更新影响PXE基本代码协议操作的参数。 + grub_efi_status_t (*set_station_ip) (struct grub_efi_pxe *this, + grub_u32_t *new_station_ip, + grub_u32_t *new_subnet_mask); //设置站ip 更新站的IP地址和子网掩码值。 + void (*setpackets) (void); //设置数据包 更新缓存的DHCP和发现数据包的内容。 + struct grub_efi_pxe_mode *mode; //模式 指向此设备的EFI_PXE_BASE_CODE_MODE数据的指针。 +} grub_efi_pxe_t; + +extern int tftp_write (const char *name); + +#define GRUB_EFI_BLACK 0x00 //前景黑 +#define GRUB_EFI_BLUE 0x01 //前景蓝 +#define GRUB_EFI_GREEN 0x02 //前景绿 +#define GRUB_EFI_CYAN 0x03 //前景青 +#define GRUB_EFI_RED 0x04 //前景红 +#define GRUB_EFI_MAGENTA 0x05 //前景品红 +#define GRUB_EFI_BROWN 0x06 //前景棕 +#define GRUB_EFI_LIGHTGRAY 0x07 //前景浅灰色 +#define GRUB_EFI_BRIGHT 0x08 //前景明亮 +#define GRUB_EFI_DARKGRAY 0x08 //前景暗灰 +#define GRUB_EFI_LIGHTBLUE 0x09 //前景浅蓝色 +#define GRUB_EFI_LIGHTGREEN 0x0A //前景浅绿色 +#define GRUB_EFI_LIGHTCYAN 0x0B //前景浅蓝色 +#define GRUB_EFI_LIGHTRED 0x0C //前景浅红 +#define GRUB_EFI_LIGHTMAGENTA 0x0D //前景浅品红 +#define GRUB_EFI_YELLOW 0x0E //前景黃色 +#define GRUB_EFI_WHITE 0x0F //前景白色 + +#define GRUB_EFI_BACKGROUND_BLACK 0x00 //背景黑 +#define GRUB_EFI_BACKGROUND_BLUE 0x10 //背景蓝 +#define GRUB_EFI_BACKGROUND_GREEN 0x20 //背景绿 +#define GRUB_EFI_BACKGROUND_CYAN 0x30 //背景青 +#define GRUB_EFI_BACKGROUND_RED 0x40 //背景红 +#define GRUB_EFI_BACKGROUND_MAGENTA 0x50 //背景品红 +#define GRUB_EFI_BACKGROUND_BROWN 0x60 //背景棕 +#define GRUB_EFI_BACKGROUND_LIGHTGRAY 0x70 //背景浅灰色 + +#define GRUB_EFI_TEXT_ATTR(fg, bg) ((fg) | ((bg))) + +/* +typedef struct { +EFI_TABLE_HEADER Hdr; +CHAR16 *FirmwareVendor; +UINT32 FirmwareRevision; +EFI_HANDLE ConsoleInHandle; +EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; +EFI_HANDLE ConsoleOutHandle; +EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; +EFI_HANDLE StandardErrorHandle; +EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr; +EFI_RUNTIME_SERVICES *RuntimeServices; +EFI_BOOT_SERVICES *BootServices; +UINTN NumberOfTableEntries; +EFI_CONFIGURATION_TABLE *ConfigurationTable; +} EFI_SYSTEM_TABLE; +*/ + +struct grub_efi_system_table //系统表 12b7ef90 +{ + grub_efi_table_header_t hdr; //表头 IBI SYST( 占18字节 + grub_efi_char16_t *firmware_vendor; //固件供应商 12b7e990->EDK II + grub_efi_uint32_t firmware_revision; //固件版本 10000 + grub_efi_handle_t console_in_handler; //控制台输入句柄 12820410 活动控制台输入设备的句柄。此句柄必须支持EFI简单文本输入协议和EFI简单文本扩展输入协议。 + grub_efi_simple_input_interface_t *con_in; //简单文本输入接口 12a9ce5c 指向与控制台输入句柄关联的EFI简单文本输入协议接口的指针 + grub_efi_handle_t console_out_handler; //控制台输出句柄 1281ce10 活动控制台输出设备的句柄。此句柄必须支持EFI简单文本输出协议 + grub_efi_simple_text_output_interface_t *con_out; //简单文本输出接口 12a9ce9c 指向与控制台输出句柄关联的EFI简单文本输出协议接口的指针。 + grub_efi_handle_t standard_error_handle; //标准错误句柄 1281cb90 活动标准错误控制台设备的句柄。此句柄必须支持EFI简单文本输出协议 + grub_efi_simple_text_output_interface_t *std_err; //标准错误输出接口 129accfc 指向与标准错误句柄关联的EFI简单文本输出协议接口的指针。 + grub_efi_runtime_services_t *runtime_services; //运行时服务 12b7ef10 指向EFI运行时服务表的指针。见第4.5节。 + grub_efi_boot_services_t *boot_services; //引导服务 12bc0fc8 指向EFI引导服务表的指针。见第4.4节。 + grub_efi_uintn_t num_table_entries; //表格项目数 07 缓冲区配置表中的系统配置表数 + grub_efi_configuration_table_t *configuration_table; //配置表 12b7dd90 指向系统配置表的指针。 +}; +typedef struct grub_efi_system_table grub_efi_system_table_t; //grub2:78(表头按18,其余按4或8) + +struct grub_efi_loaded_image //加载映像 11b45328 +{ + grub_efi_uint32_t revision; //修订 1000 + void * parent_handle; //父句柄 0 + grub_efi_system_table_t *system_table; //系统表 12b7ef90 + void * device_handle; //设备句柄 11cb5a90->hndl... + grub_efi_device_path_t *file_path; //文件路径 11afb890->04 04 32 00 \EFI\BOOT\BOOTIA32.EFI 不是设备句柄对应的设备路径 + void *reserved; //保留 00 + grub_efi_uint32_t load_options_size; //加载选项尺寸 00 + void *load_options; //加载选项 00 + void *image_base; //映像基址 114cb000 + grub_efi_uint64_t image_size; //映像尺寸 05be00 + grub_efi_memory_type_t image_code_type; //映像代码类型 01 装载程序代码 + grub_efi_memory_type_t image_data_type; //映像数据类型 02 装载数据 + grub_efi_status_t (*unload) (grub_efi_handle_t image_handle); //卸载 0f39a000 ?? +}; +typedef struct grub_efi_loaded_image grub_efi_loaded_image_t; //60(结构及void按8,其余按指定) 38 + +struct grub_efi_disk_io //磁盘输入输出 +{ + grub_efi_uint64_t revision; //修订 + grub_efi_status_t EFIAPI (*read) (struct grub_efi_disk_io *this, + grub_efi_uint32_t media_id, + grub_efi_uint64_t offset, + grub_efi_uintn_t buffer_size, + void *buffer); //读(本身,媒体标识,偏移,缓冲尺寸,缓存地址) + grub_efi_status_t EFIAPI (*write) (struct grub_efi_disk_io *this, + grub_efi_uint32_t media_id, + grub_efi_uint64_t offset, + grub_efi_uintn_t buffer_size, + void *buffer); //写 +}; +typedef struct grub_efi_disk_io grub_efi_disk_io_t; + +typedef unsigned char grub_efi_mac_t[32]; + +struct grub_efi_simple_network_mode //简单网络模式 +{ // bootia32.efi ipxe->bootia32.efi + unsigned int state; //状态 02 + unsigned int hwaddr_size; //硬件地址尺寸 06 + unsigned int media_header_size; //媒体头尺寸 0e + unsigned int max_packet_size; //最大包尺寸 05dc(1500) + unsigned int nvram_size; //虚拟ram尺寸 0200 0 + unsigned int nvram_access_size; //虚拟ram访问尺寸 04 0 + unsigned int receive_filter_mask; //接收滤波器屏蔽掩模 1f 07 + unsigned int receive_filter_setting; //接收滤波器设置 07 0 + unsigned int max_mcast_filter_count; //最大多播地址接收筛选器数 08 0 + unsigned int mcast_filter_count; //多播地址接收筛选器的当前数目 01 0 + grub_efi_mac_t mcast_filter[16]; //多播地址接收筛选器 01 00 5e 00 00 01 0 + grub_efi_mac_t current_address; //当前地址 00 0c 29 8d cc d9 + grub_efi_mac_t broadcast_address; //广播地址 ff ff ff ff ff ff + grub_efi_mac_t permanent_address; //永久地址 00 0c 29 8d cc d9 + unsigned char if_type; //接口类型 01 + unsigned char mac_changeable; //mac可更改 01 + unsigned char multitx_supported; //支持多数据包传输 00 + unsigned char media_present_supported; //支持媒体 01 + unsigned char media_present; //媒体连接 01 +}; + +enum //简单网络状态 + { + GRUB_EFI_NETWORK_STOPPED, //网络停止 0 + GRUB_EFI_NETWORK_STARTED, //网络起动 1 + GRUB_EFI_NETWORK_INITIALIZED, //已初始化 2 + }; + +enum //接收过滤器设置的位掩码值 + { + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST = 0x01, //简单网络接收 单播 + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST = 0x02, //简单网络接收 多播 + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST = 0x04, //简单网络接收 广播 + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS = 0x08, //简单网络接收 杂乱 + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST = 0x10, //简单网络接收 混杂多播 + }; + +struct grub_efi_simple_network //简单网络 +{ + grub_uint64_t revision; //修订 + grub_efi_status_t EFIAPI (*start) (struct grub_efi_simple_network *this); //开始(指向EFI_SIMPLE_NETWORK_协议实例的指针) + grub_efi_status_t EFIAPI (*stop) (struct grub_efi_simple_network *this); //停止 + grub_efi_status_t EFIAPI (*initialize) (struct grub_efi_simple_network *this, + grub_efi_uintn_t extra_rx, + grub_efi_uintn_t extra_tx); //初始化 + grub_efi_status_t EFIAPI (*reset) (struct grub_efi_simple_network *this, + grub_uint32_t ExtendedVerification); //重置 + grub_efi_status_t EFIAPI (*shutdown) (struct grub_efi_simple_network *this); //关闭 + grub_efi_status_t EFIAPI (*receive_filters) (struct grub_efi_simple_network *this, + grub_uint32_t enable, + grub_uint32_t disable, + grub_efi_boolean_t reset_mcast_filter, + grub_efi_uintn_t mcast_filter_count, + grub_efi_mac_address_t *mcast_filter); //接收过滤器 + void (*station_address) (void); //固定地址 + void (*statistics) (void); //统计 + void (*mcastiptomac) (void); //将多播IP地址映射到多播 + void (*nvdata) (void); //NVRAM数据 + grub_efi_status_t EFIAPI (*get_status) (struct grub_efi_simple_network *this, + grub_uint32_t *int_status, + void **txbuf); //获得状态 + grub_efi_status_t EFIAPI (*transmit) (struct grub_efi_simple_network *this, + grub_efi_uintn_t header_size, + grub_efi_uintn_t buffer_size, + void *buffer, + grub_efi_mac_t *src_addr, + grub_efi_mac_t *dest_addr, + grub_efi_uint16_t *protocol); //传输 + grub_efi_status_t EFIAPI (*receive) (struct grub_efi_simple_network *this, + grub_efi_uintn_t *header_size, + grub_efi_uintn_t *buffer_size, + void *buffer, + grub_efi_mac_t *src_addr, + grub_efi_mac_t *dest_addr, + grub_uint16_t *protocol); //接收 + void EFIAPI (*waitforpacket) (void); //等待包 + struct grub_efi_simple_network_mode *mode; //简单网络模式 +}; +typedef struct grub_efi_simple_network grub_efi_simple_network_t; + + +struct grub_efi_block_io //块输入输出 +{ + grub_efi_uint64_t revision; //修订 020001 + grub_efi_block_io_media_t *media; //介质 fea7ed8 + grub_efi_status_t EFIAPI (*reset) (struct grub_efi_block_io *this, + grub_efi_boolean_t extended_verification); //重置 ff95f10 + //读块(本身,媒体id,起始逻辑块,读写字节,缓存地址) ff9600e + grub_efi_status_t EFIAPI (*read_blocks) (struct grub_efi_block_io *this, //本身 + grub_efi_uint32_t media_id, //读取请求的媒体ID。相当于驱动器号. + grub_efi_lba_t lba, //要从设备上读取的起始逻辑块地址。以扇区计. + grub_efi_uintn_t buffer_size, //缓冲区的尺寸(字节)。这必须是设备内部块大小的倍数 + void *buffer); //指向数据的目标缓冲区的指针。调用方负责隐式或显式拥有缓冲区。 + //写块(本身,媒体id,起始逻辑块,读写字节,缓存地址) ff9600e + grub_efi_status_t EFIAPI (*write_blocks) (struct grub_efi_block_io *this,//本身 + grub_efi_uint32_t media_id, //读取请求的媒体ID。相当于驱动器号. + grub_efi_lba_t lba, //要从设备上读取的起始逻辑块地址。以扇区计. + grub_efi_uintn_t buffer_size, //缓冲区的尺寸(字节)。这必须是设备内部块大小的倍数。 + void *buffer); //指向数据的目标缓冲区的指针。调用方负责隐式或显式拥有缓冲区。 + //写块 ff9611b + grub_efi_status_t EFIAPI (*flush_blocks) (struct grub_efi_block_io *this); //刷新块 ff96228 将所有修改过的数据刷新到物理块设备。 +}; +typedef struct grub_efi_block_io grub_efi_block_io_t; + +#define CR(RECORD, TYPE, FIELD) \ + ((TYPE *) ((char *) (RECORD) - (char *) &(((TYPE *) 0)->FIELD))) + +enum grub_efi_ip4_config2_data_type { //IP4配置2数据类型 + GRUB_EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO, //接口信息 + GRUB_EFI_IP4_CONFIG2_DATA_TYPE_POLICY, //策略 + GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS, //手动地址 + GRUB_EFI_IP4_CONFIG2_DATA_TYPE_GATEWAY, //网关 + GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER, //dns服务器 + GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MAXIMUM //最大值 +}; +typedef enum grub_efi_ip4_config2_data_type grub_efi_ip4_config2_data_type_t; + +struct grub_efi_ip4_route_table { //IP4路线表 + grub_efi_ipv4_address_t subnet_address; //子网地址 + grub_efi_ipv4_address_t subnet_mask; //子网掩码 + grub_efi_ipv4_address_t gateway_address; //网关地址 +}; + +typedef struct grub_efi_ip4_route_table grub_efi_ip4_route_table_t; + +typedef struct { + grub_efi_ipv4_address_t station_address; //默认站IP地址,按网络字节顺序存储。 + grub_efi_ipv4_address_t subnet_mask; //默认子网掩码,按网络字节顺序存储。 + grub_efi_uint32_t route_table_size; //路由表大小,以下RouteTable中的条目数。可能为零。 + grub_efi_ip4_route_table_t *route_table; //路由表,默认路由表数据(按网络字节顺序存储)。如果route_table_size为零,则忽略。 +} grub_efi_ip4_ipconfig_data; + + +struct grub_efi_ip4_protocol +{ + grub_efi_status_t EFIAPI (*get_mode_data) (); + grub_efi_status_t EFIAPI (*configure) (); + grub_efi_status_t EFIAPI (*groups) (); + grub_efi_status_t EFIAPI (*routes) (); + grub_efi_status_t EFIAPI (*transmit) (); + grub_efi_status_t EFIAPI (*receive) (); + grub_efi_status_t EFIAPI (*cancel) (); + grub_efi_status_t EFIAPI (*poll) (); +}; +typedef struct grub_efi_ip4_protocol grub_efi_ip4_protocol_t; + +/* +重要提示:EFI_IP4_CONFIG_PROTOCOL已被新的EFI_IP4-CONFIG2_PROTOCOL替换。 +• 基于本规范的所有新设计应仅使用EFI_IP4_CONFIG2_PROTOCOL。 +• EFI_IP4_CONFIG_PROTOCOL将在本规范的下一版本中删除。 +EFI_IP4_CONFIG_PROTOCOL驱动程序为EFI IPv4协议驱动程序执行依赖于平台和策略的配置。 +*/ +struct grub_efi_ip4_config_protocol +{ +/* +开始运行EFI IPv4协议驱动程序的配置策略。 +EFI IPv4协议驱动程序调用start()函数以确定并启动平台配置策略。如果没有EFI IPv4协议驱动程序配置策略,则此确定可能就像返回EFI_UNSUPPORTED一样简单。 +它可能涉及从非易失性存储加载一些默认值、从DHCP服务器下载动态数据以及使用站点策略服务器检查权限。 +启动配置策略仅仅是个开始。它可能几乎立即完成,也可能需要几分钟才能从一个或多个服务器检索配置信息。一旦政策 +启动后,驱动程序应使用DoneEvent参数来确定配置策略何时完成。EFI_IP4_CONFIG协议。然后必须调用GetData()来确定配置是成功还是失败。 +在配置成功完成之前,尝试使用默认配置的EFI IPv4协议驱动程序实例必须返回EFI_NO_MAPPING。 +配置完成后,EFI IPv4配置协议驱动程序会向DoneEvent发送信号。然而,未来可能需要更新配置;在这种情况下, +EFI IPv4配置协议驱动程序必须发出ReconfigEvent信号,并且所有使用默认配置的EFI IPv4协议驱动程序实例都必须返回EFI_NO_MAPPING,直到重新运行配置策略。 +*/ + grub_efi_status_t EFIAPI (*start) (struct grub_efi_ip4_protocol *this, //指向EFI_IP4_CONFIG_PROTOCOL实例的指针 + grub_efi_event_t done_event, //EFI IPv4协议驱动程序配置策略完成执行时将发出信号的事件。此事件的类型必须为EVT_NOTIFY_SIGNAL + grub_efi_event_t reconfig_event); //需要更新EFI IPv4协议驱动程序配置时将发出信号的事件。此事件的类型必须为EVT_NOTIFY_SIGNAL。 + grub_efi_status_t EFIAPI (*stop) (struct grub_efi_ip4_protocol *this); + //返回EFI IPv4协议驱动程序的默认配置数据(如果有)。 + //get_data()函数在配置策略完成后返回EFI IPv4协议驱动程序的当前配置数据。 + grub_efi_status_t EFIAPI (*get_data) (struct grub_efi_ip4_protocol *this, + UINTN *IpConfigDataSize, //输入时,IpConfigData缓冲区的大小。输出时,写入IpConfigData缓冲区的字节数。 + grub_efi_ip4_ipconfig_data *IpConfigData); //指向EFI IPv4配置协议驱动程序配置数据结构的指针。EFI_IP4_IPCONFIG_DATA类型在下面的“相关定义”中定义。 +}; +typedef struct grub_efi_ip4_config_protocol grub_efi_ip4_config_protocol_t; + +struct grub_efi_ip4_config2_protocol //IP4配置2协议 +{ +//设置数据 + grub_efi_status_t EFIAPI (*set_data) (struct grub_efi_ip4_config2_protocol *this, + grub_efi_ip4_config2_data_type_t data_type, + grub_efi_uintn_t data_size, + void *data); +//获得数据 + grub_efi_status_t EFIAPI (*get_data) (struct grub_efi_ip4_config2_protocol *this, + grub_efi_ip4_config2_data_type_t data_type, + grub_efi_uintn_t *data_size, + void *data); +//注册数据通知 + grub_efi_status_t EFIAPI (*register_data_notify) (struct grub_efi_ip4_config2_protocol *this, + grub_efi_ip4_config2_data_type_t data_type, + grub_efi_event_t event); +//注销数据通知 + grub_efi_status_t EFIAPI (*unregister_datanotify) (struct grub_efi_ip4_config2_protocol *this, + grub_efi_ip4_config2_data_type_t data_type, + grub_efi_event_t event); +}; +typedef struct grub_efi_ip4_config2_protocol grub_efi_ip4_config2_protocol_t; + +#define GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE 32 //P4配置2接口信息名称尺寸 + +struct grub_efi_ip4_config2_interface_info { //P4配置2接口信息 + grub_efi_char16_t name[GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE]; //名称 + grub_efi_uint8_t if_type; //接口类型 + grub_efi_uint32_t hw_address_size; //硬件地址尺寸 + grub_efi_mac_address_t hw_address; //硬件地址 + grub_efi_ipv4_address_t station_address; //站地址 + grub_efi_ipv4_address_t subnet_mask; //子网掩码 + grub_efi_uint32_t route_table_size; //路由表尺寸 + grub_efi_ip4_route_table_t *route_table; //路由表 +}; + +typedef struct grub_efi_ip4_config2_interface_info grub_efi_ip4_config2_interface_info_t; + +enum grub_efi_ip4_config2_policy { //P4配置2策略 + GRUB_EFI_IP4_CONFIG2_POLICY_STATIC, //静态 + GRUB_EFI_IP4_CONFIG2_POLICY_DHCP, //DHCP + GRUB_EFI_IP4_CONFIG2_POLICY_MAX //最大值 +}; + +typedef enum grub_efi_ip4_config2_policy grub_efi_ip4_config2_policy_t; + +struct grub_efi_ip4_config2_manual_address {//P4配置2策略手动地址 + grub_efi_ipv4_address_t address; //地址 + grub_efi_ipv4_address_t subnet_mask; //子网掩码 +}; + +typedef struct grub_efi_ip4_config2_manual_address grub_efi_ip4_config2_manual_address_t; + +enum grub_efi_ip6_config_data_type { //ip6配置数据类型 + GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO, //接口信息 + GRUB_EFI_IP6_CONFIG_DATA_TYPE_ALT_INTERFACEID, //ALT接口 + GRUB_EFI_IP6_CONFIG_DATA_TYPE_POLICY, //策略 + GRUB_EFI_IP6_CONFIG_DATA_TYPE_DUP_ADDR_DETECT_TRANSMITS, //DUP地址检测传输 + GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS, //手动地址 + GRUB_EFI_IP6_CONFIG_DATA_TYPE_GATEWAY, //网关 + GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER, //dns服务器 + GRUB_EFI_IP6_CONFIG_DATA_TYPE_MAXIMUM //最大值 +}; +typedef enum grub_efi_ip6_config_data_type grub_efi_ip6_config_data_type_t; + +struct grub_efi_ip6_config_protocol //ip6配置协议 +{ +//设置数据 + grub_efi_status_t EFIAPI (*set_data) (struct grub_efi_ip6_config_protocol *this, + grub_efi_ip6_config_data_type_t data_type, + grub_efi_uintn_t data_size, + void *data); +//获得数据 + grub_efi_status_t EFIAPI (*get_data) (struct grub_efi_ip6_config_protocol *this, + grub_efi_ip6_config_data_type_t data_type, + grub_efi_uintn_t *data_size, + void *data); +//注册数据通知 + grub_efi_status_t EFIAPI (*register_data_notify) (struct grub_efi_ip6_config_protocol *this, + grub_efi_ip6_config_data_type_t data_type, + grub_efi_event_t event); +//注销数据通知 + grub_efi_status_t EFIAPI (*unregister_datanotify) (struct grub_efi_ip6_config_protocol *this, + grub_efi_ip6_config_data_type_t data_type, + grub_efi_event_t event); +}; +typedef struct grub_efi_ip6_config_protocol grub_efi_ip6_config_protocol_t; + +enum grub_efi_ip6_config_policy { //ip6配置策略 + GRUB_EFI_IP6_CONFIG_POLICY_MANUAL, //手动 + GRUB_EFI_IP6_CONFIG_POLICY_AUTOMATIC //自动 +}; +typedef enum grub_efi_ip6_config_policy grub_efi_ip6_config_policy_t; + +struct grub_efi_ip6_address_info { //ip6地址信息 + grub_efi_ipv6_address_t address; //地址 + grub_efi_uint8_t prefix_length; //前缀长度 +}; +typedef struct grub_efi_ip6_address_info grub_efi_ip6_address_info_t; + +struct grub_efi_ip6_route_table { //ip6路线表 + grub_efi_pxe_ipv6_address_t gateway; //网关 + grub_efi_pxe_ipv6_address_t destination; //目的地 + grub_efi_uint8_t prefix_length; //前缀长度 +}; +typedef struct grub_efi_ip6_route_table grub_efi_ip6_route_table_t; + +struct grub_efi_ip6_config_interface_info { //ip6配置接口信息 + grub_efi_char16_t name[32]; //名称 + grub_efi_uint8_t if_type; //接口类型 + grub_efi_uint32_t hw_address_size; //硬件地址尺寸 + grub_efi_mac_address_t hw_address; //硬件地址 + grub_efi_uint32_t address_info_count; //地址信息计数 + grub_efi_ip6_address_info_t *address_info; //地址信息 + grub_efi_uint32_t route_count; //路线数 + grub_efi_ip6_route_table_t *route_table; //路线表 +}; +typedef struct grub_efi_ip6_config_interface_info grub_efi_ip6_config_interface_info_t; + +struct grub_efi_ip6_config_dup_addr_detect_transmits { //ip6配置dup地址检测传送 + grub_efi_uint32_t dup_addr_detect_transmits; //dup地址检测传送 +}; +typedef struct grub_efi_ip6_config_dup_addr_detect_transmits grub_efi_ip6_config_dup_addr_detect_transmits_t; + +struct grub_efi_ip6_config_manual_address { //ip6配置手动地址 + grub_efi_ipv6_address_t address; //地址 + grub_efi_boolean_t is_anycast; //是任播 + grub_efi_uint8_t prefix_length; //前缀长度 +}; +typedef struct grub_efi_ip6_config_manual_address grub_efi_ip6_config_manual_address_t; + +struct grub_efi_load_file2 +{ + grub_efi_status_t (EFIAPI *load_file)(struct grub_efi_load_file2 *this, + grub_efi_device_path_t *file_path, + grub_efi_boolean_t boot_policy, + grub_efi_uintn_t *buffer_size, + void *buffer); +}; +typedef struct grub_efi_load_file2 grub_efi_load_file2_t; + +#define LINUX_EFI_INITRD_MEDIA_GUID \ + { 0x5568e427, 0x68fc, 0x4f3d, \ + { 0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68 } \ + } + +struct initrd_media_device_path +{ + grub_efi_vendor_media_device_path_t vendor; + grub_efi_device_path_t end; +} GRUB_PACKED; +typedef struct initrd_media_device_path initrd_media_device_path_t; + +/* +******************************************************* + UNICODE DRAWING CHARACTERS UNICODE绘图字符 +******************************************************* +#define BOXDRAW_HORIZONTAL 0x2500 //水平 ─ +#define BOXDRAW_VERTICAL 0x2502 //垂直 │ +#define BOXDRAW_DOWN_RIGHT 0x250c //左上角 ┌ uefi命名含义:绘画动作 从一点开始,向下画;再从这点向右画 +#define BOXDRAW_DOWN_LEFT 0x2510 //右上角 ┐ UEFI固件的右上角(0x2510)是宽字符 +#define BOXDRAW_UP_RIGHT 0x2514 //左下角 └ +#define BOXDRAW_UP_LEFT 0x2518 //右下角 ┘ +#define BOXDRAW_VERTICAL_RIGHT 0x251c //垂直右 ├ +#define BOXDRAW_VERTICAL_LEFT 0x2524 //垂直左 ┤ +#define BOXDRAW_DOWN_HORIZONTAL 0x252c //下水平 ┬ +#define BOXDRAW_UP_HORIZONTAL 0x2534 //上水平 ┴ +#define BOXDRAW_VERTICAL_HORIZONTAL 0x253c //垂直水平 ┼ +#define BOXDRAW_DOUBLE_HORIZONTAL 0x2550 //双水平 ═ +#define BOXDRAW_DOUBLE_VERTICAL 0x2551 //双垂直 ║ +#define BOXDRAW_DOWN_RIGHT_DOUBLE 0x2552 //下右双 ╒ +#define BOXDRAW_DOWN_DOUBLE_RIGHT 0x2553 //下双右 ╓ +#define BOXDRAW_DOUBLE_DOWN_RIGHT 0x2554 //双下右 ╔ +#define BOXDRAW_DOWN_LEFT_DOUBLE 0x2555 //下左双 ╕ +#define BOXDRAW_DOWN_DOUBLE_LEFT 0x2556 //下双左 ╖ +#define BOXDRAW_DOUBLE_DOWN_LEFT 0x2557 //双下左 ╗ +#define BOXDRAW_UP_RIGHT_DOUBLE 0x2558 //上右双 ╘ +#define BOXDRAW_UP_DOUBLE_RIGHT 0x2559 //上双右 ╙ +#define BOXDRAW_DOUBLE_UP_RIGHT 0x255a //双上右 ╚ +#define BOXDRAW_UP_LEFT_DOUBLE 0x255b //上左双 ╛ +#define BOXDRAW_UP_DOUBLE_LEFT 0x255c //上双左 ╜ +#define BOXDRAW_DOUBLE_UP_LEFT 0x255d //双上左 ╝ +#define BOXDRAW_VERTICAL_RIGHT_DOUBLE 0x255e //垂直右双 ╞ +#define BOXDRAW_VERTICAL_DOUBLE_RIGHT 0x255f //垂直双右 ╟ +#define BOXDRAW_DOUBLE_VERTICAL_RIGHT 0x2560 //双垂直右 ╠ +#define BOXDRAW_VERTICAL_LEFT_DOUBLE 0x2561 //垂直左双 ╡ +#define BOXDRAW_VERTICAL_DOUBLE_LEFT 0x2562 //垂直双左 ╢ +#define BOXDRAW_DOUBLE_VERTICAL_LEFT 0x2563 //双垂直左 ╣ +#define BOXDRAW_DOWN_HORIZONTAL_DOUBLE 0x2564 //下水平双 ╤ +#define BOXDRAW_DOWN_DOUBLE_HORIZONTAL 0x2565 //下双水平 ╥ +#define BOXDRAW_DOUBLE_DOWN_HORIZONTAL 0x2566 //双下水平 ╦ +#define BOXDRAW_UP_HORIZONTAL_DOUBLE 0x2567 //上水平双 ╧ +#define BOXDRAW_UP_DOUBLE_HORIZONTAL 0x2568 //上双水平 ╨ +#define BOXDRAW_DOUBLE_UP_HORIZONTAL 0x2569 //双上水平 ╩ +#define BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE 0x256a //垂直水平双 ╪ +#define BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL 0x256b //垂直双水平 ╫ +#define BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL 0x256c //双垂直水平 ╬ +******************************************************* + EFI Required Block Elements Code Chart EFI所需块元素代码表 +******************************************************* +#define BLOCKELEMENT_FULL_BLOCK 0x2588 //元素全块 █ +#define BLOCKELEMENT_LIGHT_SHADE 0x2591 //元素浅色 ░ +******************************************************* + EFI Required Geometric Shapes Code Chart EFI要求的几何形状代码表 +******************************************************* +#define GEOMETRICSHAPE_UP_TRIANGLE 0x25b2 //向上三角形 ▲ +#define GEOMETRICSHAPE_RIGHT_TRIANGLE 0x25ba //向右三角形 ► +#define GEOMETRICSHAPE_DOWN_TRIANGLE 0x25bc //向下三角形 ▼ +#define GEOMETRICSHAPE_LEFT_TRIANGLE 0x25c4 //向左三角形 ◄ +******************************************************* + EFI Required Arrow shapes EFI所需箭头形状 +******************************************************* +#define ARROW_LEFT 0x2190 //向左箭头 ← +#define ARROW_UP 0x2191 //向上箭头 ↑ +#define ARROW_RIGHT 0x2192 //向右箭头 → +#define ARROW_DOWN 0x2193 //向下箭头 ↓ + + +EFI简单文本输入协议定义了一个包含Unicode字符和所需EFI扫描代码的输入流。 +只有表106中定义的控制字符在Unicode输入或输出流中具有含义。控制字符定义为从U+0000到U+001F的字符。输入流不支持任何软件流控制。 +表106。支持的Unicode控制字符 +助记符 Unicode代码 描述 +Null U+0000 空字符在接收时被忽略 +BS U+0008 退格。将光标左移一列。如果光标位于左边距,则不执行任何操作。 +TAB U+0x0009 TAB +LF U+000A 换行。将光标移到下一行。 注意:只换行,不回车。 +CR U+000D 回车。将光标移到当前行的左边距。注意:只回车。 + +除了Unicode字符外,输入流还支持扫描代码。如果扫描代码设置为0x00,则Unicode字符有效,应使用。如果扫描代码设置为非0x00值,则表示表107定义的特殊键。 +表107。EFI简单文本输入协议的EFI扫描码 +EFI扫描码 描述 +0x00 空扫描代码。 +0x01 将光标上移一行。 +0x02 将光标下移一行。 +0x03 将光标右移1列。 +0x04 将光标左移1列。 +0x05 回家。 Home +0x06 结束。 end +0x07 插入。 Insert +0x08 删除。 Delete +0x09 向上翻页。 Page Up +0x0a 向下翻页。 Page Down +0x0b 功能1。 +0x0c 功能2。 +0x0d 功能3。 +0x0e 功能4。 +0x0f 功能5。 +0x10 功能6。 +0x11 功能7。 +0x12 功能8。 +0x13 功能9。 +0x14 功能10。 +0x17 逃离。 Escape + +表108。EFI简单文本输入扩展协议的EFI扫描码 +EFI扫描码 描述 +0x15 功能11 +0x16 功能12 +0x68 功能13 +0x69 功能14 +0x6A 功能15 +0x6B 功能16 +0x6C 功能17 +0x6D 功能18 +0x6E 功能19 +0x6F 功能20 +0x70 功能21 +0x71 功能22 +0x72 功能23 +0x73 功能24 +0x7F 静音 +0x80 音量增大 +0x81 音量降低 +0x100 亮度增大 +0x101 亮度降低 +0x102 暂停 +0x103 休眠 +0x104 切换显示 +0x105 恢复 +0x106 弹出 +0x8000-0xFFFF 原始设备制造商保留 + +字符串显示在输出设备上的当前光标位置,光标根据表109中列出的规则前进。 +Table 109. EFI 光标位置/前进规则 +助记符 Unicode代码 描述 +Null U+0000 忽略字符,不要移动光标。 +BS U+0008 如果光标不在显示器的左边缘,则将光标向左移动一列。 +LF U+000A 如果光标位于显示器底部,则将显示器滚动一行,不要更新光标位置。否则,将光标下移一行。 注意:只换行,不回车。 +CR U+000D 将光标移到当前行的开头。 注意:只回车。 +Other U+XXXX 在当前光标位置打印字符并将光标向右移动一列。如果这将光标移过显示器的右边缘,则该行应换行到下一行的开头。 + 这相当于插入一个CR和一个LF。注意,如果光标位于显示器的底部,并且行换行,则显示器将滚动一行。 +*/ + +/* +#if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \ + || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) +*/ +#if defined(__i386__) +#define efi_call_0(func) func() +#define efi_call_1(func, a) func(a) +#define efi_call_2(func, a, b) func(a, b) +#define efi_call_3(func, a, b, c) func(a, b, c) +#define efi_call_4(func, a, b, c, d) func(a, b, c, d) +#define efi_call_5(func, a, b, c, d, e) func(a, b, c, d, e) +#define efi_call_6(func, a, b, c, d, e, f) func(a, b, c, d, e, f) +#define efi_call_7(func, a, b, c, d, e, f, g) func(a, b, c, d, e, f, g) +#define efi_call_10(func, a, b, c, d, e, f, g, h, i, j) func(a, b, c, d, e, f, g, h, i, j) + +#else + +#define efi_call_0(func) \ + efi_wrap_0(func) +#define efi_call_1(func, a) \ + efi_wrap_1(func, (unsigned long long) (a)) +#define efi_call_2(func, a, b) \ + efi_wrap_2(func, (unsigned long long) (a), (unsigned long long) (b)) +#define efi_call_3(func, a, b, c) \ + efi_wrap_3(func, (unsigned long long) (a), (unsigned long long) (b), \ + (unsigned long long) (c)) +#define efi_call_4(func, a, b, c, d) \ + efi_wrap_4(func, (unsigned long long) (a), (unsigned long long) (b), \ + (unsigned long long) (c), (unsigned long long) (d)) +#define efi_call_5(func, a, b, c, d, e) \ + efi_wrap_5(func, (unsigned long long) (a), (unsigned long long) (b), \ + (unsigned long long) (c), (unsigned long long) (d), (unsigned long long) (e)) +#define efi_call_6(func, a, b, c, d, e, f) \ + efi_wrap_6(func, (unsigned long long) (a), (unsigned long long) (b), \ + (unsigned long long) (c), (unsigned long long) (d), (unsigned long long) (e), \ + (unsigned long long) (f)) +#define efi_call_7(func, a, b, c, d, e, f, g) \ + efi_wrap_7(func, (unsigned long long) (a), (unsigned long long) (b), \ + (unsigned long long) (c), (unsigned long long) (d), (unsigned long long) (e), \ + (unsigned long long) (f), (unsigned long long) (g)) +#define efi_call_10(func, a, b, c, d, e, f, g, h, i, j) \ + efi_wrap_10(func, (unsigned long long) (a), (unsigned long long) (b), \ + (unsigned long long) (c), (unsigned long long) (d), (unsigned long long) (e), \ + (unsigned long long) (f), (unsigned long long) (g), (unsigned long long) (h), \ + (unsigned long long) (i), (unsigned long long) (j)) + +unsigned long long EXPORT_FUNC(efi_wrap_0) (void *func); +unsigned long long EXPORT_FUNC(efi_wrap_1) (void *func, unsigned long long arg1); +unsigned long long EXPORT_FUNC(efi_wrap_2) (void *func, unsigned long long arg1, + unsigned long long arg2); +unsigned long long EXPORT_FUNC(efi_wrap_3) (void *func, unsigned long long arg1, + unsigned long long arg2, unsigned long long arg3); +unsigned long long EXPORT_FUNC(efi_wrap_4) (void *func, unsigned long long arg1, + unsigned long long arg2, unsigned long long arg3, + unsigned long long arg4); +unsigned long long EXPORT_FUNC(efi_wrap_5) (void *func, unsigned long long arg1, + unsigned long long arg2, unsigned long long arg3, + unsigned long long arg4, unsigned long long arg5); +unsigned long long EXPORT_FUNC(efi_wrap_6) (void *func, unsigned long long arg1, + unsigned long long arg2, unsigned long long arg3, + unsigned long long arg4, unsigned long long arg5, + unsigned long long arg6); +unsigned long long EXPORT_FUNC(efi_wrap_7) (void *func, unsigned long long arg1, + unsigned long long arg2, unsigned long long arg3, + unsigned long long arg4, unsigned long long arg5, + unsigned long long arg6, unsigned long long arg7); +unsigned long long EXPORT_FUNC(efi_wrap_10) (void *func, unsigned long long arg1, + unsigned long long arg2, unsigned long long arg3, + unsigned long long arg4, unsigned long long arg5, + unsigned long long arg6, unsigned long long arg7, + unsigned long long arg8, unsigned long long arg9, + unsigned long long arg10); +#endif +//_____________________________________________________________________________________ +//grub/err.h +#define GRUB_MAX_ERRMSG 256 +typedef enum + { + GRUB_ERR_NONE = 0, + GRUB_ERR_TEST_FAILURE, + GRUB_ERR_BAD_MODULE, + GRUB_ERR_OUT_OF_MEMORY, + GRUB_ERR_BAD_FILE_TYPE, + GRUB_ERR_FILE_NOT_FOUND, + GRUB_ERR_FILE_READ_ERROR, + GRUB_ERR_BAD_FILENAME, + GRUB_ERR_UNKNOWN_FS, + GRUB_ERR_BAD_FS, + GRUB_ERR_BAD_NUMBER, + GRUB_ERR_OUT_OF_RANGE, + GRUB_ERR_UNKNOWN_DEVICE, + GRUB_ERR_BAD_DEVICE, + GRUB_ERR_READ_ERROR, + GRUB_ERR_WRITE_ERROR, + GRUB_ERR_UNKNOWN_COMMAND, + GRUB_ERR_INVALID_COMMAND, + GRUB_ERR_BAD_ARGUMENT, + GRUB_ERR_BAD_PART_TABLE, + GRUB_ERR_UNKNOWN_OS, + GRUB_ERR_BAD_OS, + GRUB_ERR_NO_KERNEL, + GRUB_ERR_BAD_FONT, + GRUB_ERR_NOT_IMPLEMENTED_YET, + GRUB_ERR_SYMLINK_LOOP, + GRUB_ERR_BAD_COMPRESSED_DATA, + GRUB_ERR_MENU, + GRUB_ERR_TIMEOUT, + GRUB_ERR_IO, + GRUB_ERR_ACCESS_DENIED, + GRUB_ERR_EXTRACTOR, + GRUB_ERR_NET_BAD_ADDRESS, + GRUB_ERR_NET_ROUTE_LOOP, + GRUB_ERR_NET_NO_ROUTE, + GRUB_ERR_NET_NO_ANSWER, + GRUB_ERR_NET_NO_CARD, + GRUB_ERR_WAIT, + GRUB_ERR_BUG, + GRUB_ERR_NET_PORT_CLOSED, + GRUB_ERR_NET_INVALID_RESPONSE, + GRUB_ERR_NET_UNKNOWN_ERROR, + GRUB_ERR_NET_PACKET_TOO_BIG, + GRUB_ERR_NET_NO_DOMAIN, + GRUB_ERR_EOF, + GRUB_ERR_BAD_SIGNATURE + } +grub_err_t; + +extern grub_err_t grub_errno; + +struct grub_error_saved +{ + grub_err_t grub_errno; + char errmsg[GRUB_MAX_ERRMSG]; +}; + +extern grub_err_t EXPORT_VAR(grub_errno); +//----------------------------------------------------------------------------------------------- +//grub/types.h + +//grub/efi/efi.h +/* Functions. */ +extern void *EXPORT_FUNC(grub_efi_locate_protocol) (grub_efi_guid_t *protocol, + void *registration); +extern grub_efi_handle_t * +EXPORT_FUNC(grub_efi_locate_handle) (grub_efi_locate_search_type_t search_type, + grub_efi_guid_t *protocol, + void *search_key, + grub_efi_uintn_t *num_handles); +extern void *EXPORT_FUNC(grub_efi_open_protocol) (grub_efi_handle_t handle, + grub_efi_guid_t *protocol, + grub_efi_uint32_t attributes); +extern int EXPORT_FUNC(grub_efi_set_text_mode) (int on); +extern void EXPORT_FUNC(grub_efi_stall) (grub_efi_uintn_t microseconds); +extern void * +EXPORT_FUNC(grub_efi_allocate_pages_real) (grub_efi_physical_address_t address, + grub_efi_uintn_t pages, + grub_efi_allocate_type_t alloctype, + grub_efi_memory_type_t memtype); +extern void * +EXPORT_FUNC(grub_efi_allocate_fixed) (grub_efi_physical_address_t address, + grub_efi_uintn_t pages); +extern void * +EXPORT_FUNC(grub_efi_allocate_any_pages) (grub_efi_uintn_t pages); +extern void EXPORT_FUNC(grub_efi_free_pages) (grub_efi_physical_address_t address, + grub_efi_uintn_t pages); +extern grub_efi_uintn_t EXPORT_FUNC(grub_efi_find_mmap_size) (void); +extern int +EXPORT_FUNC(grub_efi_get_memory_map) (grub_efi_uintn_t *memory_map_size, + grub_efi_memory_descriptor_t *memory_map, + grub_efi_uintn_t *map_key, + grub_efi_uintn_t *descriptor_size, + grub_efi_uint32_t *descriptor_version); +extern void grub_efi_memory_fini (void); +extern grub_efi_loaded_image_t *grub_efi_get_loaded_image (grub_efi_handle_t image_handle); +extern void EXPORT_FUNC(grub_efi_print_device_path) (grub_efi_device_path_t *dp); +extern char *EXPORT_FUNC(grub_efi_get_filename) (grub_efi_device_path_t *dp); +extern grub_efi_device_path_t * +EXPORT_FUNC(grub_efi_get_device_path) (grub_efi_handle_t handle); +extern grub_efi_device_path_t * +EXPORT_FUNC(grub_efi_find_last_device_path) (const grub_efi_device_path_t *dp); +extern grub_efi_device_path_t * +EXPORT_FUNC(grub_efi_duplicate_device_path) (const grub_efi_device_path_t *dp); +extern grub_err_t EXPORT_FUNC (grub_efi_finish_boot_services) (grub_efi_uintn_t *outbuf_size, void *outbuf, + grub_efi_uintn_t *map_key, + grub_efi_uintn_t *efi_desc_size, + grub_efi_uint32_t *efi_desc_version); +extern grub_err_t EXPORT_FUNC (grub_efi_set_virtual_address_map) (grub_efi_uintn_t memory_map_size, + grub_efi_uintn_t descriptor_size, + grub_efi_uint32_t descriptor_version, + grub_efi_memory_descriptor_t *virtual_map); +extern void *EXPORT_FUNC (grub_efi_get_variable) (const char *variable, + const grub_efi_guid_t *guid, + grub_size_t *datasize_out); +extern grub_err_t +EXPORT_FUNC (grub_efi_set_variable) (const char *var, + const grub_efi_guid_t *guid, + void *data, + grub_size_t datasize); +extern int +EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1, + const grub_efi_device_path_t *dp2); + +extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd, + char **device, + char **path); +extern grub_efi_status_t grub_efi_allocate_pool (grub_efi_memory_type_t pool_type, + grub_efi_uintn_t buffer_size, void **buffer); +extern grub_efi_status_t grub_efi_free_pool (void *buffer); + +#if defined(__arm__) || defined(__aarch64__) +extern void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void); +extern grub_err_t EXPORT_FUNC(grub_efi_get_ram_base)(grub_addr_t *); +#include +extern grub_err_t grub_armxx_efi_linux_check_image(struct linux_armxx_kernel_header *lh); +extern grub_err_t grub_armxx_efi_linux_boot_image(grub_addr_t addr, grub_size_t size, + char *args); +#endif + +extern grub_addr_t grub_efi_modules_addr (void); + +extern void grub_efi_mm_init (void); +extern void grub_efi_mm_fini (void); +extern void grub_efi_init (void); +extern void grub_efi_fini (void); +extern void grub_efi_set_prefix (void); + +/* Variables. */ +extern grub_efi_system_table_t *EXPORT_VAR(grub_efi_system_table); +extern grub_efi_handle_t EXPORT_VAR(grub_efi_image_handle); + +extern int EXPORT_VAR(grub_efi_is_finished); + +struct grub_net_card; //网卡 + +extern grub_efi_handle_t +grub_efinet_get_device_handle (struct grub_net_card *card); +//------------------------------------------------------------------------------------ +//grub/efi/console_control.h +#define GRUB_EFI_CONSOLE_CONTROL_GUID \ + { 0xf42f7782, 0x12e, 0x4c12, \ + { 0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21 } \ + } //控制台控件GUID + +enum grub_efi_screen_mode + { + GRUB_EFI_SCREEN_TEXT, + GRUB_EFI_SCREEN_GRAPHICS, + GRUB_EFI_SCREEN_TEXT_MAX_VALUE + }; +typedef enum grub_efi_screen_mode grub_efi_screen_mode_t; + +struct grub_efi_console_control_protocol +{ + grub_efi_status_t + (*get_mode) (struct grub_efi_console_control_protocol *this, + grub_efi_screen_mode_t *mode, + grub_efi_boolean_t *uga_exists, + grub_efi_boolean_t *std_in_locked); + + grub_efi_status_t + (*set_mode) (struct grub_efi_console_control_protocol *this, + grub_efi_screen_mode_t mode); + + grub_efi_status_t + (*lock_std_in) (struct grub_efi_console_control_protocol *this, + grub_efi_char16_t *password); +}; +typedef struct grub_efi_console_control_protocol grub_efi_console_control_protocol_t; +//-------------------------------------------------------------------------------------------- +#if 0 +//grub/charset.h +#define GRUB_UINT8_1_LEADINGBIT 0x80 +#define GRUB_UINT8_2_LEADINGBITS 0xc0 +#define GRUB_UINT8_3_LEADINGBITS 0xe0 +#define GRUB_UINT8_4_LEADINGBITS 0xf0 +#define GRUB_UINT8_5_LEADINGBITS 0xf8 +#define GRUB_UINT8_6_LEADINGBITS 0xfc +#define GRUB_UINT8_7_LEADINGBITS 0xfe + +#define GRUB_UINT8_1_TRAILINGBIT 0x01 +#define GRUB_UINT8_2_TRAILINGBITS 0x03 +#define GRUB_UINT8_3_TRAILINGBITS 0x07 +#define GRUB_UINT8_4_TRAILINGBITS 0x0f +#define GRUB_UINT8_5_TRAILINGBITS 0x1f +#define GRUB_UINT8_6_TRAILINGBITS 0x3f + +#define GRUB_UCS2_LIMIT 0x10000 + +/* Process one character from UTF8 sequence. 处理UTF8序列中的一个字符。在开始设置时,*code=0, *count=0。 + At beginning set *code = 0, *count = 0. Returns 0 on failure and 失败时返回0,成功时返回1。count保存尾部字节数 + 1 on success. *count holds the number of trailing bytes. */ +static inline int +grub_utf8_process (grub_uint8_t c, grub_uint32_t *code, int *count) +{ + if (*count) + { + if ((c & GRUB_UINT8_2_LEADINGBITS) != GRUB_UINT8_1_LEADINGBIT) + { + *count = 0; + /* invalid */ + return 0; + } + else + { + *code <<= 6; + *code |= (c & GRUB_UINT8_6_TRAILINGBITS); + (*count)--; + /* Overlong. */ + if ((*count == 1 && *code <= 0x1f) + || (*count == 2 && *code <= 0xf)) + { + *code = 0; + *count = 0; + return 0; + } + return 1; + } + } + + if ((c & GRUB_UINT8_1_LEADINGBIT) == 0) + { + *code = c; + return 1; + } + if ((c & GRUB_UINT8_3_LEADINGBITS) == GRUB_UINT8_2_LEADINGBITS) + { + *count = 1; + *code = c & GRUB_UINT8_5_TRAILINGBITS; + /* Overlong */ + if (*code <= 1) + { + *count = 0; + *code = 0; + return 0; + } + return 1; + } + if ((c & GRUB_UINT8_4_LEADINGBITS) == GRUB_UINT8_3_LEADINGBITS) + { + *count = 2; + *code = c & GRUB_UINT8_4_TRAILINGBITS; + return 1; + } + if ((c & GRUB_UINT8_5_LEADINGBITS) == GRUB_UINT8_4_LEADINGBITS) + { + *count = 3; + *code = c & GRUB_UINT8_3_TRAILINGBITS; + return 1; + } + return 0; +} + +/* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE 将长度最多为 SRCSIZE 字节的UTF-8字符串(可能以null结尾)转换为UCS-2字符串 + bytes (if SRCSIZE is -1, it is ignored) in length to a UCS-2 string. (如果 SRCSIZE 为-1,则忽略该字符串)。 + Return the number of characters converted. DEST must be able to hold 返回转换的字符数。如果发现无效序列,则返回-1。 + at least DESTSIZE characters. If an invalid sequence is found, return -1. DEST 必须至少能够容纳 DESTSIZE 字符。如果 SRCEND 不为NULL, + If SRCEND is not NULL, then *SRCEND is set to the next byte after the 则 *SRCEND 被设置为 SRC 中使用的最后一个字节之后的下一个字节。 + last byte used in SRC. */ +static inline grub_size_t +grub_utf8_to_ucs2 (grub_uint16_t *dest, grub_size_t destsize, //ucs2地址,ucs2字节数 + const grub_uint8_t *src, grub_size_t srcsize, //utf8地址,utf8字节数 + const grub_uint8_t **srcend) //如果SRCEND不为NULL,则是utf8最后一个字节之后的下一个字节 +{ + grub_uint16_t *p = dest; + int count = 0; + grub_uint32_t code = 0; + + if (srcend) + *srcend = src; + + while (srcsize && destsize) + { + int was_count = count; + if (srcsize != (grub_size_t)-1) + srcsize--; + if (!grub_utf8_process (*src++, &code, &count)) + { + code = '?'; + count = 0; + /* Character c may be valid, don't eat it. */ + if (was_count) + src--; + } + if (count != 0) + continue; + if (code == 0) + break; + if (code >= GRUB_UCS2_LIMIT) + { + // 超出 UCS-2 范围 + *p++ = '?'; + destsize--; + } + else + { + *p++ = code; + destsize--; + } + } + + if (srcend) + *srcend = src; + return p - dest; +} +#endif +//-------------------------------------------------------------------------------------------- +// + +#define GRUB_LOADER_FLAG_NORETURN 1 +extern grub_err_t EXPORT_VAR(grub_errno); + +#define GRUB_PE32_SIGNATURE_SIZE 4 +#define GRUB_PE32_MSDOS_STUB_SIZE 0x80 +#define GRUB_PE32_PE32_MAGIC 0x10b +#define GRUB_PE32_PE64_MAGIC 0x20b +#define GRUB_PE32_MACHINE_I386 0x14c +#define GRUB_PE32_MACHINE_X86_64 0x8664 +#define GRUB_PE32_SCN_MEM_DISCARDABLE 0x02000000 +#define GRUB_PE32_SCN_CNT_UNINITIALIZED_DATA 0x00000080 +#define GRUB_PE32_REL_BASED_ABSOLUTE 0 +#define GRUB_PE32_REL_BASED_HIGH 1 +#define GRUB_PE32_REL_BASED_LOW 2 +#define GRUB_PE32_REL_BASED_HIGHLOW 3 +#define GRUB_PE32_REL_BASED_HIGHADJ 4 +#define GRUB_PE32_REL_BASED_MIPS_JMPADDR 5 +#define GRUB_PE32_REL_BASED_ARM_MOV32A 5 +#define GRUB_PE32_REL_BASED_RISCV_HI20 5 +#define GRUB_PE32_REL_BASED_SECTION 6 +#define GRUB_PE32_REL_BASED_REL 7 +#define GRUB_PE32_REL_BASED_ARM_MOV32T 7 +#define GRUB_PE32_REL_BASED_RISCV_LOW12I 7 +#define GRUB_PE32_REL_BASED_RISCV_LOW12S 8 +#define GRUB_PE32_REL_BASED_IA64_IMM64 9 +#define GRUB_PE32_REL_BASED_DIR64 10 +#define GRUB_PE32_REL_BASED_HIGH3ADJ 11 + +//grub/efi/pe32.h +struct grub_pe32_fixup_block +{ + grub_uint32_t page_rva; + grub_uint32_t block_size; + grub_uint16_t entries[0]; +}; + +struct grub_pe32_data_directory +{ + unsigned int rva; //RVA + unsigned int size; //尺寸 +}; + +struct grub_pe32_section_table //段表 +{ + char name[8]; //名称 msds + unsigned int virtual_size; //虚拟尺寸 047c00 + unsigned int virtual_address; //虚拟地址 019400 + unsigned int raw_data_size; //原始数据尺寸 047c00 + unsigned int raw_data_offset; //原始数据偏移 019400 + unsigned int relocations_offset; //重定位偏移 0 + unsigned int line_numbers_offset; //行数偏移 0 + unsigned short num_relocations; //重新定位数 0 + unsigned short num_line_numbers; //行数 0 + unsigned int characteristics; //特点 c0000040 +}; + +struct grub_pe64_optional_header +{ + unsigned short magic; //魔术 020b + unsigned char major_linker_version; //主连接器版本 0 + unsigned char minor_linker_version; //次连接器版本 0 + unsigned int code_size; //代码尺寸 a000 + unsigned int data_size; //数据尺寸 56c00 + unsigned int bss_size; //BSS尺寸 0 + unsigned int entry_addr; //入口地址 400 + unsigned int code_base; //代码基址 400 + + unsigned long long image_base; //映像基址 0 + + unsigned int section_alignment; //段对齐 200 + unsigned int file_alignment; //文件对齐 200 + unsigned short major_os_version; //主操作版本 0 + unsigned short minor_os_version; //次操作版本 0 + unsigned short major_image_version; //主映像版本 0 + unsigned short minor_image_version; //次映像版本 0 + unsigned short major_subsystem_version;//主子系统版本 0 + unsigned short minor_subsystem_version;//次子系统版本 0 + unsigned int reserved; //保留 0 + unsigned int image_size; //映像尺寸 061e00 + unsigned int header_size; //头部尺寸 400 + unsigned int checksum; //校验和 0 + unsigned short subsystem; //子系统 0a + unsigned short dll_characteristics; //DLL特征 0 + + unsigned long long stack_reserve_size; //栈保留尺寸 10000 + unsigned long long stack_commit_size; //栈提交尺寸 10000 + unsigned long long heap_reserve_size; //堆保留大小 10000 + unsigned long long heap_commit_size; //堆提交大小 10000 + + unsigned int loader_flags; //加载器标志 0 + unsigned int num_data_directories; //数据目录数 10 + + /* Data directories. */ + struct grub_pe32_data_directory export_table; //出口表 0,0 占8字节 + struct grub_pe32_data_directory import_table; //入口表 0,0 + struct grub_pe32_data_directory resource_table; //资源表 0,0 + struct grub_pe32_data_directory exception_table; //例外表 0,0 + struct grub_pe32_data_directory certificate_table; //证书表 0,0 + struct grub_pe32_data_directory base_relocation_table; //重定位表基址 61000,0e00 + struct grub_pe32_data_directory debug; //调试 0,0 + struct grub_pe32_data_directory architecture; //结构 0,0 + struct grub_pe32_data_directory global_ptr; //全局指针 0,0 + struct grub_pe32_data_directory tls_table; //TLS表 0,0 + struct grub_pe32_data_directory load_config_table; //加载配置表 0,0 + struct grub_pe32_data_directory bound_import; //绑定输入 0,0 + struct grub_pe32_data_directory iat; //iat 0,0 + struct grub_pe32_data_directory delay_import_descriptor;//延迟导入描述符0,0 + struct grub_pe32_data_directory com_runtime_header; //COM运行时报头 0,0 + struct grub_pe32_data_directory reserved_entry; //保留条目 0,0 +}; + +struct grub_pe32_coff_header //COFF文件头 +{ + unsigned short machine; //机器 8664 + unsigned short num_sections; //段数 0004 + unsigned int time; //时间 54a48e00 + unsigned int symtab_offset; //符号偏移 0 + unsigned int num_symbols; //符号数 0 + unsigned short optional_header_size; //可选标题大小 00f0 + unsigned short characteristics; //特点 020e +}; + +struct grub_pe32_optional_header //可选头部 +{ + unsigned short magic; //魔术 020b + unsigned char major_linker_version; //主连接器版本 0 + unsigned char minor_linker_version; //次连接器版本 0 + unsigned int code_size; //代码尺寸 a000 + unsigned int data_size; //数据尺寸 56c00 + unsigned int bss_size; //BSS尺寸 0 + unsigned int entry_addr; //入口地址 400 + unsigned int code_base; //代码基址 400 + + unsigned int data_base; //数据基址 0 + unsigned int image_base; //映像基址 0 + + unsigned int section_alignment; //段对齐 200 + unsigned int file_alignment; //文件对齐 200 + unsigned short major_os_version; //主操作版本 0 + unsigned short minor_os_version; //次操作版本 0 + unsigned short major_image_version; //主映像版本 0 + unsigned short minor_image_version; //次映像版本 0 + unsigned short major_subsystem_version; //主子系统版本 0 + unsigned short minor_subsystem_version; //次子系统版本 0 + unsigned int reserved; //保留 0 + unsigned int image_size; //映像尺寸 061e00 + unsigned int header_size; //头部尺寸 400 + unsigned int checksum; //校验和 0 + unsigned short subsystem; //子系统 0a + unsigned short dll_characteristics; //DLL特征 0 + + unsigned int stack_reserve_size; //栈保留尺寸 10000 + unsigned int stack_commit_size; //栈提交尺寸 0 ?? + unsigned int heap_reserve_size; //堆保留大小 10000 + unsigned int heap_commit_size; //堆提交尺寸 0 ?? + + unsigned int loader_flags; //加载器标志 10000 + unsigned int num_data_directories; //数据目录数 0 ?? + + /* Data directories. 数据目录 */ + struct grub_pe32_data_directory export_table; //出口表 + struct grub_pe32_data_directory import_table; //入口表 + struct grub_pe32_data_directory resource_table; //资源表 + struct grub_pe32_data_directory exception_table; //例外表 + struct grub_pe32_data_directory certificate_table; //证书表 + struct grub_pe32_data_directory base_relocation_table; //重定位表基址 + struct grub_pe32_data_directory debug; //调试 + struct grub_pe32_data_directory architecture; //结构 + struct grub_pe32_data_directory global_ptr; //全局指针 + struct grub_pe32_data_directory tls_table; //TLS表 + struct grub_pe32_data_directory load_config_table; //加载配置表 + struct grub_pe32_data_directory bound_import; //绑定输入 + struct grub_pe32_data_directory iat; //iat + struct grub_pe32_data_directory delay_import_descriptor;//延迟导入描述符 + struct grub_pe32_data_directory com_runtime_header; //COM运行时报头 + struct grub_pe32_data_directory reserved_entry; //保留条目 +}; + +struct grub_pe32_header //PE32 头 +{ + /* This should be filled in with GRUB_PE32_MSDOS_STUB. 这应该用GRUB_PE32_MSDOS_STUB */ + unsigned char msdos_stub[GRUB_PE32_MSDOS_STUB_SIZE]; //[80] 根尺寸 + + /* This is always PE\0\0. 这总是PE\0\0 */ + char signature[GRUB_PE32_SIGNATURE_SIZE]; //[4] 签名长度 + + /* The COFF file header. COFF文件头 */ + struct grub_pe32_coff_header coff_header; //COFF文件头 占0x14字节 + + /* The Optional header. */ + struct grub_pe64_optional_header optional_header; //可选头部 a0000000020b +}; + +struct grub_pe32_header_32 +{ + char signature[GRUB_PE32_SIGNATURE_SIZE]; + struct grub_pe32_coff_header coff_header; + struct grub_pe32_optional_header optional_header; +}; + +struct grub_pe32_header_64 +{ + char signature[GRUB_PE32_SIGNATURE_SIZE]; + struct grub_pe32_coff_header coff_header; + struct grub_pe64_optional_header optional_header; +}; + +typedef union //pe句柄 +{ + struct grub_pe32_header_32 pe32; + struct grub_pe32_header_64 pe32plus; +} grub_pe_header_t; + +struct pe_coff_loader_image_context //pe-coff加载程序图像上下文 +{ + grub_efi_uint64_t image_address; + grub_efi_uint64_t image_size; + grub_efi_uint64_t entry_point; + grub_efi_uintn_t size_of_headers; + grub_efi_uint16_t image_type; + grub_efi_uint16_t number_of_sections; + grub_efi_uint32_t section_alignment; + struct grub_pe32_section_table *first_section; + struct grub_pe32_data_directory *reloc_dir; + struct grub_pe32_data_directory *sec_dir; + grub_efi_uint64_t number_of_rva_and_sizes; + grub_pe_header_t *pe_hdr; +}; +typedef struct pe_coff_loader_image_context pe_coff_loader_image_context_t; + +/* The start point of the C code. */ +void grub_main (void) __attribute__ ((noreturn)); +extern unsigned int next_partition_drive; +extern unsigned int next_partition_dest; +extern unsigned int *next_partition_partition; +extern unsigned int *next_partition_type; +extern unsigned long long *next_partition_start; +extern unsigned long long *next_partition_len; +extern unsigned long long *next_partition_offset; +extern unsigned int *next_partition_entry; +extern unsigned int *next_partition_ext_offset; +extern char *next_partition_buf; +extern unsigned char partition_signature[16]; //分区签名 +extern unsigned char partition_activity_flag; //分区活动标志 +extern unsigned char *UNIFONT_START; +extern unsigned char *narrow_mem; +extern unsigned short *_gbk2utf16_2; +extern char *PAGING_TABLES_BUF; +extern unsigned char *PRINTF_BUFFER; +extern char *MENU_TITLE; +extern char *cmd_buffer; +extern char *FSYS_BUF; +extern char *CMDLINE_BUF; +extern char *COMPLETION_BUF; +extern char *UNIQUE_BUF; +extern char *HISTORY_BUF; +extern char *BUFFERADDR; +extern char *BASE_ADDR; +extern char *CMD_RUN_ON_EXIT; +extern char *SCRATCHADDR; +extern int return_value; +extern long long return_value64; +//extern int QUOTE_CHAR; +//extern char *GRUB_MOD_ADDR; +//extern char* mod_end; +extern char *CONFIG_ENTRIES; +extern unsigned char *IMAGE_BUFFER; +extern unsigned char *JPG_FILE; +extern char *menu_mem; + +extern int grub_efidisk_readwrite (int drive, grub_disk_addr_t sector, + grub_size_t size, char *buf, int read_write); + +extern char *grub_image; +extern char *g4e_data; +extern grub_efi_loaded_image_t *image; +extern grub_efi_device_path_t *efi_file_path; +extern grub_efi_handle_t efi_handle; +extern void grub_machine_fini (void); + +#define OBJ_TYPE_ELF 0x00 // 外部命令 +#define OBJ_TYPE_MEMDISK 0x01 // MOD文件 +#define OBJ_TYPE_CONFIG 0x02 // 配置菜单 +#define OBJ_TYPE_PREFIX 0x03 // 前缀路径 +#define OBJ_TYPE_FONT 0x04 // 字体 + +/* The module header. */ +struct grub_module_header +{ + /* The type of object. */ + grub_uint16_t type; + /* real_size = size - sizeof (struct grub_module_header) - pad_size */ + grub_uint16_t pad_size; + /* The size of object (including this header). */ + grub_uint32_t size; +} GRUB_PACKED; + +/* "gmim" (GRUB Module Info Magic). GRUB模块信息魔法 */ +#define GRUB_MODULE_MAGIC 0x676d696d + +struct grub_module_info32 +{ + /* Magic number so we know we have modules present. 神奇的数字,所以我们知道我们有模块存在 */ + grub_uint32_t magic; + /* The offset of the modules. 模的偏移量*/ + grub_uint32_t offset; + /* The size of all modules plus this header. 所有模块的大小加上这个标题 */ + grub_uint32_t size; +}; + +struct grub_module_info64 +{ + /* Magic number so we know we have modules present. 神奇的数字,所以我们知道我们有模块存在 */ + grub_uint32_t magic; + grub_uint32_t padding; + /* The offset of the modules. 模的偏移量*/ + grub_uint64_t offset; + /* The size of all modules plus this header. 所有模块的大小加上这个标题 */ + grub_uint64_t size; +}; + +//#if GRUB_TARGET_SIZEOF_VOID_P == 8 +#if !defined(__i386__) +#define grub_module_info grub_module_info64 +#else +#define grub_module_info grub_module_info32 +#endif + +extern grub_addr_t EXPORT_VAR (grub_modbase); + +#define FOR_MODULES(var) for (\ + var = (grub_modbase && ((((struct grub_module_info *) grub_modbase)->magic) == GRUB_MODULE_MAGIC)) ? (struct grub_module_header *) \ + (grub_modbase + (((struct grub_module_info *) grub_modbase)->offset)) : 0;\ + var && (grub_addr_t) var \ + < (grub_modbase + (((struct grub_module_info *) grub_modbase)->size)); \ + var = (struct grub_module_header *) \ + (((grub_uint32_t *) var) + ((((struct grub_module_header *) var)->size + sizeof (grub_addr_t) - 1) / sizeof (grub_addr_t)) * (sizeof (grub_addr_t) / sizeof (grub_uint32_t)))) + +//---------------------------------------------------------------------------------------------------------- +//macho.h +/* Multi-architecture header. Always in big-endian. */ + +#define GRUB_MACHO_CPUTYPE_IS_HOST32(x) ((x) == GRUB_MACHO_CPUTYPE_IA32) +#define GRUB_MACHO_CPUTYPE_IS_HOST64(x) ((x) == GRUB_MACHO_CPUTYPE_AMD64) +//#ifdef __x86_64__ +//#define GRUB_MACHO_CPUTYPE_IS_HOST_CURRENT(x) ((x) == GRUB_MACHO_CPUTYPE_AMD64) +//#else +#define GRUB_MACHO_CPUTYPE_IS_HOST_CURRENT(x) ((x) == GRUB_MACHO_CPUTYPE_IA32) +//#endif + +struct grub_macho_fat_header +{ + grub_uint32_t magic; + grub_uint32_t nfat_arch; +} GRUB_PACKED; + +enum + { + GRUB_MACHO_CPUTYPE_IA32 = 0x00000007, + GRUB_MACHO_CPUTYPE_AMD64 = 0x01000007 + }; + +#define GRUB_MACHO_FAT_MAGIC 0xcafebabe //大男子FAT魔法 +#define GRUB_MACHO_FAT_EFI_MAGIC 0x0ef1fab9U //大男子FAT_EFI魔法 + +typedef grub_uint32_t grub_macho_cpu_type_t; +typedef grub_uint32_t grub_macho_cpu_subtype_t; + +/* Architecture descriptor. Always in big-endian. */ +struct grub_macho_fat_arch +{ + grub_macho_cpu_type_t cputype; + grub_macho_cpu_subtype_t cpusubtype; + grub_uint32_t offset; + grub_uint32_t size; + grub_uint32_t align; +} GRUB_PACKED; + +/* File header for 32-bit. Always in native-endian. */ +struct grub_macho_header32 +{ +#define GRUB_MACHO_MAGIC32 0xfeedface + grub_uint32_t magic; + grub_macho_cpu_type_t cputype; + grub_macho_cpu_subtype_t cpusubtype; + grub_uint32_t filetype; + grub_uint32_t ncmds; + grub_uint32_t sizeofcmds; + grub_uint32_t flags; +} GRUB_PACKED; + +/* File header for 64-bit. Always in native-endian. */ +struct grub_macho_header64 +{ +#define GRUB_MACHO_MAGIC64 0xfeedfacf + grub_uint32_t magic; + grub_macho_cpu_type_t cputype; + grub_macho_cpu_subtype_t cpusubtype; + grub_uint32_t filetype; + grub_uint32_t ncmds; + grub_uint32_t sizeofcmds; + grub_uint32_t flags; + grub_uint32_t reserved; +} GRUB_PACKED; + +/* Common header of Mach-O commands. */ +struct grub_macho_cmd +{ + grub_uint32_t cmd; + grub_uint32_t cmdsize; +} GRUB_PACKED; + +typedef grub_uint32_t grub_macho_vmprot_t; + +/* 32-bit segment command. */ +struct grub_macho_segment32 +{ +#define GRUB_MACHO_CMD_SEGMENT32 1 + grub_uint32_t cmd; + grub_uint32_t cmdsize; + grub_uint8_t segname[16]; + grub_uint32_t vmaddr; + grub_uint32_t vmsize; + grub_uint32_t fileoff; + grub_uint32_t filesize; + grub_macho_vmprot_t maxprot; + grub_macho_vmprot_t initprot; + grub_uint32_t nsects; + grub_uint32_t flags; +} GRUB_PACKED; + +/* 64-bit segment command. */ +struct grub_macho_segment64 +{ +#define GRUB_MACHO_CMD_SEGMENT64 0x19 + grub_uint32_t cmd; + grub_uint32_t cmdsize; + grub_uint8_t segname[16]; + grub_uint64_t vmaddr; + grub_uint64_t vmsize; + grub_uint64_t fileoff; + grub_uint64_t filesize; + grub_macho_vmprot_t maxprot; + grub_macho_vmprot_t initprot; + grub_uint32_t nsects; + grub_uint32_t flags; +} GRUB_PACKED; + +#define GRUB_MACHO_CMD_THREAD 5 + +struct grub_macho_lzss_header +{ + char magic[8]; +#define GRUB_MACHO_LZSS_MAGIC "complzss" + grub_uint32_t unused; + grub_uint32_t uncompressed_size; + grub_uint32_t compressed_size; +}; + +/* Convenience union. What do we need to load to identify the file type. */ +union grub_macho_filestart +{ + struct grub_macho_fat_header fat; + struct grub_macho_header32 thin32; + struct grub_macho_header64 thin64; + struct grub_macho_lzss_header lzss; +} GRUB_PACKED; + +struct grub_macho_thread32 +{ + grub_uint32_t cmd; + grub_uint32_t cmdsize; + grub_uint8_t unknown1[48]; + grub_uint32_t entry_point; + grub_uint8_t unknown2[20]; +} GRUB_PACKED; + +struct grub_macho_thread64 +{ + grub_uint32_t cmd; + grub_uint32_t cmdsize; + grub_uint8_t unknown1[0x88]; + grub_uint64_t entry_point; + grub_uint8_t unknown2[0x20]; +} GRUB_PACKED; + +#define GRUB_MACHO_LZSS_OFFSET 0x180 + + +grub_size_t +grub_decompress_lzss (grub_uint8_t *dst, grub_uint8_t *dstend, + grub_uint8_t *src, grub_uint8_t *srcend); + +#define VDISK_MEDIA_ID 0x1 +#define DISK_TYPE_CD 0 +#define DISK_TYPE_HD 1 +#define DISK_TYPE_FD 2 + + +//struct grub_efi_block_io_media //块输入输出介质 +//{ My_Boot_ISO_xg.iso +// unsigned int media_id; //媒体标识 1 1f 1f 1 +// char removable_media; //可移动媒体 0 0 0 1 +// char media_present; //媒体目前 1 1 1 1 +// char logical_partition; //逻辑分区 0 0 0 0 +// char read_only; //只读 0 0 0 1 +// char write_caching; //写缓存 0 0 0 0 +// unsigned char pad[3]; //填充 +// unsigned int block_size; //块尺寸 200 200 200 800 +// unsigned int io_align; //IO对齐 4 4 0 0 +// unsigned char pad2[4]; //填充 +// unsigned long long last_block; //最后块 1fffff(1G) 3a38602f(465G) 1e45ff(968M) 11ad +//}; +//typedef struct grub_efi_block_io_media grub_efi_block_io_media_t; //0x20(按指定) + +typedef struct +{ + grub_efi_handle_t from_handle; + grub_efi_device_path_t *dp; + block_io_protocol_t block_io; + grub_efi_block_io_media_t media; +} grub_efivdisk_t; + +struct efidisk_data +{ + grub_efi_handle_t device_handle; + grub_efi_device_path_t *device_path; + grub_efi_device_path_t *last_device_path; + grub_efi_block_io_t *block_io; +// unsigned char partition_number; + unsigned long long partition_start; + unsigned long long partition_size; +// unsigned char partition_signature[16]; + struct efidisk_data *next; +}; + +struct grub_disk_data //efi磁盘数据 (软盘,硬盘,光盘) 注意外部命令兼容性 +{ + grub_efi_handle_t device_handle; //句柄 11cba410 hndl +// grub_efi_device_path_t *device_path; //设备路径 11cba890 类型,子类型,长度 +// grub_efi_device_path_t *last_device_path; //最后设备路径 11cba8a2 类型,子类型,长度 + grub_efi_block_io_t *block_io; //块输入输出 1280d318 修订,媒体,重置,读块,写块,清除块 + struct grub_disk_data *next; //下一个 + unsigned char drive; //from驱动器 f0 + unsigned char to_drive; //to驱动器 原生磁盘为0 + unsigned char from_log2_sector; //from每扇区字节2的幂 0b + unsigned char to_log2_sector; //to每扇区字节2的幂 原生磁盘为0 + unsigned long long start_sector; //起始扇区 原生磁盘为0 from在to的起始扇区 每扇区字节=(1 << to_log2_sector) + unsigned long long sector_count; //扇区计数 原生磁盘为0 from在to的扇区数 每扇区字节=(1 << to_log2_sector) + unsigned long long total_sectors; //总扇区数 from驱动器的总扇区数 每扇区字节=(1 << from_log2_sector) + unsigned char disk_signature[16]; //磁盘签名 软盘/光盘或略 启动wim/vhd需要 mbr类型同分区签名,gpt类型则异样 原生磁盘为0 + unsigned short to_block_size; //to块尺寸 原生磁盘为0 + unsigned char partmap_type; //硬盘分区类型 1/2=MBR/GPT + unsigned char fragment; //碎片 + unsigned char read_only; //只读 + unsigned char disk_type; //磁盘类型 0/1/2=光盘/硬盘/软盘 + unsigned char vhd_disk; //vhd磁盘 位0-1,仿真类型:1=不加载到内存 2=加载到内存 + unsigned char fill; //填充 + grub_efivdisk_t *vdisk; //虚拟磁盘指针 +} __attribute__ ((packed)); + +struct grub_part_data //efi分区数据 (硬盘) 注意外部命令兼容性 +{ + struct grub_part_data *next; //下一个 + unsigned char drive; //驱动器 + unsigned char partition_type; //MBR分区ID EE是gpt分区类型 光盘: + unsigned char partition_activity_flag; //MBR分区活动标志 80活动 光盘: 启动镜像驱动器号 + unsigned char partition_entry; //分区入口 光盘: 启动目录确认入口 + unsigned int partition_ext_offset; //扩展分区偏移 光盘: 启动目录扇区地址 + unsigned int partition; //当前分区 光盘: ffff + unsigned long long partition_offset; //分区偏移 + unsigned long long partition_start; //分区起始扇区 光盘: 引导镜像是硬盘时,分区起始扇区 + unsigned long long partition_size; //分区扇区尺寸 光盘: 引导镜像是硬盘时,分区扇区尺寸 + unsigned char partition_signature[16]; //分区签名 光盘: + unsigned int boot_start; // 光盘: 引导镜像在光盘的起始扇区(1扇区=2048字节) + unsigned int boot_size; // 光盘: 引导镜像的扇区数(1扇区=512字节) + grub_efi_handle_t part_handle; //句柄 + unsigned char boot_entry; // 光盘: 入口号 + unsigned char partition_boot; //启动分区 /efi/boot/bootx64.efi文件所在分区 +} __attribute__ ((packed)); + +extern struct grub_part_data *get_partition_info (int drive, int partition); +extern struct grub_part_data *partition_info; +extern struct grub_disk_data *previous_struct; +extern struct grub_part_data *get_boot_partition (int drive); +extern void renew_part_data (void); +extern grub_efi_handle_t pd_handle; +extern grub_efi_device_path_t *pd_dp; + +struct drive_map_slot +{ + /* Remember to update DRIVE_MAP_SLOT_SIZE once this is modified. + * The struct size must be a multiple of 4. + */ + unsigned char from_drive; + unsigned char to_drive; /* 0xFF indicates a memdrive */ + unsigned char max_head; + + unsigned char :7; + unsigned char read_only:1; //位7 + + unsigned short to_log2_sector:4; //位0-3 + unsigned short from_log2_sector:4; //位4-7 + unsigned short :2; + unsigned short fragment:1; //位10 + unsigned short :2; + unsigned short from_cdrom:1; //位13 + unsigned short to_cdrom:1; //位14 + unsigned short :1; + + unsigned char to_head; + unsigned char to_sector; + unsigned long long start_sector; + unsigned long long sector_count; +} __attribute__ ((packed)); + +struct fragment_map_slot +{ + unsigned short slot_len; + unsigned char from; + unsigned char to; + unsigned long long fragment_data[0]; +} __attribute__ ((packed)); + +struct fragment +{ + unsigned long long start_sector; + unsigned long long sector_count; +}; + +//extern struct drive_map_slot vpart_drive_map[DRIVE_MAP_SIZE + 1]; +//extern struct drive_map_slot disk_drive_map[DRIVE_MAP_SIZE + 1]; +//extern struct fragment_map_slot disk_fragment_map; +extern struct fragment_map_slot *disk_fragment_map; +//extern char disk_buffer[0x1000]; +extern char *disk_buffer; +//extern int drive_map_slot_empty (struct drive_map_slot item); +extern struct fragment_map_slot *fragment_map_slot_find(struct fragment_map_slot *q, unsigned int from); +extern int grub_SectorSequence_readwrite (int drive, struct fragment *data, unsigned char from_log2_sector, unsigned char to_log2_sector, + grub_disk_addr_t sector, grub_size_t size, char *buf, unsigned long long lba_byte, int read_write); + + +#define CDVOL_TYPE_STANDARD 0x0 +#define CDVOL_TYPE_CODED 0x1 +#define CDVOL_TYPE_END 0xFF + +#define CDVOL_ID "CD001" +#define CDVOL_ELTORITO_ID "EL TORITO SPECIFICATION" + +// ELTORITO_CATALOG.Boot.MediaTypes +#define ELTORITO_NO_EMULATION 0x00 +#define ELTORITO_12_DISKETTE 0x01 +#define ELTORITO_14_DISKETTE 0x02 +#define ELTORITO_28_DISKETTE 0x03 +#define ELTORITO_HARD_DISK 0x04 + +//Indicator types +#define ELTORITO_ID_CATALOG 0x01 +#define ELTORITO_ID_SECTION_BOOTABLE 0x88 +#define ELTORITO_ID_SECTION_NOT_BOOTABLE 0x00 +#define ELTORITO_ID_SECTION_HEADER 0x90 +#define ELTORITO_ID_SECTION_HEADER_FINAL 0x91 + +typedef union +{ + struct + { + grub_uint8_t type; + grub_uint8_t id[5]; ///< "CD001" + grub_uint8_t reserved[82]; + } unknown; + struct + { + grub_uint8_t type; ///< Must be 0 + grub_uint8_t id[5]; ///< "CD001" + grub_uint8_t version; ///< Must be 1 + grub_uint8_t system_id[32]; ///< "EL TORITO SPECIFICATION" + grub_uint8_t unused[32]; ///< Must be 0 + grub_uint8_t elt_catalog[4];///< Absolute pointer to first sector of Boot Catalog + grub_uint8_t unused2[13]; ///< Must be 0 + } boot_record_volume; + struct + { + grub_uint8_t type; + grub_uint8_t id[5]; ///< "CD001" + grub_uint8_t version; + grub_uint8_t unused; ///< Must be 0 + grub_uint8_t system_id[32]; + grub_uint8_t volume_id[32]; + grub_uint8_t unused2[8]; ///< Must be 0 + grub_uint32_t vol_space_size[2]; ///< the number of Logical Blocks + } primary_volume; +} cdrom_volume_descriptor_t; + +typedef union +{ + struct + { + grub_uint8_t reserved[0x30]; + } unknown; + /// Catalog validation entry (Catalog header) + struct + { + grub_uint8_t indicator; ///< Must be 01 + grub_uint8_t platform_id; + grub_uint16_t reserved; + grub_uint8_t manufac_id[24]; + grub_uint16_t checksum; + grub_uint16_t id55AA; + grub_uint8_t reserved1[0x10]; + } catalog; + /// Initial/Default Entry or Section Entry + struct + { + grub_uint8_t reserved[0x20]; + grub_uint8_t indicator; ///< 88 = Bootable, 00 = Not Bootable + grub_uint8_t media_type : 4; //取4位,即半字节 + grub_uint8_t reserved1 : 4; ///< Must be 0 + grub_uint16_t load_segment; + grub_uint8_t system_type; + grub_uint8_t reserved2; ///< Must be 0 + grub_uint16_t sector_count; + grub_uint32_t lba; + } boot; + /// Section Header Entry + struct + { + grub_uint8_t indicator; ///< 90 - Header, more header follw, 91 - Final Header + grub_uint8_t platform_id; + grub_uint16_t section_entries;///< Number of section entries following this header + grub_uint8_t id[28]; + grub_uint8_t reserved[0x10]; + } section; +} eltorito_catalog1_t; //0x20 + + +struct boot +{ + grub_uint8_t indicator1; //入口号: 必须从1开始,0x91结束 + grub_uint8_t platform_id; //平台类型: 0=Intel平台; 1=Power PC; 2=Mac; 0xEF=UEFI。 + grub_uint16_t section_entries; //分区入口 + grub_uint8_t manufac_id[24]; + grub_uint16_t checksum; + grub_uint16_t id55AA; + grub_uint8_t indicator88; //标志信息: 88=可引导,00=不可引导 + grub_uint8_t media_type : 4; //取4位,即半字节 + grub_uint8_t reserved1 : 4; //必须为0 + grub_uint16_t load_segment; + grub_uint8_t system_type; + grub_uint8_t reserved2; //必须为0 + grub_uint16_t sector_count; + grub_uint32_t lba; + grub_uint8_t reserved[0x14]; +} GRUB_PACKED; //0x40 +typedef struct boot eltorito_catalog0_t; + + +struct grub_packed_guid +{ + grub_uint32_t data1; + grub_uint16_t data2; + grub_uint16_t data3; + grub_uint8_t data4[8]; +} GRUB_PACKED; +typedef struct grub_packed_guid grub_packed_guid_t; + +extern grub_packed_guid_t VDISK_GUID; +extern grub_efi_uint32_t cd_boot_entry; +extern grub_efi_uint32_t cd_boot_start; +extern grub_efi_uint32_t cd_boot_size; +extern grub_efi_uint32_t cd_Image_part_start; +extern grub_efi_uint32_t cd_Image_disk_size; +extern grub_efi_uint32_t cd_map_count; +extern grub_efi_uint64_t part_addr; +extern grub_efi_uint64_t part_size; +extern struct grub_part_data *part_data; +void file_read (grub_efi_boolean_t disk, void *file, + void *buf, grub_efi_uintn_t len, grub_efi_uint64_t offset); +grub_efi_uint64_t get_size (grub_efi_boolean_t disk, void *file); + +/* vboot */ +extern grub_efi_handle_t grub_load_image (grub_efi_device_path_t *path, const char *filename, void *boot_image); +//extern grub_efi_handle_t grub_load_image (unsigned int drive, const char *filename, void *boot_image, unsigned long long file_len, grub_efi_handle_t *devhandle); +/* vdisk */ +extern grub_efi_status_t vdisk_install (int drive, int partition); +/* vpart */ +extern grub_efi_status_t vpart_install (int drive, struct grub_part_data *part); +//extern int uuid_increment; + +struct grub_efi_component_name2_protocol +{ + grub_efi_status_t (*get_driver_name) + (struct grub_efi_component_name2_protocol *this, + grub_efi_char8_t *language, + grub_efi_char16_t **driver_name); + grub_efi_status_t (*get_controller_name) + (struct grub_efi_component_name2_protocol *this, + grub_efi_handle_t controller_handle, + grub_efi_handle_t child_handle, + grub_efi_char8_t *language, + grub_efi_char16_t **controller_name); + grub_efi_char8_t *supported_languages; +}; +typedef struct grub_efi_component_name2_protocol grub_efi_component_name2_protocol_t; + +#define GRUB_EFI_FILE_PROTOCOL_REVISION 0x00010000 +#define GRUB_EFI_FILE_PROTOCOL_REVISION2 0x00020000 +#define GRUB_EFI_FILE_PROTOCOL_LATEST_REVISION GRUB_EFI_FILE_PROTOCOL_REVISION2 + +#define GRUB_EFI_FILE_REVISION GRUB_EFI_FILE_PROTOCOL_REVISION + +typedef struct +{ + grub_efi_event_t event; + grub_efi_status_t status; + grub_efi_uintn_t buffer_size; + void *buffer; +} grub_efi_file_io_token_t; + +// Open modes +#define GRUB_EFI_FILE_MODE_READ 0x0000000000000001ULL +#define GRUB_EFI_FILE_MODE_WRITE 0x0000000000000002ULL +#define GRUB_EFI_FILE_MODE_CREATE 0x8000000000000000ULL + +// File attributes +#define GRUB_EFI_FILE_READ_ONLY 0x0000000000000001ULL +#define GRUB_EFI_FILE_HIDDEN 0x0000000000000002ULL +#define GRUB_EFI_FILE_SYSTEM 0x0000000000000004ULL +#define GRUB_EFI_FILE_RESERVED 0x0000000000000008ULL +#define GRUB_EFI_FILE_DIRECTORY 0x0000000000000010ULL +#define GRUB_EFI_FILE_ARCHIVE 0x0000000000000020ULL +#define GRUB_EFI_FILE_VALID_ATTR 0x0000000000000037ULL + +struct grub_efi_file_protocol +{ + grub_efi_uint64_t revision; + grub_efi_status_t (*file_open) (struct grub_efi_file_protocol *this, + struct grub_efi_file_protocol **new_handle, + grub_efi_char16_t *file_name, + grub_efi_uint64_t open_mode, + grub_efi_uint64_t attributes); + grub_efi_status_t (*file_close) (struct grub_efi_file_protocol *this); + grub_efi_status_t (*file_delete) (struct grub_efi_file_protocol *this); + grub_efi_status_t (*file_read) (struct grub_efi_file_protocol *this, + grub_efi_uintn_t *buffer_size, + void *buffer); + grub_efi_status_t (*file_write) (struct grub_efi_file_protocol *this, + grub_efi_uintn_t *buffer_size, + void *buffer); + grub_efi_status_t (*get_pos) (struct grub_efi_file_protocol *this, + grub_efi_uint64_t *pos); + grub_efi_status_t (*set_pos) (struct grub_efi_file_protocol *this, + grub_efi_uint64_t pos); + grub_efi_status_t (*get_info) (struct grub_efi_file_protocol *this, + grub_efi_guid_t *information_type, + grub_efi_uintn_t *buffer_size, + void *buffer); + grub_efi_status_t (*set_info) (struct grub_efi_file_protocol *this, + grub_efi_guid_t *information_type, + grub_efi_uintn_t buffer_size, + void *buffer); + grub_efi_status_t (*flush) (struct grub_efi_file_protocol *this); + grub_efi_status_t (*open_ex) (struct grub_efi_file_protocol *this, + struct grub_efi_file_protocol **new_handle, + grub_efi_char16_t *file_name, + grub_efi_uint64_t open_mode, + grub_efi_uint64_t attributes, + grub_efi_file_io_token_t *token); + grub_efi_status_t (*read_ex) (struct grub_efi_file_protocol *this, + grub_efi_file_io_token_t *token); + grub_efi_status_t (*write_ex) (struct grub_efi_file_protocol *this, + grub_efi_file_io_token_t *token); + grub_efi_status_t (*flush_ex) (struct grub_efi_file_protocol *this, + grub_efi_file_io_token_t *token); +}; +typedef struct grub_efi_file_protocol grub_efi_file_protocol_t; +typedef grub_efi_file_protocol_t *grub_efi_file_handle_t; +typedef grub_efi_file_protocol_t grub_efi_file_t; + +#define GRUB_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION 0x00010000 +#define GRUB_EFI_FILE_IO_REVISION GRUB_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION +#define EFI_REMOVABLE_MEDIA_FILE_NAME_IA32 "/EFI/BOOT/BOOTIA32.EFI" +#define EFI_REMOVABLE_MEDIA_FILE_NAME_X64 "/EFI/BOOT/BOOTX64.EFI" +#define EFI_REMOVABLE_MEDIA_FILE_NAME_ARM "/EFI/BOOT/BOOTARM.EFI" +#define EFI_REMOVABLE_MEDIA_FILE_NAME_AARCH64 "/EFI/BOOT/BOOTAA64.EFI" + +#if defined(__i386__) + #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_IA32 +#else + #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_X64 +//#elif defined (__arm__) +// #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_ARM +//#elif defined (__aarch64__) +// #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_AARCH64 +//#else +// #error Unknown Processor Type +#endif + +struct grub_efi_simple_fs_protocol +{ + grub_efi_uint64_t revision; + grub_efi_status_t (*open_volume) (struct grub_efi_simple_fs_protocol *this, + grub_efi_file_protocol_t **root); +}; +typedef struct grub_efi_simple_fs_protocol grub_efi_simple_fs_protocol_t; + +#define GRUB_EFI_FILE_INFO_GUID \ + { 0x09576e92, 0x6d3f, 0x11d2, \ + { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +#define GRUB_EFI_FILE_SYSTEM_INFO_GUID \ + { 0x09576e93, 0x6d3f, 0x11d2, \ + { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +#define GRUB_EFI_FILE_SYSTEM_VOLUME_LABEL_GUID \ + { 0xdb47d7d3, 0xfe81, 0x11d3, \ + { 0x9a, 0x35, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +#define GRUB_GPT_HEADER_MAGIC \ + { 0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54 } + +#define GRUB_GPT_HEADER_VERSION \ + grub_cpu_to_le32_compile_time (0x00010000U) + +#define GRUB_GPT_PARTITION_TYPE_EFI_SYSTEM \ + { 0xc12a7328, 0xf81f, 0x11d2, { 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } } + +typedef struct grub_efi_file_info +{ + /* size of file_info structure */ + grub_efi_uint64_t size; + grub_efi_uint64_t file_size; + grub_efi_uint64_t physical_size; + grub_efi_time_t create_time; + grub_efi_time_t last_access_time; + grub_efi_time_t modification_time; + grub_efi_uint64_t attribute; + grub_efi_char16_t file_name[1]; +} grub_efi_file_info_t; + +typedef struct grub_efi_file_system_info +{ + grub_efi_uint64_t size; + grub_efi_boolean_t read_only; + grub_efi_uint64_t volume_size; + grub_efi_uint64_t free_space; + grub_efi_uint32_t block_size; + grub_efi_char16_t volume_label[1]; +} grub_efi_fs_info_t; + +typedef struct grub_efi_file_system_volume_label +{ + grub_efi_char16_t volume_label[1]; +} grub_efi_fs_label_t; + +typedef __WCHAR_TYPE__ wchar_t; +/* 宽字符,gcc在linux下,使用4个字节存储一个字符。 + * 比如 wchar_t p[] = L"1122",它存储为:31 00 00 00 31 00 00 00 32 00 00 00 32 00 00 00 + * 而普通字符,使用1个字节存储一个字符。 + * 比如 char p2[] = "1122",它存储为:31 31 32 32 + */ + +extern void grub_efidisk_fini (void); +extern void grub_efidisk_init (void); +extern void enumerate_disks (void); +extern grub_efi_device_path_protocol_t* + grub_efi_create_device_node (grub_efi_uint8_t node_type, grub_efi_uintn_t node_subtype,grub_efi_uint16_t node_length); +extern grub_efi_device_path_protocol_t* + grub_efi_append_device_node (const grub_efi_device_path_protocol_t *device_path, + const grub_efi_device_path_protocol_t *device_node); +extern int grub_efi_is_child_dp (const grub_efi_device_path_t *child, + const grub_efi_device_path_t *parent); +extern grub_efi_boolean_t guidcmp (const grub_packed_guid_t *g1, const grub_packed_guid_t *g2); +extern grub_packed_guid_t * guidcpy (grub_packed_guid_t *dst, const grub_packed_guid_t *src); + +extern char * grub_strchr (const char *s, int c); +extern char * grub_strrchr (const char *s, int c); +extern int gopprobe (char *arg, int flags); + +////////////////////////////////////////////////////////////////////////////////// +/* Based on UEFI specification. 基于UEFI规范 */ +/* +GOP (图形输出协议) +GOP (Graphic Output Protocol),是用来将图形驱动程序延伸至UEFI固件的接口,借以取代传统VBIOS(视讯BIOS)在开机资源要求等初始化行为。 +GOP: 无 64 KB 的限制。32 位元保护模式。不需要 CSM。速度最佳化 (快速开机支持)。 +*/ + +#define GRUB_EFI_GOP_GUID \ + { 0x9042a9de, 0x23dc, 0x4a38, { 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a }} + +typedef enum + { +//像素是32位,字节0代表红色,字节1代表绿色,字节2代表蓝色,字节3保留。这是物理帧缓冲区的定义。红色、绿色和蓝色组件的字节值表示颜色强度。此颜色强度值的范围从最小强度0到最大强度255。 + GRUB_EFI_GOT_RGBA8, //红绿兰A 8位 +//像素是32位,字节0代表蓝色,字节1代表绿色,字节2代表红色,字节3保留。这是物理帧缓冲区的定义。红色、绿色和蓝色组件的字节值表示颜色强度。此颜色强度值的范围从最小强度0到最大强度255。 + GRUB_EFI_GOT_BGRA8, //兰绿红A 8位 通常使用 最低位兰,最高位A +//物理帧缓冲区的像素定义由EFI像素位掩码定义。 + GRUB_EFI_GOT_BITMASK, //位掩模 +//此模式不支持物理帧缓冲区。 + PixelBltOnly, +//有效的EFI图形像素格式枚举值小于此值。 + PixelFormatMax + } + grub_efi_gop_pixel_format_t; //gop像素格式 + +//EFI_GRAPHICS_OUTPUT_BLT_PIXEL +struct grub_efi_gop_blt_pixel //gop_blt像素 +{ + grub_uint8_t blue; //兰 + grub_uint8_t green; //绿 + grub_uint8_t red; //红 + grub_uint8_t reserved; //保留 +}; + +//如果在RedMask、GreenMask或BlueMask中设置了一个位,那么这些像素位表示相应的颜色。 +//RedMask、GreenMask、BlueMask和ReserverdMask中的位不能超过圈位位置。位掩码中红色、绿色和蓝色组件的值表示颜色强度。 +//颜色强度必须随着每个颜色遮罩的颜色值的增加而增加,颜色遮罩中所有位的最小强度清除为颜色遮罩集中所有位的最大强度。 +//EFI_PIXEL_BITMASK +struct grub_efi_gop_pixel_bitmask //gop像素位掩模 +{ + grub_uint32_t r; //红 + grub_uint32_t g; //绿 + grub_uint32_t b; //兰 + grub_uint32_t a; //保留 +}; + +//EFI_GRAPHICS_OUTPUT_MODE_INFORMATION +struct grub_efi_gop_mode_info //gop模式信息 +{ + grub_efi_uint32_t version; //版本 值为零表示本规范中定义的EFI图形输出模式信息结构。本规范的未来版本可能会以向后兼容的方式扩展此数据结构,并增加版本的值。 + grub_efi_uint32_t width; //宽 视频屏幕的大小,以X维像素为单位。 + grub_efi_uint32_t height; //高 视频屏幕的大小(以Y维像素为单位)。 + grub_efi_gop_pixel_format_t pixel_format; //像素格式 定义像素物理格式的枚举。PixelBltOnly意味着线性帧缓冲区不可用于此模式。 + struct grub_efi_gop_pixel_bitmask pixel_bitmask; //像素位掩模 此位掩码仅在PixelFormat设置为PixelPixelBitMask时有效。正在设置的位定义了用于什么目的的位,如红色、绿色、蓝色或保留位。 + grub_efi_uint32_t pixels_per_scanline; //每扫描行像素数 定义每个视频内存行的像素元素数。出于性能原因,或者由于硬件限制,扫描线可能会被填充到一定的内存对齐量。 + //这些填充像素元素位于水平分辨率覆盖的区域之外,不可见。对于直接帧缓冲区访问,此数字用作视频内存中像素线开始之间的间隔.基于单个像素元素和像素扫描线的大小, + //视频内存中从像素元素(x,y)到像素元素(x,y+1)的偏移量必须计算为“sizeof(pixellement)*PixelsPerScanLine”, + //不是“sizeof(pixellement)*HorizontalResolution”,尽管在许多情况下这些值可以重合。 + //此值取决于视频硬件和模式分辨率。GOP实现负责为该字段提供准确的值。 +}; + +//是只读的,只有使用适当的接口函数才能更改值: +struct grub_efi_gop_mode //gop模式 +{ + grub_efi_uint32_t max_mode; //最大模式 QueryMode()和SetMode()支持的模式数。 + grub_efi_uint32_t mode; //模式 图形设备的当前模式。有效的模式编号是0到MaxMode-1。 + struct grub_efi_gop_mode_info *info; //模式信息 指向只读EFI_GRAPHICS_OUTPUT_MODE_INFORMATION数据的指针。 + grub_efi_uintn_t info_size; //信息尺寸 信息结构的大小(字节)。本规范的未来版本可能会增加EFI_GRAPHICS_OUTPUT_MODE_INFORMATION 数据的大小。 + grub_efi_physical_address_t fb_base; //物理地址 图形线性帧缓冲区的基址。信息包含允许软件不使用Blt()直接绘制到帧缓冲区所需的信息。FrameBufferBase中的偏移量0表示显示的左上角像素。 + grub_efi_uintn_t fb_size; //缓存尺寸 支持由PixelsPerScanLine x VerticalResolution x PixelElementSize定义的活动模式所需的帧缓冲区量。 +}; + +/* Forward declaration. 前向声明*/ +struct grub_efi_gop; + +typedef grub_efi_status_t +(*grub_efi_gop_query_mode_t) (struct grub_efi_gop *this, + grub_efi_uint32_t mode_number, + grub_efi_uintn_t *size_of_info, + struct grub_efi_gop_mode_info **info); //gop查询模式(本身,模式号,返回信息尺寸,返回信息) + +typedef grub_efi_status_t +(*grub_efi_gop_set_mode_t) (struct grub_efi_gop *this, + grub_efi_uint32_t mode_number); //gop设置模式(本身,模式号) + +//说明: 函数的作用是:将BltBuffer矩形绘制到视频屏幕上。 +//BltBuffer表示将使用BltOperation指定的操作在图形屏幕上绘制的高宽像素矩形。Delta值可用于在BltBuffer的子矩形上执行BltOperation。 +typedef grub_efi_status_t +(*grub_efi_gop_blt_t) (struct grub_efi_gop *this, //本身 + void *buffer, //缓存 要传输到图形屏幕的数据。尺寸至少为Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL). + grub_efi_uintn_t operation, //操作 将BltBuffer复制到图形屏幕时要执行的操作。 + grub_efi_uintn_t sx, //源x 用于BltOperation的源的X坐标。屏幕的原点是0,0,这是屏幕的左上角。 + grub_efi_uintn_t sy, //源y 用于BltOperation的源的Y坐标。屏幕的原点是0,0,这是屏幕的左上角。 + grub_efi_uintn_t dx, //目的x BltOperation目标的X坐标。屏幕的原点是0,0,这是屏幕的左上角。 + grub_efi_uintn_t dy, //目的y BltOperation目标的Y坐标。屏幕的原点是0,0,这是屏幕的左上角。 + grub_efi_uintn_t width, //宽 blt矩形中矩形的宽度(像素)。每个像素由EFI_GRAPHICS_OUTPUT_BLT_PIXEL元素表示。 + grub_efi_uintn_t height, //高 blt矩形中矩形的高度(像素)。 + grub_efi_uintn_t delta); //增量 不用于EfiBltVideoFill或EfiBltVideoToVideo操作。如果使用0的增量,则整个BltBuffer正在运行。 + //如果正在使用BltBuffer的子矩形,则Delta表示BltBuffer行中的字节数。 + +//表113描述了矩形上支持的bltoperation。矩形有坐标(左,上)(右,下): +typedef enum + { +//将数据从BltBuffer像素(0,0)直接写入视频显示矩形(DestinationX,DestinationY)(DestinationX+宽度,DestinationY+高度)。只有一个像素将使用从BltBuffer。不使用增量。 + GRUB_EFI_BLT_VIDEO_FILL, //BLT视频填充 +//从视频显示矩形(SourceX,SourceY)(SourceX+Width,SourceY+Height)读取数据,并将其放置在BltBuffer矩形(DestinationX,DestinationY)(DestinationX+Width,DestinationY+Height)中。 +//如果DestinationX或DestinationY不为零,则Delta必须设置为BltBuffer中一行的长度(字节)。 + GRUB_EFI_BLT_VIDEO_TO_BLT_BUFFER, //BLT视频到BLT缓冲区 +//将数据从BltBuffer矩形(SourceX,SourceY)(SourceX+Width,SourceY+Height)直接写入视频显示矩形(DestinationX,DestinationY)(DestinationX+Width,DestinationY+Height)。 +//如果SourceX或SourceY不为零,则Delta必须设置为BltBuffer中一行的长度(以字节为单位)。 + GRUB_EFI_BLT_BUFFER_TO_VIDEO, //BLT缓冲区到视频 +//从视频显示矩形(SourceX,SourceY)(SourceX+Width,SourceY+Height)复制到视频显示矩形(DestinationX,DestinationY)(DestinationX+Width,DestinationY+Height)。 +//此模式中不使用BltBuffer和Delta。源矩形和目标矩形的重叠没有限制。 + GRUB_EFI_BLT_VIDEO_TO_VIDEO, //BLT视频到视频 + GRUB_EFI_BLT_OPERATION_MAX //BLT最大操作 + } + grub_efi_gop_blt_operation_t; //gop blt操作 + +//EFI_GRAPHICS_OUTPUT_PROTOCOL +struct grub_efi_gop +{ + grub_efi_gop_query_mode_t query_mode; //gop查询模式 返回图形设备和一组活动视频输出设备支持的可用图形模式的信息 + grub_efi_gop_set_mode_t set_mode; //gop设置模式 将视频设备设置为指定模式,并将输出显示的可见部分清除为黑色。 +//UEFI标准中的Blt 函数不仅可以将内容传送至帧缓冲区(EfiBltBufferToVideo),还可以保存帧缓冲区中的内容(EfiBltVideoToBltBuffer), +//或是将帧缓冲区中一个位置的内容移动至另一位置(EfiBltVideoToVideo)。 + grub_efi_gop_blt_t blt; //gop_blt 基于视频设备帧缓冲区的软件抽象 + struct grub_efi_gop_mode *mode; //gop模式 指向EFI图形输出协议模式数据的指针。 +}; + +//说明 +//EFI_GRAPHICS_OUTPUT_协议提供了一个软件抽象,允许将像素直接绘制到帧缓冲区。EFI_-GRAPHICS_-OUTPUT_协议设计为轻量级,支持在操作系统引导之前进行图形输出的基本需求。 + + + +/* +注意: 以下代码示例是预期字段用法的示例: +INTN +GetPixelElementSize (IN EFI_PIXEL_BITMASK *PixelBits) //获得像素元素尺寸(像素位掩模) +{ + INTN HighestPixel = -1; //最高像素 + INTN BluePixel; //兰像素 + INTN RedPixel; //红像素 + INTN GreenPixel; //绿像素 + INTN RsvdPixel; //保留像素 + BluePixel = FindHighestSetBit (PixelBits->BlueMask); //查找最高点设置位(像素位掩模->兰掩模) ff + RedPixel = FindHighestSetBit (PixelBits->RedMask); //ff0000 + GreenPixel = FindHighestSetBit (PixelBits->GreenMask); //ff00 + RsvdPixel = FindHighestSetBit (PixelBits->ReservedMask);//0 + HighestPixel = max (BluePixel, RedPixel); //ff0000 + HighestPixel = max (HighestPixel, GreenPixel); //ff0000 + HighestPixel = max (HighestPixel, RsvdPixel); //ff0000 + return HighestPixel; +} +EFI_PHYSICAL_ADDRESS NewPixelAddress; 物理地址 新像素地址 +EFI_PHYSICAL_ADDRESS CurrentPixelAddress; 物理地址 当前像素地址 +EFI_GRAPHICS_OUTPUT_MODE_INFORMATION OutputInfo; 图形输出模式信息 输出信息 +INTN PixelElementSize; +switch (OutputInfo.PixelFormat) //输出信息.像素格式 +{ + case PixelBitMask: //位掩模 + PixelElementSize = GetPixelElementSize (&OutputInfo.PixelInformation); //输出信息.像素格式 + break; + case PixelBlueGreenRedReserved8BitPerColor: //兰绿红A + case PixelRedGreenBlueReserved8BitPerColor: //红绿兰A + PixelElementSize = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); + break; +} +// +// NewPixelAddress after execution points to the pixel 执行后的新像素地址指向当前像素地址所指像素下一行的像素 +// positioned one line below the one pointed by +// CurrentPixelAddress +// +NewPixelAddress = CurrentPixelAddress + (PixelElementSize * OutputInfo.PixelsPerScanLine); +注释结束代码示例。 +*/ +//////////////////////////////////////////////////////////////////////////////// +typedef enum grub_net_card_flags + { + GRUB_NET_CARD_HWADDRESS_IMMUTABLE = 1, + GRUB_NET_CARD_NO_MANUAL_INTERFACES = 2 + } grub_net_card_flags_t; + +typedef enum grub_link_level_protocol_id +{ + GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET //NET链接级别协议以太网 +} grub_link_level_protocol_id_t; + +typedef struct grub_net_link_level_address +{ + grub_link_level_protocol_id_t type; //类型 + union + { + unsigned char mac[6]; //mac + }; +} grub_net_link_level_address_t; //网络链路级地址 + + +struct grub_net_slaac_mac_list +{ + struct grub_net_slaac_mac_list *next; + struct grub_net_slaac_mac_list **prev; + grub_net_link_level_address_t address; + int slaac_counter; + char *name; +}; + +struct grub_net_buff +{ + /* Pointer to the start of the buffer. */ + grub_uint8_t *head; + /* Pointer to the data. */ + grub_uint8_t *data; + /* Pointer to the tail. */ + grub_uint8_t *tail; + /* Pointer to the end of the buffer. */ + grub_uint8_t *end; +}; + +struct grub_net_card_driver +{ + struct grub_net_card_driver *next; + struct grub_net_card_driver **prev; + const char *name; + grub_err_t (*open) (struct grub_net_card *dev); + void (*close) (struct grub_net_card *dev); + grub_err_t (*send) (struct grub_net_card *dev, + struct grub_net_buff *buf); + struct grub_net_buff * (*recv) (struct grub_net_card *dev); +}; + +struct grub_net_card //网卡 +{ + struct grub_net_card *next; //下一个 + struct grub_net_card **prev; //上一个 + const char *name; //名称 + struct grub_net_card_driver *driver; //驱动器 + grub_net_link_level_address_t default_address; //网络链路级地址 + grub_net_card_flags_t flags; //标记 + int num_ifaces; //网络数 + int opened; //已打开 + unsigned idle_poll_delay_ms; //空闲轮询延迟ms + unsigned long long last_poll; //最后获得 + grub_size_t mtu; //最大包尺寸 + struct grub_net_slaac_mac_list *slaac_list; //网从mac列表 + grub_ssize_t new_ll_entry; //新入口 + struct grub_net_link_layer_entry *link_layer_table; //网络链接层入口 + void *txbuf; //tx缓存地址 + void *rcvbuf; //rcv缓存地址 + grub_size_t rcvbufsize; //rcv缓存尺寸 + grub_size_t txbufsize; //tx缓存尺寸 + int txbusy; //tx忙碌 + union + { + struct + { + struct grub_efi_simple_network *efi_net; //简单网络 + grub_efi_handle_t efi_handle; //句柄 + grub_size_t last_pkt_size; //最后pkt尺寸 + }; + void *data; //数据指针 + int data_num; //数据号 + }; +} GRUB_PACKED; + +#define GRUB_NET_BOOTP_MAC_ADDR_LEN 16 +typedef grub_uint8_t grub_net_bootp_mac_addr_t[GRUB_NET_BOOTP_MAC_ADDR_LEN]; + +typedef struct grub_net_network_level_address +{ + grub_network_level_protocol_id_t type; + union + { + grub_uint32_t ipv4; + grub_uint64_t ipv6[2]; + }; + grub_dns_option_t option; +} grub_net_network_level_address_t; + +struct grub_net_network_level_interface +{ + struct grub_net_network_level_interface *next; + struct grub_net_network_level_interface **prev; + char *name; + struct grub_net_card *card; + grub_net_network_level_address_t address; + grub_net_link_level_address_t hwaddress; + grub_net_interface_flags_t flags; + grub_efi_pxe_dhcpv4_packet_t *dhcp_ack; + grub_size_t dhcp_acklen; + grub_uint16_t vlantag; + void *data; +}; + +//====================================================================================================================== + +struct grub_efi_service_binding; + +typedef grub_efi_status_t +(*grub_efi_service_binding_create_child) (struct grub_efi_service_binding *this, + grub_efi_handle_t *child_handle); + +typedef grub_efi_status_t +(*grub_efi_service_binding_destroy_child) (struct grub_efi_service_binding *this, + grub_efi_handle_t *child_handle); + +typedef struct grub_efi_service_binding +{ + grub_efi_service_binding_create_child create_child; + grub_efi_service_binding_destroy_child destroy_child; +} grub_efi_service_binding_t; + +typedef struct grub_efi_dhcp4_protocol grub_efi_dhcp4_protocol_t; + +enum grub_efi_dhcp4_state { + GRUB_EFI_DHCP4_STOPPED, //已停止 + GRUB_EFI_DHCP4_INIT, //初始化 + GRUB_EFI_DHCP4_SELECTING, //正在选择 + GRUB_EFI_DHCP4_REQUESTING, //正在请求 + GRUB_EFI_DHCP4_BOUND, //形成 + GRUB_EFI_DHCP4_RENEWING, //正在更新 + GRUB_EFI_DHCP4_REBINDING, //重新绑定 + GRUB_EFI_DHCP4_INIT_REBOOT,//初始化重新启动 + GRUB_EFI_DHCP4_REBOOTING //重新启动 +}; + +typedef enum grub_efi_dhcp4_state grub_efi_dhcp4_state_t; + +struct grub_efi_dhcp4_header { + grub_efi_uint8_t op_code; + grub_efi_uint8_t hw_type; + grub_efi_uint8_t hw_addr_len; + grub_efi_uint8_t hops; + grub_efi_uint32_t xid; + grub_efi_uint16_t seconds; + grub_efi_uint16_t reserved; + grub_efi_ipv4_address_t client_addr; + grub_efi_ipv4_address_t your_addr; + grub_efi_ipv4_address_t server_addr; + grub_efi_ipv4_address_t gateway_addr; + grub_efi_uint8_t client_hw_addr[16]; + grub_efi_char8_t server_name[64]; + grub_efi_char8_t boot_file_name[128]; +} GRUB_PACKED; + +typedef struct grub_efi_dhcp4_header grub_efi_dhcp4_header_t; + +struct grub_efi_dhcp4_packet { //数据包 + grub_efi_uint32_t size; //缓冲尺寸 数据包缓冲区的大小 + grub_efi_uint32_t length; //数据包尺寸 从标头的第一个字节开始的数据包长度 + struct { + grub_efi_dhcp4_header_t header; //数据包报头 + grub_efi_uint32_t magik; //魔术 + grub_efi_uint8_t option[1]; //选项数据 + } dhcp4; +} GRUB_PACKED; + +typedef struct grub_efi_dhcp4_packet grub_efi_dhcp4_packet_t; + +struct grub_efi_dhcp4_listen_point { + grub_efi_ipv4_address_t listen_address; + grub_efi_ipv4_address_t subnet_mask; + grub_efi_uint16_t listen_port; +}; + +typedef struct grub_efi_dhcp4_listen_point grub_efi_dhcp4_listen_point_t; + +struct grub_efi_dhcp4_transmit_receive_token { + grub_efi_status_t status; + grub_efi_event_t completion_event; + grub_efi_ipv4_address_t remote_address; + grub_efi_uint16_t remote_port; + grub_efi_ipv4_address_t gateway_address; + grub_efi_uint32_t listen_point_count; + grub_efi_dhcp4_listen_point_t *listen_points; + grub_efi_uint32_t timeout_value; + grub_efi_dhcp4_packet_t *packet; + grub_efi_uint32_t response_count; + grub_efi_dhcp4_packet_t *response_list; +}; + +typedef struct grub_efi_dhcp4_transmit_receive_token grub_efi_dhcp4_transmit_receive_token_t; + +enum grub_efi_dhcp4_event { + GRUB_EFI_DHCP4_SEND_DISCOVER = 0X01, + GRUB_EFI_DHCP4_RCVD_OFFER, + GRUB_EFI_DHCP4_SELECT_OFFER, + GRUB_EFI_DHCP4_SEND_REQUEST, + GRUB_EFI_DHCP4_RCVD_ACK, + GRUB_EFI_DHCP4_RCVD_NAK, + GRUB_EFI_DHCP4_SEND_DECLINE, + GRUB_EFI_DHCP4_BOUND_COMPLETED, + GRUB_EFI_DHCP4_ENTER_RENEWING, + GRUB_EFI_DHCP4_ENTER_REBINDING, + GRUB_EFI_DHCP4_ADDRESS_LOST, + GRUB_EFI_DHCP4_FAIL +}; + +typedef enum grub_efi_dhcp4_event grub_efi_dhcp4_event_t; + +struct grub_efi_dhcp4_packet_option { + grub_efi_uint8_t op_code; + grub_efi_uint8_t length; + grub_efi_uint8_t data[1]; +} GRUB_PACKED; + +typedef struct grub_efi_dhcp4_packet_option grub_efi_dhcp4_packet_option_t; + +struct grub_efi_dhcp4_config_data { + grub_efi_uint32_t discover_try_count; + grub_efi_uint32_t *discover_timeout; + grub_efi_uint32_t request_try_count; + grub_efi_uint32_t *request_timeout; + grub_efi_ipv4_address_t client_address; + grub_efi_status_t (*dhcp4_callback) ( + grub_efi_dhcp4_protocol_t *this, + void *context, + grub_efi_dhcp4_state_t current_state, + grub_efi_dhcp4_event_t dhcp4_event, + grub_efi_dhcp4_packet_t *packet, + grub_efi_dhcp4_packet_t **new_packet + ); + void *callback_context; + grub_efi_uint32_t option_count; + grub_efi_dhcp4_packet_option_t **option_list; +}; + +typedef struct grub_efi_dhcp4_config_data grub_efi_dhcp4_config_data_t; + +struct grub_efi_dhcp4_mode_data { + grub_efi_dhcp4_state_t state; //状态 + grub_efi_dhcp4_config_data_t config_data; //配置数据 + grub_efi_ipv4_address_t client_address; //客户端IP地址 + grub_efi_mac_address_t client_mac_address; //客户MAC地址 + grub_efi_ipv4_address_t server_address; //服务器IP地址 + grub_efi_ipv4_address_t router_address; //路由器IP地址 + grub_efi_ipv4_address_t subnet_mask; //子网掩码 + grub_efi_uint32_t lease_time; //IP地址的租用时间 + grub_efi_dhcp4_packet_t *reply_packet; //回复数据包指针 +}; + +typedef struct grub_efi_dhcp4_mode_data grub_efi_dhcp4_mode_data_t; + +struct grub_efi_dhcp4_protocol { + //返回EFI DHCPv4协议驱动程序的当前操作模式和缓存数据包。 + grub_efi_status_t (*get_mode_data) (grub_efi_dhcp4_protocol_t *this, //获取模式数据 + grub_efi_dhcp4_mode_data_t *dhcp4_mode_data); +/*初始化、更改或重置EFI DHCPv4协议驱动程序的操作设置 + 只有当以下两个条件都为真时,才能成功调用此函数: + •此EFI DHCPv4协议驱动程序实例处于Dhcp4Stopped、Dhcp4Init、Dhcp4NitReboot或Dhcp4Bound状态。 + •此EFI DHCPv4服务绑定协议驱动程序实例控制的其他EFI DHCPv4协议驱动程序示例均未配置此EFI DHCPv4协议驱动程序。 + 当此驱动程序处于Dhcp4Stop状态时,它可以转换为以下两种可能的初始状态之一: +• Dhcp4Init +• Dhcp4InitReboot + 驱动程序可以通过使用非NULL的Dhcp4CfgData调用Configure()来转换到这些状态。 + 驱动程序将根据ClientAddress参数中提供的客户端网络地址和OptionList参数中的DHCP选项转换到适当的状态,如RFC 2131所述。 + 当在Dhcp4CfgData设置为NULL的情况下成功调用Configure()时,EFI DHCPv4协议驱动程序中的默认配置数据将被重置, + EFI DHCPv4协议驱动程序的状态将不会改变。如果一个实例希望使另一个实例能够配置EFI DHCPv4协议驱动程序, + 则必须在Dhcp4CfgData设置为NULL的情况下调用此函数。 +*/ + grub_efi_status_t (*configure) (grub_efi_dhcp4_protocol_t *this, //配置 + grub_efi_dhcp4_config_data_t *dhcp4_cfg_data); + grub_efi_status_t (*start) (grub_efi_dhcp4_protocol_t *this, //开始 + grub_efi_event_t completion_event); + grub_efi_status_t (*renew_rebind) (grub_efi_dhcp4_protocol_t *this, //重新绑定 + grub_efi_boolean_t rebind_request, + grub_efi_event_t completion_event); + grub_efi_status_t (*release) (grub_efi_dhcp4_protocol_t *this); //释放 + grub_efi_status_t (*stop) (grub_efi_dhcp4_protocol_t *this); //停止 + grub_efi_status_t (*build) (grub_efi_dhcp4_protocol_t *this, //构建 + grub_efi_dhcp4_packet_t *seed_packet, + grub_efi_uint32_t delete_count, + grub_efi_uint8_t *delete_list, + grub_efi_uint32_t append_count, + grub_efi_dhcp4_packet_option_t *append_list[], + grub_efi_dhcp4_packet_t **new_packet); + grub_efi_status_t (*transmit_receive) (grub_efi_dhcp4_protocol_t *this, //发送接收 + grub_efi_dhcp4_transmit_receive_token_t *token); + grub_efi_status_t (*parse) (grub_efi_dhcp4_protocol_t *this, //解析 + grub_efi_dhcp4_packet_t *packet, + grub_efi_uint32_t *option_count, + grub_efi_dhcp4_packet_option_t *packet_option_list[]); +}; + +typedef struct grub_efi_dhcp6_protocol grub_efi_dhcp6_protocol_t; + +struct grub_efi_dhcp6_retransmission { + grub_efi_uint32_t irt; + grub_efi_uint32_t mrc; + grub_efi_uint32_t mrt; + grub_efi_uint32_t mrd; +}; + +typedef struct grub_efi_dhcp6_retransmission grub_efi_dhcp6_retransmission_t; + +enum grub_efi_dhcp6_event { + GRUB_EFI_DHCP6_SEND_SOLICIT, + GRUB_EFI_DHCP6_RCVD_ADVERTISE, + GRUB_EFI_DHCP6_SELECT_ADVERTISE, + GRUB_EFI_DHCP6_SEND_REQUEST, + GRUB_EFI_DHCP6_RCVD_REPLY, + GRUB_EFI_DHCP6_RCVD_RECONFIGURE, + GRUB_EFI_DHCP6_SEND_DECLINE, + GRUB_EFI_DHCP6_SEND_CONFIRM, + GRUB_EFI_DHCP6_SEND_RELEASE, + GRUB_EFI_DHCP6_SEND_RENEW, + GRUB_EFI_DHCP6_SEND_REBIND +}; + +typedef enum grub_efi_dhcp6_event grub_efi_dhcp6_event_t; + +struct grub_efi_dhcp6_packet_option { + grub_efi_uint16_t op_code; + grub_efi_uint16_t op_len; + grub_efi_uint8_t data[1]; +} GRUB_PACKED; + +typedef struct grub_efi_dhcp6_packet_option grub_efi_dhcp6_packet_option_t; + +struct grub_efi_dhcp6_header { + grub_efi_uint32_t transaction_id:24; + grub_efi_uint32_t message_type:8; +} GRUB_PACKED; + +typedef struct grub_efi_dhcp6_header grub_efi_dhcp6_header_t; + +struct grub_efi_dhcp6_packet { + grub_efi_uint32_t size; + grub_efi_uint32_t length; + struct { + grub_efi_dhcp6_header_t header; + grub_efi_uint8_t option[1]; + } dhcp6; +} GRUB_PACKED; + +typedef struct grub_efi_dhcp6_packet grub_efi_dhcp6_packet_t; + +struct grub_efi_dhcp6_ia_address { + grub_efi_ipv6_address_t ip_address; + grub_efi_uint32_t preferred_lifetime; + grub_efi_uint32_t valid_lifetime; +}; + +typedef struct grub_efi_dhcp6_ia_address grub_efi_dhcp6_ia_address_t; + +enum grub_efi_dhcp6_state { + GRUB_EFI_DHCP6_INIT, + GRUB_EFI_DHCP6_SELECTING, + GRUB_EFI_DHCP6_REQUESTING, + GRUB_EFI_DHCP6_DECLINING, + GRUB_EFI_DHCP6_CONFIRMING, + GRUB_EFI_DHCP6_RELEASING, + GRUB_EFI_DHCP6_BOUND, + GRUB_EFI_DHCP6_RENEWING, + GRUB_EFI_DHCP6_REBINDING +}; + +typedef enum grub_efi_dhcp6_state grub_efi_dhcp6_state_t; + +#define GRUB_EFI_DHCP6_IA_TYPE_NA 3 +#define GRUB_EFI_DHCP6_IA_TYPE_TA 4 + +struct grub_efi_dhcp6_ia_descriptor { + grub_efi_uint16_t type; + grub_efi_uint32_t ia_id; +}; + +typedef struct grub_efi_dhcp6_ia_descriptor grub_efi_dhcp6_ia_descriptor_t; + +struct grub_efi_dhcp6_ia { + grub_efi_dhcp6_ia_descriptor_t descriptor; + grub_efi_dhcp6_state_t state; + grub_efi_dhcp6_packet_t *reply_packet; + grub_efi_uint32_t ia_address_count; + grub_efi_dhcp6_ia_address_t ia_address[1]; +}; + +typedef struct grub_efi_dhcp6_ia grub_efi_dhcp6_ia_t; + +struct grub_efi_dhcp6_duid { + grub_efi_uint16_t length; + grub_efi_uint8_t duid[1]; +}; + +typedef struct grub_efi_dhcp6_duid grub_efi_dhcp6_duid_t; + +struct grub_efi_dhcp6_mode_data { + grub_efi_dhcp6_duid_t *client_id; + grub_efi_dhcp6_ia_t *ia; +}; + +typedef struct grub_efi_dhcp6_mode_data grub_efi_dhcp6_mode_data_t; + +struct grub_efi_dhcp6_config_data { + grub_efi_status_t (*dhcp6_callback) (grub_efi_dhcp6_protocol_t this, + void *context, + grub_efi_dhcp6_state_t current_state, + grub_efi_dhcp6_event_t dhcp6_event, + grub_efi_dhcp6_packet_t *packet, + grub_efi_dhcp6_packet_t **new_packet); + void *callback_context; + grub_efi_uint32_t option_count; + grub_efi_dhcp6_packet_option_t **option_list; + grub_efi_dhcp6_ia_descriptor_t ia_descriptor; + grub_efi_event_t ia_info_event; + grub_efi_boolean_t reconfigure_accept; + grub_efi_boolean_t rapid_commit; + grub_efi_dhcp6_retransmission_t *solicit_retransmission; +}; + +typedef struct grub_efi_dhcp6_config_data grub_efi_dhcp6_config_data_t; + +struct grub_efi_dhcp6_protocol { + grub_efi_status_t (*get_mode_data) (grub_efi_dhcp6_protocol_t *this, + grub_efi_dhcp6_mode_data_t *dhcp6_mode_data, + grub_efi_dhcp6_config_data_t *dhcp6_config_data); + grub_efi_status_t (*configure) (grub_efi_dhcp6_protocol_t *this, + grub_efi_dhcp6_config_data_t *dhcp6_cfg_data); + grub_efi_status_t (*start) (grub_efi_dhcp6_protocol_t *this); + grub_efi_status_t (*info_request) (grub_efi_dhcp6_protocol_t *this, + grub_efi_boolean_t send_client_id, + grub_efi_dhcp6_packet_option_t *option_request, + grub_efi_uint32_t option_count, + grub_efi_dhcp6_packet_option_t *option_list[], + grub_efi_dhcp6_retransmission_t *retransmission, + grub_efi_event_t timeout_event, + grub_efi_status_t (*reply_callback) (grub_efi_dhcp6_protocol_t *this, + void *context, + grub_efi_dhcp6_packet_t *packet), + void *callback_context); + grub_efi_status_t (*renew_rebind) (grub_efi_dhcp6_protocol_t *this, + grub_efi_boolean_t rebind_request); + grub_efi_status_t (*decline) (grub_efi_dhcp6_protocol_t *this, + grub_efi_uint32_t address_count, + grub_efi_ipv6_address_t *addresses); + grub_efi_status_t (*release) (grub_efi_dhcp6_protocol_t *this, + grub_efi_uint32_t address_count, + grub_efi_ipv6_address_t *addresses); + grub_efi_status_t (*stop) (grub_efi_dhcp6_protocol_t *this); + grub_efi_status_t (*parse) (grub_efi_dhcp6_protocol_t *this, + grub_efi_dhcp6_packet_t *packet, + grub_efi_uint32_t *option_count, + grub_efi_dhcp6_packet_option_t *packet_option_list[]); +}; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//http.c +#define EFIHTTP_WAIT_TIME 10000 // 10000ms = 10s +#define EFIHTTP_RX_BUF_LEN 10240 + +//****************************************** +// Protocol Interface Structure 协议接口结构 +//****************************************** +struct grub_efi_http; + +//****************************************** +// EFI_HTTP_VERSION HTTP版本 +//****************************************** +typedef enum { + GRUB_EFI_HTTPVERSION10, //HTTP版本10 + GRUB_EFI_HTTPVERSION11, //HTTP版本11 + GRUB_EFI_HTTPVERSIONUNSUPPORTED //不支持HTTP版本 +} grub_efi_http_version_t; + +//****************************************** +// EFI_HTTPv4_ACCESS_POINT HTTPv4访问点 +//****************************************** +typedef struct { + grub_efi_boolean_t use_default_address; //使用默认地址 设置为TRUE可指示EFI HTTP实例在该实例建立的每个TCP连接中使用默认地址信息。此外,当设置为TRUE时,LocalAddress和LocalSubnet将被忽略 + grub_efi_ipv4_address_t local_address; //本地地址 如果UseDefaultAddress设置为FALSE,则定义此实例打开的每个TCP连接中要使用的本地IP地址。 + grub_efi_ipv4_address_t local_subnet; //本地子网 如果UseDefaultAddress设置为FALSE,则定义此实例打开的每个TCP连接中要使用的本地子网。 + grub_efi_uint16_t local_port; //本地端口 这定义了此实例打开的每个TCP连接中要使用的本地端口。 +} grub_efi_httpv4_access_point_t; + +//****************************************** +// EFI_HTTPv6_ACCESS_POINT HTTPv6访问点 +//****************************************** +typedef struct { + grub_efi_ipv6_address_t local_address; //本地地址 要在此实例打开的每个TCP连接中使用的本地IP地址。 + grub_efi_uint16_t local_port; //本地端口 要在此实例打开的每个TCP连接中使用的本地端口。 +} grub_efi_httpv6_access_point_t; + +//****************************************** +// EFI_HTTP_CONFIG_DATA HTTP配置数据 +//****************************************** +typedef struct { + grub_efi_http_version_t http_version; //HTTP版本 此实例将支持的HTTP版本 + grub_efi_uint32_t timeout_millisec; //超时(毫秒) 阻止请求时超时(以毫秒为单位) + grub_efi_boolean_t local_address_is_ipv6; //本地地址是ipv6 定义此实例使用的EFI DNS和TCP协议的行为。如果为FALSE,此实例将使用EFI_DNSO_PROTOCOLEFI_TCP4_协议。如果为TRUE,则此实例将使用EFI_DNS6-PROTOCOL和EFI_TCP6-PROTOCOL。 + union { + grub_efi_httpv4_access_point_t *ipv4_node; //ipv4节点 当LocalAddressIsIPv6为FALSE时,这将指向本地底层TCP协议使用的地址、子网和端口。 + grub_efi_httpv6_access_point_t *ipv6_node; //ipv6节点 当LocalAddressIsIPv6为TRUE时,它指向底层TCP协议使用的本地IPv6地址和端口。 + } access_point; //切入点 +} grub_efi_http_config_data_t; + +//****************************************** +// EFI_HTTP_METHOD HTTP方法 +//****************************************** +typedef enum { + GRUB_EFI_HTTPMETHODGET, //HTTP方法 获得 请求指定的页面信息,并返回实体主体。 + GRUB_EFI_HTTPMETHODPOST, //HTTP方法 发布 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。 + GRUB_EFI_HTTPMETHODPATCH, //HTTP方法 修补 是对 PUT 方法的补充,用来对已知资源进行局部更新 。 + GRUB_EFI_HTTPMETHODOPTIONS, //HTTP方法 选择 允许客户端查看服务器的性能。 + GRUB_EFI_HTTPMETHODCONNECT, //HTTP方法 连接 HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。 + GRUB_EFI_HTTPMETHODHEAD, //HTTP方法 头部 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头 + GRUB_EFI_HTTPMETHODPUT, //HTTP方法 安置 从客户端向服务器传送的数据取代指定的文档的内容。 + GRUB_EFI_HTTPMETHODDELETE, //HTTP方法 删除 请求服务器删除指定的页面。 + GRUB_EFI_HTTPMETHODTRACE, //HTTP方法 跟踪 回显服务器收到的请求,主要用于测试或诊断。 +} grub_efi_http_method_t; + +//****************************************** +// EFI_HTTP_REQUEST_DATA HTTP请求数据 +//****************************************** +typedef struct { + grub_efi_http_method_t method; //方法 此HTTP请求的HTTP方法(例如GET、POST)。 + grub_efi_char16_t *url; //网址 远程主机的URI。根据此字段中的信息,HTTP实例将能够确定是使用HTTP还是HTTPS,还将能够确定要使用的端口号。如果没有指定端口号,则假定为端口80(HTTP)。有关URI语法的更多详细信息,请参阅RFC 3986。 +} grub_efi_http_request_data_t; + +typedef enum { + GRUB_EFI_HTTP_STATUS_UNSUPPORTED_STATUS = 0, //不受支持的状态 + GRUB_EFI_HTTP_STATUS_100_CONTINUE, //继续 + GRUB_EFI_HTTP_STATUS_101_SWITCHING_PROTOCOLS, //交换协议 + GRUB_EFI_HTTP_STATUS_200_OK, //ok + GRUB_EFI_HTTP_STATUS_201_CREATED, //已创建 + GRUB_EFI_HTTP_STATUS_202_ACCEPTED, //公认 + GRUB_EFI_HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION, //非权威信息 + GRUB_EFI_HTTP_STATUS_204_NO_CONTENT, //无内容 + GRUB_EFI_HTTP_STATUS_205_RESET_CONTENT, //重置内容 + GRUB_EFI_HTTP_STATUS_206_PARTIAL_CONTENT, //部分内容 + GRUB_EFI_HTTP_STATUS_300_MULTIPLE_CHIOCES, //多种选择 + GRUB_EFI_HTTP_STATUS_301_MOVED_PERMANENTLY, //永久移动 + GRUB_EFI_HTTP_STATUS_302_FOUND, //发现 + GRUB_EFI_HTTP_STATUS_303_SEE_OTHER, //另见 + GRUB_EFI_HTTP_STATUS_304_NOT_MODIFIED, //未修改 + GRUB_EFI_HTTP_STATUS_305_USE_PROXY, //使用代理服务器 + GRUB_EFI_HTTP_STATUS_307_TEMPORARY_REDIRECT, //暂时重定向 + GRUB_EFI_HTTP_STATUS_400_BAD_REQUEST, //错误的请求 + GRUB_EFI_HTTP_STATUS_401_UNAUTHORIZED, //未经授权 + GRUB_EFI_HTTP_STATUS_402_PAYMENT_REQUIRED, //需要付款 + GRUB_EFI_HTTP_STATUS_403_FORBIDDEN, //禁止的 + GRUB_EFI_HTTP_STATUS_404_NOT_FOUND, //未找到 + GRUB_EFI_HTTP_STATUS_405_METHOD_NOT_ALLOWED, //不允许的方法 + GRUB_EFI_HTTP_STATUS_406_NOT_ACCEPTABLE, //不能接受的 + GRUB_EFI_HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED, //要求代理授权 + GRUB_EFI_HTTP_STATUS_408_REQUEST_TIME_OUT, //请求超时 + GRUB_EFI_HTTP_STATUS_409_CONFLICT, //冲突 + GRUB_EFI_HTTP_STATUS_410_GONE, //离去 + GRUB_EFI_HTTP_STATUS_411_LENGTH_REQUIRED, //所需长度 + GRUB_EFI_HTTP_STATUS_412_PRECONDITION_FAILED, //失败的前提 + GRUB_EFI_HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE, //求的实体太大 + GRUB_EFI_HTTP_STATUS_414_REQUEST_URI_TOO_LARGE, //请求URI太大 + GRUB_EFI_HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE, //不受支持的媒体类型 + GRUB_EFI_HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED, //未满足要求的范围 + GRUB_EFI_HTTP_STATUS_417_EXPECTATION_FAILED, //预期失败 + GRUB_EFI_HTTP_STATUS_500_INTERNAL_SERVER_ERROR, //内部服务器错误 + GRUB_EFI_HTTP_STATUS_501_NOT_IMPLEMENTED, //未实现 + GRUB_EFI_HTTP_STATUS_502_BAD_GATEWAY, //错误的网关 + GRUB_EFI_HTTP_STATUS_503_SERVICE_UNAVAILABLE, //暂停服务 + GRUB_EFI_HTTP_STATUS_504_GATEWAY_TIME_OUT, //网关超时 + GRUB_EFI_HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED //不支持HTTP版本 +} grub_efi_http_status_code_t; //状态 + +//****************************************** +// EFI_HTTP_RESPONSE_DATA HTTP响应数据 +//****************************************** +typedef struct { + grub_efi_http_status_code_t status_code; //状态码 远程主机返回的响应状态代码。 +} grub_efi_http_response_data_t; + +//****************************************** +// EFI_HTTP_HEADER HTTP头 +//****************************************** +typedef struct { + grub_efi_char8_t *field_name; //字段名称 以Null结尾的字符串,用于描述字段名称。有关字段名称的详细信息,请参阅RFC 2616第14节。 + grub_efi_char8_t *field_value; //字段值 以Null结尾的字符串,用于描述相应的字段值。有关字段值的详细信息,请参阅RFC 2616第14节。 +} grub_efi_http_header_t; + +//****************************************** +// EFI_HTTP_MESSAGE HTTP消息 +//****************************************** +//HTTP驱动程序将根据中包含的信息准备一个请求字符串,并将其排队到要发送到远程主机的底层TCP实例。 +//通常,结构中的所有字段都包含内容(当HTTP方法不是POST或PUT时,Body和BodyLength除外),但有一种特殊情况当使用PUT或POST发送大量数据时。 +//根据数据的大小,它可能不是能够存储在连续的内存块中,因此需要以块的形式提供数据。在这个情况下,如果Body不为NULL,BodyLength为非零, +//并且所有其他字段都为NULL或0,则HTTP驱动程序将对要发送到成功发送令牌的最后一个远程主机的数据进行排队。如果之前没有令牌发送成功, +//此函数将返回。 +//HTTP驱动程序应关闭现有的(如果有的话)基础TCP实例并创建新的TCP实例如果请求URL中的主机名与以前对request()的调用不同。 +//这与RFC 2616建议HTTP客户端应尝试维护开放的TCP连接客户端和主机之间。 +typedef struct { + union { + grub_efi_http_request_data_t *request; //请求 当令牌用于发送HTTP请求时,request是指向包含URL和HTTP方法等数据的存储的指针。 + grub_efi_http_response_data_t *response; //响应 当用于等待响应时,response指向包含HTTP响应状态代码的存储。 + } data; //数据 + grub_efi_uint32_t header_count; //标题计数 标头列表中的HTTP标头结构数。根据请求,此计数由调用者提供。响应时,此计数由HTTP驱动程序提供。 + grub_efi_http_header_t *headers; //标头 包含HTTP标头列表的数组。根据请求,此数组由调用方填充。响应时,此数组由HTTP驱动程序分配和填充。调用方负责在请求和响应时释放此内存。 + grub_efi_uint32_t body_length; //体长 HTTP正文的长度(以字节为单位)。这可以是零,具体取决于HttpMethod类型。 + void *body; //体 与HTTP请求或响应关联的正文。这可以是NULL,具体取决于HttpMethod类型。 +} grub_efi_http_message_t; + +//****************************************** +// EFI_HTTP_TOKEN HTTP令牌 +//****************************************** +typedef struct { + grub_efi_event_t event; //事件 EFI HTTP协议驱动程序更新Status字段后,将发出此事件的信号。事件的类型必须是EFI_NOTIFY_SIGNAL。事件的任务优先级(TPL)必须低于或等于TPL_CALLBACK。 + grub_efi_status_t status; //状态 如果HTTP请求为成功发送或发生意外错误: +//EFI_SUCCESS:HTTP请求已成功发送到远程主机。 +//EFI_HTTP_ERROR:响应消息成功收到,但包含HTTP错误。响应状态代码为在Token中返回。 +//EFI_ABORTED:调用方取消了HTTP请求,并且从传输队列中删除。 +//EFI_TIMEOUT:HTTP请求在到达之前超时远程主机。 +//EFI_DEVICE_ERROR:意外的系统或网络错误发生。 + grub_efi_http_message_t *message; //信息 指向包含HTTP消息数据的存储的指针。 +} grub_efi_http_token_t; + +struct grub_efi_http { +//获得模式数据 +//获取当前操作状态。返回当前HTTP子实例的操作参数。 + grub_efi_status_t + (*get_mode_data) (struct grub_efi_http *this, //指向EFI_HTTP_PROTOCOL实例的指针。 + grub_efi_http_config_data_t *http_config_data); //指向此HTTP实例的操作参数的缓冲区的指针。调用方负责为HttpConfigData和HttpConfigData->AccessPoint分配内存。IPv6节点/IPv4节点。事实上,建议分配足够的内存来记录IPv6Node,因为它足够大,可以满足所有可能性。 +//配置 +//初始化、更改或重置EFI HTTP协议实例中的操作设置 +//Configure()函数执行以下操作: +//•当HttpConfigData不为NULL时,通过配置超时、本地地址、端口等初始化此EFI HTTP实例。 +//•当HttpConfigData为NULL时,通过关闭与远程主机的所有活动连接、取消所有异步令牌以及在不通知适当主机的情况下刷新请求和响应缓冲区来重置此EFI HTTP实例。。 +//在Configure()函数执行并成功返回之前,此实例无法执行其他EFI HTTP函数。 + grub_efi_status_t + (*configure) (struct grub_efi_http *this, //指向EFI_HTTP_PROTOCOL实例的指针。 + grub_efi_http_config_data_t *http_config_data); //配置数据 指向用于配置实例的配置数据的指针。 +//请求 +//将请求令牌排入传输队列。此功能是非阻塞操作。 +//Request()函数将HTTP请求排队到此HTTP实例,类似于EFI TCP驱动程序中的Transmit()函数。当HTTP请求成功发送时,或者出现错误时,将更新令牌中的Status,并发出Event信号。 + grub_efi_status_t + (*request) (struct grub_efi_http *this, //指向EFI_HTTP_PROTOCOL实例的指针。 + grub_efi_http_token_t *token); //令牌 指向包含HTTP请求令牌的存储的指针。 +//取消 +//中止挂起的请求或响应操作。 +//Cancel()函数中止挂起的HTTP请求或响应事务。如果取消时Token不为NULL并且处于发送或接收队列中,则其Token->Status将设置为EFI_ABORTED,然后Token->Event将发出信号。如果令牌不在其中一个队列中,这通常意味着异步操作已经完成,则返回EFI_not_FOUND。如果Token为NULL,则Request()或Response()发出的所有异步令牌都将中止。 + grub_efi_status_t + (*cancel) (struct grub_efi_http *this, //指向EFI_HTTP_PROTOCOL实例的指针。 + grub_efi_http_token_t *token); //令牌 指向包含HTTP请求或响应令牌的存储。 +//响应 +//将响应令牌排入接收队列。此功能是非阻塞操作。 +//Response() 函数将对此HTTP实例的HTTP响应排队,类似于EFI TCP驱动程序中的Receive()函数。当成功接收到HTTP响应时,或者如果出现错误,将更新令牌中的Status,并发出Event信号。 +//HTTP驱动程序将接收令牌排入底层TCP实例的队列。当在中接收到数据时底层TCP实例,数据将被解析,令牌将被填充响应数据。 +//如果从远程主机接收的数据包含不完整或无效的HTTP标头,即HTTP驱动程序将继续(异步)等待从远程主机发送更多数据,然后再发出信号令牌中的事件。 +//调用方负责为Body分配缓冲区并在BodyLength中指定大小。如果远程主机提供一个包含内容正文的响应,最多BodyLength字节将从接收缓冲区复制到正文中, +//并且BodyLength将根据接收到的字节数进行更新并复制到Body。这允许客户端将大文件分块下载,而不是下载到一个文件中连续的内存块。 +//类似于HTTP请求,如果Body不为NULL并且BodyLength为非零并且所有其他字段都为NULL或0,则HTTP驱动程序将接收令牌排队到底层TCP实例。 +//如果数据到达接收缓冲区,则最多BodyLength字节的数据将被复制到Body。HTTP然后,驱动程序将用接收并复制到Body的字节数更新BodyLength。 +//如果HTTP驱动程序与响应URL中指定的主机没有打开的底层TCP连接,response()将返回EFI_ACCESS_DENIED。这与RFC 2616的建议一致,即HTTP客户端应尝试维护客户端和主机之间的开放TCP连接。 + grub_efi_status_t + (*response) (struct grub_efi_http *this, //指向EFI_HTTP_PROTOCOL实例的指针。 + grub_efi_http_token_t *token); //令牌 指向包含HTTP响应令牌的存储的指针。有关EFI_HTTP_TOKEN的定义,请参阅Request()函数。 +//获得 +//轮询以接收传入的HTTP响应并发送传出的HTTP请求。 +//轮询传入的数据包并处理传出的数据包。 +//网络驱动程序和应用程序可以使用Poll()函数来增加数据包在通信设备之间移动的速率,以及发送和接收队列。 +//在某些系统中的周期性计时器事件受管网络驱动程序可能不会轮询底层通信设备足够快以发送和/或接收所有数据分组,而不会丢失传入分组或丢弃传出分组。 +//驱动程序和应用程序正在经历数据包丢失,应尝试更频繁地调用Poll()函数。 + grub_efi_status_t + (*poll) (struct grub_efi_http *this); //指向EFI_HTTP_PROTOCOL实例的指针。 +}; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* +//EFI_HTTP_UTILITIES_PROTOCOL EFI HTTP实用程序协议接口 +//协议GUID +#define EFI_HTTP_UTILITIES_PROTOCOL_GUID \ +{ 0x3E35C163, 0x4074, 0x45DD,\ + { 0x43, 0x1E, 0x23, 0x98, 0x9D, 0xD8, 0x6B, 0x32 }} + +//协议接口结构 +//EFI HTTP实用程序协议设计用于EFI驱动程序和应用程序解析字节流中的HTTP头。该驱动程序既不依赖于网络连接,也不依赖于底层网络基础设施的存在。 +typedef struct _EFI_HTTP_UTILITIES_PROTOCOL { + EFI_HTTP_UTILS_BUILD Build; //创建 基于种子标头、要删除的字段和要附加的字段的组合创建HTTP标头。 + EFI_HTTP_UTILS_PARSE Parse; //解析 解析HTTP头并生成一个键/值对数组。 +} EFI_HTTP_UTILITIES_PROTOCOL; + +//EFI_HTTP_UTILITIES_PROTOCOL.Build() //创建 +//提供在原始HTTP消息中添加、删除或替换HTTP标头的功能 +//Build()函数用于通过提供添加、删除或替换HTTP标头的功能来管理HTTP消息的标头部分。 +//EFI协议 +typedef +EFI_STATUS +(EFIAPI *EFI_HTTP_UTILS_BUILD) ( + IN EFI_HTTP_UTILITIES_PROTOCOL *This, //指向EFI_HTTP_UTILITIES_PROTOCOL实例的指针。 + IN UINTN SeedMessageSize //种子消息尺寸 初始HTTP标头的大小。这可以是零。 + IN VOID *SeedMessage, OPTIONAL //种子消息 要用作构建新HTTP标头的基础的初始HTTP标头。如果为NULL,则忽略SeedMessageSize。 + IN UINTN DeleteCount //删除计数 DeleteList中终止为null的HTTP标头字段名的数目。 + IN CHAR8 *DeleteList[], OPTIONAL //删除列表 要从SeedMessage中删除的以null结尾的HTTP标头字段名称的列表。此列表中只有字段名,因为字段值与此操作无关。 + IN UINTN AppendCount //附加计数 AppendList中的标头字段数。 + IN EFI_HTTP_HEADER *AppendList[], OPTIONAL //附加列表 用于填充NewMessage的HTTP标头的列表。如果SeedMessage不为NULL,则AppendList将被附加到NewMessage中的SeedMessage的现有列表中 + OUT UINTN *NewMessageSize, //新消息尺寸 指向NewMessage中标头字段数的指针。 + OUT VOID **NewMessage, //新建消息 指向基于的新HTTP标头列表的指针 +); + +//EFI_HTTP_UTILITIES_PROTOCOL.Parse() //解析 +//将HTTP标头解析为键/值对数组。 +//Parse()函数用于将存储在HttpHeader中的数据转换为与其对应值配对的字段列表。 +//EFI Protocol +typedef +EFI_STATUS +(EFIAPI *EFI_HTTP_UTILS_PARSE) ( + IN EFI_HTTP_PROTOCOL *This, //指向EFI_HTTP_UTILITIES_PROTOCOL实例的指针。 + IN CHAR8 *HttpMessage, //Http消息 包含未格式化的原始HTTP标头字符串 + IN UINTN HttpMessageSize, //Http消息尺寸 HTTP标头的尺寸 + OUT EFI_HTTP_HEADER **HeaderFields, //标题字段 键/值头对的数组 + OUT UINTN *FieldCount //字段计数 HeaderFields中的标头数。 +); +*/ + +typedef struct grub_efi_http grub_efi_http_t; //协议接口结构 + +typedef struct grub_efi_net_interface grub_efi_net_interface_t; +typedef struct grub_efi_net_ip_config grub_efi_net_ip_config_t; +typedef union grub_efi_net_ip_address grub_efi_net_ip_address_t; +typedef struct grub_efi_net_ip_manual_address grub_efi_net_ip_manual_address_t; + +struct grub_efi_net_interface //网络接口 +{ + char *name; //名称 + int prefer_ip6; //首选ip6 + struct grub_efi_net_device *dev; //网络设备 + struct grub_efi_net_io *io; //网络io + grub_efi_net_ip_config_t *ip_config; //ip配置 + int io_type; //io类型 + struct grub_efi_net_interface *next; //下一个 +}; + +#define efi_net_interface_get_hw_address(inf) inf->ip_config->get_hw_address (inf->dev) +#define efi_net_interface_get_address(inf) inf->ip_config->get_address (inf->dev) +#define efi_net_interface_get_route_table(inf) inf->ip_config->get_route_table (inf->dev) +#define efi_net_interface_set_address(inf, addr, with_subnet) inf->ip_config->set_address (inf->dev, addr, with_subnet) +#define efi_net_interface_set_gateway(inf, addr) inf->ip_config->set_gateway (inf->dev, addr) +#define efi_net_interface_set_dns(inf, addr) inf->ip_config->set_dns (inf->dev, addr) + +#define efi_net_interface_configure(inf) inf->io->configure (inf->dev, inf->prefer_ip6) +#define efi_net_interface_open(inf, file, name) inf->io->open (inf->dev, inf->prefer_ip6, file, name, inf->io_type) +#define efi_net_interface_read(inf, file, buf, sz) inf->io->read (inf->dev, inf->prefer_ip6, file, buf, sz) +#define efi_net_interface_close(inf, file) inf->io->close (inf->dev, inf->prefer_ip6, file) +#define efi_net_interface(m,...) efi_net_interface_ ## m (net_interface, ## __VA_ARGS__) + +struct grub_efi_net_ip_config +{ + char * (*get_hw_address) (struct grub_efi_net_device *dev); + char * (*get_address) (struct grub_efi_net_device *dev); + char ** (*get_route_table) (struct grub_efi_net_device *dev); + grub_efi_net_interface_t * (*best_interface) (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *address); + int (*set_address) (struct grub_efi_net_device *dev, grub_efi_net_ip_manual_address_t *net_ip, int with_subnet); + int (*set_gateway) (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *address); + int (*set_dns) (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *dns); +}; + +union grub_efi_net_ip_address +{ + grub_efi_ipv4_address_t ip4; + grub_efi_ipv6_address_t ip6; +}; + +struct grub_efi_net_ip_manual_address +{ + int is_ip6; + union + { + grub_efi_ip4_config2_manual_address_t ip4; + grub_efi_ip6_config_manual_address_t ip6; + }; +}; + +struct grub_efi_net_device +{ + grub_efi_handle_t handle; + grub_efi_ip4_config2_protocol_t *ip4_config; + grub_efi_ip6_config_protocol_t *ip6_config; + grub_efi_handle_t http_handle; + grub_efi_http_t *http; + grub_efi_handle_t ip4_pxe_handle; + grub_efi_pxe_t *ip4_pxe; + grub_efi_handle_t ip6_pxe_handle; + grub_efi_pxe_t *ip6_pxe; + grub_efi_handle_t dhcp4_handle; + grub_efi_dhcp4_protocol_t *dhcp4; + grub_efi_handle_t dhcp6_handle; + grub_efi_dhcp6_protocol_t *dhcp6; + char *card_name; + grub_efi_net_interface_t *net_interfaces; + struct grub_efi_net_device *next; +}; + +struct grub_efi_net_io +{ + void (*configure) (struct grub_efi_net_device *dev, int prefer_ip6); + grub_err_t (*open) (struct grub_efi_net_device *dev, + int prefer_ip6, + //grub_file_t file, + char *file, + const char *filename, + int type); + grub_ssize_t (*read) (struct grub_efi_net_device *dev, + int prefer_ip6, + //grub_file_t file, + char *file, + char *buf, + grub_size_t len); + grub_err_t (*close) (struct grub_efi_net_device *dev, + int prefer_ip6, + //grub_file_t file); + char *file); +}; + +extern struct grub_efi_net_device *net_devices; + +extern struct grub_efi_net_io io_http; +extern struct grub_efi_net_io io_pxe; + +extern grub_efi_net_ip_config_t *efi_net_ip4_config; +extern grub_efi_net_ip_config_t *efi_net_ip6_config; + +char * +grub_efi_ip4_address_to_string (grub_efi_ipv4_address_t *address); + +char * +grub_efi_ip6_address_to_string (grub_efi_pxe_ipv6_address_t *address); + +char * +grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_address_t hw_address); + +int +grub_efi_string_to_ip4_address (const char *val, grub_efi_ipv4_address_t *address, const char **rest); + +int +grub_efi_string_to_ip6_address (const char *val, grub_efi_ipv6_address_t *address, const char **rest); + +char * +grub_efi_ip6_interface_name (struct grub_efi_net_device *dev); + +char * +grub_efi_ip4_interface_name (struct grub_efi_net_device *dev); + +grub_efi_net_interface_t * +grub_efi_net_create_interface (struct grub_efi_net_device *dev, + const char *interface_name, + grub_efi_net_ip_manual_address_t *net_ip, + int has_subnet); + +int grub_efi_net_fs_init (void); +void grub_efi_net_fs_fini (void); +int grub_efi_net_boot_from_https (void); +int grub_efi_net_boot_from_opa (void); + +extern grub_efi_status_t EFIAPI blockio_read_write (block_io_protocol_t *this, grub_efi_uint32_t media_id, + grub_efi_lba_t lba, grub_efi_uintn_t len, void *buf, int read_write); +extern grub_size_t block_io_protocol_this; +extern int get_efi_device_boot_path (int drive, int flags); +extern grub_efi_device_path_t * grub_efi_file_device_path (grub_efi_device_path_t *dp, const char *filename); +extern int no_install_vdisk; +extern grub_efi_physical_address_t grub4dos_self_address; +extern grub_uint64_t grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r); +extern grub_uint64_t EXPORT_FUNC (__umoddi3) (grub_uint64_t a, grub_uint64_t b); +extern grub_uint64_t EXPORT_FUNC (__udivdi3) (grub_uint64_t a, grub_uint64_t b); +extern void start_event (void); +extern void close_event (void); +extern int find_specified_file (int drive, int partition, char* file); +extern char *vhd_file_name; +extern char vhd_file_path [128]; +extern int GetParentUtf8Name (char *dest, grub_uint16_t *src); +extern int GetSectorSequence (char* Utf8Name, struct fragment_map_slot** SectorSeq, int exist); +extern char *preset_menu; +extern int use_preset_menu; +//====================================================================================================================== + +#define GRUB_RSDP_SIGNATURE "RSD PTR " +#define GRUB_RSDP_SIGNATURE_SIZE 8 + +struct grub_acpi_rsdp_v10 +{ + grub_uint8_t signature[GRUB_RSDP_SIGNATURE_SIZE]; + grub_uint8_t checksum; + grub_uint8_t oemid[6]; + grub_uint8_t revision; + grub_uint32_t rsdt_addr; +} __attribute__ ((packed)); + +struct grub_acpi_rsdp_v20 +{ + struct grub_acpi_rsdp_v10 rsdpv1; + grub_uint32_t length; + grub_uint64_t xsdt_addr; + grub_uint8_t checksum; + grub_uint8_t reserved[3]; +} __attribute__ ((packed)); + +struct grub_acpi_table_header +{ + grub_uint8_t signature[4]; + grub_uint32_t length; + grub_uint8_t revision; + grub_uint8_t checksum; + grub_uint8_t oemid[6]; + grub_uint8_t oemtable[8]; + grub_uint32_t oemrev; + grub_uint8_t creator_id[4]; + grub_uint32_t creator_rev; +} __attribute__ ((packed)); + +#define GRUB_ACPI_FADT_SIGNATURE "FACP" + +struct grub_acpi_fadt +{ + struct grub_acpi_table_header hdr; + grub_uint32_t facs_addr; + grub_uint32_t dsdt_addr; + grub_uint8_t somefields1[20]; + grub_uint32_t pm1a; + grub_uint8_t somefields2[8]; + grub_uint32_t pmtimer; + grub_uint8_t somefields3[32]; + grub_uint32_t flags; + grub_uint8_t somefields4[16]; + grub_uint64_t facs_xaddr; + grub_uint64_t dsdt_xaddr; + grub_uint8_t somefields5[96]; +} __attribute__ ((packed)); + +#define GRUB_ACPI_SLP_EN (1 << 13) +#define GRUB_ACPI_SLP_TYP_OFFSET 10 + +enum +{ + GRUB_ACPI_OPCODE_ZERO = 0, GRUB_ACPI_OPCODE_ONE = 1, + GRUB_ACPI_OPCODE_NAME = 8, GRUB_ACPI_OPCODE_ALIAS = 0x06, + GRUB_ACPI_OPCODE_BYTE_CONST = 0x0a, + GRUB_ACPI_OPCODE_WORD_CONST = 0x0b, + GRUB_ACPI_OPCODE_DWORD_CONST = 0x0c, + GRUB_ACPI_OPCODE_STRING_CONST = 0x0d, + GRUB_ACPI_OPCODE_SCOPE = 0x10, + GRUB_ACPI_OPCODE_BUFFER = 0x11, + GRUB_ACPI_OPCODE_PACKAGE = 0x12, + GRUB_ACPI_OPCODE_METHOD = 0x14, GRUB_ACPI_OPCODE_EXTOP = 0x5b, + GRUB_ACPI_OPCODE_ADD = 0x72, + GRUB_ACPI_OPCODE_CONCAT = 0x73, + GRUB_ACPI_OPCODE_SUBTRACT = 0x74, + GRUB_ACPI_OPCODE_MULTIPLY = 0x77, + GRUB_ACPI_OPCODE_DIVIDE = 0x78, + GRUB_ACPI_OPCODE_LSHIFT = 0x79, + GRUB_ACPI_OPCODE_RSHIFT = 0x7a, + GRUB_ACPI_OPCODE_AND = 0x7b, + GRUB_ACPI_OPCODE_NAND = 0x7c, + GRUB_ACPI_OPCODE_OR = 0x7d, + GRUB_ACPI_OPCODE_NOR = 0x7e, + GRUB_ACPI_OPCODE_XOR = 0x7f, + GRUB_ACPI_OPCODE_CONCATRES = 0x84, + GRUB_ACPI_OPCODE_MOD = 0x85, + GRUB_ACPI_OPCODE_INDEX = 0x88, + GRUB_ACPI_OPCODE_CREATE_DWORD_FIELD = 0x8a, + GRUB_ACPI_OPCODE_CREATE_WORD_FIELD = 0x8b, + GRUB_ACPI_OPCODE_CREATE_BYTE_FIELD = 0x8c, + GRUB_ACPI_OPCODE_TOSTRING = 0x9c, + GRUB_ACPI_OPCODE_IF = 0xa0, GRUB_ACPI_OPCODE_ONES = 0xff +}; + +enum +{ + GRUB_ACPI_EXTOPCODE_MUTEX = 0x01, + GRUB_ACPI_EXTOPCODE_EVENT_OP = 0x02, + GRUB_ACPI_EXTOPCODE_OPERATION_REGION = 0x80, + GRUB_ACPI_EXTOPCODE_FIELD_OP = 0x81, + GRUB_ACPI_EXTOPCODE_DEVICE_OP = 0x82, + GRUB_ACPI_EXTOPCODE_PROCESSOR_OP = 0x83, + GRUB_ACPI_EXTOPCODE_POWER_RES_OP = 0x84, + GRUB_ACPI_EXTOPCODE_THERMAL_ZONE_OP = 0x85, + GRUB_ACPI_EXTOPCODE_INDEX_FIELD_OP = 0x86, + GRUB_ACPI_EXTOPCODE_BANK_FIELD_OP = 0x87, +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//grub/charse.h +#define GRUB_MAX_UTF8_PER_UTF16 4 +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//grub/compiler.h + +/* GCC version checking borrowed from glibc. */ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define GNUC_PREREQ(maj,min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#else +# define GNUC_PREREQ(maj,min) 0 +#endif + +/* Does this compiler support compile-time error attributes? */ +#if GNUC_PREREQ(4,3) +# define ATTRIBUTE_ERROR(msg) \ + __attribute__ ((__error__ (msg))) +#else +# define ATTRIBUTE_ERROR(msg) __attribute__ ((noreturn)) +#endif + +#if GNUC_PREREQ(4,4) +# define GNU_PRINTF gnu_printf +#else +# define GNU_PRINTF printf +#endif + +#if GNUC_PREREQ(3,4) +# define WARN_UNUSED_RESULT __attribute__ ((warn_unused_result)) +#else +# define WARN_UNUSED_RESULT +#endif + +#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__) +# define CLANG_PREREQ(maj,min) \ + ((__clang_major__ > (maj)) || \ + (__clang_major__ == (maj) && __clang_minor__ >= (min))) +#else +# define CLANG_PREREQ(maj,min) 0 +#endif + +#define UNUSED __attribute__((__unused__)) +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//grub/safemath.h + +/* These appear in gcc 5.1 and clang 3.8. */ +#if GNUC_PREREQ(5, 1) || CLANG_PREREQ(3, 8) + +#define grub_add(a, b, res) __builtin_add_overflow(a, b, res) +#define grub_sub(a, b, res) __builtin_sub_overflow(a, b, res) +#define grub_mul(a, b, res) __builtin_mul_overflow(a, b, res) + +#else +/* + * Copyright 2020 Rasmus Villemoes + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +/* + * The code used in this header was taken from linux kernel commit + * f0907827a8a9152aedac2833ed1b674a7b2a44f2 + * Rasmus Villemoes , the original author of the + * patch, was contacted directly, confirmed his authorship of the code, and + * gave his permission on treating that dual license as MIT and including into + * GRUB2 sources + */ + +#include +#define is_signed_type(type) (((type)(-1)) < (type)1) +#define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type))) +#define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T))) +#define type_min(T) ((T)((T)-type_max(T)-(T)1)) + +#define __unsigned_add_overflow(a, b, d) ({ \ + typeof(+(a)) __a = (a); \ + typeof(+(b)) __b = (b); \ + typeof(d) __d = (d); \ + (void) (&__a == &__b); \ + (void) (&__a == __d); \ + *__d = __a + __b; \ + *__d < __a; \ +}) +#define __unsigned_sub_overflow(a, b, d) ({ \ + typeof(+(a)) __a = (a); \ + typeof(+(b)) __b = (b); \ + typeof(d) __d = (d); \ + (void) (&__a == &__b); \ + (void) (&__a == __d); \ + *__d = __a - __b; \ + __a < __b; \ +}) +#define __unsigned_mul_overflow(a, b, d) ({ \ + typeof(+(a)) __a = (a); \ + typeof(+(b)) __b = (b); \ + typeof(d) __d = (d); \ + (void) (&__a == &__b); \ + (void) (&__a == __d); \ + *__d = __a * __b; \ + __builtin_constant_p(__b) ? \ + __b > 0 && __a > type_max(typeof(__a)) / __b :\ + __a > 0 && __b > type_max(typeof(__b)) / __a; \ +}) + +#define __signed_add_overflow(a, b, d) ({ \ + typeof(+(a)) __a = (a); \ + typeof(+(b)) __b = (b); \ + typeof(d) __d = (d); \ + (void) (&__a == &__b); \ + (void) (&__a == __d); \ + *__d = (grub_uint64_t)__a + (grub_uint64_t)__b; \ + (((~(__a ^ __b)) & (*__d ^ __a)) \ + & type_min(typeof(__a))) != 0; \ +}) + +#define __signed_sub_overflow(a, b, d) ({ \ + typeof(+(a)) __a = (a); \ + typeof(+(b)) __b = (b); \ + typeof(d) __d = (d); \ + (void) (&__a == &__b); \ + (void) (&__a == __d); \ + *__d = (grub_uint64_t)__a - (grub_uint64_t)__b; \ + ((((__a ^ __b)) & (*__d ^ __a)) \ + & type_min(typeof(__a))) != 0; \ +}) + +#define __signed_mul_overflow(a, b, d) ({ \ + typeof(+(a)) __a = (a); \ + typeof(+(b)) __b = (b); \ + typeof(d) __d = (d); \ + typeof(+(a)) __tmax = type_max(typeof(+(a))); \ + typeof(+(a)) __tmin = type_min(typeof(+(a))); \ + (void) (&__a == &__b); \ + (void) (&__a == __d); \ + *__d = (grub_uint64_t)__a * (grub_uint64_t)__b; \ + (__b > 0 && (__a > __tmax/__b || __a < __tmin/__b)) ||\ + (__b < (typeof(__b))-1 && \ + (__a > __tmin/__b || __a < __tmax/__b)) || \ + (__b == (typeof(__b))-1 && __a == __tmin); \ +}) + +#define grub_add(a, b, d) \ + __builtin_choose_expr(is_signed_type(typeof(+(a))), \ + __signed_add_overflow(a, b, d), \ + __unsigned_add_overflow(a, b, d)) + +#define grub_sub(a, b, d) \ + __builtin_choose_expr(is_signed_type(typeof(+(a))), \ + __signed_sub_overflow(a, b, d), \ + __unsigned_sub_overflow(a, b, d)) + +#define grub_mul(a, b, d) \ + __builtin_choose_expr(is_signed_type(typeof(+(a))), \ + __signed_mul_overflow(a, b, d), \ + __unsigned_mul_overflow(a, b, d)) + +#endif + +extern void init_cookie ( void ); +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#if 0 +static const unsigned short _gbk2utf16_2[] = +{ //gbk utf16 + 0x8140, 0x4E02, // {{{ + 0x8144, 0x4E0F, + 0x8145, 0x4E12, + 0x8146, 0x4E17, + 0x814A, 0x4E23, + 0x814B, 0x4E26, + 0x814C, 0x4E29, + 0x814F, 0x4E31, + 0x8150, 0x4E33, + 0x8151, 0x4E35, + 0x8152, 0x4E37, + 0x8153, 0x4E3C, + 0x8157, 0x4E44, + 0x8158, 0x4E46, + 0x8159, 0x4E4A, + 0x815A, 0x4E51, + 0x815B, 0x4E55, + 0x815C, 0x4E57, + 0x816B, 0x4E72, + 0x817D, 0x4E87, + 0x817E, 0x4E8A, + 0x8180, 0x4E90, + 0x8183, 0x4E99, + 0x8187, 0x4EA3, + 0x8188, 0x4EAA, + 0x818C, 0x4EB4, + 0x8194, 0x4EC8, + 0x8195, 0x4ECC, + 0x8198, 0x4ED2, + 0x819C, 0x4EE0, + 0x819D, 0x4EE2, + 0x81A0, 0x4EE9, + 0x81A4, 0x4EF1, + 0x81A5, 0x4EF4, + 0x81A9, 0x4EFC, + 0x81AA, 0x4EFE, + 0x81AB, 0x4F00, + 0x81BC, 0x4F21, + 0x81BD, 0x4F23, + 0x81C3, 0x4F31, + 0x81C4, 0x4F33, + 0x81C5, 0x4F35, + 0x81C6, 0x4F37, + 0x81C7, 0x4F39, + 0x81C8, 0x4F3B, + 0x81D6, 0x4F52, + 0x81D7, 0x4F54, + 0x81D8, 0x4F56, + 0x81DB, 0x4F66, + 0x81DC, 0x4F68, + 0x81E3, 0x4F75, + 0x81E8, 0x4F7D, + 0x81EF, 0x4F8A, + 0x81F0, 0x4F8C, + 0x81F1, 0x4F8E, + 0x81F2, 0x4F90, + 0x81FA, 0x4F9C, + 0x8240, 0x4FA4, + 0x8241, 0x4FAB, + 0x8242, 0x4FAD, + 0x8260, 0x4FD9, + 0x8261, 0x4FDB, + 0x8262, 0x4FE0, + 0x8263, 0x4FE2, + 0x8266, 0x4FE7, + 0x8269, 0x4FF0, + 0x826A, 0x4FF2, + 0x826F, 0x4FF9, + 0x8280, 0x500B, + 0x8281, 0x500E, + 0x8284, 0x5013, + 0x8288, 0x501B, + 0x828B, 0x5020, + 0x828F, 0x5027, + 0x8290, 0x502B, + 0x829C, 0x503B, + 0x829D, 0x503D, + 0x82A8, 0x504D, + 0x82B2, 0x505B, + 0x82EE, 0x50A4, + 0x82EF, 0x50A6, + 0x82FE, 0x50BC, + 0x836E, 0x50F4, + 0x837E, 0x5108, + 0x83B3, 0x5142, + 0x83B4, 0x5147, + 0x83B5, 0x514A, + 0x83B6, 0x514C, + 0x83BF, 0x515B, + 0x83CB, 0x516F, + 0x83CC, 0x5172, + 0x83CD, 0x517A, + 0x83DC, 0x5198, + 0x83DD, 0x519A, + 0x83E1, 0x51A1, + 0x83E2, 0x51A3, + 0x83EA, 0x51B4, + 0x83F3, 0x51C5, + 0x83F4, 0x51C8, + 0x83F5, 0x51CA, + 0x83F8, 0x51D0, + 0x8443, 0x51DC, + 0x844E, 0x51EC, + 0x844F, 0x51EE, + 0x8452, 0x51F4, + 0x8453, 0x51F7, + 0x8454, 0x51FE, + 0x8457, 0x5209, + 0x845F, 0x521C, + 0x8468, 0x522A, + 0x8469, 0x522C, + 0x846A, 0x522F, + 0x846F, 0x523C, + 0x8470, 0x523E, + 0x8477, 0x524B, + 0x847C, 0x5255, + 0x8483, 0x525D, + 0x8489, 0x5266, + 0x848A, 0x5268, + 0x849B, 0x527E, + 0x849C, 0x5280, + 0x84B2, 0x529C, + 0x84CA, 0x52C8, + 0x84CB, 0x52CA, + 0x84D0, 0x52D1, + 0x84D4, 0x52D7, + 0x84F9, 0x5307, + 0x84FE, 0x530E, + 0x8544, 0x5318, + 0x8549, 0x5322, + 0x855E, 0x5340, + 0x855F, 0x5342, + 0x8560, 0x5344, + 0x8561, 0x5346, + 0x8565, 0x5350, + 0x8566, 0x5354, + 0x8569, 0x535B, + 0x856A, 0x535D, + 0x856B, 0x5365, + 0x856C, 0x5368, + 0x856D, 0x536A, + 0x8570, 0x5372, + 0x8571, 0x5376, + 0x8572, 0x5379, + 0x8579, 0x5383, + 0x857C, 0x538A, + 0x8587, 0x5399, + 0x858A, 0x539E, + 0x858D, 0x53A4, + 0x858E, 0x53A7, + 0x85A1, 0x53C0, + 0x85AC, 0x53D5, + 0x85AD, 0x53DA, + 0x85B3, 0x53E7, + 0x85B4, 0x53F4, + 0x85B5, 0x53FA, + 0x85B9, 0x5402, + 0x85BA, 0x5405, + 0x85BB, 0x5407, + 0x85BC, 0x540B, + 0x85BD, 0x5414, + 0x85C1, 0x541C, + 0x85C2, 0x5422, + 0x85C5, 0x542A, + 0x85C6, 0x5430, + 0x85C7, 0x5433, + 0x85CA, 0x543A, + 0x85CB, 0x543D, + 0x85CC, 0x543F, + 0x85D1, 0x5447, + 0x85D2, 0x5449, + 0x85D7, 0x5451, + 0x85D8, 0x545A, + 0x85DE, 0x5463, + 0x85DF, 0x5465, + 0x85E0, 0x5467, + 0x85E9, 0x5474, + 0x85EE, 0x5481, + 0x85EF, 0x5483, + 0x85F0, 0x5485, + 0x85F5, 0x548D, + 0x85F6, 0x5491, + 0x85F7, 0x5493, + 0x85FA, 0x549C, + 0x8640, 0x54A2, + 0x8641, 0x54A5, + 0x8642, 0x54AE, + 0x8643, 0x54B0, + 0x8644, 0x54B2, + 0x864A, 0x54BC, + 0x864B, 0x54BE, + 0x864C, 0x54C3, + 0x864D, 0x54C5, + 0x8650, 0x54D6, + 0x8651, 0x54D8, + 0x8652, 0x54DB, + 0x8663, 0x54FB, + 0x8664, 0x54FE, + 0x8665, 0x5500, + 0x866A, 0x5508, + 0x867C, 0x5521, + 0x8682, 0x552B, + 0x8683, 0x552D, + 0x8684, 0x5532, + 0x868C, 0x553D, + 0x868D, 0x5540, + 0x868E, 0x5542, + 0x868F, 0x5545, + 0x86A8, 0x556B, + 0x86B1, 0x557D, + 0x86B2, 0x557F, + 0x86B8, 0x5590, + 0x86C0, 0x559E, + 0x86D1, 0x55B2, + 0x86D2, 0x55B4, + 0x86D3, 0x55B6, + 0x86D4, 0x55B8, + 0x86D5, 0x55BA, + 0x86D6, 0x55BC, + 0x86E4, 0x55D5, + 0x86EA, 0x55DE, + 0x86EB, 0x55E0, + 0x86EC, 0x55E2, + 0x86ED, 0x55E7, + 0x86EE, 0x55E9, + 0x86F3, 0x55F4, + 0x86F4, 0x55F6, + 0x86FA, 0x55FF, + 0x8744, 0x560D, + 0x875D, 0x5633, + 0x875E, 0x5635, + 0x8761, 0x563A, + 0x8780, 0x5663, + 0x87E1, 0x56DC, + 0x87E2, 0x56E3, + 0x87E9, 0x56EC, + 0x87F6, 0x5705, + 0x87F7, 0x5707, + 0x8853, 0x572B, + 0x885D, 0x573F, + 0x885E, 0x5741, + 0x8865, 0x574B, + 0x886F, 0x5765, + 0x8870, 0x5767, + 0x8871, 0x576C, + 0x8872, 0x576E, + 0x8880, 0x5781, + 0x8895, 0x57A5, + 0x8896, 0x57A8, + 0x8897, 0x57AA, + 0x8898, 0x57AC, + 0x889C, 0x57B3, + 0x88B4, 0x57D3, + 0x88B9, 0x57DE, + 0x88C5, 0x57EE, + 0x88D1, 0x5801, + 0x88D8, 0x580C, + 0x88E6, 0x581F, + 0x8976, 0x587F, + 0x8977, 0x5882, + 0x8978, 0x5884, + 0x89D0, 0x58ED, + 0x89D1, 0x58EF, + 0x89E0, 0x5903, + 0x89E8, 0x590E, + 0x89EF, 0x591B, + 0x89F6, 0x5926, + 0x89F7, 0x5928, + 0x89F8, 0x592C, + 0x89F9, 0x5930, + 0x89FE, 0x593B, + 0x8A44, 0x5943, + 0x8A47, 0x594A, + 0x8A4A, 0x5950, + 0x8A4D, 0x5959, + 0x8A53, 0x5961, + 0x8A63, 0x5975, + 0x8A64, 0x5977, + 0x8A6B, 0x5985, + 0x8A6C, 0x5989, + 0x8A75, 0x5998, + 0x8A7E, 0x59A6, + 0x8A80, 0x59A7, + 0x8A8B, 0x59BA, + 0x8A9E, 0x59D9, + 0x8A9F, 0x59DB, + 0x8AA5, 0x59E4, + 0x8AB7, 0x59FA, + 0x8ABB, 0x5A00, + 0x8ABC, 0x5A02, + 0x8AC3, 0x5A12, + 0x8ACF, 0x5A24, + 0x8ADA, 0x5A33, + 0x8ADB, 0x5A35, + 0x8B40, 0x5A61, + 0x8B85, 0x5AB4, + 0x8B9C, 0x5AD3, + 0x8B9D, 0x5AD5, + 0x8B9E, 0x5AD7, + 0x8BA5, 0x5AE2, + 0x8BAA, 0x5AEA, + 0x8BED, 0x5B33, + 0x8C48, 0x5B52, + 0x8C49, 0x5B56, + 0x8C4A, 0x5B5E, + 0x8C4F, 0x5B6B, + 0x8C53, 0x5B72, + 0x8C54, 0x5B74, + 0x8C5D, 0x5B82, + 0x8C5E, 0x5B86, + 0x8C5F, 0x5B8A, + 0x8C65, 0x5B94, + 0x8C66, 0x5B96, + 0x8C67, 0x5B9F, + 0x8C71, 0x5BB7, + 0x8C77, 0x5BC3, + 0x8C80, 0x5BD1, + 0x8C8A, 0x5BE0, + 0x8C94, 0x5BEF, + 0x8C9E, 0x5C00, + 0x8CA1, 0x5C05, + 0x8CA8, 0x5C10, + 0x8CAB, 0x5C17, + 0x8CAC, 0x5C19, + 0x8CAD, 0x5C1B, + 0x8CB2, 0x5C23, + 0x8CB3, 0x5C26, + 0x8CD1, 0x5C5F, + 0x8CD2, 0x5C62, + 0x8CD3, 0x5C64, + 0x8CDB, 0x5C70, + 0x8CE7, 0x5C80, + 0x8CF4, 0x5C95, + 0x8D40, 0x5CAA, + 0x8D44, 0x5CB2, + 0x8D45, 0x5CB4, + 0x8D46, 0x5CB6, + 0x8D4B, 0x5CBE, + 0x8D4C, 0x5CC0, + 0x8D6A, 0x5CE7, + 0x8D6B, 0x5CE9, + 0x8D80, 0x5D01, + 0x8D8E, 0x5D15, + 0x8D9A, 0x5D25, + 0x8D9B, 0x5D28, + 0x8DC3, 0x5D5C, + 0x8DCF, 0x5D6A, + 0x8E77, 0x5DDC, + 0x8E7C, 0x5DEA, + 0x8E80, 0x5DF0, + 0x8E8A, 0x5E04, + 0x8E8B, 0x5E07, + 0x8E93, 0x5E17, + 0x8EAE, 0x5E43, + 0x8ED4, 0x5E75, + 0x8ED5, 0x5E77, + 0x8ED6, 0x5E79, + 0x8ED7, 0x5E7E, + 0x8EDB, 0x5E85, + 0x8EE1, 0x5E92, + 0x8EE2, 0x5E98, + 0x8EE3, 0x5E9B, + 0x8EE4, 0x5E9D, + 0x8EF3, 0x5EB4, + 0x8F5B, 0x5EE9, + 0x8F65, 0x5EF5, + 0x8F6E, 0x5F09, + 0x8F72, 0x5F10, + 0x8F73, 0x5F12, + 0x8F74, 0x5F14, + 0x8F75, 0x5F16, + 0x8F80, 0x5F28, + 0x8F83, 0x5F2E, + 0x8F84, 0x5F30, + 0x8F8C, 0x5F3B, + 0x8F9F, 0x5F51, + 0x8FA0, 0x5F54, + 0x8FA8, 0x5F63, + 0x8FA9, 0x5F65, + 0x8FAC, 0x5F6B, + 0x8FAF, 0x5F72, + 0x8FB3, 0x5F78, + 0x8FB4, 0x5F7A, + 0x8FB8, 0x5F83, + 0x8FB9, 0x5F86, + 0x8FBD, 0x5F91, + 0x8FC0, 0x5F96, + 0x8FCD, 0x5FA9, + 0x8FD6, 0x5FB6, + 0x8FE4, 0x5FCE, + 0x8FF3, 0x5FEC, + 0x8FFD, 0x5FFC, + 0x8FFE, 0x6007, + 0x9046, 0x6013, + 0x9049, 0x601A, + 0x905E, 0x6040, + 0x9066, 0x604C, + 0x9069, 0x6051, + 0x9077, 0x606E, + 0x907C, 0x6077, + 0x907D, 0x607E, + 0x907E, 0x6080, + 0x908C, 0x6093, + 0x908D, 0x6095, + 0x9091, 0x609C, + 0x9092, 0x609E, + 0x9097, 0x60A7, + 0x909A, 0x60AE, + 0x909B, 0x60B0, + 0x909C, 0x60B3, + 0x90B7, 0x60D9, + 0x90B8, 0x60DB, + 0x90B9, 0x60DE, + 0x90BF, 0x60EA, + 0x90C2, 0x60F5, + 0x90CE, 0x6107, + 0x90E1, 0x6125, + 0x9140, 0x6147, + 0x9141, 0x6149, + 0x9142, 0x614B, + 0x9143, 0x614D, + 0x9163, 0x6176, + 0x917E, 0x6195, + 0x91AA, 0x61C9, + 0x91B0, 0x61D3, + 0x91DF, 0x6207, + 0x91E0, 0x6209, + 0x91E3, 0x6219, + 0x91E7, 0x6220, + 0x91E8, 0x6223, + 0x91ED, 0x622B, + 0x91EE, 0x622D, + 0x91FA, 0x6242, + 0x91FE, 0x624A, + 0x9250, 0x6268, + 0x9259, 0x627D, + 0x9267, 0x6294, + 0x9268, 0x6299, + 0x926C, 0x62A3, + 0x927B, 0x62BA, + 0x927C, 0x62BE, + 0x9280, 0x62C3, + 0x9281, 0x62CB, + 0x9282, 0x62CF, + 0x9283, 0x62D1, + 0x9284, 0x62D5, + 0x9289, 0x62E4, + 0x928C, 0x62F0, + 0x928D, 0x62F2, + 0x928E, 0x62F5, + 0x9293, 0x6300, + 0x92A5, 0x631C, + 0x92A8, 0x6329, + 0x92BA, 0x6344, + 0x92BD, 0x634A, + 0x92CA, 0x6360, + 0x92CE, 0x6368, + 0x92DE, 0x6381, + 0x92E3, 0x638B, + 0x92E4, 0x638D, + 0x92E5, 0x6391, + 0x92E9, 0x6397, + 0x92F1, 0x63A1, + 0x92F2, 0x63A4, + 0x92F3, 0x63A6, + 0x92F4, 0x63AB, + 0x92F5, 0x63AF, + 0x92FA, 0x63B9, + 0x92FB, 0x63BB, + 0x92FC, 0x63BD, + 0x9343, 0x63C5, + 0x9349, 0x63D1, + 0x9354, 0x63DF, + 0x9355, 0x63E2, + 0x9361, 0x63F3, + 0x9362, 0x63F5, + 0x9363, 0x63F7, + 0x9368, 0x63FE, + 0x937A, 0x641D, + 0x937B, 0x641F, + 0x9380, 0x6425, + 0x9384, 0x642B, + 0x9392, 0x643E, + 0x9393, 0x6440, + 0x9396, 0x6449, + 0x939E, 0x6453, + 0x93AF, 0x6468, + 0x93C4, 0x6483, + 0x93C5, 0x6486, + 0x93E2, 0x64AF, + 0x93E7, 0x64B6, + 0x93E8, 0x64B9, + 0x93E9, 0x64BB, + 0x93ED, 0x64C1, + 0x93F7, 0x64CF, + 0x93F8, 0x64D1, + 0x9446, 0x64E3, + 0x9447, 0x64E5, + 0x948E, 0x6537, + 0x948F, 0x653A, + 0x949D, 0x6550, + 0x94A3, 0x655A, + 0x94A4, 0x655C, + 0x94B1, 0x6571, + 0x94B2, 0x6573, + 0x94CA, 0x6592, + 0x94CE, 0x6598, + 0x94CF, 0x659A, + 0x94D2, 0x65A0, + 0x94D5, 0x65A6, + 0x94D6, 0x65A8, + 0x94D7, 0x65AA, + 0x94D8, 0x65AC, + 0x94D9, 0x65AE, + 0x94E7, 0x65C2, + 0x94EC, 0x65CD, + 0x94FA, 0x65E1, + 0x954B, 0x6601, + 0x9551, 0x660B, + 0x9552, 0x660D, + 0x955C, 0x661E, + 0x9561, 0x6626, + 0x9566, 0x662E, + 0x9567, 0x6630, + 0x956F, 0x663D, + 0x9572, 0x6642, + 0x957E, 0x6658, + 0x9580, 0x6659, + 0x9585, 0x6660, + 0x9588, 0x6665, + 0x9589, 0x6667, + 0x9592, 0x6675, + 0x959B, 0x6683, + 0x95E4, 0x66DA, + 0x95F5, 0x66F1, + 0x95F8, 0x66F8, + 0x95FB, 0x66FD, + 0x9644, 0x670C, + 0x964A, 0x6716, + 0x964E, 0x671C, + 0x964F, 0x671E, + 0x9656, 0x6727, + 0x9657, 0x6729, + 0x9658, 0x672E, + 0x9659, 0x6730, + 0x9664, 0x6741, + 0x9667, 0x6747, + 0x966A, 0x674D, + 0x966B, 0x6752, + 0x9673, 0x675D, + 0x967B, 0x676E, + 0x967C, 0x6771, + 0x967D, 0x6774, + 0x967E, 0x6776, + 0x9684, 0x677D, + 0x9685, 0x6780, + 0x968A, 0x6788, + 0x968B, 0x678A, + 0x9694, 0x6796, + 0x9695, 0x6799, + 0x9696, 0x679B, + 0x969A, 0x67A4, + 0x969B, 0x67A6, + 0x969C, 0x67A9, + 0x969D, 0x67AC, + 0x969E, 0x67AE, + 0x96A1, 0x67B4, + 0x96AA, 0x67C2, + 0x96B8, 0x67DB, + 0x96B9, 0x67DF, + 0x96BA, 0x67E1, + 0x96C4, 0x67F2, + 0x96CD, 0x67FE, + 0x96D2, 0x6806, + 0x96D3, 0x680D, + 0x96D4, 0x6810, + 0x96D5, 0x6812, + 0x96F3, 0x683F, + 0x96F4, 0x6847, + 0x96F5, 0x684B, + 0x96F6, 0x684D, + 0x96F7, 0x684F, + 0x96F8, 0x6852, + 0x9744, 0x686A, + 0x974D, 0x6875, + 0x9757, 0x6882, + 0x9758, 0x6884, + 0x9778, 0x68AE, + 0x977B, 0x68B4, + 0x9787, 0x68C1, + 0x978E, 0x68CA, + 0x978F, 0x68CC, + 0x9798, 0x68D9, + 0x97AA, 0x68EF, + 0x97B1, 0x68FB, + 0x97BE, 0x690C, + 0x97BF, 0x690F, + 0x97C0, 0x6911, + 0x97E4, 0x693E, + 0x97FE, 0x695F, + 0x9856, 0x6981, + 0x9857, 0x6983, + 0x9858, 0x6985, + 0x9872, 0x69AC, + 0x988B, 0x69CB, + 0x988C, 0x69CD, + 0x988D, 0x69CF, + 0x98B4, 0x69FE, + 0x98D1, 0x6A20, + 0x98D8, 0x6A29, + 0x98DD, 0x6A30, + 0x98FE, 0x6A5A, + 0x996B, 0x6A8F, + 0x9982, 0x6AAA, + 0x9A47, 0x6B38, + 0x9A51, 0x6B48, + 0x9A78, 0x6B7A, + 0x9A7D, 0x6B85, + 0x9A7E, 0x6B88, + 0x9A80, 0x6B8C, + 0x9A9F, 0x6BB6, + 0x9AA7, 0x6BC0, + 0x9AAF, 0x6BCC, + 0x9AB0, 0x6BCE, + 0x9AB3, 0x6BD8, + 0x9AB4, 0x6BDA, + 0x9AC8, 0x6BF4, + 0x9ADB, 0x6C0E, + 0x9ADC, 0x6C12, + 0x9ADD, 0x6C17, + 0x9AE1, 0x6C20, + 0x9AE2, 0x6C23, + 0x9AE3, 0x6C25, + 0x9AE7, 0x6C31, + 0x9AE8, 0x6C33, + 0x9AF4, 0x6C48, + 0x9AFD, 0x6C56, + 0x9AFE, 0x6C58, + 0x9B4C, 0x6C71, + 0x9B4D, 0x6C73, + 0x9B4E, 0x6C75, + 0x9B56, 0x6C84, + 0x9B57, 0x6C87, + 0x9B62, 0x6C9A, + 0x9B66, 0x6CA0, + 0x9B67, 0x6CA2, + 0x9B68, 0x6CA8, + 0x9B69, 0x6CAC, + 0x9B70, 0x6CBA, + 0x9B78, 0x6CCB, + 0x9B7E, 0x6CD8, + 0x9B84, 0x6CDF, + 0x9B85, 0x6CE4, + 0x9B88, 0x6CE9, + 0x9B8B, 0x6CF2, + 0x9B8C, 0x6CF4, + 0x9B8D, 0x6CF9, + 0x9B97, 0x6D0D, + 0x9B9F, 0x6D18, + 0x9BA8, 0x6D26, + 0x9BAF, 0x6D34, + 0x9BB3, 0x6D3A, + 0x9BB6, 0x6D42, + 0x9BB7, 0x6D44, + 0x9BB8, 0x6D49, + 0x9BB9, 0x6D4C, + 0x9BBA, 0x6D50, + 0x9BBF, 0x6D5B, + 0x9BC0, 0x6D5D, + 0x9BC1, 0x6D5F, + 0x9BDF, 0x6D8D, + 0x9BE2, 0x6D92, + 0x9BE8, 0x6D9C, + 0x9BE9, 0x6DA2, + 0x9BEA, 0x6DA5, + 0x9C48, 0x6DD7, + 0x9C4C, 0x6DDF, + 0x9C4F, 0x6DE5, + 0x9C54, 0x6DED, + 0x9C57, 0x6DF2, + 0x9C5B, 0x6DF8, + 0x9C5C, 0x6DFA, + 0x9C69, 0x6E0B, + 0x9C6A, 0x6E0F, + 0x9C6D, 0x6E15, + 0x9C74, 0x6E22, + 0x9C78, 0x6E2A, + 0x9C79, 0x6E2C, + 0x9C7A, 0x6E2E, + 0x9C7D, 0x6E33, + 0x9C7E, 0x6E35, + 0x9C82, 0x6E39, + 0x9C97, 0x6E55, + 0x9C98, 0x6E57, + 0x9CBD, 0x6E84, + 0x9CD5, 0x6EA6, + 0x9CDC, 0x6EB0, + 0x9CDD, 0x6EB3, + 0x9CDE, 0x6EB5, + 0x9CE1, 0x6EBC, + 0x9CEF, 0x6ED0, + 0x9CF0, 0x6ED2, + 0x9CF1, 0x6ED6, + 0x9CF7, 0x6EE3, + 0x9CF8, 0x6EE7, + 0x9D6E, 0x6F2C, + 0x9D6F, 0x6F2E, + 0x9D70, 0x6F30, + 0x9D71, 0x6F32, + 0x9D86, 0x6F4C, + 0x9D94, 0x6F5D, + 0x9DA4, 0x6F73, + 0x9DA8, 0x6F79, + 0x9DA9, 0x6F7B, + 0x9DE1, 0x6FC1, + 0x9DFA, 0x6FDF, + 0x9EBB, 0x706E, + 0x9EC0, 0x7077, + 0x9EC4, 0x707D, + 0x9ED2, 0x7093, + 0x9EE4, 0x70B0, + 0x9EE5, 0x70B2, + 0x9EE9, 0x70BA, + 0x9EF0, 0x70C9, + 0x9EFE, 0x70DA, + 0x9F47, 0x70E5, + 0x9F48, 0x70EA, + 0x9F49, 0x70EE, + 0x9F51, 0x70F8, + 0x9F67, 0x7114, + 0x9F68, 0x7117, + 0x9F80, 0x7135, + 0x9F93, 0x714B, + 0x9F94, 0x714D, + 0x9FA2, 0x715D, + 0x9FA8, 0x7165, + 0x9FB5, 0x7179, + 0x9FE3, 0x71B4, + 0xA04E, 0x71E6, + 0xA08C, 0x7229, + 0xA08D, 0x722B, + 0xA094, 0x723A, + 0xA095, 0x723C, + 0xA096, 0x723E, + 0xA0AA, 0x725A, + 0xA0AB, 0x725C, + 0xA0AC, 0x725E, + 0xA0AD, 0x7260, + 0xA0B1, 0x7268, + 0xA0C7, 0x728C, + 0xA0C8, 0x728E, + 0xA0E3, 0x72AE, + 0xA0E7, 0x72B5, + 0xA0F6, 0x72CF, + 0xA0F7, 0x72D1, + 0xA0FC, 0x72D8, + 0xA1A4, 0x00B7, + 0xA1A5, 0x02C9, + 0xA1A6, 0x02C7, + 0xA1A7, 0x00A8, + 0xA1A8, 0x3003, + 0xA1A9, 0x3005, + 0xA1AA, 0x2014, + 0xA1AB, 0xFF5E, + 0xA1AC, 0x2016, + 0xA1AD, 0x2026, + 0xA1C0, 0x00B1, + 0xA1C1, 0x00D7, + 0xA1C2, 0x00F7, + 0xA1C3, 0x2236, + 0xA1C6, 0x2211, + 0xA1C7, 0x220F, + 0xA1C8, 0x222A, + 0xA1C9, 0x2229, + 0xA1CA, 0x2208, + 0xA1CB, 0x2237, + 0xA1CC, 0x221A, + 0xA1CD, 0x22A5, + 0xA1CE, 0x2225, + 0xA1CF, 0x2220, + 0xA1D0, 0x2312, + 0xA1D1, 0x2299, + 0xA1D2, 0x222B, + 0xA1D3, 0x222E, + 0xA1D4, 0x2261, + 0xA1D5, 0x224C, + 0xA1D6, 0x2248, + 0xA1D7, 0x223D, + 0xA1D8, 0x221D, + 0xA1D9, 0x2260, + 0xA1DE, 0x221E, + 0xA1DF, 0x2235, + 0xA1E0, 0x2234, + 0xA1E1, 0x2642, + 0xA1E2, 0x2640, + 0xA1E3, 0x00B0, + 0xA1E6, 0x2103, + 0xA1E7, 0xFF04, + 0xA1E8, 0x00A4, + 0xA1EB, 0x2030, + 0xA1EC, 0x00A7, + 0xA1ED, 0x2116, + 0xA1EE, 0x2606, + 0xA1EF, 0x2605, + 0xA1F0, 0x25CB, + 0xA1F1, 0x25CF, + 0xA1F2, 0x25CE, + 0xA1F3, 0x25C7, + 0xA1F4, 0x25C6, + 0xA1F5, 0x25A1, + 0xA1F6, 0x25A0, + 0xA1F7, 0x25B3, + 0xA1F8, 0x25B2, + 0xA1F9, 0x203B, + 0xA1FA, 0x2192, + 0xA1FD, 0x2193, + 0xA1FE, 0x3013, + 0xA3A4, 0xFFE5, + 0xA3FE, 0xFFE3, + 0xA6F2, 0xFE31, + 0xA7A7, 0x0401, + 0xA7D7, 0x0451, + 0xA842, 0x02D9, + 0xA843, 0x2013, + 0xA844, 0x2015, + 0xA845, 0x2025, + 0xA846, 0x2035, + 0xA847, 0x2105, + 0xA848, 0x2109, + 0xA84D, 0x2215, + 0xA84E, 0x221F, + 0xA84F, 0x2223, + 0xA850, 0x2252, + 0xA853, 0x22BF, + 0xA891, 0x2609, + 0xA892, 0x2295, + 0xA893, 0x3012, + 0xA8A1, 0x0101, + 0xA8A2, 0x00E1, + 0xA8A3, 0x01CE, + 0xA8A4, 0x00E0, + 0xA8A5, 0x0113, + 0xA8A6, 0x00E9, + 0xA8A7, 0x011B, + 0xA8A8, 0x00E8, + 0xA8A9, 0x012B, + 0xA8AA, 0x00ED, + 0xA8AB, 0x01D0, + 0xA8AC, 0x00EC, + 0xA8AD, 0x014D, + 0xA8AE, 0x00F3, + 0xA8AF, 0x01D2, + 0xA8B0, 0x00F2, + 0xA8B1, 0x016B, + 0xA8B2, 0x00FA, + 0xA8B3, 0x01D4, + 0xA8B4, 0x00F9, + 0xA8B5, 0x01D6, + 0xA8B6, 0x01D8, + 0xA8B7, 0x01DA, + 0xA8B8, 0x01DC, + 0xA8B9, 0x00FC, + 0xA8BA, 0x00EA, + 0xA8BB, 0x0251, + 0xA8BC, 0xE7C7, + 0xA8BD, 0x0144, + 0xA8BE, 0x0148, + 0xA8BF, 0xE7C8, + 0xA8C0, 0x0261, + 0xA949, 0x32A3, + 0xA94F, 0x33A1, + 0xA950, 0x33C4, + 0xA951, 0x33CE, + 0xA954, 0x33D5, + 0xA955, 0xFE30, + 0xA956, 0xFFE2, + 0xA957, 0xFFE4, + 0xA959, 0x2121, + 0xA95A, 0x3231, + 0xA95C, 0x2010, + 0xA960, 0x30FC, + 0xA965, 0x3006, + 0xA996, 0x3007, + 0xAA42, 0x72DF, + 0xAA4D, 0x72F9, + 0xAA52, 0x7302, + 0xAA60, 0x7314, + 0xAA6B, 0x732D, + 0xAA86, 0x7351, + 0xAA9E, 0x736E, + 0xAB53, 0x7388, + 0xAB54, 0x738A, + 0xAB6C, 0x73AA, + 0xAB6F, 0x73B1, + 0xAB79, 0x73C1, + 0xAB82, 0x73CE, + 0xAB8E, 0x73DF, + 0xAB93, 0x73E6, + 0xAB94, 0x73E8, + 0xAC4B, 0x7404, + 0xAC63, 0x7427, + 0xAC64, 0x7429, + 0xAC65, 0x742B, + 0xAC66, 0x742D, + 0xAC67, 0x742F, + 0xAC87, 0x7456, + 0xAC88, 0x7458, + 0xAC89, 0x745D, + 0xAD43, 0x747F, + 0xAD44, 0x7482, + 0xAD4D, 0x748F, + 0xAD59, 0x749D, + 0xAD93, 0x74DD, + 0xAD94, 0x74DF, + 0xAD95, 0x74E1, + 0xAD96, 0x74E5, + 0xAE40, 0x74F3, + 0xAE41, 0x74F5, + 0xAE55, 0x750E, + 0xAE56, 0x7510, + 0xAE57, 0x7512, + 0xAE5C, 0x751B, + 0xAE66, 0x752A, + 0xAE67, 0x752E, + 0xAE68, 0x7534, + 0xAE69, 0x7536, + 0xAE6A, 0x7539, + 0xAE6D, 0x753F, + 0xAE76, 0x754D, + 0xAE92, 0x7573, + 0xAEA0, 0x7587, + 0xAF46, 0x7590, + 0xAF47, 0x7593, + 0xAF48, 0x7595, + 0xAF49, 0x7598, + 0xAF4C, 0x759E, + 0xAF4D, 0x75A2, + 0xAF53, 0x75AD, + 0xAF5B, 0x75C6, + 0xAF62, 0x75D3, + 0xAF63, 0x75D7, + 0xAF6B, 0x75E5, + 0xAF6C, 0x75E9, + 0xAF7B, 0x7602, + 0xAF7C, 0x7604, + 0xAF82, 0x760B, + 0xAF8A, 0x7616, + 0xAF8B, 0x761A, + 0xAF8F, 0x7621, + 0xAF90, 0x7623, + 0xAF93, 0x762C, + 0xAF9D, 0x763D, + 0xAFA0, 0x7644, + 0xB04D, 0x7655, + 0xB053, 0x765D, + 0xB06C, 0x767C, + 0xB070, 0x7683, + 0xB071, 0x7685, + 0xB078, 0x7692, + 0xB093, 0x76B3, + 0xB0A0, 0x76C3, + 0xB0A1, 0x554A, + 0xB0A2, 0x963F, + 0xB0A3, 0x57C3, + 0xB0A4, 0x6328, + 0xB0A5, 0x54CE, + 0xB0A6, 0x5509, + 0xB0A7, 0x54C0, + 0xB0A8, 0x7691, + 0xB0A9, 0x764C, + 0xB0AA, 0x853C, + 0xB0AB, 0x77EE, + 0xB0AC, 0x827E, + 0xB0AD, 0x788D, + 0xB0AE, 0x7231, + 0xB0AF, 0x9698, + 0xB0B0, 0x978D, + 0xB0B1, 0x6C28, + 0xB0B2, 0x5B89, + 0xB0B3, 0x4FFA, + 0xB0B4, 0x6309, + 0xB0B5, 0x6697, + 0xB0B6, 0x5CB8, + 0xB0B7, 0x80FA, + 0xB0B8, 0x6848, + 0xB0B9, 0x80AE, + 0xB0BA, 0x6602, + 0xB0BB, 0x76CE, + 0xB0BC, 0x51F9, + 0xB0BD, 0x6556, + 0xB0BE, 0x71AC, + 0xB0BF, 0x7FF1, + 0xB0C0, 0x8884, + 0xB0C1, 0x50B2, + 0xB0C2, 0x5965, + 0xB0C3, 0x61CA, + 0xB0C4, 0x6FB3, + 0xB0C5, 0x82AD, + 0xB0C6, 0x634C, + 0xB0C7, 0x6252, + 0xB0C8, 0x53ED, + 0xB0C9, 0x5427, + 0xB0CA, 0x7B06, + 0xB0CB, 0x516B, + 0xB0CC, 0x75A4, + 0xB0CD, 0x5DF4, + 0xB0CE, 0x62D4, + 0xB0CF, 0x8DCB, + 0xB0D0, 0x9776, + 0xB0D1, 0x628A, + 0xB0D2, 0x8019, + 0xB0D3, 0x575D, + 0xB0D4, 0x9738, + 0xB0D5, 0x7F62, + 0xB0D6, 0x7238, + 0xB0D7, 0x767D, + 0xB0D8, 0x67CF, + 0xB0D9, 0x767E, + 0xB0DA, 0x6446, + 0xB0DB, 0x4F70, + 0xB0DC, 0x8D25, + 0xB0DD, 0x62DC, + 0xB0DE, 0x7A17, + 0xB0DF, 0x6591, + 0xB0E0, 0x73ED, + 0xB0E1, 0x642C, + 0xB0E2, 0x6273, + 0xB0E3, 0x822C, + 0xB0E4, 0x9881, + 0xB0E5, 0x677F, + 0xB0E6, 0x7248, + 0xB0E7, 0x626E, + 0xB0E8, 0x62CC, + 0xB0E9, 0x4F34, + 0xB0EA, 0x74E3, + 0xB0EB, 0x534A, + 0xB0EC, 0x529E, + 0xB0ED, 0x7ECA, + 0xB0EE, 0x90A6, + 0xB0EF, 0x5E2E, + 0xB0F0, 0x6886, + 0xB0F1, 0x699C, + 0xB0F2, 0x8180, + 0xB0F3, 0x7ED1, + 0xB0F4, 0x68D2, + 0xB0F5, 0x78C5, + 0xB0F6, 0x868C, + 0xB0F7, 0x9551, + 0xB0F8, 0x508D, + 0xB0F9, 0x8C24, + 0xB0FA, 0x82DE, + 0xB0FB, 0x80DE, + 0xB0FC, 0x5305, + 0xB0FD, 0x8912, + 0xB0FE, 0x5265, + 0xB140, 0x76C4, + 0xB141, 0x76C7, + 0xB142, 0x76C9, + 0xB145, 0x76D3, + 0xB146, 0x76D5, + 0xB159, 0x76F0, + 0xB15A, 0x76F3, + 0xB160, 0x76FD, + 0xB167, 0x770A, + 0xB168, 0x770C, + 0xB178, 0x7721, + 0xB17C, 0x7727, + 0xB180, 0x772C, + 0xB181, 0x772E, + 0xB187, 0x7739, + 0xB188, 0x773B, + 0xB18C, 0x7742, + 0xB1A0, 0x775C, + 0xB1A1, 0x8584, + 0xB1A2, 0x96F9, + 0xB1A3, 0x4FDD, + 0xB1A4, 0x5821, + 0xB1A5, 0x9971, + 0xB1A6, 0x5B9D, + 0xB1A7, 0x62B1, + 0xB1A8, 0x62A5, + 0xB1A9, 0x66B4, + 0xB1AA, 0x8C79, + 0xB1AB, 0x9C8D, + 0xB1AC, 0x7206, + 0xB1AD, 0x676F, + 0xB1AE, 0x7891, + 0xB1AF, 0x60B2, + 0xB1B0, 0x5351, + 0xB1B1, 0x5317, + 0xB1B2, 0x8F88, + 0xB1B3, 0x80CC, + 0xB1B4, 0x8D1D, + 0xB1B5, 0x94A1, + 0xB1B6, 0x500D, + 0xB1B7, 0x72C8, + 0xB1B8, 0x5907, + 0xB1B9, 0x60EB, + 0xB1BA, 0x7119, + 0xB1BB, 0x88AB, + 0xB1BC, 0x5954, + 0xB1BD, 0x82EF, + 0xB1BE, 0x672C, + 0xB1BF, 0x7B28, + 0xB1C0, 0x5D29, + 0xB1C1, 0x7EF7, + 0xB1C2, 0x752D, + 0xB1C3, 0x6CF5, + 0xB1C4, 0x8E66, + 0xB1C5, 0x8FF8, + 0xB1C6, 0x903C, + 0xB1C7, 0x9F3B, + 0xB1C8, 0x6BD4, + 0xB1C9, 0x9119, + 0xB1CA, 0x7B14, + 0xB1CB, 0x5F7C, + 0xB1CC, 0x78A7, + 0xB1CD, 0x84D6, + 0xB1CE, 0x853D, + 0xB1CF, 0x6BD5, + 0xB1D0, 0x6BD9, + 0xB1D1, 0x6BD6, + 0xB1D2, 0x5E01, + 0xB1D3, 0x5E87, + 0xB1D4, 0x75F9, + 0xB1D5, 0x95ED, + 0xB1D6, 0x655D, + 0xB1D7, 0x5F0A, + 0xB1D8, 0x5FC5, + 0xB1D9, 0x8F9F, + 0xB1DA, 0x58C1, + 0xB1DB, 0x81C2, + 0xB1DC, 0x907F, + 0xB1DD, 0x965B, + 0xB1DE, 0x97AD, + 0xB1DF, 0x8FB9, + 0xB1E0, 0x7F16, + 0xB1E1, 0x8D2C, + 0xB1E2, 0x6241, + 0xB1E3, 0x4FBF, + 0xB1E4, 0x53D8, + 0xB1E5, 0x535E, + 0xB1E8, 0x8FAB, + 0xB1E9, 0x904D, + 0xB1EA, 0x6807, + 0xB1EB, 0x5F6A, + 0xB1EC, 0x8198, + 0xB1ED, 0x8868, + 0xB1EE, 0x9CD6, + 0xB1EF, 0x618B, + 0xB1F0, 0x522B, + 0xB1F1, 0x762A, + 0xB1F2, 0x5F6C, + 0xB1F3, 0x658C, + 0xB1F4, 0x6FD2, + 0xB1F5, 0x6EE8, + 0xB1F6, 0x5BBE, + 0xB1F7, 0x6448, + 0xB1F8, 0x5175, + 0xB1F9, 0x51B0, + 0xB1FA, 0x67C4, + 0xB1FB, 0x4E19, + 0xB1FC, 0x79C9, + 0xB1FD, 0x997C, + 0xB1FE, 0x70B3, + 0xB244, 0x7764, + 0xB245, 0x7767, + 0xB26E, 0x77A1, + 0xB271, 0x77A6, + 0xB272, 0x77A8, + 0xB273, 0x77AB, + 0xB279, 0x77B4, + 0xB280, 0x77BC, + 0xB281, 0x77BE, + 0xB2A0, 0x77E4, + 0xB2A1, 0x75C5, + 0xB2A2, 0x5E76, + 0xB2A3, 0x73BB, + 0xB2A4, 0x83E0, + 0xB2A5, 0x64AD, + 0xB2A6, 0x62E8, + 0xB2A7, 0x94B5, + 0xB2A8, 0x6CE2, + 0xB2A9, 0x535A, + 0xB2AA, 0x52C3, + 0xB2AB, 0x640F, + 0xB2AC, 0x94C2, + 0xB2AD, 0x7B94, + 0xB2AE, 0x4F2F, + 0xB2AF, 0x5E1B, + 0xB2B0, 0x8236, + 0xB2B1, 0x8116, + 0xB2B2, 0x818A, + 0xB2B3, 0x6E24, + 0xB2B4, 0x6CCA, + 0xB2B5, 0x9A73, + 0xB2B6, 0x6355, + 0xB2B7, 0x535C, + 0xB2B8, 0x54FA, + 0xB2B9, 0x8865, + 0xB2BA, 0x57E0, + 0xB2BB, 0x4E0D, + 0xB2BC, 0x5E03, + 0xB2BD, 0x6B65, + 0xB2BE, 0x7C3F, + 0xB2BF, 0x90E8, + 0xB2C0, 0x6016, + 0xB2C1, 0x64E6, + 0xB2C2, 0x731C, + 0xB2C3, 0x88C1, + 0xB2C4, 0x6750, + 0xB2C5, 0x624D, + 0xB2C6, 0x8D22, + 0xB2C7, 0x776C, + 0xB2C8, 0x8E29, + 0xB2C9, 0x91C7, + 0xB2CA, 0x5F69, + 0xB2CB, 0x83DC, + 0xB2CC, 0x8521, + 0xB2CD, 0x9910, + 0xB2CE, 0x53C2, + 0xB2CF, 0x8695, + 0xB2D0, 0x6B8B, + 0xB2D1, 0x60ED, + 0xB2D2, 0x60E8, + 0xB2D3, 0x707F, + 0xB2D4, 0x82CD, + 0xB2D5, 0x8231, + 0xB2D6, 0x4ED3, + 0xB2D7, 0x6CA7, + 0xB2D8, 0x85CF, + 0xB2D9, 0x64CD, + 0xB2DA, 0x7CD9, + 0xB2DB, 0x69FD, + 0xB2DC, 0x66F9, + 0xB2DD, 0x8349, + 0xB2DE, 0x5395, + 0xB2DF, 0x7B56, + 0xB2E0, 0x4FA7, + 0xB2E1, 0x518C, + 0xB2E2, 0x6D4B, + 0xB2E3, 0x5C42, + 0xB2E4, 0x8E6D, + 0xB2E5, 0x63D2, + 0xB2E6, 0x53C9, + 0xB2E7, 0x832C, + 0xB2E8, 0x8336, + 0xB2E9, 0x67E5, + 0xB2EA, 0x78B4, + 0xB2EB, 0x643D, + 0xB2EC, 0x5BDF, + 0xB2ED, 0x5C94, + 0xB2EE, 0x5DEE, + 0xB2EF, 0x8BE7, + 0xB2F0, 0x62C6, + 0xB2F1, 0x67F4, + 0xB2F2, 0x8C7A, + 0xB2F3, 0x6400, + 0xB2F4, 0x63BA, + 0xB2F5, 0x8749, + 0xB2F6, 0x998B, + 0xB2F7, 0x8C17, + 0xB2F8, 0x7F20, + 0xB2F9, 0x94F2, + 0xB2FA, 0x4EA7, + 0xB2FB, 0x9610, + 0xB2FC, 0x98A4, + 0xB2FD, 0x660C, + 0xB2FE, 0x7316, + 0xB340, 0x77E6, + 0xB341, 0x77E8, + 0xB342, 0x77EA, + 0xB349, 0x77F7, + 0xB359, 0x7813, + 0xB35A, 0x7815, + 0xB35B, 0x7819, + 0xB35C, 0x781B, + 0xB35D, 0x781E, + 0xB361, 0x7824, + 0xB362, 0x7828, + 0xB36C, 0x783D, + 0xB36D, 0x783F, + 0xB372, 0x7846, + 0xB377, 0x784D, + 0xB378, 0x784F, + 0xB379, 0x7851, + 0xB3A1, 0x573A, + 0xB3A2, 0x5C1D, + 0xB3A3, 0x5E38, + 0xB3A4, 0x957F, + 0xB3A5, 0x507F, + 0xB3A6, 0x80A0, + 0xB3A7, 0x5382, + 0xB3A8, 0x655E, + 0xB3A9, 0x7545, + 0xB3AA, 0x5531, + 0xB3AB, 0x5021, + 0xB3AC, 0x8D85, + 0xB3AD, 0x6284, + 0xB3AE, 0x949E, + 0xB3AF, 0x671D, + 0xB3B0, 0x5632, + 0xB3B1, 0x6F6E, + 0xB3B2, 0x5DE2, + 0xB3B3, 0x5435, + 0xB3B4, 0x7092, + 0xB3B5, 0x8F66, + 0xB3B6, 0x626F, + 0xB3B7, 0x64A4, + 0xB3B8, 0x63A3, + 0xB3B9, 0x5F7B, + 0xB3BA, 0x6F88, + 0xB3BB, 0x90F4, + 0xB3BC, 0x81E3, + 0xB3BD, 0x8FB0, + 0xB3BE, 0x5C18, + 0xB3BF, 0x6668, + 0xB3C0, 0x5FF1, + 0xB3C1, 0x6C89, + 0xB3C2, 0x9648, + 0xB3C3, 0x8D81, + 0xB3C4, 0x886C, + 0xB3C5, 0x6491, + 0xB3C6, 0x79F0, + 0xB3C7, 0x57CE, + 0xB3C8, 0x6A59, + 0xB3C9, 0x6210, + 0xB3CA, 0x5448, + 0xB3CB, 0x4E58, + 0xB3CC, 0x7A0B, + 0xB3CD, 0x60E9, + 0xB3CE, 0x6F84, + 0xB3CF, 0x8BDA, + 0xB3D0, 0x627F, + 0xB3D1, 0x901E, + 0xB3D2, 0x9A8B, + 0xB3D3, 0x79E4, + 0xB3D4, 0x5403, + 0xB3D5, 0x75F4, + 0xB3D6, 0x6301, + 0xB3D7, 0x5319, + 0xB3D8, 0x6C60, + 0xB3D9, 0x8FDF, + 0xB3DA, 0x5F1B, + 0xB3DB, 0x9A70, + 0xB3DC, 0x803B, + 0xB3DD, 0x9F7F, + 0xB3DE, 0x4F88, + 0xB3DF, 0x5C3A, + 0xB3E0, 0x8D64, + 0xB3E1, 0x7FC5, + 0xB3E2, 0x65A5, + 0xB3E3, 0x70BD, + 0xB3E4, 0x5145, + 0xB3E5, 0x51B2, + 0xB3E6, 0x866B, + 0xB3E7, 0x5D07, + 0xB3E8, 0x5BA0, + 0xB3E9, 0x62BD, + 0xB3EA, 0x916C, + 0xB3EB, 0x7574, + 0xB3EC, 0x8E0C, + 0xB3ED, 0x7A20, + 0xB3EE, 0x6101, + 0xB3EF, 0x7B79, + 0xB3F0, 0x4EC7, + 0xB3F1, 0x7EF8, + 0xB3F2, 0x7785, + 0xB3F3, 0x4E11, + 0xB3F4, 0x81ED, + 0xB3F5, 0x521D, + 0xB3F6, 0x51FA, + 0xB3F7, 0x6A71, + 0xB3F8, 0x53A8, + 0xB3F9, 0x8E87, + 0xB3FA, 0x9504, + 0xB3FB, 0x96CF, + 0xB3FC, 0x6EC1, + 0xB3FD, 0x9664, + 0xB3FE, 0x695A, + 0xB443, 0x7888, + 0xB448, 0x7892, + 0xB44C, 0x7899, + 0xB44F, 0x78A0, + 0xB450, 0x78A2, + 0xB451, 0x78A4, + 0xB452, 0x78A6, + 0xB48C, 0x78F3, + 0xB4A1, 0x7840, + 0xB4A2, 0x50A8, + 0xB4A3, 0x77D7, + 0xB4A4, 0x6410, + 0xB4A5, 0x89E6, + 0xB4A6, 0x5904, + 0xB4A7, 0x63E3, + 0xB4A8, 0x5DDD, + 0xB4A9, 0x7A7F, + 0xB4AA, 0x693D, + 0xB4AB, 0x4F20, + 0xB4AC, 0x8239, + 0xB4AD, 0x5598, + 0xB4AE, 0x4E32, + 0xB4AF, 0x75AE, + 0xB4B0, 0x7A97, + 0xB4B1, 0x5E62, + 0xB4B2, 0x5E8A, + 0xB4B3, 0x95EF, + 0xB4B4, 0x521B, + 0xB4B5, 0x5439, + 0xB4B6, 0x708A, + 0xB4B7, 0x6376, + 0xB4B8, 0x9524, + 0xB4B9, 0x5782, + 0xB4BA, 0x6625, + 0xB4BB, 0x693F, + 0xB4BC, 0x9187, + 0xB4BD, 0x5507, + 0xB4BE, 0x6DF3, + 0xB4BF, 0x7EAF, + 0xB4C0, 0x8822, + 0xB4C1, 0x6233, + 0xB4C2, 0x7EF0, + 0xB4C3, 0x75B5, + 0xB4C4, 0x8328, + 0xB4C5, 0x78C1, + 0xB4C6, 0x96CC, + 0xB4C7, 0x8F9E, + 0xB4C8, 0x6148, + 0xB4C9, 0x74F7, + 0xB4CA, 0x8BCD, + 0xB4CB, 0x6B64, + 0xB4CC, 0x523A, + 0xB4CD, 0x8D50, + 0xB4CE, 0x6B21, + 0xB4CF, 0x806A, + 0xB4D0, 0x8471, + 0xB4D1, 0x56F1, + 0xB4D2, 0x5306, + 0xB4D3, 0x4ECE, + 0xB4D4, 0x4E1B, + 0xB4D5, 0x51D1, + 0xB4D6, 0x7C97, + 0xB4D7, 0x918B, + 0xB4D8, 0x7C07, + 0xB4D9, 0x4FC3, + 0xB4DA, 0x8E7F, + 0xB4DB, 0x7BE1, + 0xB4DC, 0x7A9C, + 0xB4DD, 0x6467, + 0xB4DE, 0x5D14, + 0xB4DF, 0x50AC, + 0xB4E0, 0x8106, + 0xB4E1, 0x7601, + 0xB4E2, 0x7CB9, + 0xB4E3, 0x6DEC, + 0xB4E4, 0x7FE0, + 0xB4E5, 0x6751, + 0xB4E6, 0x5B58, + 0xB4E7, 0x5BF8, + 0xB4E8, 0x78CB, + 0xB4E9, 0x64AE, + 0xB4EA, 0x6413, + 0xB4EB, 0x63AA, + 0xB4EC, 0x632B, + 0xB4ED, 0x9519, + 0xB4EE, 0x642D, + 0xB4EF, 0x8FBE, + 0xB4F0, 0x7B54, + 0xB4F1, 0x7629, + 0xB4F2, 0x6253, + 0xB4F3, 0x5927, + 0xB4F4, 0x5446, + 0xB4F5, 0x6B79, + 0xB4F6, 0x50A3, + 0xB4F7, 0x6234, + 0xB4F8, 0x5E26, + 0xB4F9, 0x6B86, + 0xB4FA, 0x4EE3, + 0xB4FB, 0x8D37, + 0xB4FC, 0x888B, + 0xB4FD, 0x5F85, + 0xB4FE, 0x902E, + 0xB569, 0x793D, + 0xB56A, 0x793F, + 0xB56F, 0x7947, + 0xB57D, 0x7961, + 0xB57E, 0x7963, + 0xB580, 0x7964, + 0xB581, 0x7966, + 0xB586, 0x796E, + 0xB58E, 0x7979, + 0xB5A1, 0x6020, + 0xB5A2, 0x803D, + 0xB5A3, 0x62C5, + 0xB5A4, 0x4E39, + 0xB5A5, 0x5355, + 0xB5A6, 0x90F8, + 0xB5A7, 0x63B8, + 0xB5A8, 0x80C6, + 0xB5A9, 0x65E6, + 0xB5AA, 0x6C2E, + 0xB5AB, 0x4F46, + 0xB5AC, 0x60EE, + 0xB5AD, 0x6DE1, + 0xB5AE, 0x8BDE, + 0xB5AF, 0x5F39, + 0xB5B0, 0x86CB, + 0xB5B1, 0x5F53, + 0xB5B2, 0x6321, + 0xB5B3, 0x515A, + 0xB5B4, 0x8361, + 0xB5B5, 0x6863, + 0xB5B6, 0x5200, + 0xB5B7, 0x6363, + 0xB5B8, 0x8E48, + 0xB5B9, 0x5012, + 0xB5BA, 0x5C9B, + 0xB5BB, 0x7977, + 0xB5BC, 0x5BFC, + 0xB5BD, 0x5230, + 0xB5BE, 0x7A3B, + 0xB5BF, 0x60BC, + 0xB5C0, 0x9053, + 0xB5C1, 0x76D7, + 0xB5C2, 0x5FB7, + 0xB5C3, 0x5F97, + 0xB5C4, 0x7684, + 0xB5C5, 0x8E6C, + 0xB5C6, 0x706F, + 0xB5C7, 0x767B, + 0xB5C8, 0x7B49, + 0xB5C9, 0x77AA, + 0xB5CA, 0x51F3, + 0xB5CB, 0x9093, + 0xB5CC, 0x5824, + 0xB5CD, 0x4F4E, + 0xB5CE, 0x6EF4, + 0xB5CF, 0x8FEA, + 0xB5D0, 0x654C, + 0xB5D1, 0x7B1B, + 0xB5D2, 0x72C4, + 0xB5D3, 0x6DA4, + 0xB5D4, 0x7FDF, + 0xB5D5, 0x5AE1, + 0xB5D6, 0x62B5, + 0xB5D7, 0x5E95, + 0xB5D8, 0x5730, + 0xB5D9, 0x8482, + 0xB5DA, 0x7B2C, + 0xB5DB, 0x5E1D, + 0xB5DC, 0x5F1F, + 0xB5DD, 0x9012, + 0xB5DE, 0x7F14, + 0xB5DF, 0x98A0, + 0xB5E0, 0x6382, + 0xB5E1, 0x6EC7, + 0xB5E2, 0x7898, + 0xB5E3, 0x70B9, + 0xB5E4, 0x5178, + 0xB5E5, 0x975B, + 0xB5E6, 0x57AB, + 0xB5E7, 0x7535, + 0xB5E8, 0x4F43, + 0xB5E9, 0x7538, + 0xB5EA, 0x5E97, + 0xB5EB, 0x60E6, + 0xB5EC, 0x5960, + 0xB5ED, 0x6DC0, + 0xB5EE, 0x6BBF, + 0xB5EF, 0x7889, + 0xB5F0, 0x53FC, + 0xB5F1, 0x96D5, + 0xB5F2, 0x51CB, + 0xB5F3, 0x5201, + 0xB5F4, 0x6389, + 0xB5F5, 0x540A, + 0xB5F6, 0x9493, + 0xB5F7, 0x8C03, + 0xB5F8, 0x8DCC, + 0xB5F9, 0x7239, + 0xB5FA, 0x789F, + 0xB5FB, 0x8776, + 0xB5FC, 0x8FED, + 0xB5FD, 0x8C0D, + 0xB5FE, 0x53E0, + 0xB663, 0x79BC, + 0xB664, 0x79BF, + 0xB665, 0x79C2, + 0xB66A, 0x79CA, + 0xB66B, 0x79CC, + 0xB67C, 0x79E5, + 0xB67D, 0x79E8, + 0xB67E, 0x79EA, + 0xB680, 0x79EC, + 0xB681, 0x79EE, + 0xB68B, 0x79FC, + 0xB68E, 0x7A01, + 0xB695, 0x7A0C, + 0xB6A1, 0x4E01, + 0xB6A2, 0x76EF, + 0xB6A3, 0x53EE, + 0xB6A4, 0x9489, + 0xB6A5, 0x9876, + 0xB6A6, 0x9F0E, + 0xB6A7, 0x952D, + 0xB6A8, 0x5B9A, + 0xB6A9, 0x8BA2, + 0xB6AA, 0x4E22, + 0xB6AB, 0x4E1C, + 0xB6AC, 0x51AC, + 0xB6AD, 0x8463, + 0xB6AE, 0x61C2, + 0xB6AF, 0x52A8, + 0xB6B0, 0x680B, + 0xB6B1, 0x4F97, + 0xB6B2, 0x606B, + 0xB6B3, 0x51BB, + 0xB6B4, 0x6D1E, + 0xB6B5, 0x515C, + 0xB6B6, 0x6296, + 0xB6B7, 0x6597, + 0xB6B8, 0x9661, + 0xB6B9, 0x8C46, + 0xB6BA, 0x9017, + 0xB6BB, 0x75D8, + 0xB6BC, 0x90FD, + 0xB6BD, 0x7763, + 0xB6BE, 0x6BD2, + 0xB6BF, 0x728A, + 0xB6C0, 0x72EC, + 0xB6C1, 0x8BFB, + 0xB6C2, 0x5835, + 0xB6C3, 0x7779, + 0xB6C4, 0x8D4C, + 0xB6C5, 0x675C, + 0xB6C6, 0x9540, + 0xB6C7, 0x809A, + 0xB6C8, 0x5EA6, + 0xB6C9, 0x6E21, + 0xB6CA, 0x5992, + 0xB6CB, 0x7AEF, + 0xB6CC, 0x77ED, + 0xB6CD, 0x953B, + 0xB6CE, 0x6BB5, + 0xB6CF, 0x65AD, + 0xB6D0, 0x7F0E, + 0xB6D1, 0x5806, + 0xB6D2, 0x5151, + 0xB6D3, 0x961F, + 0xB6D4, 0x5BF9, + 0xB6D5, 0x58A9, + 0xB6D6, 0x5428, + 0xB6D7, 0x8E72, + 0xB6D8, 0x6566, + 0xB6D9, 0x987F, + 0xB6DA, 0x56E4, + 0xB6DB, 0x949D, + 0xB6DC, 0x76FE, + 0xB6DD, 0x9041, + 0xB6DE, 0x6387, + 0xB6DF, 0x54C6, + 0xB6E0, 0x591A, + 0xB6E1, 0x593A, + 0xB6E2, 0x579B, + 0xB6E3, 0x8EB2, + 0xB6E4, 0x6735, + 0xB6E5, 0x8DFA, + 0xB6E6, 0x8235, + 0xB6E7, 0x5241, + 0xB6E8, 0x60F0, + 0xB6E9, 0x5815, + 0xB6EA, 0x86FE, + 0xB6EB, 0x5CE8, + 0xB6EC, 0x9E45, + 0xB6ED, 0x4FC4, + 0xB6EE, 0x989D, + 0xB6EF, 0x8BB9, + 0xB6F0, 0x5A25, + 0xB6F1, 0x6076, + 0xB6F2, 0x5384, + 0xB6F3, 0x627C, + 0xB6F4, 0x904F, + 0xB6F5, 0x9102, + 0xB6F6, 0x997F, + 0xB6F7, 0x6069, + 0xB6F8, 0x800C, + 0xB6F9, 0x513F, + 0xB6FA, 0x8033, + 0xB6FB, 0x5C14, + 0xB6FC, 0x9975, + 0xB6FD, 0x6D31, + 0xB6FE, 0x4E8C, + 0xB740, 0x7A1D, + 0xB741, 0x7A1F, + 0xB756, 0x7A38, + 0xB757, 0x7A3A, + 0xB758, 0x7A3E, + 0xB78A, 0x7A75, + 0xB78F, 0x7A82, + 0xB790, 0x7A85, + 0xB791, 0x7A87, + 0xB79E, 0x7A9E, + 0xB7A1, 0x8D30, + 0xB7A2, 0x53D1, + 0xB7A3, 0x7F5A, + 0xB7A4, 0x7B4F, + 0xB7A5, 0x4F10, + 0xB7A6, 0x4E4F, + 0xB7A7, 0x9600, + 0xB7A8, 0x6CD5, + 0xB7A9, 0x73D0, + 0xB7AA, 0x85E9, + 0xB7AB, 0x5E06, + 0xB7AC, 0x756A, + 0xB7AD, 0x7FFB, + 0xB7AE, 0x6A0A, + 0xB7AF, 0x77FE, + 0xB7B0, 0x9492, + 0xB7B1, 0x7E41, + 0xB7B2, 0x51E1, + 0xB7B3, 0x70E6, + 0xB7B4, 0x53CD, + 0xB7B5, 0x8FD4, + 0xB7B6, 0x8303, + 0xB7B7, 0x8D29, + 0xB7B8, 0x72AF, + 0xB7B9, 0x996D, + 0xB7BA, 0x6CDB, + 0xB7BB, 0x574A, + 0xB7BC, 0x82B3, + 0xB7BD, 0x65B9, + 0xB7BE, 0x80AA, + 0xB7BF, 0x623F, + 0xB7C0, 0x9632, + 0xB7C1, 0x59A8, + 0xB7C2, 0x4EFF, + 0xB7C3, 0x8BBF, + 0xB7C4, 0x7EBA, + 0xB7C5, 0x653E, + 0xB7C6, 0x83F2, + 0xB7C7, 0x975E, + 0xB7C8, 0x5561, + 0xB7C9, 0x98DE, + 0xB7CA, 0x80A5, + 0xB7CB, 0x532A, + 0xB7CC, 0x8BFD, + 0xB7CD, 0x5420, + 0xB7CE, 0x80BA, + 0xB7CF, 0x5E9F, + 0xB7D0, 0x6CB8, + 0xB7D1, 0x8D39, + 0xB7D2, 0x82AC, + 0xB7D3, 0x915A, + 0xB7D4, 0x5429, + 0xB7D5, 0x6C1B, + 0xB7D6, 0x5206, + 0xB7D7, 0x7EB7, + 0xB7D8, 0x575F, + 0xB7D9, 0x711A, + 0xB7DA, 0x6C7E, + 0xB7DB, 0x7C89, + 0xB7DC, 0x594B, + 0xB7DD, 0x4EFD, + 0xB7DE, 0x5FFF, + 0xB7DF, 0x6124, + 0xB7E0, 0x7CAA, + 0xB7E1, 0x4E30, + 0xB7E2, 0x5C01, + 0xB7E3, 0x67AB, + 0xB7E4, 0x8702, + 0xB7E5, 0x5CF0, + 0xB7E6, 0x950B, + 0xB7E7, 0x98CE, + 0xB7E8, 0x75AF, + 0xB7E9, 0x70FD, + 0xB7EA, 0x9022, + 0xB7EB, 0x51AF, + 0xB7EC, 0x7F1D, + 0xB7ED, 0x8BBD, + 0xB7EE, 0x5949, + 0xB7EF, 0x51E4, + 0xB7F0, 0x4F5B, + 0xB7F1, 0x5426, + 0xB7F2, 0x592B, + 0xB7F3, 0x6577, + 0xB7F4, 0x80A4, + 0xB7F5, 0x5B75, + 0xB7F6, 0x6276, + 0xB7F7, 0x62C2, + 0xB7F8, 0x8F90, + 0xB7F9, 0x5E45, + 0xB7FA, 0x6C1F, + 0xB7FB, 0x7B26, + 0xB7FC, 0x4F0F, + 0xB7FD, 0x4FD8, + 0xB7FE, 0x670D, + 0xB842, 0x7AA7, + 0xB873, 0x7AE4, + 0xB87A, 0x7AEE, + 0xB887, 0x7AFE, + 0xB88B, 0x7B05, + 0xB88C, 0x7B07, + 0xB88D, 0x7B09, + 0xB891, 0x7B10, + 0xB897, 0x7B1A, + 0xB89A, 0x7B1F, + 0xB89E, 0x7B27, + 0xB89F, 0x7B29, + 0xB8A0, 0x7B2D, + 0xB8A1, 0x6D6E, + 0xB8A2, 0x6DAA, + 0xB8A3, 0x798F, + 0xB8A4, 0x88B1, + 0xB8A5, 0x5F17, + 0xB8A6, 0x752B, + 0xB8A7, 0x629A, + 0xB8A8, 0x8F85, + 0xB8A9, 0x4FEF, + 0xB8AA, 0x91DC, + 0xB8AB, 0x65A7, + 0xB8AC, 0x812F, + 0xB8AD, 0x8151, + 0xB8AE, 0x5E9C, + 0xB8AF, 0x8150, + 0xB8B0, 0x8D74, + 0xB8B1, 0x526F, + 0xB8B2, 0x8986, + 0xB8B3, 0x8D4B, + 0xB8B4, 0x590D, + 0xB8B5, 0x5085, + 0xB8B6, 0x4ED8, + 0xB8B7, 0x961C, + 0xB8B8, 0x7236, + 0xB8B9, 0x8179, + 0xB8BA, 0x8D1F, + 0xB8BB, 0x5BCC, + 0xB8BC, 0x8BA3, + 0xB8BD, 0x9644, + 0xB8BE, 0x5987, + 0xB8BF, 0x7F1A, + 0xB8C0, 0x5490, + 0xB8C1, 0x5676, + 0xB8C2, 0x560E, + 0xB8C3, 0x8BE5, + 0xB8C4, 0x6539, + 0xB8C5, 0x6982, + 0xB8C6, 0x9499, + 0xB8C7, 0x76D6, + 0xB8C8, 0x6E89, + 0xB8C9, 0x5E72, + 0xB8CA, 0x7518, + 0xB8CB, 0x6746, + 0xB8CC, 0x67D1, + 0xB8CD, 0x7AFF, + 0xB8CE, 0x809D, + 0xB8CF, 0x8D76, + 0xB8D0, 0x611F, + 0xB8D1, 0x79C6, + 0xB8D2, 0x6562, + 0xB8D3, 0x8D63, + 0xB8D4, 0x5188, + 0xB8D5, 0x521A, + 0xB8D6, 0x94A2, + 0xB8D7, 0x7F38, + 0xB8D8, 0x809B, + 0xB8D9, 0x7EB2, + 0xB8DA, 0x5C97, + 0xB8DB, 0x6E2F, + 0xB8DC, 0x6760, + 0xB8DD, 0x7BD9, + 0xB8DE, 0x768B, + 0xB8DF, 0x9AD8, + 0xB8E0, 0x818F, + 0xB8E1, 0x7F94, + 0xB8E2, 0x7CD5, + 0xB8E3, 0x641E, + 0xB8E4, 0x9550, + 0xB8E5, 0x7A3F, + 0xB8E6, 0x544A, + 0xB8E7, 0x54E5, + 0xB8E8, 0x6B4C, + 0xB8E9, 0x6401, + 0xB8EA, 0x6208, + 0xB8EB, 0x9E3D, + 0xB8EC, 0x80F3, + 0xB8ED, 0x7599, + 0xB8EE, 0x5272, + 0xB8EF, 0x9769, + 0xB8F0, 0x845B, + 0xB8F1, 0x683C, + 0xB8F2, 0x86E4, + 0xB8F3, 0x9601, + 0xB8F4, 0x9694, + 0xB8F5, 0x94EC, + 0xB8F6, 0x4E2A, + 0xB8F7, 0x5404, + 0xB8F8, 0x7ED9, + 0xB8F9, 0x6839, + 0xB8FA, 0x8DDF, + 0xB8FB, 0x8015, + 0xB8FC, 0x66F4, + 0xB8FD, 0x5E9A, + 0xB8FE, 0x7FB9, + 0xB942, 0x7B32, + 0xB947, 0x7B39, + 0xB948, 0x7B3B, + 0xB949, 0x7B3D, + 0xB950, 0x7B46, + 0xB951, 0x7B48, + 0xB952, 0x7B4A, + 0xB955, 0x7B53, + 0xB956, 0x7B55, + 0xB957, 0x7B57, + 0xB958, 0x7B59, + 0xB959, 0x7B5C, + 0xB95C, 0x7B61, + 0xB96C, 0x7B76, + 0xB96D, 0x7B78, + 0xB96E, 0x7B7A, + 0xB971, 0x7B7F, + 0xB983, 0x7B96, + 0xB9A1, 0x57C2, + 0xB9A2, 0x803F, + 0xB9A3, 0x6897, + 0xB9A4, 0x5DE5, + 0xB9A5, 0x653B, + 0xB9A6, 0x529F, + 0xB9A7, 0x606D, + 0xB9A8, 0x9F9A, + 0xB9A9, 0x4F9B, + 0xB9AA, 0x8EAC, + 0xB9AB, 0x516C, + 0xB9AC, 0x5BAB, + 0xB9AD, 0x5F13, + 0xB9AE, 0x5DE9, + 0xB9AF, 0x6C5E, + 0xB9B0, 0x62F1, + 0xB9B1, 0x8D21, + 0xB9B2, 0x5171, + 0xB9B3, 0x94A9, + 0xB9B4, 0x52FE, + 0xB9B5, 0x6C9F, + 0xB9B6, 0x82DF, + 0xB9B7, 0x72D7, + 0xB9B8, 0x57A2, + 0xB9B9, 0x6784, + 0xB9BA, 0x8D2D, + 0xB9BB, 0x591F, + 0xB9BC, 0x8F9C, + 0xB9BD, 0x83C7, + 0xB9BE, 0x5495, + 0xB9BF, 0x7B8D, + 0xB9C0, 0x4F30, + 0xB9C1, 0x6CBD, + 0xB9C2, 0x5B64, + 0xB9C3, 0x59D1, + 0xB9C4, 0x9F13, + 0xB9C5, 0x53E4, + 0xB9C6, 0x86CA, + 0xB9C7, 0x9AA8, + 0xB9C8, 0x8C37, + 0xB9C9, 0x80A1, + 0xB9CA, 0x6545, + 0xB9CB, 0x987E, + 0xB9CC, 0x56FA, + 0xB9CD, 0x96C7, + 0xB9CE, 0x522E, + 0xB9CF, 0x74DC, + 0xB9D0, 0x5250, + 0xB9D1, 0x5BE1, + 0xB9D2, 0x6302, + 0xB9D3, 0x8902, + 0xB9D4, 0x4E56, + 0xB9D5, 0x62D0, + 0xB9D6, 0x602A, + 0xB9D7, 0x68FA, + 0xB9D8, 0x5173, + 0xB9D9, 0x5B98, + 0xB9DA, 0x51A0, + 0xB9DB, 0x89C2, + 0xB9DC, 0x7BA1, + 0xB9DD, 0x9986, + 0xB9DE, 0x7F50, + 0xB9DF, 0x60EF, + 0xB9E0, 0x704C, + 0xB9E1, 0x8D2F, + 0xB9E2, 0x5149, + 0xB9E3, 0x5E7F, + 0xB9E4, 0x901B, + 0xB9E5, 0x7470, + 0xB9E6, 0x89C4, + 0xB9E7, 0x572D, + 0xB9E8, 0x7845, + 0xB9E9, 0x5F52, + 0xB9EA, 0x9F9F, + 0xB9EB, 0x95FA, + 0xB9EC, 0x8F68, + 0xB9ED, 0x9B3C, + 0xB9EE, 0x8BE1, + 0xB9EF, 0x7678, + 0xB9F0, 0x6842, + 0xB9F1, 0x67DC, + 0xB9F2, 0x8DEA, + 0xB9F3, 0x8D35, + 0xB9F4, 0x523D, + 0xB9F5, 0x8F8A, + 0xB9F6, 0x6EDA, + 0xB9F7, 0x68CD, + 0xB9F8, 0x9505, + 0xB9F9, 0x90ED, + 0xB9FA, 0x56FD, + 0xB9FB, 0x679C, + 0xB9FC, 0x88F9, + 0xB9FD, 0x8FC7, + 0xB9FE, 0x54C8, + 0xBA40, 0x7BC5, + 0xBA49, 0x7BD2, + 0xBA68, 0x7BFD, + 0xBAA0, 0x7C42, + 0xBAA1, 0x9AB8, + 0xBAA2, 0x5B69, + 0xBAA3, 0x6D77, + 0xBAA4, 0x6C26, + 0xBAA5, 0x4EA5, + 0xBAA6, 0x5BB3, + 0xBAA7, 0x9A87, + 0xBAA8, 0x9163, + 0xBAA9, 0x61A8, + 0xBAAA, 0x90AF, + 0xBAAB, 0x97E9, + 0xBAAC, 0x542B, + 0xBAAD, 0x6DB5, + 0xBAAE, 0x5BD2, + 0xBAAF, 0x51FD, + 0xBAB0, 0x558A, + 0xBAB1, 0x7F55, + 0xBAB2, 0x7FF0, + 0xBAB3, 0x64BC, + 0xBAB4, 0x634D, + 0xBAB5, 0x65F1, + 0xBAB6, 0x61BE, + 0xBAB7, 0x608D, + 0xBAB8, 0x710A, + 0xBAB9, 0x6C57, + 0xBABA, 0x6C49, + 0xBABB, 0x592F, + 0xBABC, 0x676D, + 0xBABD, 0x822A, + 0xBABE, 0x58D5, + 0xBABF, 0x568E, + 0xBAC0, 0x8C6A, + 0xBAC1, 0x6BEB, + 0xBAC2, 0x90DD, + 0xBAC3, 0x597D, + 0xBAC4, 0x8017, + 0xBAC5, 0x53F7, + 0xBAC6, 0x6D69, + 0xBAC7, 0x5475, + 0xBAC8, 0x559D, + 0xBAC9, 0x8377, + 0xBACA, 0x83CF, + 0xBACB, 0x6838, + 0xBACC, 0x79BE, + 0xBACD, 0x548C, + 0xBACE, 0x4F55, + 0xBACF, 0x5408, + 0xBAD0, 0x76D2, + 0xBAD1, 0x8C89, + 0xBAD2, 0x9602, + 0xBAD3, 0x6CB3, + 0xBAD4, 0x6DB8, + 0xBAD5, 0x8D6B, + 0xBAD6, 0x8910, + 0xBAD7, 0x9E64, + 0xBAD8, 0x8D3A, + 0xBAD9, 0x563F, + 0xBADA, 0x9ED1, + 0xBADB, 0x75D5, + 0xBADC, 0x5F88, + 0xBADD, 0x72E0, + 0xBADE, 0x6068, + 0xBADF, 0x54FC, + 0xBAE0, 0x4EA8, + 0xBAE1, 0x6A2A, + 0xBAE2, 0x8861, + 0xBAE3, 0x6052, + 0xBAE4, 0x8F70, + 0xBAE5, 0x54C4, + 0xBAE6, 0x70D8, + 0xBAE7, 0x8679, + 0xBAE8, 0x9E3F, + 0xBAE9, 0x6D2A, + 0xBAEA, 0x5B8F, + 0xBAEB, 0x5F18, + 0xBAEC, 0x7EA2, + 0xBAED, 0x5589, + 0xBAEE, 0x4FAF, + 0xBAEF, 0x7334, + 0xBAF0, 0x543C, + 0xBAF1, 0x539A, + 0xBAF2, 0x5019, + 0xBAF3, 0x540E, + 0xBAF4, 0x547C, + 0xBAF5, 0x4E4E, + 0xBAF6, 0x5FFD, + 0xBAF7, 0x745A, + 0xBAF8, 0x58F6, + 0xBAF9, 0x846B, + 0xBAFA, 0x80E1, + 0xBAFB, 0x8774, + 0xBAFC, 0x72D0, + 0xBAFD, 0x7CCA, + 0xBAFE, 0x6E56, + 0xBB80, 0x7C88, + 0xBB8A, 0x7C96, + 0xBB90, 0x7CA3, + 0xBBA1, 0x5F27, + 0xBBA2, 0x864E, + 0xBBA3, 0x552C, + 0xBBA4, 0x62A4, + 0xBBA5, 0x4E92, + 0xBBA6, 0x6CAA, + 0xBBA7, 0x6237, + 0xBBA8, 0x82B1, + 0xBBA9, 0x54D7, + 0xBBAA, 0x534E, + 0xBBAB, 0x733E, + 0xBBAC, 0x6ED1, + 0xBBAD, 0x753B, + 0xBBAE, 0x5212, + 0xBBAF, 0x5316, + 0xBBB0, 0x8BDD, + 0xBBB1, 0x69D0, + 0xBBB2, 0x5F8A, + 0xBBB3, 0x6000, + 0xBBB4, 0x6DEE, + 0xBBB5, 0x574F, + 0xBBB6, 0x6B22, + 0xBBB7, 0x73AF, + 0xBBB8, 0x6853, + 0xBBB9, 0x8FD8, + 0xBBBA, 0x7F13, + 0xBBBB, 0x6362, + 0xBBBC, 0x60A3, + 0xBBBD, 0x5524, + 0xBBBE, 0x75EA, + 0xBBBF, 0x8C62, + 0xBBC0, 0x7115, + 0xBBC1, 0x6DA3, + 0xBBC2, 0x5BA6, + 0xBBC3, 0x5E7B, + 0xBBC4, 0x8352, + 0xBBC5, 0x614C, + 0xBBC6, 0x9EC4, + 0xBBC7, 0x78FA, + 0xBBC8, 0x8757, + 0xBBC9, 0x7C27, + 0xBBCA, 0x7687, + 0xBBCB, 0x51F0, + 0xBBCC, 0x60F6, + 0xBBCD, 0x714C, + 0xBBCE, 0x6643, + 0xBBCF, 0x5E4C, + 0xBBD0, 0x604D, + 0xBBD1, 0x8C0E, + 0xBBD2, 0x7070, + 0xBBD3, 0x6325, + 0xBBD4, 0x8F89, + 0xBBD5, 0x5FBD, + 0xBBD6, 0x6062, + 0xBBD7, 0x86D4, + 0xBBD8, 0x56DE, + 0xBBD9, 0x6BC1, + 0xBBDA, 0x6094, + 0xBBDB, 0x6167, + 0xBBDC, 0x5349, + 0xBBDD, 0x60E0, + 0xBBDE, 0x6666, + 0xBBDF, 0x8D3F, + 0xBBE0, 0x79FD, + 0xBBE1, 0x4F1A, + 0xBBE2, 0x70E9, + 0xBBE3, 0x6C47, + 0xBBE4, 0x8BB3, + 0xBBE5, 0x8BF2, + 0xBBE6, 0x7ED8, + 0xBBE7, 0x8364, + 0xBBE8, 0x660F, + 0xBBE9, 0x5A5A, + 0xBBEA, 0x9B42, + 0xBBEB, 0x6D51, + 0xBBEC, 0x6DF7, + 0xBBED, 0x8C41, + 0xBBEE, 0x6D3B, + 0xBBEF, 0x4F19, + 0xBBF0, 0x706B, + 0xBBF1, 0x83B7, + 0xBBF2, 0x6216, + 0xBBF3, 0x60D1, + 0xBBF4, 0x970D, + 0xBBF5, 0x8D27, + 0xBBF6, 0x7978, + 0xBBF7, 0x51FB, + 0xBBF8, 0x573E, + 0xBBF9, 0x57FA, + 0xBBFA, 0x673A, + 0xBBFB, 0x7578, + 0xBBFC, 0x7A3D, + 0xBBFD, 0x79EF, + 0xBBFE, 0x7B95, + 0xBC45, 0x7CC6, + 0xBC46, 0x7CC9, + 0xBC47, 0x7CCB, + 0xBC4F, 0x7CD8, + 0xBC8F, 0x7D21, + 0xBCA1, 0x808C, + 0xBCA2, 0x9965, + 0xBCA3, 0x8FF9, + 0xBCA4, 0x6FC0, + 0xBCA5, 0x8BA5, + 0xBCA6, 0x9E21, + 0xBCA7, 0x59EC, + 0xBCA8, 0x7EE9, + 0xBCA9, 0x7F09, + 0xBCAA, 0x5409, + 0xBCAB, 0x6781, + 0xBCAC, 0x68D8, + 0xBCAD, 0x8F91, + 0xBCAE, 0x7C4D, + 0xBCAF, 0x96C6, + 0xBCB0, 0x53CA, + 0xBCB1, 0x6025, + 0xBCB2, 0x75BE, + 0xBCB3, 0x6C72, + 0xBCB4, 0x5373, + 0xBCB5, 0x5AC9, + 0xBCB6, 0x7EA7, + 0xBCB7, 0x6324, + 0xBCB8, 0x51E0, + 0xBCB9, 0x810A, + 0xBCBA, 0x5DF1, + 0xBCBB, 0x84DF, + 0xBCBC, 0x6280, + 0xBCBD, 0x5180, + 0xBCBE, 0x5B63, + 0xBCBF, 0x4F0E, + 0xBCC0, 0x796D, + 0xBCC1, 0x5242, + 0xBCC2, 0x60B8, + 0xBCC3, 0x6D4E, + 0xBCC4, 0x5BC4, + 0xBCC5, 0x5BC2, + 0xBCC6, 0x8BA1, + 0xBCC7, 0x8BB0, + 0xBCC8, 0x65E2, + 0xBCC9, 0x5FCC, + 0xBCCA, 0x9645, + 0xBCCB, 0x5993, + 0xBCCC, 0x7EE7, + 0xBCCD, 0x7EAA, + 0xBCCE, 0x5609, + 0xBCCF, 0x67B7, + 0xBCD0, 0x5939, + 0xBCD1, 0x4F73, + 0xBCD2, 0x5BB6, + 0xBCD3, 0x52A0, + 0xBCD4, 0x835A, + 0xBCD5, 0x988A, + 0xBCD6, 0x8D3E, + 0xBCD7, 0x7532, + 0xBCD8, 0x94BE, + 0xBCD9, 0x5047, + 0xBCDA, 0x7A3C, + 0xBCDB, 0x4EF7, + 0xBCDC, 0x67B6, + 0xBCDD, 0x9A7E, + 0xBCDE, 0x5AC1, + 0xBCDF, 0x6B7C, + 0xBCE0, 0x76D1, + 0xBCE1, 0x575A, + 0xBCE2, 0x5C16, + 0xBCE3, 0x7B3A, + 0xBCE4, 0x95F4, + 0xBCE5, 0x714E, + 0xBCE6, 0x517C, + 0xBCE7, 0x80A9, + 0xBCE8, 0x8270, + 0xBCE9, 0x5978, + 0xBCEA, 0x7F04, + 0xBCEB, 0x8327, + 0xBCEC, 0x68C0, + 0xBCED, 0x67EC, + 0xBCEE, 0x78B1, + 0xBCEF, 0x7877, + 0xBCF0, 0x62E3, + 0xBCF1, 0x6361, + 0xBCF2, 0x7B80, + 0xBCF3, 0x4FED, + 0xBCF4, 0x526A, + 0xBCF5, 0x51CF, + 0xBCF6, 0x8350, + 0xBCF7, 0x69DB, + 0xBCF8, 0x9274, + 0xBCF9, 0x8DF5, + 0xBCFA, 0x8D31, + 0xBCFB, 0x89C1, + 0xBCFC, 0x952E, + 0xBCFD, 0x7BAD, + 0xBCFE, 0x4EF6, + 0xBDA1, 0x5065, + 0xBDA2, 0x8230, + 0xBDA3, 0x5251, + 0xBDA4, 0x996F, + 0xBDA5, 0x6E10, + 0xBDA6, 0x6E85, + 0xBDA7, 0x6DA7, + 0xBDA8, 0x5EFA, + 0xBDA9, 0x50F5, + 0xBDAA, 0x59DC, + 0xBDAB, 0x5C06, + 0xBDAC, 0x6D46, + 0xBDAD, 0x6C5F, + 0xBDAE, 0x7586, + 0xBDAF, 0x848B, + 0xBDB0, 0x6868, + 0xBDB1, 0x5956, + 0xBDB2, 0x8BB2, + 0xBDB3, 0x5320, + 0xBDB4, 0x9171, + 0xBDB5, 0x964D, + 0xBDB6, 0x8549, + 0xBDB7, 0x6912, + 0xBDB8, 0x7901, + 0xBDB9, 0x7126, + 0xBDBA, 0x80F6, + 0xBDBB, 0x4EA4, + 0xBDBC, 0x90CA, + 0xBDBD, 0x6D47, + 0xBDBE, 0x9A84, + 0xBDBF, 0x5A07, + 0xBDC0, 0x56BC, + 0xBDC1, 0x6405, + 0xBDC2, 0x94F0, + 0xBDC3, 0x77EB, + 0xBDC4, 0x4FA5, + 0xBDC5, 0x811A, + 0xBDC6, 0x72E1, + 0xBDC7, 0x89D2, + 0xBDC8, 0x997A, + 0xBDC9, 0x7F34, + 0xBDCA, 0x7EDE, + 0xBDCB, 0x527F, + 0xBDCC, 0x6559, + 0xBDCD, 0x9175, + 0xBDCE, 0x8F7F, + 0xBDCF, 0x8F83, + 0xBDD0, 0x53EB, + 0xBDD1, 0x7A96, + 0xBDD2, 0x63ED, + 0xBDD3, 0x63A5, + 0xBDD4, 0x7686, + 0xBDD5, 0x79F8, + 0xBDD6, 0x8857, + 0xBDD7, 0x9636, + 0xBDD8, 0x622A, + 0xBDD9, 0x52AB, + 0xBDDA, 0x8282, + 0xBDDB, 0x6854, + 0xBDDC, 0x6770, + 0xBDDD, 0x6377, + 0xBDDE, 0x776B, + 0xBDDF, 0x7AED, + 0xBDE0, 0x6D01, + 0xBDE1, 0x7ED3, + 0xBDE2, 0x89E3, + 0xBDE3, 0x59D0, + 0xBDE4, 0x6212, + 0xBDE5, 0x85C9, + 0xBDE6, 0x82A5, + 0xBDE7, 0x754C, + 0xBDE8, 0x501F, + 0xBDE9, 0x4ECB, + 0xBDEA, 0x75A5, + 0xBDEB, 0x8BEB, + 0xBDEC, 0x5C4A, + 0xBDED, 0x5DFE, + 0xBDEE, 0x7B4B, + 0xBDEF, 0x65A4, + 0xBDF0, 0x91D1, + 0xBDF1, 0x4ECA, + 0xBDF2, 0x6D25, + 0xBDF3, 0x895F, + 0xBDF4, 0x7D27, + 0xBDF5, 0x9526, + 0xBDF6, 0x4EC5, + 0xBDF7, 0x8C28, + 0xBDF8, 0x8FDB, + 0xBDF9, 0x9773, + 0xBDFA, 0x664B, + 0xBDFB, 0x7981, + 0xBDFC, 0x8FD1, + 0xBDFD, 0x70EC, + 0xBDFE, 0x6D78, + 0xBEA1, 0x5C3D, + 0xBEA2, 0x52B2, + 0xBEA3, 0x8346, + 0xBEA4, 0x5162, + 0xBEA5, 0x830E, + 0xBEA6, 0x775B, + 0xBEA7, 0x6676, + 0xBEA8, 0x9CB8, + 0xBEA9, 0x4EAC, + 0xBEAA, 0x60CA, + 0xBEAB, 0x7CBE, + 0xBEAC, 0x7CB3, + 0xBEAD, 0x7ECF, + 0xBEAE, 0x4E95, + 0xBEAF, 0x8B66, + 0xBEB0, 0x666F, + 0xBEB1, 0x9888, + 0xBEB2, 0x9759, + 0xBEB3, 0x5883, + 0xBEB4, 0x656C, + 0xBEB5, 0x955C, + 0xBEB6, 0x5F84, + 0xBEB7, 0x75C9, + 0xBEB8, 0x9756, + 0xBEB9, 0x7ADF, + 0xBEBA, 0x7ADE, + 0xBEBB, 0x51C0, + 0xBEBC, 0x70AF, + 0xBEBD, 0x7A98, + 0xBEBE, 0x63EA, + 0xBEBF, 0x7A76, + 0xBEC0, 0x7EA0, + 0xBEC1, 0x7396, + 0xBEC2, 0x97ED, + 0xBEC3, 0x4E45, + 0xBEC4, 0x7078, + 0xBEC5, 0x4E5D, + 0xBEC6, 0x9152, + 0xBEC7, 0x53A9, + 0xBEC8, 0x6551, + 0xBEC9, 0x65E7, + 0xBECA, 0x81FC, + 0xBECB, 0x8205, + 0xBECC, 0x548E, + 0xBECD, 0x5C31, + 0xBECE, 0x759A, + 0xBECF, 0x97A0, + 0xBED0, 0x62D8, + 0xBED1, 0x72D9, + 0xBED2, 0x75BD, + 0xBED3, 0x5C45, + 0xBED4, 0x9A79, + 0xBED5, 0x83CA, + 0xBED6, 0x5C40, + 0xBED7, 0x5480, + 0xBED8, 0x77E9, + 0xBED9, 0x4E3E, + 0xBEDA, 0x6CAE, + 0xBEDB, 0x805A, + 0xBEDC, 0x62D2, + 0xBEDD, 0x636E, + 0xBEDE, 0x5DE8, + 0xBEDF, 0x5177, + 0xBEE0, 0x8DDD, + 0xBEE1, 0x8E1E, + 0xBEE2, 0x952F, + 0xBEE3, 0x4FF1, + 0xBEE4, 0x53E5, + 0xBEE5, 0x60E7, + 0xBEE6, 0x70AC, + 0xBEE7, 0x5267, + 0xBEE8, 0x6350, + 0xBEE9, 0x9E43, + 0xBEEA, 0x5A1F, + 0xBEEB, 0x5026, + 0xBEEC, 0x7737, + 0xBEED, 0x5377, + 0xBEEE, 0x7EE2, + 0xBEEF, 0x6485, + 0xBEF0, 0x652B, + 0xBEF1, 0x6289, + 0xBEF2, 0x6398, + 0xBEF3, 0x5014, + 0xBEF4, 0x7235, + 0xBEF5, 0x89C9, + 0xBEF6, 0x51B3, + 0xBEF7, 0x8BC0, + 0xBEF8, 0x7EDD, + 0xBEF9, 0x5747, + 0xBEFA, 0x83CC, + 0xBEFB, 0x94A7, + 0xBEFC, 0x519B, + 0xBEFD, 0x541B, + 0xBEFE, 0x5CFB, + 0xBF80, 0x7E3A, + 0xBFA1, 0x4FCA, + 0xBFA2, 0x7AE3, + 0xBFA3, 0x6D5A, + 0xBFA4, 0x90E1, + 0xBFA5, 0x9A8F, + 0xBFA6, 0x5580, + 0xBFA7, 0x5496, + 0xBFA8, 0x5361, + 0xBFA9, 0x54AF, + 0xBFAA, 0x5F00, + 0xBFAB, 0x63E9, + 0xBFAC, 0x6977, + 0xBFAD, 0x51EF, + 0xBFAE, 0x6168, + 0xBFAF, 0x520A, + 0xBFB0, 0x582A, + 0xBFB1, 0x52D8, + 0xBFB2, 0x574E, + 0xBFB3, 0x780D, + 0xBFB4, 0x770B, + 0xBFB5, 0x5EB7, + 0xBFB6, 0x6177, + 0xBFB7, 0x7CE0, + 0xBFB8, 0x625B, + 0xBFB9, 0x6297, + 0xBFBA, 0x4EA2, + 0xBFBB, 0x7095, + 0xBFBC, 0x8003, + 0xBFBD, 0x62F7, + 0xBFBE, 0x70E4, + 0xBFBF, 0x9760, + 0xBFC0, 0x5777, + 0xBFC1, 0x82DB, + 0xBFC2, 0x67EF, + 0xBFC3, 0x68F5, + 0xBFC4, 0x78D5, + 0xBFC5, 0x9897, + 0xBFC6, 0x79D1, + 0xBFC7, 0x58F3, + 0xBFC8, 0x54B3, + 0xBFC9, 0x53EF, + 0xBFCA, 0x6E34, + 0xBFCB, 0x514B, + 0xBFCC, 0x523B, + 0xBFCD, 0x5BA2, + 0xBFCE, 0x8BFE, + 0xBFCF, 0x80AF, + 0xBFD0, 0x5543, + 0xBFD1, 0x57A6, + 0xBFD2, 0x6073, + 0xBFD3, 0x5751, + 0xBFD4, 0x542D, + 0xBFD5, 0x7A7A, + 0xBFD6, 0x6050, + 0xBFD7, 0x5B54, + 0xBFD8, 0x63A7, + 0xBFD9, 0x62A0, + 0xBFDA, 0x53E3, + 0xBFDB, 0x6263, + 0xBFDC, 0x5BC7, + 0xBFDD, 0x67AF, + 0xBFDE, 0x54ED, + 0xBFDF, 0x7A9F, + 0xBFE0, 0x82E6, + 0xBFE1, 0x9177, + 0xBFE2, 0x5E93, + 0xBFE3, 0x88E4, + 0xBFE4, 0x5938, + 0xBFE5, 0x57AE, + 0xBFE6, 0x630E, + 0xBFE7, 0x8DE8, + 0xBFE8, 0x80EF, + 0xBFE9, 0x5757, + 0xBFEA, 0x7B77, + 0xBFEB, 0x4FA9, + 0xBFEC, 0x5FEB, + 0xBFED, 0x5BBD, + 0xBFEE, 0x6B3E, + 0xBFEF, 0x5321, + 0xBFF0, 0x7B50, + 0xBFF1, 0x72C2, + 0xBFF2, 0x6846, + 0xBFF3, 0x77FF, + 0xBFF4, 0x7736, + 0xBFF5, 0x65F7, + 0xBFF6, 0x51B5, + 0xBFF7, 0x4E8F, + 0xBFF8, 0x76D4, + 0xBFF9, 0x5CBF, + 0xBFFA, 0x7AA5, + 0xBFFB, 0x8475, + 0xBFFC, 0x594E, + 0xBFFD, 0x9B41, + 0xBFFE, 0x5080, + 0xC080, 0x7EAE, + 0xC081, 0x7EB4, + 0xC084, 0x7ED6, + 0xC085, 0x7EE4, + 0xC086, 0x7EEC, + 0xC087, 0x7EF9, + 0xC088, 0x7F0A, + 0xC089, 0x7F10, + 0xC08A, 0x7F1E, + 0xC08B, 0x7F37, + 0xC08C, 0x7F39, + 0xC094, 0x7F43, + 0xC0A1, 0x9988, + 0xC0A2, 0x6127, + 0xC0A3, 0x6E83, + 0xC0A4, 0x5764, + 0xC0A5, 0x6606, + 0xC0A6, 0x6346, + 0xC0A7, 0x56F0, + 0xC0A8, 0x62EC, + 0xC0A9, 0x6269, + 0xC0AA, 0x5ED3, + 0xC0AB, 0x9614, + 0xC0AC, 0x5783, + 0xC0AD, 0x62C9, + 0xC0AE, 0x5587, + 0xC0AF, 0x8721, + 0xC0B0, 0x814A, + 0xC0B1, 0x8FA3, + 0xC0B2, 0x5566, + 0xC0B3, 0x83B1, + 0xC0B4, 0x6765, + 0xC0B5, 0x8D56, + 0xC0B6, 0x84DD, + 0xC0B7, 0x5A6A, + 0xC0B8, 0x680F, + 0xC0B9, 0x62E6, + 0xC0BA, 0x7BEE, + 0xC0BB, 0x9611, + 0xC0BC, 0x5170, + 0xC0BD, 0x6F9C, + 0xC0BE, 0x8C30, + 0xC0BF, 0x63FD, + 0xC0C0, 0x89C8, + 0xC0C1, 0x61D2, + 0xC0C2, 0x7F06, + 0xC0C3, 0x70C2, + 0xC0C4, 0x6EE5, + 0xC0C5, 0x7405, + 0xC0C6, 0x6994, + 0xC0C7, 0x72FC, + 0xC0C8, 0x5ECA, + 0xC0C9, 0x90CE, + 0xC0CA, 0x6717, + 0xC0CB, 0x6D6A, + 0xC0CC, 0x635E, + 0xC0CD, 0x52B3, + 0xC0CE, 0x7262, + 0xC0CF, 0x8001, + 0xC0D0, 0x4F6C, + 0xC0D1, 0x59E5, + 0xC0D2, 0x916A, + 0xC0D3, 0x70D9, + 0xC0D4, 0x6D9D, + 0xC0D5, 0x52D2, + 0xC0D6, 0x4E50, + 0xC0D7, 0x96F7, + 0xC0D8, 0x956D, + 0xC0D9, 0x857E, + 0xC0DA, 0x78CA, + 0xC0DB, 0x7D2F, + 0xC0DC, 0x5121, + 0xC0DD, 0x5792, + 0xC0DE, 0x64C2, + 0xC0DF, 0x808B, + 0xC0E0, 0x7C7B, + 0xC0E1, 0x6CEA, + 0xC0E2, 0x68F1, + 0xC0E3, 0x695E, + 0xC0E4, 0x51B7, + 0xC0E5, 0x5398, + 0xC0E6, 0x68A8, + 0xC0E7, 0x7281, + 0xC0E8, 0x9ECE, + 0xC0E9, 0x7BF1, + 0xC0EA, 0x72F8, + 0xC0EB, 0x79BB, + 0xC0EC, 0x6F13, + 0xC0ED, 0x7406, + 0xC0EE, 0x674E, + 0xC0EF, 0x91CC, + 0xC0F0, 0x9CA4, + 0xC0F1, 0x793C, + 0xC0F2, 0x8389, + 0xC0F3, 0x8354, + 0xC0F4, 0x540F, + 0xC0F5, 0x6817, + 0xC0F6, 0x4E3D, + 0xC0F7, 0x5389, + 0xC0F8, 0x52B1, + 0xC0F9, 0x783E, + 0xC0FA, 0x5386, + 0xC0FB, 0x5229, + 0xC0FC, 0x5088, + 0xC0FD, 0x4F8B, + 0xC0FE, 0x4FD0, + 0xC140, 0x7F56, + 0xC141, 0x7F59, + 0xC146, 0x7F60, + 0xC151, 0x7F73, + 0xC164, 0x7F8B, + 0xC165, 0x7F8D, + 0xC172, 0x7FA0, + 0xC17E, 0x7FB1, + 0xC187, 0x7FBE, + 0xC188, 0x7FC0, + 0xC190, 0x7FCB, + 0xC191, 0x7FCD, + 0xC1A1, 0x75E2, + 0xC1A2, 0x7ACB, + 0xC1A3, 0x7C92, + 0xC1A4, 0x6CA5, + 0xC1A5, 0x96B6, + 0xC1A6, 0x529B, + 0xC1A7, 0x7483, + 0xC1A8, 0x54E9, + 0xC1A9, 0x4FE9, + 0xC1AA, 0x8054, + 0xC1AB, 0x83B2, + 0xC1AC, 0x8FDE, + 0xC1AD, 0x9570, + 0xC1AE, 0x5EC9, + 0xC1AF, 0x601C, + 0xC1B0, 0x6D9F, + 0xC1B1, 0x5E18, + 0xC1B2, 0x655B, + 0xC1B3, 0x8138, + 0xC1B4, 0x94FE, + 0xC1B5, 0x604B, + 0xC1B6, 0x70BC, + 0xC1B7, 0x7EC3, + 0xC1B8, 0x7CAE, + 0xC1B9, 0x51C9, + 0xC1BA, 0x6881, + 0xC1BB, 0x7CB1, + 0xC1BC, 0x826F, + 0xC1BD, 0x4E24, + 0xC1BE, 0x8F86, + 0xC1BF, 0x91CF, + 0xC1C0, 0x667E, + 0xC1C1, 0x4EAE, + 0xC1C2, 0x8C05, + 0xC1C3, 0x64A9, + 0xC1C4, 0x804A, + 0xC1C5, 0x50DA, + 0xC1C6, 0x7597, + 0xC1C7, 0x71CE, + 0xC1C8, 0x5BE5, + 0xC1C9, 0x8FBD, + 0xC1CA, 0x6F66, + 0xC1CB, 0x4E86, + 0xC1CC, 0x6482, + 0xC1CD, 0x9563, + 0xC1CE, 0x5ED6, + 0xC1CF, 0x6599, + 0xC1D0, 0x5217, + 0xC1D1, 0x88C2, + 0xC1D2, 0x70C8, + 0xC1D3, 0x52A3, + 0xC1D4, 0x730E, + 0xC1D5, 0x7433, + 0xC1D6, 0x6797, + 0xC1D7, 0x78F7, + 0xC1D8, 0x9716, + 0xC1D9, 0x4E34, + 0xC1DA, 0x90BB, + 0xC1DB, 0x9CDE, + 0xC1DC, 0x6DCB, + 0xC1DD, 0x51DB, + 0xC1DE, 0x8D41, + 0xC1DF, 0x541D, + 0xC1E0, 0x62CE, + 0xC1E1, 0x73B2, + 0xC1E2, 0x83F1, + 0xC1E3, 0x96F6, + 0xC1E4, 0x9F84, + 0xC1E5, 0x94C3, + 0xC1E6, 0x4F36, + 0xC1E7, 0x7F9A, + 0xC1E8, 0x51CC, + 0xC1E9, 0x7075, + 0xC1EA, 0x9675, + 0xC1EB, 0x5CAD, + 0xC1EC, 0x9886, + 0xC1ED, 0x53E6, + 0xC1EE, 0x4EE4, + 0xC1EF, 0x6E9C, + 0xC1F0, 0x7409, + 0xC1F1, 0x69B4, + 0xC1F2, 0x786B, + 0xC1F3, 0x998F, + 0xC1F4, 0x7559, + 0xC1F5, 0x5218, + 0xC1F6, 0x7624, + 0xC1F7, 0x6D41, + 0xC1F8, 0x67F3, + 0xC1F9, 0x516D, + 0xC1FA, 0x9F99, + 0xC1FB, 0x804B, + 0xC1FC, 0x5499, + 0xC1FD, 0x7B3C, + 0xC1FE, 0x7ABF, + 0xC240, 0x7FE4, + 0xC247, 0x7FEF, + 0xC248, 0x7FF2, + 0xC253, 0x8002, + 0xC25A, 0x8011, + 0xC25B, 0x8013, + 0xC261, 0x8021, + 0xC26A, 0x8032, + 0xC26B, 0x8034, + 0xC26E, 0x803C, + 0xC26F, 0x803E, + 0xC27B, 0x8053, + 0xC280, 0x8059, + 0xC2A1, 0x9686, + 0xC2A2, 0x5784, + 0xC2A3, 0x62E2, + 0xC2A4, 0x9647, + 0xC2A5, 0x697C, + 0xC2A6, 0x5A04, + 0xC2A7, 0x6402, + 0xC2A8, 0x7BD3, + 0xC2A9, 0x6F0F, + 0xC2AA, 0x964B, + 0xC2AB, 0x82A6, + 0xC2AC, 0x5362, + 0xC2AD, 0x9885, + 0xC2AE, 0x5E90, + 0xC2AF, 0x7089, + 0xC2B0, 0x63B3, + 0xC2B1, 0x5364, + 0xC2B2, 0x864F, + 0xC2B3, 0x9C81, + 0xC2B4, 0x9E93, + 0xC2B5, 0x788C, + 0xC2B6, 0x9732, + 0xC2B7, 0x8DEF, + 0xC2B8, 0x8D42, + 0xC2B9, 0x9E7F, + 0xC2BA, 0x6F5E, + 0xC2BB, 0x7984, + 0xC2BC, 0x5F55, + 0xC2BD, 0x9646, + 0xC2BE, 0x622E, + 0xC2BF, 0x9A74, + 0xC2C0, 0x5415, + 0xC2C1, 0x94DD, + 0xC2C2, 0x4FA3, + 0xC2C3, 0x65C5, + 0xC2C4, 0x5C65, + 0xC2C5, 0x5C61, + 0xC2C6, 0x7F15, + 0xC2C7, 0x8651, + 0xC2C8, 0x6C2F, + 0xC2C9, 0x5F8B, + 0xC2CA, 0x7387, + 0xC2CB, 0x6EE4, + 0xC2CC, 0x7EFF, + 0xC2CD, 0x5CE6, + 0xC2CE, 0x631B, + 0xC2CF, 0x5B6A, + 0xC2D0, 0x6EE6, + 0xC2D1, 0x5375, + 0xC2D2, 0x4E71, + 0xC2D3, 0x63A0, + 0xC2D4, 0x7565, + 0xC2D5, 0x62A1, + 0xC2D6, 0x8F6E, + 0xC2D7, 0x4F26, + 0xC2D8, 0x4ED1, + 0xC2D9, 0x6CA6, + 0xC2DA, 0x7EB6, + 0xC2DB, 0x8BBA, + 0xC2DC, 0x841D, + 0xC2DD, 0x87BA, + 0xC2DE, 0x7F57, + 0xC2DF, 0x903B, + 0xC2E0, 0x9523, + 0xC2E1, 0x7BA9, + 0xC2E2, 0x9AA1, + 0xC2E3, 0x88F8, + 0xC2E4, 0x843D, + 0xC2E5, 0x6D1B, + 0xC2E6, 0x9A86, + 0xC2E7, 0x7EDC, + 0xC2E8, 0x5988, + 0xC2E9, 0x9EBB, + 0xC2EA, 0x739B, + 0xC2EB, 0x7801, + 0xC2EC, 0x8682, + 0xC2ED, 0x9A6C, + 0xC2EE, 0x9A82, + 0xC2EF, 0x561B, + 0xC2F0, 0x5417, + 0xC2F1, 0x57CB, + 0xC2F2, 0x4E70, + 0xC2F3, 0x9EA6, + 0xC2F4, 0x5356, + 0xC2F5, 0x8FC8, + 0xC2F6, 0x8109, + 0xC2F7, 0x7792, + 0xC2F8, 0x9992, + 0xC2F9, 0x86EE, + 0xC2FA, 0x6EE1, + 0xC2FB, 0x8513, + 0xC2FC, 0x66FC, + 0xC2FD, 0x6162, + 0xC2FE, 0x6F2B, + 0xC340, 0x807E, + 0xC343, 0x8085, + 0xC344, 0x8088, + 0xC345, 0x808A, + 0xC34E, 0x8097, + 0xC34F, 0x8099, + 0xC350, 0x809E, + 0xC351, 0x80A3, + 0xC355, 0x80AC, + 0xC356, 0x80B0, + 0xC357, 0x80B3, + 0xC35C, 0x80BB, + 0xC35D, 0x80C5, + 0xC36A, 0x80D8, + 0xC36F, 0x80E6, + 0xC370, 0x80EE, + 0xC371, 0x80F5, + 0xC372, 0x80F7, + 0xC373, 0x80F9, + 0xC374, 0x80FB, + 0xC37E, 0x810B, + 0xC380, 0x810C, + 0xC381, 0x8115, + 0xC382, 0x8117, + 0xC383, 0x8119, + 0xC396, 0x8130, + 0xC39A, 0x8137, + 0xC3A0, 0x813F, + 0xC3A1, 0x8C29, + 0xC3A2, 0x8292, + 0xC3A3, 0x832B, + 0xC3A4, 0x76F2, + 0xC3A5, 0x6C13, + 0xC3A6, 0x5FD9, + 0xC3A7, 0x83BD, + 0xC3A8, 0x732B, + 0xC3A9, 0x8305, + 0xC3AA, 0x951A, + 0xC3AB, 0x6BDB, + 0xC3AC, 0x77DB, + 0xC3AD, 0x94C6, + 0xC3AE, 0x536F, + 0xC3AF, 0x8302, + 0xC3B0, 0x5192, + 0xC3B1, 0x5E3D, + 0xC3B2, 0x8C8C, + 0xC3B3, 0x8D38, + 0xC3B4, 0x4E48, + 0xC3B5, 0x73AB, + 0xC3B6, 0x679A, + 0xC3B7, 0x6885, + 0xC3B8, 0x9176, + 0xC3B9, 0x9709, + 0xC3BA, 0x7164, + 0xC3BB, 0x6CA1, + 0xC3BC, 0x7709, + 0xC3BD, 0x5A92, + 0xC3BE, 0x9541, + 0xC3BF, 0x6BCF, + 0xC3C0, 0x7F8E, + 0xC3C1, 0x6627, + 0xC3C2, 0x5BD0, + 0xC3C3, 0x59B9, + 0xC3C4, 0x5A9A, + 0xC3C5, 0x95E8, + 0xC3C6, 0x95F7, + 0xC3C7, 0x4EEC, + 0xC3C8, 0x840C, + 0xC3C9, 0x8499, + 0xC3CA, 0x6AAC, + 0xC3CB, 0x76DF, + 0xC3CC, 0x9530, + 0xC3CD, 0x731B, + 0xC3CE, 0x68A6, + 0xC3CF, 0x5B5F, + 0xC3D0, 0x772F, + 0xC3D1, 0x919A, + 0xC3D2, 0x9761, + 0xC3D3, 0x7CDC, + 0xC3D4, 0x8FF7, + 0xC3D5, 0x8C1C, + 0xC3D6, 0x5F25, + 0xC3D7, 0x7C73, + 0xC3D8, 0x79D8, + 0xC3D9, 0x89C5, + 0xC3DA, 0x6CCC, + 0xC3DB, 0x871C, + 0xC3DC, 0x5BC6, + 0xC3DD, 0x5E42, + 0xC3DE, 0x68C9, + 0xC3DF, 0x7720, + 0xC3E0, 0x7EF5, + 0xC3E1, 0x5195, + 0xC3E2, 0x514D, + 0xC3E3, 0x52C9, + 0xC3E4, 0x5A29, + 0xC3E5, 0x7F05, + 0xC3E6, 0x9762, + 0xC3E7, 0x82D7, + 0xC3E8, 0x63CF, + 0xC3E9, 0x7784, + 0xC3EA, 0x85D0, + 0xC3EB, 0x79D2, + 0xC3EC, 0x6E3A, + 0xC3ED, 0x5E99, + 0xC3EE, 0x5999, + 0xC3EF, 0x8511, + 0xC3F0, 0x706D, + 0xC3F1, 0x6C11, + 0xC3F2, 0x62BF, + 0xC3F3, 0x76BF, + 0xC3F4, 0x654F, + 0xC3F5, 0x60AF, + 0xC3F6, 0x95FD, + 0xC3F7, 0x660E, + 0xC3F8, 0x879F, + 0xC3F9, 0x9E23, + 0xC3FA, 0x94ED, + 0xC3FB, 0x540D, + 0xC3FC, 0x547D, + 0xC3FD, 0x8C2C, + 0xC3FE, 0x6478, + 0xC446, 0x8147, + 0xC447, 0x8149, + 0xC44B, 0x8152, + 0xC458, 0x8166, + 0xC459, 0x8168, + 0xC45D, 0x816F, + 0xC464, 0x8181, + 0xC46A, 0x8189, + 0xC46F, 0x8190, + 0xC480, 0x81A7, + 0xC481, 0x81A9, + 0xC499, 0x81CB, + 0xC4A1, 0x6479, + 0xC4A2, 0x8611, + 0xC4A3, 0x6A21, + 0xC4A4, 0x819C, + 0xC4A5, 0x78E8, + 0xC4A6, 0x6469, + 0xC4A7, 0x9B54, + 0xC4A8, 0x62B9, + 0xC4A9, 0x672B, + 0xC4AA, 0x83AB, + 0xC4AB, 0x58A8, + 0xC4AC, 0x9ED8, + 0xC4AD, 0x6CAB, + 0xC4AE, 0x6F20, + 0xC4AF, 0x5BDE, + 0xC4B0, 0x964C, + 0xC4B1, 0x8C0B, + 0xC4B2, 0x725F, + 0xC4B3, 0x67D0, + 0xC4B4, 0x62C7, + 0xC4B5, 0x7261, + 0xC4B6, 0x4EA9, + 0xC4B7, 0x59C6, + 0xC4B8, 0x6BCD, + 0xC4B9, 0x5893, + 0xC4BA, 0x66AE, + 0xC4BB, 0x5E55, + 0xC4BC, 0x52DF, + 0xC4BD, 0x6155, + 0xC4BE, 0x6728, + 0xC4BF, 0x76EE, + 0xC4C0, 0x7766, + 0xC4C1, 0x7267, + 0xC4C2, 0x7A46, + 0xC4C3, 0x62FF, + 0xC4C4, 0x54EA, + 0xC4C5, 0x5450, + 0xC4C6, 0x94A0, + 0xC4C7, 0x90A3, + 0xC4C8, 0x5A1C, + 0xC4C9, 0x7EB3, + 0xC4CA, 0x6C16, + 0xC4CB, 0x4E43, + 0xC4CC, 0x5976, + 0xC4CD, 0x8010, + 0xC4CE, 0x5948, + 0xC4CF, 0x5357, + 0xC4D0, 0x7537, + 0xC4D1, 0x96BE, + 0xC4D2, 0x56CA, + 0xC4D3, 0x6320, + 0xC4D4, 0x8111, + 0xC4D5, 0x607C, + 0xC4D6, 0x95F9, + 0xC4D7, 0x6DD6, + 0xC4D8, 0x5462, + 0xC4D9, 0x9981, + 0xC4DA, 0x5185, + 0xC4DB, 0x5AE9, + 0xC4DC, 0x80FD, + 0xC4DD, 0x59AE, + 0xC4DE, 0x9713, + 0xC4DF, 0x502A, + 0xC4E0, 0x6CE5, + 0xC4E1, 0x5C3C, + 0xC4E2, 0x62DF, + 0xC4E3, 0x4F60, + 0xC4E4, 0x533F, + 0xC4E5, 0x817B, + 0xC4E6, 0x9006, + 0xC4E7, 0x6EBA, + 0xC4E8, 0x852B, + 0xC4E9, 0x62C8, + 0xC4EA, 0x5E74, + 0xC4EB, 0x78BE, + 0xC4EC, 0x64B5, + 0xC4ED, 0x637B, + 0xC4EE, 0x5FF5, + 0xC4EF, 0x5A18, + 0xC4F0, 0x917F, + 0xC4F1, 0x9E1F, + 0xC4F2, 0x5C3F, + 0xC4F3, 0x634F, + 0xC4F4, 0x8042, + 0xC4F5, 0x5B7D, + 0xC4F6, 0x556E, + 0xC4F7, 0x954A, + 0xC4F8, 0x954D, + 0xC4F9, 0x6D85, + 0xC4FA, 0x60A8, + 0xC4FB, 0x67E0, + 0xC4FC, 0x72DE, + 0xC4FD, 0x51DD, + 0xC4FE, 0x5B81, + 0xC554, 0x81EB, + 0xC560, 0x81FD, + 0xC561, 0x81FF, + 0xC562, 0x8203, + 0xC56A, 0x8211, + 0xC56B, 0x8213, + 0xC572, 0x821D, + 0xC573, 0x8220, + 0xC578, 0x8229, + 0xC579, 0x822E, + 0xC57A, 0x8232, + 0xC57B, 0x823A, + 0xC57E, 0x823F, + 0xC586, 0x8248, + 0xC587, 0x824A, + 0xC593, 0x8259, + 0xC5A0, 0x8269, + 0xC5A1, 0x62E7, + 0xC5A2, 0x6CDE, + 0xC5A3, 0x725B, + 0xC5A4, 0x626D, + 0xC5A5, 0x94AE, + 0xC5A6, 0x7EBD, + 0xC5A7, 0x8113, + 0xC5A8, 0x6D53, + 0xC5A9, 0x519C, + 0xC5AA, 0x5F04, + 0xC5AB, 0x5974, + 0xC5AC, 0x52AA, + 0xC5AD, 0x6012, + 0xC5AE, 0x5973, + 0xC5AF, 0x6696, + 0xC5B0, 0x8650, + 0xC5B1, 0x759F, + 0xC5B2, 0x632A, + 0xC5B3, 0x61E6, + 0xC5B4, 0x7CEF, + 0xC5B5, 0x8BFA, + 0xC5B6, 0x54E6, + 0xC5B7, 0x6B27, + 0xC5B8, 0x9E25, + 0xC5B9, 0x6BB4, + 0xC5BA, 0x85D5, + 0xC5BB, 0x5455, + 0xC5BC, 0x5076, + 0xC5BD, 0x6CA4, + 0xC5BE, 0x556A, + 0xC5BF, 0x8DB4, + 0xC5C0, 0x722C, + 0xC5C1, 0x5E15, + 0xC5C2, 0x6015, + 0xC5C3, 0x7436, + 0xC5C4, 0x62CD, + 0xC5C5, 0x6392, + 0xC5C6, 0x724C, + 0xC5C7, 0x5F98, + 0xC5C8, 0x6E43, + 0xC5C9, 0x6D3E, + 0xC5CA, 0x6500, + 0xC5CB, 0x6F58, + 0xC5CC, 0x76D8, + 0xC5CD, 0x78D0, + 0xC5CE, 0x76FC, + 0xC5CF, 0x7554, + 0xC5D0, 0x5224, + 0xC5D1, 0x53DB, + 0xC5D2, 0x4E53, + 0xC5D3, 0x5E9E, + 0xC5D4, 0x65C1, + 0xC5D5, 0x802A, + 0xC5D6, 0x80D6, + 0xC5D7, 0x629B, + 0xC5D8, 0x5486, + 0xC5D9, 0x5228, + 0xC5DA, 0x70AE, + 0xC5DB, 0x888D, + 0xC5DC, 0x8DD1, + 0xC5DD, 0x6CE1, + 0xC5DE, 0x5478, + 0xC5DF, 0x80DA, + 0xC5E0, 0x57F9, + 0xC5E1, 0x88F4, + 0xC5E2, 0x8D54, + 0xC5E3, 0x966A, + 0xC5E4, 0x914D, + 0xC5E5, 0x4F69, + 0xC5E6, 0x6C9B, + 0xC5E7, 0x55B7, + 0xC5E8, 0x76C6, + 0xC5E9, 0x7830, + 0xC5EA, 0x62A8, + 0xC5EB, 0x70F9, + 0xC5EC, 0x6F8E, + 0xC5ED, 0x5F6D, + 0xC5EE, 0x84EC, + 0xC5EF, 0x68DA, + 0xC5F0, 0x787C, + 0xC5F1, 0x7BF7, + 0xC5F2, 0x81A8, + 0xC5F3, 0x670B, + 0xC5F4, 0x9E4F, + 0xC5F5, 0x6367, + 0xC5F6, 0x78B0, + 0xC5F7, 0x576F, + 0xC5F8, 0x7812, + 0xC5F9, 0x9739, + 0xC5FA, 0x6279, + 0xC5FB, 0x62AB, + 0xC5FC, 0x5288, + 0xC5FD, 0x7435, + 0xC5FE, 0x6BD7, + 0xC644, 0x8271, + 0xC64D, 0x8283, + 0xC651, 0x8289, + 0xC652, 0x828C, + 0xC653, 0x8290, + 0xC65A, 0x829E, + 0xC65B, 0x82A0, + 0xC65E, 0x82A7, + 0xC65F, 0x82B2, + 0xC66B, 0x82C9, + 0xC66C, 0x82D0, + 0xC66D, 0x82D6, + 0xC670, 0x82DD, + 0xC671, 0x82E2, + 0xC679, 0x82F0, + 0xC67E, 0x82F8, + 0xC680, 0x82FA, + 0xC688, 0x830D, + 0xC689, 0x8310, + 0xC68C, 0x8316, + 0xC69B, 0x832E, + 0xC69C, 0x8330, + 0xC69D, 0x8332, + 0xC69E, 0x8337, + 0xC69F, 0x833B, + 0xC6A0, 0x833D, + 0xC6A1, 0x5564, + 0xC6A2, 0x813E, + 0xC6A3, 0x75B2, + 0xC6A4, 0x76AE, + 0xC6A5, 0x5339, + 0xC6A6, 0x75DE, + 0xC6A7, 0x50FB, + 0xC6A8, 0x5C41, + 0xC6A9, 0x8B6C, + 0xC6AA, 0x7BC7, + 0xC6AB, 0x504F, + 0xC6AC, 0x7247, + 0xC6AD, 0x9A97, + 0xC6AE, 0x98D8, + 0xC6AF, 0x6F02, + 0xC6B0, 0x74E2, + 0xC6B1, 0x7968, + 0xC6B2, 0x6487, + 0xC6B3, 0x77A5, + 0xC6B4, 0x62FC, + 0xC6B5, 0x9891, + 0xC6B6, 0x8D2B, + 0xC6B7, 0x54C1, + 0xC6B8, 0x8058, + 0xC6B9, 0x4E52, + 0xC6BA, 0x576A, + 0xC6BB, 0x82F9, + 0xC6BC, 0x840D, + 0xC6BD, 0x5E73, + 0xC6BE, 0x51ED, + 0xC6BF, 0x74F6, + 0xC6C0, 0x8BC4, + 0xC6C1, 0x5C4F, + 0xC6C2, 0x5761, + 0xC6C3, 0x6CFC, + 0xC6C4, 0x9887, + 0xC6C5, 0x5A46, + 0xC6C6, 0x7834, + 0xC6C7, 0x9B44, + 0xC6C8, 0x8FEB, + 0xC6C9, 0x7C95, + 0xC6CA, 0x5256, + 0xC6CB, 0x6251, + 0xC6CC, 0x94FA, + 0xC6CD, 0x4EC6, + 0xC6CE, 0x8386, + 0xC6CF, 0x8461, + 0xC6D0, 0x83E9, + 0xC6D1, 0x84B2, + 0xC6D2, 0x57D4, + 0xC6D3, 0x6734, + 0xC6D4, 0x5703, + 0xC6D5, 0x666E, + 0xC6D6, 0x6D66, + 0xC6D7, 0x8C31, + 0xC6D8, 0x66DD, + 0xC6D9, 0x7011, + 0xC6DA, 0x671F, + 0xC6DB, 0x6B3A, + 0xC6DC, 0x6816, + 0xC6DD, 0x621A, + 0xC6DE, 0x59BB, + 0xC6DF, 0x4E03, + 0xC6E0, 0x51C4, + 0xC6E1, 0x6F06, + 0xC6E2, 0x67D2, + 0xC6E3, 0x6C8F, + 0xC6E4, 0x5176, + 0xC6E5, 0x68CB, + 0xC6E6, 0x5947, + 0xC6E7, 0x6B67, + 0xC6E8, 0x7566, + 0xC6E9, 0x5D0E, + 0xC6EA, 0x8110, + 0xC6EB, 0x9F50, + 0xC6EC, 0x65D7, + 0xC6ED, 0x7948, + 0xC6EE, 0x7941, + 0xC6EF, 0x9A91, + 0xC6F0, 0x8D77, + 0xC6F1, 0x5C82, + 0xC6F2, 0x4E5E, + 0xC6F3, 0x4F01, + 0xC6F4, 0x542F, + 0xC6F5, 0x5951, + 0xC6F6, 0x780C, + 0xC6F7, 0x5668, + 0xC6F8, 0x6C14, + 0xC6F9, 0x8FC4, + 0xC6FA, 0x5F03, + 0xC6FB, 0x6C7D, + 0xC6FC, 0x6CE3, + 0xC6FD, 0x8BAB, + 0xC6FE, 0x6390, + 0xC746, 0x8348, + 0xC74C, 0x8353, + 0xC752, 0x835D, + 0xC753, 0x8362, + 0xC773, 0x839D, + 0xC774, 0x839F, + 0xC780, 0x83AF, + 0xC781, 0x83B5, + 0xC782, 0x83BB, + 0xC788, 0x83C6, + 0xC78B, 0x83CB, + 0xC792, 0x83D5, + 0xC793, 0x83D7, + 0xC797, 0x83DE, + 0xC7A1, 0x6070, + 0xC7A2, 0x6D3D, + 0xC7A3, 0x7275, + 0xC7A4, 0x6266, + 0xC7A5, 0x948E, + 0xC7A6, 0x94C5, + 0xC7A7, 0x5343, + 0xC7A8, 0x8FC1, + 0xC7A9, 0x7B7E, + 0xC7AA, 0x4EDF, + 0xC7AB, 0x8C26, + 0xC7AC, 0x4E7E, + 0xC7AD, 0x9ED4, + 0xC7AE, 0x94B1, + 0xC7AF, 0x94B3, + 0xC7B0, 0x524D, + 0xC7B1, 0x6F5C, + 0xC7B2, 0x9063, + 0xC7B3, 0x6D45, + 0xC7B4, 0x8C34, + 0xC7B5, 0x5811, + 0xC7B6, 0x5D4C, + 0xC7B7, 0x6B20, + 0xC7B8, 0x6B49, + 0xC7B9, 0x67AA, + 0xC7BA, 0x545B, + 0xC7BB, 0x8154, + 0xC7BC, 0x7F8C, + 0xC7BD, 0x5899, + 0xC7BE, 0x8537, + 0xC7BF, 0x5F3A, + 0xC7C0, 0x62A2, + 0xC7C1, 0x6A47, + 0xC7C2, 0x9539, + 0xC7C3, 0x6572, + 0xC7C4, 0x6084, + 0xC7C5, 0x6865, + 0xC7C6, 0x77A7, + 0xC7C7, 0x4E54, + 0xC7C8, 0x4FA8, + 0xC7C9, 0x5DE7, + 0xC7CA, 0x9798, + 0xC7CB, 0x64AC, + 0xC7CC, 0x7FD8, + 0xC7CD, 0x5CED, + 0xC7CE, 0x4FCF, + 0xC7CF, 0x7A8D, + 0xC7D0, 0x5207, + 0xC7D1, 0x8304, + 0xC7D2, 0x4E14, + 0xC7D3, 0x602F, + 0xC7D4, 0x7A83, + 0xC7D5, 0x94A6, + 0xC7D6, 0x4FB5, + 0xC7D7, 0x4EB2, + 0xC7D8, 0x79E6, + 0xC7D9, 0x7434, + 0xC7DA, 0x52E4, + 0xC7DB, 0x82B9, + 0xC7DC, 0x64D2, + 0xC7DD, 0x79BD, + 0xC7DE, 0x5BDD, + 0xC7DF, 0x6C81, + 0xC7E0, 0x9752, + 0xC7E1, 0x8F7B, + 0xC7E2, 0x6C22, + 0xC7E3, 0x503E, + 0xC7E4, 0x537F, + 0xC7E5, 0x6E05, + 0xC7E6, 0x64CE, + 0xC7E7, 0x6674, + 0xC7E8, 0x6C30, + 0xC7E9, 0x60C5, + 0xC7EA, 0x9877, + 0xC7EB, 0x8BF7, + 0xC7EC, 0x5E86, + 0xC7ED, 0x743C, + 0xC7EE, 0x7A77, + 0xC7EF, 0x79CB, + 0xC7F0, 0x4E18, + 0xC7F1, 0x90B1, + 0xC7F2, 0x7403, + 0xC7F3, 0x6C42, + 0xC7F4, 0x56DA, + 0xC7F5, 0x914B, + 0xC7F6, 0x6CC5, + 0xC7F7, 0x8D8B, + 0xC7F8, 0x533A, + 0xC7F9, 0x86C6, + 0xC7FA, 0x66F2, + 0xC7FB, 0x8EAF, + 0xC7FC, 0x5C48, + 0xC7FD, 0x9A71, + 0xC7FE, 0x6E20, + 0xC84D, 0x8402, + 0xC84E, 0x8405, + 0xC853, 0x8410, + 0xC88C, 0x8458, + 0xC891, 0x8462, + 0xC897, 0x846A, + 0xC89B, 0x8472, + 0xC89C, 0x8474, + 0xC89D, 0x8477, + 0xC89E, 0x8479, + 0xC8A1, 0x53D6, + 0xC8A2, 0x5A36, + 0xC8A3, 0x9F8B, + 0xC8A4, 0x8DA3, + 0xC8A5, 0x53BB, + 0xC8A6, 0x5708, + 0xC8A7, 0x98A7, + 0xC8A8, 0x6743, + 0xC8A9, 0x919B, + 0xC8AA, 0x6CC9, + 0xC8AB, 0x5168, + 0xC8AC, 0x75CA, + 0xC8AD, 0x62F3, + 0xC8AE, 0x72AC, + 0xC8AF, 0x5238, + 0xC8B0, 0x529D, + 0xC8B1, 0x7F3A, + 0xC8B2, 0x7094, + 0xC8B3, 0x7638, + 0xC8B4, 0x5374, + 0xC8B5, 0x9E4A, + 0xC8B6, 0x69B7, + 0xC8B7, 0x786E, + 0xC8B8, 0x96C0, + 0xC8B9, 0x88D9, + 0xC8BA, 0x7FA4, + 0xC8BB, 0x7136, + 0xC8BC, 0x71C3, + 0xC8BD, 0x5189, + 0xC8BE, 0x67D3, + 0xC8BF, 0x74E4, + 0xC8C0, 0x58E4, + 0xC8C1, 0x6518, + 0xC8C2, 0x56B7, + 0xC8C3, 0x8BA9, + 0xC8C4, 0x9976, + 0xC8C5, 0x6270, + 0xC8C6, 0x7ED5, + 0xC8C7, 0x60F9, + 0xC8C8, 0x70ED, + 0xC8C9, 0x58EC, + 0xC8CA, 0x4EC1, + 0xC8CB, 0x4EBA, + 0xC8CC, 0x5FCD, + 0xC8CD, 0x97E7, + 0xC8CE, 0x4EFB, + 0xC8CF, 0x8BA4, + 0xC8D0, 0x5203, + 0xC8D1, 0x598A, + 0xC8D2, 0x7EAB, + 0xC8D3, 0x6254, + 0xC8D4, 0x4ECD, + 0xC8D5, 0x65E5, + 0xC8D6, 0x620E, + 0xC8D7, 0x8338, + 0xC8D8, 0x84C9, + 0xC8D9, 0x8363, + 0xC8DA, 0x878D, + 0xC8DB, 0x7194, + 0xC8DC, 0x6EB6, + 0xC8DD, 0x5BB9, + 0xC8DE, 0x7ED2, + 0xC8DF, 0x5197, + 0xC8E0, 0x63C9, + 0xC8E1, 0x67D4, + 0xC8E2, 0x8089, + 0xC8E3, 0x8339, + 0xC8E4, 0x8815, + 0xC8E5, 0x5112, + 0xC8E6, 0x5B7A, + 0xC8E7, 0x5982, + 0xC8E8, 0x8FB1, + 0xC8E9, 0x4E73, + 0xC8EA, 0x6C5D, + 0xC8EB, 0x5165, + 0xC8EC, 0x8925, + 0xC8ED, 0x8F6F, + 0xC8EE, 0x962E, + 0xC8EF, 0x854A, + 0xC8F0, 0x745E, + 0xC8F1, 0x9510, + 0xC8F2, 0x95F0, + 0xC8F3, 0x6DA6, + 0xC8F4, 0x82E5, + 0xC8F5, 0x5F31, + 0xC8F6, 0x6492, + 0xC8F7, 0x6D12, + 0xC8F8, 0x8428, + 0xC8F9, 0x816E, + 0xC8FA, 0x9CC3, + 0xC8FB, 0x585E, + 0xC8FC, 0x8D5B, + 0xC8FD, 0x4E09, + 0xC8FE, 0x53C1, + 0xC949, 0x848A, + 0xC94A, 0x848D, + 0xC953, 0x8498, + 0xC969, 0x84B3, + 0xC96F, 0x84BE, + 0xC970, 0x84C0, + 0xC97B, 0x84D2, + 0xC97E, 0x84D7, + 0xC985, 0x84DE, + 0xC988, 0x84E4, + 0xC9A1, 0x4F1E, + 0xC9A2, 0x6563, + 0xC9A3, 0x6851, + 0xC9A4, 0x55D3, + 0xC9A5, 0x4E27, + 0xC9A6, 0x6414, + 0xC9A7, 0x9A9A, + 0xC9A8, 0x626B, + 0xC9A9, 0x5AC2, + 0xC9AA, 0x745F, + 0xC9AB, 0x8272, + 0xC9AC, 0x6DA9, + 0xC9AD, 0x68EE, + 0xC9AE, 0x50E7, + 0xC9AF, 0x838E, + 0xC9B0, 0x7802, + 0xC9B1, 0x6740, + 0xC9B2, 0x5239, + 0xC9B3, 0x6C99, + 0xC9B4, 0x7EB1, + 0xC9B5, 0x50BB, + 0xC9B6, 0x5565, + 0xC9B7, 0x715E, + 0xC9B8, 0x7B5B, + 0xC9B9, 0x6652, + 0xC9BA, 0x73CA, + 0xC9BB, 0x82EB, + 0xC9BC, 0x6749, + 0xC9BD, 0x5C71, + 0xC9BE, 0x5220, + 0xC9BF, 0x717D, + 0xC9C0, 0x886B, + 0xC9C1, 0x95EA, + 0xC9C2, 0x9655, + 0xC9C3, 0x64C5, + 0xC9C4, 0x8D61, + 0xC9C5, 0x81B3, + 0xC9C6, 0x5584, + 0xC9C7, 0x6C55, + 0xC9C8, 0x6247, + 0xC9C9, 0x7F2E, + 0xC9CA, 0x5892, + 0xC9CB, 0x4F24, + 0xC9CC, 0x5546, + 0xC9CD, 0x8D4F, + 0xC9CE, 0x664C, + 0xC9CF, 0x4E0A, + 0xC9D0, 0x5C1A, + 0xC9D1, 0x88F3, + 0xC9D2, 0x68A2, + 0xC9D3, 0x634E, + 0xC9D4, 0x7A0D, + 0xC9D5, 0x70E7, + 0xC9D6, 0x828D, + 0xC9D7, 0x52FA, + 0xC9D8, 0x97F6, + 0xC9D9, 0x5C11, + 0xC9DA, 0x54E8, + 0xC9DB, 0x90B5, + 0xC9DC, 0x7ECD, + 0xC9DD, 0x5962, + 0xC9DE, 0x8D4A, + 0xC9DF, 0x86C7, + 0xC9E2, 0x8D66, + 0xC9E3, 0x6444, + 0xC9E4, 0x5C04, + 0xC9E5, 0x6151, + 0xC9E6, 0x6D89, + 0xC9E7, 0x793E, + 0xC9E8, 0x8BBE, + 0xC9E9, 0x7837, + 0xC9EA, 0x7533, + 0xC9EB, 0x547B, + 0xC9EC, 0x4F38, + 0xC9ED, 0x8EAB, + 0xC9EE, 0x6DF1, + 0xC9EF, 0x5A20, + 0xC9F0, 0x7EC5, + 0xC9F1, 0x795E, + 0xC9F2, 0x6C88, + 0xC9F3, 0x5BA1, + 0xC9F4, 0x5A76, + 0xC9F5, 0x751A, + 0xC9F6, 0x80BE, + 0xC9F7, 0x614E, + 0xC9F8, 0x6E17, + 0xC9F9, 0x58F0, + 0xC9FA, 0x751F, + 0xC9FB, 0x7525, + 0xC9FC, 0x7272, + 0xC9FD, 0x5347, + 0xC9FE, 0x7EF3, + 0xCA4D, 0x8512, + 0xCA57, 0x8520, + 0xCA97, 0x8573, + 0xCAA1, 0x7701, + 0xCAA2, 0x76DB, + 0xCAA3, 0x5269, + 0xCAA4, 0x80DC, + 0xCAA5, 0x5723, + 0xCAA6, 0x5E08, + 0xCAA7, 0x5931, + 0xCAA8, 0x72EE, + 0xCAA9, 0x65BD, + 0xCAAA, 0x6E7F, + 0xCAAB, 0x8BD7, + 0xCAAC, 0x5C38, + 0xCAAD, 0x8671, + 0xCAAE, 0x5341, + 0xCAAF, 0x77F3, + 0xCAB0, 0x62FE, + 0xCAB1, 0x65F6, + 0xCAB2, 0x4EC0, + 0xCAB3, 0x98DF, + 0xCAB4, 0x8680, + 0xCAB5, 0x5B9E, + 0xCAB6, 0x8BC6, + 0xCAB7, 0x53F2, + 0xCAB8, 0x77E2, + 0xCAB9, 0x4F7F, + 0xCABA, 0x5C4E, + 0xCABB, 0x9A76, + 0xCABC, 0x59CB, + 0xCABD, 0x5F0F, + 0xCABE, 0x793A, + 0xCABF, 0x58EB, + 0xCAC0, 0x4E16, + 0xCAC1, 0x67FF, + 0xCAC2, 0x4E8B, + 0xCAC3, 0x62ED, + 0xCAC4, 0x8A93, + 0xCAC5, 0x901D, + 0xCAC6, 0x52BF, + 0xCAC7, 0x662F, + 0xCAC8, 0x55DC, + 0xCAC9, 0x566C, + 0xCACA, 0x9002, + 0xCACB, 0x4ED5, + 0xCACC, 0x4F8D, + 0xCACD, 0x91CA, + 0xCACE, 0x9970, + 0xCACF, 0x6C0F, + 0xCAD0, 0x5E02, + 0xCAD1, 0x6043, + 0xCAD2, 0x5BA4, + 0xCAD3, 0x89C6, + 0xCAD4, 0x8BD5, + 0xCAD5, 0x6536, + 0xCAD6, 0x624B, + 0xCAD7, 0x9996, + 0xCAD8, 0x5B88, + 0xCAD9, 0x5BFF, + 0xCADA, 0x6388, + 0xCADB, 0x552E, + 0xCADC, 0x53D7, + 0xCADD, 0x7626, + 0xCADE, 0x517D, + 0xCADF, 0x852C, + 0xCAE0, 0x67A2, + 0xCAE1, 0x68B3, + 0xCAE2, 0x6B8A, + 0xCAE3, 0x6292, + 0xCAE4, 0x8F93, + 0xCAE5, 0x53D4, + 0xCAE6, 0x8212, + 0xCAE7, 0x6DD1, + 0xCAE8, 0x758F, + 0xCAE9, 0x4E66, + 0xCAEA, 0x8D4E, + 0xCAEB, 0x5B70, + 0xCAEC, 0x719F, + 0xCAED, 0x85AF, + 0xCAEE, 0x6691, + 0xCAEF, 0x66D9, + 0xCAF0, 0x7F72, + 0xCAF1, 0x8700, + 0xCAF2, 0x9ECD, + 0xCAF3, 0x9F20, + 0xCAF4, 0x5C5E, + 0xCAF5, 0x672F, + 0xCAF6, 0x8FF0, + 0xCAF7, 0x6811, + 0xCAF8, 0x675F, + 0xCAF9, 0x620D, + 0xCAFA, 0x7AD6, + 0xCAFB, 0x5885, + 0xCAFC, 0x5EB6, + 0xCAFD, 0x6570, + 0xCAFE, 0x6F31, + 0xCB42, 0x8586, + 0xCB5F, 0x85A9, + 0xCB69, 0x85B8, + 0xCB80, 0x85D4, + 0xCBA1, 0x6055, + 0xCBA2, 0x5237, + 0xCBA3, 0x800D, + 0xCBA4, 0x6454, + 0xCBA5, 0x8870, + 0xCBA6, 0x7529, + 0xCBA7, 0x5E05, + 0xCBA8, 0x6813, + 0xCBA9, 0x62F4, + 0xCBAA, 0x971C, + 0xCBAB, 0x53CC, + 0xCBAC, 0x723D, + 0xCBAD, 0x8C01, + 0xCBAE, 0x6C34, + 0xCBAF, 0x7761, + 0xCBB0, 0x7A0E, + 0xCBB1, 0x542E, + 0xCBB2, 0x77AC, + 0xCBB3, 0x987A, + 0xCBB4, 0x821C, + 0xCBB5, 0x8BF4, + 0xCBB6, 0x7855, + 0xCBB7, 0x6714, + 0xCBB8, 0x70C1, + 0xCBB9, 0x65AF, + 0xCBBA, 0x6495, + 0xCBBB, 0x5636, + 0xCBBC, 0x601D, + 0xCBBD, 0x79C1, + 0xCBBE, 0x53F8, + 0xCBBF, 0x4E1D, + 0xCBC0, 0x6B7B, + 0xCBC1, 0x8086, + 0xCBC2, 0x5BFA, + 0xCBC3, 0x55E3, + 0xCBC4, 0x56DB, + 0xCBC5, 0x4F3A, + 0xCBC6, 0x4F3C, + 0xCBC7, 0x9972, + 0xCBC8, 0x5DF3, + 0xCBC9, 0x677E, + 0xCBCA, 0x8038, + 0xCBCB, 0x6002, + 0xCBCC, 0x9882, + 0xCBCD, 0x9001, + 0xCBCE, 0x5B8B, + 0xCBCF, 0x8BBC, + 0xCBD0, 0x8BF5, + 0xCBD1, 0x641C, + 0xCBD2, 0x8258, + 0xCBD3, 0x64DE, + 0xCBD4, 0x55FD, + 0xCBD5, 0x82CF, + 0xCBD6, 0x9165, + 0xCBD7, 0x4FD7, + 0xCBD8, 0x7D20, + 0xCBD9, 0x901F, + 0xCBDA, 0x7C9F, + 0xCBDB, 0x50F3, + 0xCBDC, 0x5851, + 0xCBDD, 0x6EAF, + 0xCBDE, 0x5BBF, + 0xCBDF, 0x8BC9, + 0xCBE0, 0x8083, + 0xCBE1, 0x9178, + 0xCBE2, 0x849C, + 0xCBE3, 0x7B97, + 0xCBE4, 0x867D, + 0xCBE5, 0x968B, + 0xCBE6, 0x968F, + 0xCBE7, 0x7EE5, + 0xCBE8, 0x9AD3, + 0xCBE9, 0x788E, + 0xCBEA, 0x5C81, + 0xCBEB, 0x7A57, + 0xCBEC, 0x9042, + 0xCBED, 0x96A7, + 0xCBEE, 0x795F, + 0xCBEF, 0x5B59, + 0xCBF0, 0x635F, + 0xCBF1, 0x7B0B, + 0xCBF2, 0x84D1, + 0xCBF3, 0x68AD, + 0xCBF4, 0x5506, + 0xCBF5, 0x7F29, + 0xCBF6, 0x7410, + 0xCBF7, 0x7D22, + 0xCBF8, 0x9501, + 0xCBF9, 0x6240, + 0xCBFA, 0x584C, + 0xCBFB, 0x4ED6, + 0xCBFC, 0x5B83, + 0xCBFD, 0x5979, + 0xCBFE, 0x5854, + 0xCC69, 0x8628, + 0xCCA1, 0x736D, + 0xCCA2, 0x631E, + 0xCCA3, 0x8E4B, + 0xCCA4, 0x8E0F, + 0xCCA5, 0x80CE, + 0xCCA6, 0x82D4, + 0xCCA7, 0x62AC, + 0xCCA8, 0x53F0, + 0xCCA9, 0x6CF0, + 0xCCAA, 0x915E, + 0xCCAB, 0x592A, + 0xCCAC, 0x6001, + 0xCCAD, 0x6C70, + 0xCCAE, 0x574D, + 0xCCAF, 0x644A, + 0xCCB0, 0x8D2A, + 0xCCB1, 0x762B, + 0xCCB2, 0x6EE9, + 0xCCB3, 0x575B, + 0xCCB4, 0x6A80, + 0xCCB5, 0x75F0, + 0xCCB6, 0x6F6D, + 0xCCB7, 0x8C2D, + 0xCCB8, 0x8C08, + 0xCCB9, 0x5766, + 0xCCBA, 0x6BEF, + 0xCCBB, 0x8892, + 0xCCBC, 0x78B3, + 0xCCBD, 0x63A2, + 0xCCBE, 0x53F9, + 0xCCBF, 0x70AD, + 0xCCC0, 0x6C64, + 0xCCC1, 0x5858, + 0xCCC2, 0x642A, + 0xCCC3, 0x5802, + 0xCCC4, 0x68E0, + 0xCCC5, 0x819B, + 0xCCC6, 0x5510, + 0xCCC7, 0x7CD6, + 0xCCC8, 0x5018, + 0xCCC9, 0x8EBA, + 0xCCCA, 0x6DCC, + 0xCCCB, 0x8D9F, + 0xCCCC, 0x70EB, + 0xCCCD, 0x638F, + 0xCCCE, 0x6D9B, + 0xCCCF, 0x6ED4, + 0xCCD0, 0x7EE6, + 0xCCD1, 0x8404, + 0xCCD2, 0x6843, + 0xCCD3, 0x9003, + 0xCCD4, 0x6DD8, + 0xCCD5, 0x9676, + 0xCCD6, 0x8BA8, + 0xCCD7, 0x5957, + 0xCCD8, 0x7279, + 0xCCD9, 0x85E4, + 0xCCDA, 0x817E, + 0xCCDB, 0x75BC, + 0xCCDC, 0x8A8A, + 0xCCDD, 0x68AF, + 0xCCDE, 0x5254, + 0xCCDF, 0x8E22, + 0xCCE0, 0x9511, + 0xCCE1, 0x63D0, + 0xCCE2, 0x9898, + 0xCCE3, 0x8E44, + 0xCCE4, 0x557C, + 0xCCE5, 0x4F53, + 0xCCE6, 0x66FF, + 0xCCE7, 0x568F, + 0xCCE8, 0x60D5, + 0xCCE9, 0x6D95, + 0xCCEA, 0x5243, + 0xCCEB, 0x5C49, + 0xCCEC, 0x5929, + 0xCCED, 0x6DFB, + 0xCCEE, 0x586B, + 0xCCEF, 0x7530, + 0xCCF0, 0x751C, + 0xCCF1, 0x606C, + 0xCCF2, 0x8214, + 0xCCF3, 0x8146, + 0xCCF4, 0x6311, + 0xCCF5, 0x6761, + 0xCCF6, 0x8FE2, + 0xCCF7, 0x773A, + 0xCCF8, 0x8DF3, + 0xCCF9, 0x8D34, + 0xCCFA, 0x94C1, + 0xCCFB, 0x5E16, + 0xCCFC, 0x5385, + 0xCCFD, 0x542C, + 0xCCFE, 0x70C3, + 0xCD40, 0x866D, + 0xCD56, 0x8694, + 0xCD64, 0x86AB, + 0xCD74, 0x86C5, + 0xCD75, 0x86C8, + 0xCD7D, 0x86DA, + 0xCD7E, 0x86DC, + 0xCD80, 0x86DD, + 0xCD8C, 0x86EF, + 0xCD94, 0x86FF, + 0xCD95, 0x8701, + 0xCD9F, 0x8714, + 0xCDA0, 0x8716, + 0xCDA1, 0x6C40, + 0xCDA2, 0x5EF7, + 0xCDA3, 0x505C, + 0xCDA4, 0x4EAD, + 0xCDA5, 0x5EAD, + 0xCDA6, 0x633A, + 0xCDA7, 0x8247, + 0xCDA8, 0x901A, + 0xCDA9, 0x6850, + 0xCDAA, 0x916E, + 0xCDAB, 0x77B3, + 0xCDAC, 0x540C, + 0xCDAD, 0x94DC, + 0xCDAE, 0x5F64, + 0xCDAF, 0x7AE5, + 0xCDB0, 0x6876, + 0xCDB1, 0x6345, + 0xCDB2, 0x7B52, + 0xCDB3, 0x7EDF, + 0xCDB4, 0x75DB, + 0xCDB5, 0x5077, + 0xCDB6, 0x6295, + 0xCDB7, 0x5934, + 0xCDB8, 0x900F, + 0xCDB9, 0x51F8, + 0xCDBA, 0x79C3, + 0xCDBB, 0x7A81, + 0xCDBC, 0x56FE, + 0xCDBD, 0x5F92, + 0xCDBE, 0x9014, + 0xCDBF, 0x6D82, + 0xCDC0, 0x5C60, + 0xCDC1, 0x571F, + 0xCDC2, 0x5410, + 0xCDC3, 0x5154, + 0xCDC4, 0x6E4D, + 0xCDC5, 0x56E2, + 0xCDC6, 0x63A8, + 0xCDC7, 0x9893, + 0xCDC8, 0x817F, + 0xCDC9, 0x8715, + 0xCDCA, 0x892A, + 0xCDCB, 0x9000, + 0xCDCC, 0x541E, + 0xCDCD, 0x5C6F, + 0xCDCE, 0x81C0, + 0xCDCF, 0x62D6, + 0xCDD0, 0x6258, + 0xCDD1, 0x8131, + 0xCDD2, 0x9E35, + 0xCDD3, 0x9640, + 0xCDD4, 0x9A6E, + 0xCDD5, 0x9A7C, + 0xCDD6, 0x692D, + 0xCDD7, 0x59A5, + 0xCDD8, 0x62D3, + 0xCDD9, 0x553E, + 0xCDDA, 0x6316, + 0xCDDB, 0x54C7, + 0xCDDC, 0x86D9, + 0xCDDD, 0x6D3C, + 0xCDDE, 0x5A03, + 0xCDDF, 0x74E6, + 0xCDE0, 0x889C, + 0xCDE1, 0x6B6A, + 0xCDE2, 0x5916, + 0xCDE3, 0x8C4C, + 0xCDE4, 0x5F2F, + 0xCDE5, 0x6E7E, + 0xCDE6, 0x73A9, + 0xCDE7, 0x987D, + 0xCDE8, 0x4E38, + 0xCDE9, 0x70F7, + 0xCDEA, 0x5B8C, + 0xCDEB, 0x7897, + 0xCDEC, 0x633D, + 0xCDED, 0x665A, + 0xCDEE, 0x7696, + 0xCDEF, 0x60CB, + 0xCDF0, 0x5B9B, + 0xCDF1, 0x5A49, + 0xCDF2, 0x4E07, + 0xCDF3, 0x8155, + 0xCDF4, 0x6C6A, + 0xCDF5, 0x738B, + 0xCDF6, 0x4EA1, + 0xCDF7, 0x6789, + 0xCDF8, 0x7F51, + 0xCDF9, 0x5F80, + 0xCDFA, 0x65FA, + 0xCDFB, 0x671B, + 0xCDFC, 0x5FD8, + 0xCDFD, 0x5984, + 0xCDFE, 0x5A01, + 0xCE40, 0x8719, + 0xCE41, 0x871B, + 0xCE42, 0x871D, + 0xCE45, 0x8724, + 0xCE61, 0x874D, + 0xCE69, 0x8758, + 0xCE7A, 0x876F, + 0xCE7E, 0x8775, + 0xCE87, 0x8784, + 0xCE8C, 0x878C, + 0xCEA1, 0x5DCD, + 0xCEA2, 0x5FAE, + 0xCEA3, 0x5371, + 0xCEA4, 0x97E6, + 0xCEA5, 0x8FDD, + 0xCEA6, 0x6845, + 0xCEA7, 0x56F4, + 0xCEA8, 0x552F, + 0xCEA9, 0x60DF, + 0xCEAA, 0x4E3A, + 0xCEAB, 0x6F4D, + 0xCEAC, 0x7EF4, + 0xCEAD, 0x82C7, + 0xCEAE, 0x840E, + 0xCEAF, 0x59D4, + 0xCEB0, 0x4F1F, + 0xCEB1, 0x4F2A, + 0xCEB2, 0x5C3E, + 0xCEB3, 0x7EAC, + 0xCEB4, 0x672A, + 0xCEB5, 0x851A, + 0xCEB6, 0x5473, + 0xCEB7, 0x754F, + 0xCEB8, 0x80C3, + 0xCEB9, 0x5582, + 0xCEBA, 0x9B4F, + 0xCEBB, 0x4F4D, + 0xCEBC, 0x6E2D, + 0xCEBD, 0x8C13, + 0xCEBE, 0x5C09, + 0xCEBF, 0x6170, + 0xCEC0, 0x536B, + 0xCEC1, 0x761F, + 0xCEC2, 0x6E29, + 0xCEC3, 0x868A, + 0xCEC4, 0x6587, + 0xCEC5, 0x95FB, + 0xCEC6, 0x7EB9, + 0xCEC7, 0x543B, + 0xCEC8, 0x7A33, + 0xCEC9, 0x7D0A, + 0xCECA, 0x95EE, + 0xCECB, 0x55E1, + 0xCECC, 0x7FC1, + 0xCECD, 0x74EE, + 0xCECE, 0x631D, + 0xCECF, 0x8717, + 0xCED0, 0x6DA1, + 0xCED1, 0x7A9D, + 0xCED2, 0x6211, + 0xCED3, 0x65A1, + 0xCED4, 0x5367, + 0xCED5, 0x63E1, + 0xCED6, 0x6C83, + 0xCED7, 0x5DEB, + 0xCED8, 0x545C, + 0xCED9, 0x94A8, + 0xCEDA, 0x4E4C, + 0xCEDB, 0x6C61, + 0xCEDC, 0x8BEC, + 0xCEDD, 0x5C4B, + 0xCEDE, 0x65E0, + 0xCEDF, 0x829C, + 0xCEE0, 0x68A7, + 0xCEE1, 0x543E, + 0xCEE2, 0x5434, + 0xCEE3, 0x6BCB, + 0xCEE4, 0x6B66, + 0xCEE5, 0x4E94, + 0xCEE6, 0x6342, + 0xCEE7, 0x5348, + 0xCEE8, 0x821E, + 0xCEE9, 0x4F0D, + 0xCEEA, 0x4FAE, + 0xCEEB, 0x575E, + 0xCEEC, 0x620A, + 0xCEED, 0x96FE, + 0xCEEE, 0x6664, + 0xCEEF, 0x7269, + 0xCEF0, 0x52FF, + 0xCEF1, 0x52A1, + 0xCEF2, 0x609F, + 0xCEF3, 0x8BEF, + 0xCEF4, 0x6614, + 0xCEF5, 0x7199, + 0xCEF6, 0x6790, + 0xCEF7, 0x897F, + 0xCEF8, 0x7852, + 0xCEF9, 0x77FD, + 0xCEFA, 0x6670, + 0xCEFB, 0x563B, + 0xCEFC, 0x5438, + 0xCEFD, 0x9521, + 0xCEFE, 0x727A, + 0xCF45, 0x87AE, + 0xCF49, 0x87B4, + 0xCF96, 0x8814, + 0xCFA0, 0x8823, + 0xCFA1, 0x7A00, + 0xCFA2, 0x606F, + 0xCFA3, 0x5E0C, + 0xCFA4, 0x6089, + 0xCFA5, 0x819D, + 0xCFA6, 0x5915, + 0xCFA7, 0x60DC, + 0xCFA8, 0x7184, + 0xCFA9, 0x70EF, + 0xCFAA, 0x6EAA, + 0xCFAB, 0x6C50, + 0xCFAC, 0x7280, + 0xCFAD, 0x6A84, + 0xCFAE, 0x88AD, + 0xCFAF, 0x5E2D, + 0xCFB0, 0x4E60, + 0xCFB1, 0x5AB3, + 0xCFB2, 0x559C, + 0xCFB3, 0x94E3, + 0xCFB4, 0x6D17, + 0xCFB5, 0x7CFB, + 0xCFB6, 0x9699, + 0xCFB7, 0x620F, + 0xCFB8, 0x7EC6, + 0xCFB9, 0x778E, + 0xCFBA, 0x867E, + 0xCFBB, 0x5323, + 0xCFBC, 0x971E, + 0xCFBD, 0x8F96, + 0xCFBE, 0x6687, + 0xCFBF, 0x5CE1, + 0xCFC0, 0x4FA0, + 0xCFC1, 0x72ED, + 0xCFC2, 0x4E0B, + 0xCFC3, 0x53A6, + 0xCFC4, 0x590F, + 0xCFC5, 0x5413, + 0xCFC6, 0x6380, + 0xCFC7, 0x9528, + 0xCFC8, 0x5148, + 0xCFC9, 0x4ED9, + 0xCFCA, 0x9C9C, + 0xCFCB, 0x7EA4, + 0xCFCC, 0x54B8, + 0xCFCD, 0x8D24, + 0xCFCE, 0x8854, + 0xCFCF, 0x8237, + 0xCFD0, 0x95F2, + 0xCFD1, 0x6D8E, + 0xCFD2, 0x5F26, + 0xCFD3, 0x5ACC, + 0xCFD4, 0x663E, + 0xCFD5, 0x9669, + 0xCFD6, 0x73B0, + 0xCFD7, 0x732E, + 0xCFD8, 0x53BF, + 0xCFD9, 0x817A, + 0xCFDA, 0x9985, + 0xCFDB, 0x7FA1, + 0xCFDC, 0x5BAA, + 0xCFDD, 0x9677, + 0xCFDE, 0x9650, + 0xCFDF, 0x7EBF, + 0xCFE0, 0x76F8, + 0xCFE1, 0x53A2, + 0xCFE2, 0x9576, + 0xCFE3, 0x9999, + 0xCFE4, 0x7BB1, + 0xCFE5, 0x8944, + 0xCFE6, 0x6E58, + 0xCFE7, 0x4E61, + 0xCFE8, 0x7FD4, + 0xCFE9, 0x7965, + 0xCFEA, 0x8BE6, + 0xCFEB, 0x60F3, + 0xCFEC, 0x54CD, + 0xCFED, 0x4EAB, + 0xCFEE, 0x9879, + 0xCFEF, 0x5DF7, + 0xCFF0, 0x6A61, + 0xCFF1, 0x50CF, + 0xCFF2, 0x5411, + 0xCFF3, 0x8C61, + 0xCFF4, 0x8427, + 0xCFF5, 0x785D, + 0xCFF6, 0x9704, + 0xCFF7, 0x524A, + 0xCFF8, 0x54EE, + 0xCFF9, 0x56A3, + 0xCFFA, 0x9500, + 0xCFFB, 0x6D88, + 0xCFFC, 0x5BB5, + 0xCFFD, 0x6DC6, + 0xCFFE, 0x6653, + 0xD06A, 0x8858, + 0xD074, 0x886A, + 0xD075, 0x886D, + 0xD076, 0x886F, + 0xD077, 0x8871, + 0xD082, 0x8880, + 0xD083, 0x8883, + 0xD088, 0x888C, + 0xD09A, 0x88A3, + 0xD0A1, 0x5C0F, + 0xD0A2, 0x5B5D, + 0xD0A3, 0x6821, + 0xD0A4, 0x8096, + 0xD0A5, 0x5578, + 0xD0A6, 0x7B11, + 0xD0A7, 0x6548, + 0xD0A8, 0x6954, + 0xD0A9, 0x4E9B, + 0xD0AA, 0x6B47, + 0xD0AB, 0x874E, + 0xD0AC, 0x978B, + 0xD0AD, 0x534F, + 0xD0AE, 0x631F, + 0xD0AF, 0x643A, + 0xD0B0, 0x90AA, + 0xD0B1, 0x659C, + 0xD0B2, 0x80C1, + 0xD0B3, 0x8C10, + 0xD0B4, 0x5199, + 0xD0B5, 0x68B0, + 0xD0B6, 0x5378, + 0xD0B7, 0x87F9, + 0xD0B8, 0x61C8, + 0xD0B9, 0x6CC4, + 0xD0BA, 0x6CFB, + 0xD0BB, 0x8C22, + 0xD0BC, 0x5C51, + 0xD0BD, 0x85AA, + 0xD0BE, 0x82AF, + 0xD0BF, 0x950C, + 0xD0C0, 0x6B23, + 0xD0C1, 0x8F9B, + 0xD0C2, 0x65B0, + 0xD0C3, 0x5FFB, + 0xD0C4, 0x5FC3, + 0xD0C5, 0x4FE1, + 0xD0C6, 0x8845, + 0xD0C7, 0x661F, + 0xD0C8, 0x8165, + 0xD0C9, 0x7329, + 0xD0CA, 0x60FA, + 0xD0CB, 0x5174, + 0xD0CC, 0x5211, + 0xD0CD, 0x578B, + 0xD0CE, 0x5F62, + 0xD0CF, 0x90A2, + 0xD0D0, 0x884C, + 0xD0D1, 0x9192, + 0xD0D2, 0x5E78, + 0xD0D3, 0x674F, + 0xD0D4, 0x6027, + 0xD0D5, 0x59D3, + 0xD0D6, 0x5144, + 0xD0D7, 0x51F6, + 0xD0D8, 0x80F8, + 0xD0D9, 0x5308, + 0xD0DA, 0x6C79, + 0xD0DB, 0x96C4, + 0xD0DC, 0x718A, + 0xD0DD, 0x4F11, + 0xD0DE, 0x4FEE, + 0xD0DF, 0x7F9E, + 0xD0E0, 0x673D, + 0xD0E1, 0x55C5, + 0xD0E2, 0x9508, + 0xD0E3, 0x79C0, + 0xD0E4, 0x8896, + 0xD0E5, 0x7EE3, + 0xD0E6, 0x589F, + 0xD0E7, 0x620C, + 0xD0E8, 0x9700, + 0xD0E9, 0x865A, + 0xD0EA, 0x5618, + 0xD0EB, 0x987B, + 0xD0EC, 0x5F90, + 0xD0ED, 0x8BB8, + 0xD0EE, 0x84C4, + 0xD0EF, 0x9157, + 0xD0F0, 0x53D9, + 0xD0F1, 0x65ED, + 0xD0F2, 0x5E8F, + 0xD0F3, 0x755C, + 0xD0F4, 0x6064, + 0xD0F5, 0x7D6E, + 0xD0F6, 0x5A7F, + 0xD0F7, 0x7EEA, + 0xD0F8, 0x7EED, + 0xD0F9, 0x8F69, + 0xD0FA, 0x55A7, + 0xD0FB, 0x5BA3, + 0xD0FC, 0x60AC, + 0xD0FD, 0x65CB, + 0xD0FE, 0x7384, + 0xD140, 0x88AC, + 0xD15C, 0x88D3, + 0xD16F, 0x88F2, + 0xD175, 0x88FD, + 0xD180, 0x8909, + 0xD186, 0x8911, + 0xD19F, 0x8935, + 0xD1A0, 0x8937, + 0xD1A1, 0x9009, + 0xD1A2, 0x7663, + 0xD1A3, 0x7729, + 0xD1A4, 0x7EDA, + 0xD1A5, 0x9774, + 0xD1A6, 0x859B, + 0xD1A7, 0x5B66, + 0xD1A8, 0x7A74, + 0xD1A9, 0x96EA, + 0xD1AA, 0x8840, + 0xD1AB, 0x52CB, + 0xD1AC, 0x718F, + 0xD1AD, 0x5FAA, + 0xD1AE, 0x65EC, + 0xD1AF, 0x8BE2, + 0xD1B0, 0x5BFB, + 0xD1B1, 0x9A6F, + 0xD1B2, 0x5DE1, + 0xD1B3, 0x6B89, + 0xD1B4, 0x6C5B, + 0xD1B5, 0x8BAD, + 0xD1B6, 0x8BAF, + 0xD1B7, 0x900A, + 0xD1B8, 0x8FC5, + 0xD1B9, 0x538B, + 0xD1BA, 0x62BC, + 0xD1BB, 0x9E26, + 0xD1BC, 0x9E2D, + 0xD1BD, 0x5440, + 0xD1BE, 0x4E2B, + 0xD1BF, 0x82BD, + 0xD1C0, 0x7259, + 0xD1C1, 0x869C, + 0xD1C2, 0x5D16, + 0xD1C3, 0x8859, + 0xD1C4, 0x6DAF, + 0xD1C5, 0x96C5, + 0xD1C6, 0x54D1, + 0xD1C7, 0x4E9A, + 0xD1C8, 0x8BB6, + 0xD1C9, 0x7109, + 0xD1CA, 0x54BD, + 0xD1CB, 0x9609, + 0xD1CC, 0x70DF, + 0xD1CD, 0x6DF9, + 0xD1CE, 0x76D0, + 0xD1CF, 0x4E25, + 0xD1D0, 0x7814, + 0xD1D1, 0x8712, + 0xD1D2, 0x5CA9, + 0xD1D3, 0x5EF6, + 0xD1D4, 0x8A00, + 0xD1D5, 0x989C, + 0xD1D6, 0x960E, + 0xD1D7, 0x708E, + 0xD1D8, 0x6CBF, + 0xD1D9, 0x5944, + 0xD1DA, 0x63A9, + 0xD1DB, 0x773C, + 0xD1DC, 0x884D, + 0xD1DD, 0x6F14, + 0xD1DE, 0x8273, + 0xD1DF, 0x5830, + 0xD1E0, 0x71D5, + 0xD1E1, 0x538C, + 0xD1E2, 0x781A, + 0xD1E3, 0x96C1, + 0xD1E4, 0x5501, + 0xD1E5, 0x5F66, + 0xD1E6, 0x7130, + 0xD1E7, 0x5BB4, + 0xD1E8, 0x8C1A, + 0xD1E9, 0x9A8C, + 0xD1EA, 0x6B83, + 0xD1EB, 0x592E, + 0xD1EC, 0x9E2F, + 0xD1ED, 0x79E7, + 0xD1EE, 0x6768, + 0xD1EF, 0x626C, + 0xD1F0, 0x4F6F, + 0xD1F1, 0x75A1, + 0xD1F2, 0x7F8A, + 0xD1F3, 0x6D0B, + 0xD1F4, 0x9633, + 0xD1F5, 0x6C27, + 0xD1F6, 0x4EF0, + 0xD1F7, 0x75D2, + 0xD1F8, 0x517B, + 0xD1F9, 0x6837, + 0xD1FA, 0x6F3E, + 0xD1FB, 0x9080, + 0xD1FC, 0x8170, + 0xD1FD, 0x5996, + 0xD1FE, 0x7476, + 0xD27E, 0x897C, + 0xD282, 0x8980, + 0xD283, 0x8982, + 0xD2A1, 0x6447, + 0xD2A2, 0x5C27, + 0xD2A3, 0x9065, + 0xD2A4, 0x7A91, + 0xD2A5, 0x8C23, + 0xD2A6, 0x59DA, + 0xD2A7, 0x54AC, + 0xD2A8, 0x8200, + 0xD2A9, 0x836F, + 0xD2AA, 0x8981, + 0xD2AB, 0x8000, + 0xD2AC, 0x6930, + 0xD2AD, 0x564E, + 0xD2AE, 0x8036, + 0xD2AF, 0x7237, + 0xD2B0, 0x91CE, + 0xD2B1, 0x51B6, + 0xD2B2, 0x4E5F, + 0xD2B3, 0x9875, + 0xD2B4, 0x6396, + 0xD2B5, 0x4E1A, + 0xD2B6, 0x53F6, + 0xD2B7, 0x66F3, + 0xD2B8, 0x814B, + 0xD2B9, 0x591C, + 0xD2BA, 0x6DB2, + 0xD2BB, 0x4E00, + 0xD2BC, 0x58F9, + 0xD2BD, 0x533B, + 0xD2BE, 0x63D6, + 0xD2BF, 0x94F1, + 0xD2C0, 0x4F9D, + 0xD2C1, 0x4F0A, + 0xD2C2, 0x8863, + 0xD2C3, 0x9890, + 0xD2C4, 0x5937, + 0xD2C5, 0x9057, + 0xD2C6, 0x79FB, + 0xD2C7, 0x4EEA, + 0xD2C8, 0x80F0, + 0xD2C9, 0x7591, + 0xD2CA, 0x6C82, + 0xD2CB, 0x5B9C, + 0xD2CC, 0x59E8, + 0xD2CD, 0x5F5D, + 0xD2CE, 0x6905, + 0xD2CF, 0x8681, + 0xD2D0, 0x501A, + 0xD2D1, 0x5DF2, + 0xD2D2, 0x4E59, + 0xD2D3, 0x77E3, + 0xD2D4, 0x4EE5, + 0xD2D5, 0x827A, + 0xD2D6, 0x6291, + 0xD2D7, 0x6613, + 0xD2D8, 0x9091, + 0xD2D9, 0x5C79, + 0xD2DA, 0x4EBF, + 0xD2DB, 0x5F79, + 0xD2DC, 0x81C6, + 0xD2DD, 0x9038, + 0xD2DE, 0x8084, + 0xD2DF, 0x75AB, + 0xD2E0, 0x4EA6, + 0xD2E1, 0x88D4, + 0xD2E2, 0x610F, + 0xD2E3, 0x6BC5, + 0xD2E4, 0x5FC6, + 0xD2E5, 0x4E49, + 0xD2E6, 0x76CA, + 0xD2E7, 0x6EA2, + 0xD2E8, 0x8BE3, + 0xD2E9, 0x8BAE, + 0xD2EA, 0x8C0A, + 0xD2EB, 0x8BD1, + 0xD2EC, 0x5F02, + 0xD2ED, 0x7FFC, + 0xD2EE, 0x7FCC, + 0xD2EF, 0x7ECE, + 0xD2F0, 0x8335, + 0xD2F1, 0x836B, + 0xD2F2, 0x56E0, + 0xD2F3, 0x6BB7, + 0xD2F4, 0x97F3, + 0xD2F5, 0x9634, + 0xD2F6, 0x59FB, + 0xD2F7, 0x541F, + 0xD2F8, 0x94F6, + 0xD2F9, 0x6DEB, + 0xD2FA, 0x5BC5, + 0xD2FB, 0x996E, + 0xD2FC, 0x5C39, + 0xD2FD, 0x5F15, + 0xD2FE, 0x9690, + 0xD35F, 0x89C3, + 0xD360, 0x89CD, + 0xD367, 0x89DB, + 0xD368, 0x89DD, + 0xD36D, 0x89E4, + 0xD3A1, 0x5370, + 0xD3A2, 0x82F1, + 0xD3A3, 0x6A31, + 0xD3A4, 0x5A74, + 0xD3A5, 0x9E70, + 0xD3A6, 0x5E94, + 0xD3A7, 0x7F28, + 0xD3A8, 0x83B9, + 0xD3AB, 0x8367, + 0xD3AC, 0x8747, + 0xD3AD, 0x8FCE, + 0xD3AE, 0x8D62, + 0xD3AF, 0x76C8, + 0xD3B0, 0x5F71, + 0xD3B1, 0x9896, + 0xD3B2, 0x786C, + 0xD3B3, 0x6620, + 0xD3B4, 0x54DF, + 0xD3B5, 0x62E5, + 0xD3B6, 0x4F63, + 0xD3B7, 0x81C3, + 0xD3B8, 0x75C8, + 0xD3B9, 0x5EB8, + 0xD3BA, 0x96CD, + 0xD3BB, 0x8E0A, + 0xD3BC, 0x86F9, + 0xD3BD, 0x548F, + 0xD3BE, 0x6CF3, + 0xD3BF, 0x6D8C, + 0xD3C0, 0x6C38, + 0xD3C1, 0x607F, + 0xD3C2, 0x52C7, + 0xD3C3, 0x7528, + 0xD3C4, 0x5E7D, + 0xD3C5, 0x4F18, + 0xD3C6, 0x60A0, + 0xD3C7, 0x5FE7, + 0xD3C8, 0x5C24, + 0xD3C9, 0x7531, + 0xD3CA, 0x90AE, + 0xD3CB, 0x94C0, + 0xD3CC, 0x72B9, + 0xD3CD, 0x6CB9, + 0xD3CE, 0x6E38, + 0xD3CF, 0x9149, + 0xD3D0, 0x6709, + 0xD3D1, 0x53CB, + 0xD3D2, 0x53F3, + 0xD3D3, 0x4F51, + 0xD3D4, 0x91C9, + 0xD3D5, 0x8BF1, + 0xD3D6, 0x53C8, + 0xD3D7, 0x5E7C, + 0xD3D8, 0x8FC2, + 0xD3D9, 0x6DE4, + 0xD3DA, 0x4E8E, + 0xD3DB, 0x76C2, + 0xD3DC, 0x6986, + 0xD3DD, 0x865E, + 0xD3DE, 0x611A, + 0xD3DF, 0x8206, + 0xD3E0, 0x4F59, + 0xD3E1, 0x4FDE, + 0xD3E2, 0x903E, + 0xD3E3, 0x9C7C, + 0xD3E4, 0x6109, + 0xD3E5, 0x6E1D, + 0xD3E6, 0x6E14, + 0xD3E7, 0x9685, + 0xD3E8, 0x4E88, + 0xD3E9, 0x5A31, + 0xD3EA, 0x96E8, + 0xD3EB, 0x4E0E, + 0xD3EC, 0x5C7F, + 0xD3ED, 0x79B9, + 0xD3EE, 0x5B87, + 0xD3EF, 0x8BED, + 0xD3F0, 0x7FBD, + 0xD3F1, 0x7389, + 0xD3F2, 0x57DF, + 0xD3F3, 0x828B, + 0xD3F4, 0x90C1, + 0xD3F5, 0x5401, + 0xD3F6, 0x9047, + 0xD3F7, 0x55BB, + 0xD3F8, 0x5CEA, + 0xD3F9, 0x5FA1, + 0xD3FA, 0x6108, + 0xD3FB, 0x6B32, + 0xD3FC, 0x72F1, + 0xD3FD, 0x80B2, + 0xD3FE, 0x8A89, + 0xD4A1, 0x6D74, + 0xD4A2, 0x5BD3, + 0xD4A3, 0x88D5, + 0xD4A4, 0x9884, + 0xD4A5, 0x8C6B, + 0xD4A6, 0x9A6D, + 0xD4A7, 0x9E33, + 0xD4A8, 0x6E0A, + 0xD4A9, 0x51A4, + 0xD4AA, 0x5143, + 0xD4AB, 0x57A3, + 0xD4AC, 0x8881, + 0xD4AD, 0x539F, + 0xD4AE, 0x63F4, + 0xD4AF, 0x8F95, + 0xD4B0, 0x56ED, + 0xD4B1, 0x5458, + 0xD4B2, 0x5706, + 0xD4B3, 0x733F, + 0xD4B4, 0x6E90, + 0xD4B5, 0x7F18, + 0xD4B6, 0x8FDC, + 0xD4B7, 0x82D1, + 0xD4B8, 0x613F, + 0xD4B9, 0x6028, + 0xD4BA, 0x9662, + 0xD4BB, 0x66F0, + 0xD4BC, 0x7EA6, + 0xD4BD, 0x8D8A, + 0xD4BE, 0x8DC3, + 0xD4BF, 0x94A5, + 0xD4C0, 0x5CB3, + 0xD4C1, 0x7CA4, + 0xD4C2, 0x6708, + 0xD4C3, 0x60A6, + 0xD4C4, 0x9605, + 0xD4C5, 0x8018, + 0xD4C6, 0x4E91, + 0xD4C7, 0x90E7, + 0xD4C8, 0x5300, + 0xD4C9, 0x9668, + 0xD4CA, 0x5141, + 0xD4CB, 0x8FD0, + 0xD4CC, 0x8574, + 0xD4CD, 0x915D, + 0xD4CE, 0x6655, + 0xD4CF, 0x97F5, + 0xD4D0, 0x5B55, + 0xD4D1, 0x531D, + 0xD4D2, 0x7838, + 0xD4D3, 0x6742, + 0xD4D4, 0x683D, + 0xD4D5, 0x54C9, + 0xD4D6, 0x707E, + 0xD4D7, 0x5BB0, + 0xD4D8, 0x8F7D, + 0xD4D9, 0x518D, + 0xD4DA, 0x5728, + 0xD4DB, 0x54B1, + 0xD4DC, 0x6512, + 0xD4DD, 0x6682, + 0xD4DE, 0x8D5E, + 0xD4DF, 0x8D43, + 0xD4E0, 0x810F, + 0xD4E1, 0x846C, + 0xD4E2, 0x906D, + 0xD4E3, 0x7CDF, + 0xD4E4, 0x51FF, + 0xD4E5, 0x85FB, + 0xD4E6, 0x67A3, + 0xD4E7, 0x65E9, + 0xD4E8, 0x6FA1, + 0xD4E9, 0x86A4, + 0xD4EA, 0x8E81, + 0xD4EB, 0x566A, + 0xD4EC, 0x9020, + 0xD4ED, 0x7682, + 0xD4EE, 0x7076, + 0xD4EF, 0x71E5, + 0xD4F0, 0x8D23, + 0xD4F1, 0x62E9, + 0xD4F2, 0x5219, + 0xD4F3, 0x6CFD, + 0xD4F4, 0x8D3C, + 0xD4F5, 0x600E, + 0xD4F6, 0x589E, + 0xD4F7, 0x618E, + 0xD4F8, 0x66FE, + 0xD4F9, 0x8D60, + 0xD4FA, 0x624E, + 0xD4FB, 0x55B3, + 0xD4FC, 0x6E23, + 0xD4FD, 0x672D, + 0xD4FE, 0x8F67, + 0xD5A1, 0x94E1, + 0xD5A2, 0x95F8, + 0xD5A3, 0x7728, + 0xD5A4, 0x6805, + 0xD5A5, 0x69A8, + 0xD5A6, 0x548B, + 0xD5A7, 0x4E4D, + 0xD5A8, 0x70B8, + 0xD5A9, 0x8BC8, + 0xD5AA, 0x6458, + 0xD5AB, 0x658B, + 0xD5AC, 0x5B85, + 0xD5AD, 0x7A84, + 0xD5AE, 0x503A, + 0xD5AF, 0x5BE8, + 0xD5B0, 0x77BB, + 0xD5B1, 0x6BE1, + 0xD5B2, 0x8A79, + 0xD5B3, 0x7C98, + 0xD5B4, 0x6CBE, + 0xD5B5, 0x76CF, + 0xD5B6, 0x65A9, + 0xD5B7, 0x8F97, + 0xD5B8, 0x5D2D, + 0xD5B9, 0x5C55, + 0xD5BA, 0x8638, + 0xD5BB, 0x6808, + 0xD5BC, 0x5360, + 0xD5BD, 0x6218, + 0xD5BE, 0x7AD9, + 0xD5BF, 0x6E5B, + 0xD5C0, 0x7EFD, + 0xD5C1, 0x6A1F, + 0xD5C2, 0x7AE0, + 0xD5C3, 0x5F70, + 0xD5C4, 0x6F33, + 0xD5C5, 0x5F20, + 0xD5C6, 0x638C, + 0xD5C7, 0x6DA8, + 0xD5C8, 0x6756, + 0xD5C9, 0x4E08, + 0xD5CA, 0x5E10, + 0xD5CB, 0x8D26, + 0xD5CC, 0x4ED7, + 0xD5CD, 0x80C0, + 0xD5CE, 0x7634, + 0xD5CF, 0x969C, + 0xD5D0, 0x62DB, + 0xD5D1, 0x662D, + 0xD5D2, 0x627E, + 0xD5D3, 0x6CBC, + 0xD5D4, 0x8D75, + 0xD5D5, 0x7167, + 0xD5D6, 0x7F69, + 0xD5D7, 0x5146, + 0xD5D8, 0x8087, + 0xD5D9, 0x53EC, + 0xD5DA, 0x906E, + 0xD5DB, 0x6298, + 0xD5DC, 0x54F2, + 0xD5DD, 0x86F0, + 0xD5DE, 0x8F99, + 0xD5DF, 0x8005, + 0xD5E0, 0x9517, + 0xD5E1, 0x8517, + 0xD5E2, 0x8FD9, + 0xD5E3, 0x6D59, + 0xD5E4, 0x73CD, + 0xD5E5, 0x659F, + 0xD5E6, 0x771F, + 0xD5E7, 0x7504, + 0xD5E8, 0x7827, + 0xD5E9, 0x81FB, + 0xD5EA, 0x8D1E, + 0xD5EB, 0x9488, + 0xD5EC, 0x4FA6, + 0xD5ED, 0x6795, + 0xD5EE, 0x75B9, + 0xD5EF, 0x8BCA, + 0xD5F0, 0x9707, + 0xD5F1, 0x632F, + 0xD5F2, 0x9547, + 0xD5F3, 0x9635, + 0xD5F4, 0x84B8, + 0xD5F5, 0x6323, + 0xD5F6, 0x7741, + 0xD5F7, 0x5F81, + 0xD5F8, 0x72F0, + 0xD5F9, 0x4E89, + 0xD5FA, 0x6014, + 0xD5FB, 0x6574, + 0xD5FC, 0x62EF, + 0xD5FD, 0x6B63, + 0xD5FE, 0x653F, + 0xD6A1, 0x5E27, + 0xD6A2, 0x75C7, + 0xD6A3, 0x90D1, + 0xD6A4, 0x8BC1, + 0xD6A5, 0x829D, + 0xD6A6, 0x679D, + 0xD6A7, 0x652F, + 0xD6A8, 0x5431, + 0xD6A9, 0x8718, + 0xD6AA, 0x77E5, + 0xD6AB, 0x80A2, + 0xD6AC, 0x8102, + 0xD6AD, 0x6C41, + 0xD6AE, 0x4E4B, + 0xD6AF, 0x7EC7, + 0xD6B0, 0x804C, + 0xD6B1, 0x76F4, + 0xD6B2, 0x690D, + 0xD6B3, 0x6B96, + 0xD6B4, 0x6267, + 0xD6B5, 0x503C, + 0xD6B6, 0x4F84, + 0xD6B7, 0x5740, + 0xD6B8, 0x6307, + 0xD6B9, 0x6B62, + 0xD6BA, 0x8DBE, + 0xD6BB, 0x53EA, + 0xD6BC, 0x65E8, + 0xD6BD, 0x7EB8, + 0xD6BE, 0x5FD7, + 0xD6BF, 0x631A, + 0xD6C0, 0x63B7, + 0xD6C3, 0x7F6E, + 0xD6C4, 0x5E1C, + 0xD6C5, 0x5CD9, + 0xD6C6, 0x5236, + 0xD6C7, 0x667A, + 0xD6C8, 0x79E9, + 0xD6C9, 0x7A1A, + 0xD6CA, 0x8D28, + 0xD6CB, 0x7099, + 0xD6CC, 0x75D4, + 0xD6CD, 0x6EDE, + 0xD6CE, 0x6CBB, + 0xD6CF, 0x7A92, + 0xD6D0, 0x4E2D, + 0xD6D1, 0x76C5, + 0xD6D2, 0x5FE0, + 0xD6D3, 0x949F, + 0xD6D4, 0x8877, + 0xD6D5, 0x7EC8, + 0xD6D6, 0x79CD, + 0xD6D7, 0x80BF, + 0xD6D8, 0x91CD, + 0xD6D9, 0x4EF2, + 0xD6DA, 0x4F17, + 0xD6DB, 0x821F, + 0xD6DC, 0x5468, + 0xD6DD, 0x5DDE, + 0xD6DE, 0x6D32, + 0xD6DF, 0x8BCC, + 0xD6E0, 0x7CA5, + 0xD6E1, 0x8F74, + 0xD6E2, 0x8098, + 0xD6E3, 0x5E1A, + 0xD6E4, 0x5492, + 0xD6E5, 0x76B1, + 0xD6E6, 0x5B99, + 0xD6E7, 0x663C, + 0xD6E8, 0x9AA4, + 0xD6E9, 0x73E0, + 0xD6EA, 0x682A, + 0xD6EB, 0x86DB, + 0xD6EC, 0x6731, + 0xD6ED, 0x732A, + 0xD6EE, 0x8BF8, + 0xD6EF, 0x8BDB, + 0xD6F0, 0x9010, + 0xD6F1, 0x7AF9, + 0xD6F2, 0x70DB, + 0xD6F3, 0x716E, + 0xD6F4, 0x62C4, + 0xD6F5, 0x77A9, + 0xD6F6, 0x5631, + 0xD6F7, 0x4E3B, + 0xD6F8, 0x8457, + 0xD6F9, 0x67F1, + 0xD6FA, 0x52A9, + 0xD6FB, 0x86C0, + 0xD6FC, 0x8D2E, + 0xD6FD, 0x94F8, + 0xD6FE, 0x7B51, + 0xD799, 0x8BAC, + 0xD79A, 0x8BB1, + 0xD79B, 0x8BBB, + 0xD79C, 0x8BC7, + 0xD79D, 0x8BD0, + 0xD79E, 0x8BEA, + 0xD79F, 0x8C09, + 0xD7A0, 0x8C1E, + 0xD7A1, 0x4F4F, + 0xD7A2, 0x6CE8, + 0xD7A3, 0x795D, + 0xD7A4, 0x9A7B, + 0xD7A5, 0x6293, + 0xD7A6, 0x722A, + 0xD7A7, 0x62FD, + 0xD7A8, 0x4E13, + 0xD7A9, 0x7816, + 0xD7AA, 0x8F6C, + 0xD7AB, 0x64B0, + 0xD7AC, 0x8D5A, + 0xD7AD, 0x7BC6, + 0xD7AE, 0x6869, + 0xD7AF, 0x5E84, + 0xD7B0, 0x88C5, + 0xD7B1, 0x5986, + 0xD7B2, 0x649E, + 0xD7B3, 0x58EE, + 0xD7B4, 0x72B6, + 0xD7B5, 0x690E, + 0xD7B6, 0x9525, + 0xD7B7, 0x8FFD, + 0xD7B8, 0x8D58, + 0xD7B9, 0x5760, + 0xD7BA, 0x7F00, + 0xD7BB, 0x8C06, + 0xD7BC, 0x51C6, + 0xD7BD, 0x6349, + 0xD7BE, 0x62D9, + 0xD7BF, 0x5353, + 0xD7C0, 0x684C, + 0xD7C1, 0x7422, + 0xD7C2, 0x8301, + 0xD7C3, 0x914C, + 0xD7C4, 0x5544, + 0xD7C5, 0x7740, + 0xD7C6, 0x707C, + 0xD7C7, 0x6D4A, + 0xD7C8, 0x5179, + 0xD7C9, 0x54A8, + 0xD7CA, 0x8D44, + 0xD7CB, 0x59FF, + 0xD7CC, 0x6ECB, + 0xD7CD, 0x6DC4, + 0xD7CE, 0x5B5C, + 0xD7CF, 0x7D2B, + 0xD7D0, 0x4ED4, + 0xD7D1, 0x7C7D, + 0xD7D2, 0x6ED3, + 0xD7D3, 0x5B50, + 0xD7D4, 0x81EA, + 0xD7D5, 0x6E0D, + 0xD7D6, 0x5B57, + 0xD7D7, 0x9B03, + 0xD7D8, 0x68D5, + 0xD7D9, 0x8E2A, + 0xD7DA, 0x5B97, + 0xD7DB, 0x7EFC, + 0xD7DC, 0x603B, + 0xD7DD, 0x7EB5, + 0xD7DE, 0x90B9, + 0xD7DF, 0x8D70, + 0xD7E0, 0x594F, + 0xD7E1, 0x63CD, + 0xD7E2, 0x79DF, + 0xD7E3, 0x8DB3, + 0xD7E4, 0x5352, + 0xD7E5, 0x65CF, + 0xD7E6, 0x7956, + 0xD7E7, 0x8BC5, + 0xD7E8, 0x963B, + 0xD7E9, 0x7EC4, + 0xD7EA, 0x94BB, + 0xD7EB, 0x7E82, + 0xD7EC, 0x5634, + 0xD7ED, 0x9189, + 0xD7EE, 0x6700, + 0xD7EF, 0x7F6A, + 0xD7F0, 0x5C0A, + 0xD7F1, 0x9075, + 0xD7F2, 0x6628, + 0xD7F3, 0x5DE6, + 0xD7F4, 0x4F50, + 0xD7F5, 0x67DE, + 0xD7F6, 0x505A, + 0xD7F7, 0x4F5C, + 0xD7F8, 0x5750, + 0xD7F9, 0x5EA7, + 0xD84D, 0x8C48, + 0xD880, 0x8C88, + 0xD881, 0x8C8B, + 0xD8A1, 0x4E8D, + 0xD8A2, 0x4E0C, + 0xD8A3, 0x5140, + 0xD8A4, 0x4E10, + 0xD8A5, 0x5EFF, + 0xD8A6, 0x5345, + 0xD8A7, 0x4E15, + 0xD8A8, 0x4E98, + 0xD8A9, 0x4E1E, + 0xD8AA, 0x9B32, + 0xD8AB, 0x5B6C, + 0xD8AC, 0x5669, + 0xD8AD, 0x4E28, + 0xD8AE, 0x79BA, + 0xD8AF, 0x4E3F, + 0xD8B0, 0x5315, + 0xD8B1, 0x4E47, + 0xD8B2, 0x592D, + 0xD8B3, 0x723B, + 0xD8B4, 0x536E, + 0xD8B5, 0x6C10, + 0xD8B6, 0x56DF, + 0xD8B7, 0x80E4, + 0xD8B8, 0x9997, + 0xD8B9, 0x6BD3, + 0xD8BA, 0x777E, + 0xD8BB, 0x9F17, + 0xD8BC, 0x4E36, + 0xD8BD, 0x4E9F, + 0xD8BE, 0x9F10, + 0xD8BF, 0x4E5C, + 0xD8C0, 0x4E69, + 0xD8C1, 0x4E93, + 0xD8C2, 0x8288, + 0xD8C3, 0x5B5B, + 0xD8C4, 0x556C, + 0xD8C5, 0x560F, + 0xD8C6, 0x4EC4, + 0xD8C7, 0x538D, + 0xD8C8, 0x539D, + 0xD8C9, 0x53A3, + 0xD8CA, 0x53A5, + 0xD8CB, 0x53AE, + 0xD8CC, 0x9765, + 0xD8CD, 0x8D5D, + 0xD8CE, 0x531A, + 0xD8CF, 0x53F5, + 0xD8D0, 0x5326, + 0xD8D1, 0x532E, + 0xD8D2, 0x533E, + 0xD8D3, 0x8D5C, + 0xD8D4, 0x5366, + 0xD8D5, 0x5363, + 0xD8D6, 0x5202, + 0xD8D7, 0x5208, + 0xD8D8, 0x520E, + 0xD8D9, 0x522D, + 0xD8DA, 0x5233, + 0xD8DD, 0x524C, + 0xD8DE, 0x525E, + 0xD8DF, 0x5261, + 0xD8E0, 0x525C, + 0xD8E1, 0x84AF, + 0xD8E2, 0x527D, + 0xD8E3, 0x5282, + 0xD8E4, 0x5281, + 0xD8E5, 0x5290, + 0xD8E6, 0x5293, + 0xD8E7, 0x5182, + 0xD8E8, 0x7F54, + 0xD8E9, 0x4EBB, + 0xD8EA, 0x4EC3, + 0xD8EB, 0x4EC9, + 0xD8EC, 0x4EC2, + 0xD8ED, 0x4EE8, + 0xD8EE, 0x4EE1, + 0xD8EF, 0x4EEB, + 0xD8F0, 0x4EDE, + 0xD8F1, 0x4F1B, + 0xD8F2, 0x4EF3, + 0xD8F3, 0x4F22, + 0xD8F4, 0x4F64, + 0xD8F5, 0x4EF5, + 0xD8F6, 0x4F25, + 0xD8F7, 0x4F27, + 0xD8F8, 0x4F09, + 0xD8F9, 0x4F2B, + 0xD8FA, 0x4F5E, + 0xD8FB, 0x4F67, + 0xD8FC, 0x6538, + 0xD8FD, 0x4F5A, + 0xD8FE, 0x4F5D, + 0xD9A1, 0x4F5F, + 0xD9A2, 0x4F57, + 0xD9A3, 0x4F32, + 0xD9A4, 0x4F3D, + 0xD9A5, 0x4F76, + 0xD9A6, 0x4F74, + 0xD9A7, 0x4F91, + 0xD9A8, 0x4F89, + 0xD9A9, 0x4F83, + 0xD9AA, 0x4F8F, + 0xD9AB, 0x4F7E, + 0xD9AC, 0x4F7B, + 0xD9AD, 0x4FAA, + 0xD9AE, 0x4F7C, + 0xD9AF, 0x4FAC, + 0xD9B0, 0x4F94, + 0xD9B1, 0x4FE6, + 0xD9B2, 0x4FE8, + 0xD9B3, 0x4FEA, + 0xD9B4, 0x4FC5, + 0xD9B5, 0x4FDA, + 0xD9B6, 0x4FE3, + 0xD9B7, 0x4FDC, + 0xD9B8, 0x4FD1, + 0xD9B9, 0x4FDF, + 0xD9BA, 0x4FF8, + 0xD9BB, 0x5029, + 0xD9BC, 0x504C, + 0xD9BD, 0x4FF3, + 0xD9BE, 0x502C, + 0xD9BF, 0x500F, + 0xD9C0, 0x502E, + 0xD9C1, 0x502D, + 0xD9C2, 0x4FFE, + 0xD9C3, 0x501C, + 0xD9C4, 0x500C, + 0xD9C5, 0x5025, + 0xD9C6, 0x5028, + 0xD9C7, 0x507E, + 0xD9C8, 0x5043, + 0xD9C9, 0x5055, + 0xD9CA, 0x5048, + 0xD9CB, 0x504E, + 0xD9CC, 0x506C, + 0xD9CD, 0x507B, + 0xD9CE, 0x50A5, + 0xD9CF, 0x50A7, + 0xD9D0, 0x50A9, + 0xD9D1, 0x50BA, + 0xD9D2, 0x50D6, + 0xD9D3, 0x5106, + 0xD9D4, 0x50ED, + 0xD9D5, 0x50EC, + 0xD9D6, 0x50E6, + 0xD9D7, 0x50EE, + 0xD9D8, 0x5107, + 0xD9D9, 0x510B, + 0xD9DA, 0x4EDD, + 0xD9DB, 0x6C3D, + 0xD9DC, 0x4F58, + 0xD9DD, 0x4F65, + 0xD9DE, 0x4FCE, + 0xD9DF, 0x9FA0, + 0xD9E0, 0x6C46, + 0xD9E1, 0x7C74, + 0xD9E2, 0x516E, + 0xD9E3, 0x5DFD, + 0xD9E4, 0x9EC9, + 0xD9E5, 0x9998, + 0xD9E6, 0x5181, + 0xD9E7, 0x5914, + 0xD9E8, 0x52F9, + 0xD9E9, 0x530D, + 0xD9EA, 0x8A07, + 0xD9EB, 0x5310, + 0xD9EC, 0x51EB, + 0xD9ED, 0x5919, + 0xD9EE, 0x5155, + 0xD9EF, 0x4EA0, + 0xD9F0, 0x5156, + 0xD9F1, 0x4EB3, + 0xD9F2, 0x886E, + 0xD9F3, 0x88A4, + 0xD9F4, 0x4EB5, + 0xD9F5, 0x8114, + 0xD9F6, 0x88D2, + 0xD9F7, 0x7980, + 0xD9F8, 0x5B34, + 0xD9F9, 0x8803, + 0xD9FA, 0x7FB8, + 0xD9FB, 0x51AB, + 0xD9FC, 0x51B1, + 0xD9FD, 0x51BD, + 0xD9FE, 0x51BC, + 0xDA4F, 0x8D20, + 0xDA52, 0x8D57, + 0xDA53, 0x8D5F, + 0xDA54, 0x8D65, + 0xDA58, 0x8D6C, + 0xDA80, 0x8DA2, + 0xDA8E, 0x8DB2, + 0xDA91, 0x8DB9, + 0xDA92, 0x8DBB, + 0xDA93, 0x8DBD, + 0xDA97, 0x8DC5, + 0xDA9C, 0x8DCD, + 0xDA9D, 0x8DD0, + 0xDAA1, 0x51C7, + 0xDAA2, 0x5196, + 0xDAA3, 0x51A2, + 0xDAA4, 0x51A5, + 0xDAA5, 0x8BA0, + 0xDAA8, 0x8BAA, + 0xDAAB, 0x8BB7, + 0xDAAE, 0x8BCB, + 0xDAAF, 0x8BCF, + 0xDAB0, 0x8BCE, + 0xDAB4, 0x8BD6, + 0xDAB7, 0x8BDC, + 0xDABA, 0x8BE4, + 0xDABD, 0x8BEE, + 0xDABE, 0x8BF0, + 0xDABF, 0x8BF3, + 0xDAC0, 0x8BF6, + 0xDAC1, 0x8BF9, + 0xDAC2, 0x8BFC, + 0xDAC5, 0x8C02, + 0xDAC6, 0x8C04, + 0xDAC7, 0x8C07, + 0xDAC8, 0x8C0C, + 0xDAC9, 0x8C0F, + 0xDACF, 0x8C19, + 0xDAD0, 0x8C1B, + 0xDAD1, 0x8C18, + 0xDAD2, 0x8C1D, + 0xDAD6, 0x8C25, + 0xDAD7, 0x8C27, + 0xDAE0, 0x5369, + 0xDAE1, 0x537A, + 0xDAE2, 0x961D, + 0xDAE3, 0x9622, + 0xDAE4, 0x9621, + 0xDAE5, 0x9631, + 0xDAE6, 0x962A, + 0xDAE7, 0x963D, + 0xDAE8, 0x963C, + 0xDAE9, 0x9642, + 0xDAEA, 0x9649, + 0xDAEB, 0x9654, + 0xDAEC, 0x965F, + 0xDAED, 0x9667, + 0xDAEE, 0x966C, + 0xDAEF, 0x9672, + 0xDAF0, 0x9674, + 0xDAF1, 0x9688, + 0xDAF2, 0x968D, + 0xDAF3, 0x9697, + 0xDAF4, 0x96B0, + 0xDAF5, 0x9097, + 0xDAF6, 0x909B, + 0xDAF7, 0x909D, + 0xDAF8, 0x9099, + 0xDAF9, 0x90AC, + 0xDAFA, 0x90A1, + 0xDAFB, 0x90B4, + 0xDAFC, 0x90B3, + 0xDAFD, 0x90B6, + 0xDAFE, 0x90BA, + 0xDB40, 0x8DD5, + 0xDB43, 0x8DDC, + 0xDB4A, 0x8DE9, + 0xDB50, 0x8DF4, + 0xDB51, 0x8DF6, + 0xDB52, 0x8DFC, + 0xDB5D, 0x8E0B, + 0xDB73, 0x8E2B, + 0xDB74, 0x8E2D, + 0xDB75, 0x8E30, + 0xDB7E, 0x8E3E, + 0xDB80, 0x8E3F, + 0xDB81, 0x8E43, + 0xDB9F, 0x8E6E, + 0xDBA0, 0x8E71, + 0xDBA1, 0x90B8, + 0xDBA2, 0x90B0, + 0xDBA3, 0x90CF, + 0xDBA4, 0x90C5, + 0xDBA5, 0x90BE, + 0xDBA6, 0x90D0, + 0xDBA7, 0x90C4, + 0xDBA8, 0x90C7, + 0xDBA9, 0x90D3, + 0xDBAA, 0x90E6, + 0xDBAB, 0x90E2, + 0xDBAC, 0x90DC, + 0xDBAD, 0x90D7, + 0xDBAE, 0x90DB, + 0xDBAF, 0x90EB, + 0xDBB0, 0x90EF, + 0xDBB1, 0x90FE, + 0xDBB2, 0x9104, + 0xDBB3, 0x9122, + 0xDBB4, 0x911E, + 0xDBB5, 0x9123, + 0xDBB6, 0x9131, + 0xDBB7, 0x912F, + 0xDBB8, 0x9139, + 0xDBB9, 0x9143, + 0xDBBA, 0x9146, + 0xDBBB, 0x520D, + 0xDBBC, 0x5942, + 0xDBBD, 0x52A2, + 0xDBC0, 0x52BE, + 0xDBC1, 0x54FF, + 0xDBC2, 0x52D0, + 0xDBC3, 0x52D6, + 0xDBC4, 0x52F0, + 0xDBC5, 0x53DF, + 0xDBC6, 0x71EE, + 0xDBC7, 0x77CD, + 0xDBC8, 0x5EF4, + 0xDBC9, 0x51F5, + 0xDBCA, 0x51FC, + 0xDBCB, 0x9B2F, + 0xDBCC, 0x53B6, + 0xDBCD, 0x5F01, + 0xDBCE, 0x755A, + 0xDBCF, 0x5DEF, + 0xDBD0, 0x574C, + 0xDBD1, 0x57A9, + 0xDBD2, 0x57A1, + 0xDBD3, 0x587E, + 0xDBD4, 0x58BC, + 0xDBD5, 0x58C5, + 0xDBD6, 0x58D1, + 0xDBD7, 0x5729, + 0xDBD8, 0x572C, + 0xDBD9, 0x572A, + 0xDBDA, 0x5733, + 0xDBDB, 0x5739, + 0xDBDE, 0x575C, + 0xDBDF, 0x573B, + 0xDBE0, 0x5742, + 0xDBE1, 0x5769, + 0xDBE2, 0x5785, + 0xDBE3, 0x576B, + 0xDBE4, 0x5786, + 0xDBE5, 0x577C, + 0xDBE6, 0x577B, + 0xDBE7, 0x5768, + 0xDBE8, 0x576D, + 0xDBE9, 0x5776, + 0xDBEA, 0x5773, + 0xDBEB, 0x57AD, + 0xDBEC, 0x57A4, + 0xDBED, 0x578C, + 0xDBEE, 0x57B2, + 0xDBEF, 0x57CF, + 0xDBF0, 0x57A7, + 0xDBF1, 0x57B4, + 0xDBF2, 0x5793, + 0xDBF3, 0x57A0, + 0xDBF4, 0x57D5, + 0xDBF5, 0x57D8, + 0xDBF6, 0x57DA, + 0xDBF7, 0x57D9, + 0xDBF8, 0x57D2, + 0xDBF9, 0x57B8, + 0xDBFA, 0x57F4, + 0xDBFB, 0x57EF, + 0xDBFC, 0x57F8, + 0xDBFD, 0x57E4, + 0xDBFE, 0x57DD, + 0xDC40, 0x8E73, + 0xDC41, 0x8E75, + 0xDC49, 0x8E80, + 0xDC4D, 0x8E86, + 0xDC5F, 0x8E9D, + 0xDCA1, 0x580B, + 0xDCA2, 0x580D, + 0xDCA3, 0x57FD, + 0xDCA4, 0x57ED, + 0xDCA5, 0x5800, + 0xDCA6, 0x581E, + 0xDCA7, 0x5819, + 0xDCA8, 0x5844, + 0xDCA9, 0x5820, + 0xDCAA, 0x5865, + 0xDCAB, 0x586C, + 0xDCAC, 0x5881, + 0xDCAD, 0x5889, + 0xDCAE, 0x589A, + 0xDCAF, 0x5880, + 0xDCB0, 0x99A8, + 0xDCB1, 0x9F19, + 0xDCB2, 0x61FF, + 0xDCB3, 0x8279, + 0xDCB4, 0x827D, + 0xDCB5, 0x827F, + 0xDCB6, 0x828F, + 0xDCB7, 0x828A, + 0xDCB8, 0x82A8, + 0xDCB9, 0x8284, + 0xDCBA, 0x828E, + 0xDCBB, 0x8291, + 0xDCBC, 0x8297, + 0xDCBD, 0x8299, + 0xDCBE, 0x82AB, + 0xDCBF, 0x82B8, + 0xDCC0, 0x82BE, + 0xDCC1, 0x82B0, + 0xDCC2, 0x82C8, + 0xDCC3, 0x82CA, + 0xDCC4, 0x82E3, + 0xDCC5, 0x8298, + 0xDCC6, 0x82B7, + 0xDCC7, 0x82AE, + 0xDCCA, 0x82C1, + 0xDCCB, 0x82A9, + 0xDCCC, 0x82B4, + 0xDCCD, 0x82A1, + 0xDCCE, 0x82AA, + 0xDCCF, 0x829F, + 0xDCD0, 0x82C4, + 0xDCD1, 0x82CE, + 0xDCD2, 0x82A4, + 0xDCD3, 0x82E1, + 0xDCD4, 0x8309, + 0xDCD5, 0x82F7, + 0xDCD6, 0x82E4, + 0xDCD7, 0x830F, + 0xDCD8, 0x8307, + 0xDCD9, 0x82DC, + 0xDCDA, 0x82F4, + 0xDCDB, 0x82D2, + 0xDCDC, 0x82D8, + 0xDCDD, 0x830C, + 0xDCDE, 0x82FB, + 0xDCDF, 0x82D3, + 0xDCE0, 0x8311, + 0xDCE1, 0x831A, + 0xDCE2, 0x8306, + 0xDCE5, 0x82E0, + 0xDCE6, 0x82D5, + 0xDCE7, 0x831C, + 0xDCE8, 0x8351, + 0xDCEB, 0x8308, + 0xDCEC, 0x8392, + 0xDCED, 0x833C, + 0xDCEE, 0x8334, + 0xDCEF, 0x8331, + 0xDCF0, 0x839B, + 0xDCF1, 0x835E, + 0xDCF2, 0x832F, + 0xDCF3, 0x834F, + 0xDCF4, 0x8347, + 0xDCF5, 0x8343, + 0xDCF6, 0x835F, + 0xDCF7, 0x8340, + 0xDCF8, 0x8317, + 0xDCF9, 0x8360, + 0xDCFA, 0x832D, + 0xDCFB, 0x833A, + 0xDCFC, 0x8333, + 0xDCFD, 0x8366, + 0xDCFE, 0x8365, + 0xDDA1, 0x8368, + 0xDDA2, 0x831B, + 0xDDA3, 0x8369, + 0xDDA4, 0x836C, + 0xDDA5, 0x836A, + 0xDDA8, 0x83B0, + 0xDDA9, 0x8378, + 0xDDAC, 0x83A0, + 0xDDAD, 0x83AA, + 0xDDAE, 0x8393, + 0xDDAF, 0x839C, + 0xDDB0, 0x8385, + 0xDDB1, 0x837C, + 0xDDB2, 0x83B6, + 0xDDB3, 0x83A9, + 0xDDB4, 0x837D, + 0xDDB5, 0x83B8, + 0xDDB6, 0x837B, + 0xDDB7, 0x8398, + 0xDDB8, 0x839E, + 0xDDB9, 0x83A8, + 0xDDBA, 0x83BA, + 0xDDBB, 0x83BC, + 0xDDBC, 0x83C1, + 0xDDBD, 0x8401, + 0xDDBE, 0x83E5, + 0xDDBF, 0x83D8, + 0xDDC0, 0x5807, + 0xDDC1, 0x8418, + 0xDDC2, 0x840B, + 0xDDC3, 0x83DD, + 0xDDC4, 0x83FD, + 0xDDC5, 0x83D6, + 0xDDC6, 0x841C, + 0xDDC7, 0x8438, + 0xDDC8, 0x8411, + 0xDDC9, 0x8406, + 0xDDCA, 0x83D4, + 0xDDCB, 0x83DF, + 0xDDCC, 0x840F, + 0xDDCD, 0x8403, + 0xDDD0, 0x83EA, + 0xDDD1, 0x83C5, + 0xDDD2, 0x83C0, + 0xDDD3, 0x8426, + 0xDDD4, 0x83F0, + 0xDDD5, 0x83E1, + 0xDDD6, 0x845C, + 0xDDD7, 0x8451, + 0xDDD8, 0x845A, + 0xDDD9, 0x8459, + 0xDDDA, 0x8473, + 0xDDDD, 0x847A, + 0xDDDE, 0x8489, + 0xDDDF, 0x8478, + 0xDDE0, 0x843C, + 0xDDE1, 0x8446, + 0xDDE2, 0x8469, + 0xDDE3, 0x8476, + 0xDDE4, 0x848C, + 0xDDE5, 0x848E, + 0xDDE6, 0x8431, + 0xDDE7, 0x846D, + 0xDDE8, 0x84C1, + 0xDDE9, 0x84CD, + 0xDDEA, 0x84D0, + 0xDDEB, 0x84E6, + 0xDDEC, 0x84BD, + 0xDDED, 0x84D3, + 0xDDEE, 0x84CA, + 0xDDEF, 0x84BF, + 0xDDF0, 0x84BA, + 0xDDF1, 0x84E0, + 0xDDF2, 0x84A1, + 0xDDF3, 0x84B9, + 0xDDF4, 0x84B4, + 0xDDF5, 0x8497, + 0xDDF6, 0x84E5, + 0xDDF7, 0x84E3, + 0xDDF8, 0x850C, + 0xDDF9, 0x750D, + 0xDDFA, 0x8538, + 0xDDFB, 0x84F0, + 0xDDFC, 0x8539, + 0xDDFD, 0x851F, + 0xDDFE, 0x853A, + 0xDE61, 0x8F6A, + 0xDE62, 0x8F80, + 0xDE63, 0x8F8C, + 0xDE64, 0x8F92, + 0xDE65, 0x8F9D, + 0xDE6D, 0x8FAA, + 0xDE7D, 0x8FC3, + 0xDE7E, 0x8FC6, + 0xDE85, 0x8FCF, + 0xDE86, 0x8FD2, + 0xDE89, 0x8FDA, + 0xDE8C, 0x8FE3, + 0xDE8D, 0x8FE7, + 0xDE8E, 0x8FEC, + 0xDE8F, 0x8FEF, + 0xDE9C, 0x900C, + 0xDE9D, 0x900E, + 0xDE9E, 0x9013, + 0xDE9F, 0x9015, + 0xDEA0, 0x9018, + 0xDEA1, 0x8556, + 0xDEA2, 0x853B, + 0xDEA3, 0x84FF, + 0xDEA4, 0x84FC, + 0xDEA5, 0x8559, + 0xDEA6, 0x8548, + 0xDEA7, 0x8568, + 0xDEA8, 0x8564, + 0xDEA9, 0x855E, + 0xDEAA, 0x857A, + 0xDEAB, 0x77A2, + 0xDEAC, 0x8543, + 0xDEAD, 0x8572, + 0xDEAE, 0x857B, + 0xDEAF, 0x85A4, + 0xDEB0, 0x85A8, + 0xDEB1, 0x8587, + 0xDEB2, 0x858F, + 0xDEB3, 0x8579, + 0xDEB4, 0x85AE, + 0xDEB5, 0x859C, + 0xDEB6, 0x8585, + 0xDEB7, 0x85B9, + 0xDEB8, 0x85B7, + 0xDEB9, 0x85B0, + 0xDEBA, 0x85D3, + 0xDEBB, 0x85C1, + 0xDEBC, 0x85DC, + 0xDEBD, 0x85FF, + 0xDEBE, 0x8627, + 0xDEBF, 0x8605, + 0xDEC0, 0x8629, + 0xDEC1, 0x8616, + 0xDEC2, 0x863C, + 0xDEC3, 0x5EFE, + 0xDEC4, 0x5F08, + 0xDEC5, 0x593C, + 0xDEC6, 0x5941, + 0xDEC7, 0x8037, + 0xDEC8, 0x5955, + 0xDEC9, 0x595A, + 0xDECA, 0x5958, + 0xDECB, 0x530F, + 0xDECC, 0x5C22, + 0xDECD, 0x5C25, + 0xDECE, 0x5C2C, + 0xDECF, 0x5C34, + 0xDED0, 0x624C, + 0xDED1, 0x626A, + 0xDED2, 0x629F, + 0xDED3, 0x62BB, + 0xDED4, 0x62CA, + 0xDED5, 0x62DA, + 0xDED6, 0x62D7, + 0xDED7, 0x62EE, + 0xDED8, 0x6322, + 0xDED9, 0x62F6, + 0xDEDA, 0x6339, + 0xDEDB, 0x634B, + 0xDEDC, 0x6343, + 0xDEDD, 0x63AD, + 0xDEDE, 0x63F6, + 0xDEDF, 0x6371, + 0xDEE0, 0x637A, + 0xDEE1, 0x638E, + 0xDEE2, 0x63B4, + 0xDEE3, 0x636D, + 0xDEE4, 0x63AC, + 0xDEE5, 0x638A, + 0xDEE6, 0x6369, + 0xDEE7, 0x63AE, + 0xDEE8, 0x63BC, + 0xDEE9, 0x63F2, + 0xDEEA, 0x63F8, + 0xDEEB, 0x63E0, + 0xDEEC, 0x63FF, + 0xDEED, 0x63C4, + 0xDEEE, 0x63DE, + 0xDEEF, 0x63CE, + 0xDEF0, 0x6452, + 0xDEF1, 0x63C6, + 0xDEF2, 0x63BE, + 0xDEF3, 0x6445, + 0xDEF4, 0x6441, + 0xDEF5, 0x640B, + 0xDEF6, 0x641B, + 0xDEF7, 0x6420, + 0xDEF8, 0x640C, + 0xDEF9, 0x6426, + 0xDEFA, 0x6421, + 0xDEFB, 0x645E, + 0xDEFC, 0x6484, + 0xDEFD, 0x646D, + 0xDEFE, 0x6496, + 0xDF40, 0x9019, + 0xDF41, 0x901C, + 0xDF50, 0x9037, + 0xDF53, 0x903D, + 0xDF56, 0x9043, + 0xDF5E, 0x904E, + 0xDF6A, 0x9064, + 0xDF7D, 0x907E, + 0xDF7E, 0x9081, + 0xDF8B, 0x9092, + 0xDF8C, 0x9094, + 0xDF8D, 0x9096, + 0xDF8E, 0x9098, + 0xDF8F, 0x909A, + 0xDF90, 0x909C, + 0xDF99, 0x90AB, + 0xDF9A, 0x90AD, + 0xDF9B, 0x90B2, + 0xDF9C, 0x90B7, + 0xDFA1, 0x647A, + 0xDFA4, 0x6499, + 0xDFA5, 0x64BA, + 0xDFA6, 0x64C0, + 0xDFA7, 0x64D0, + 0xDFA8, 0x64D7, + 0xDFA9, 0x64E4, + 0xDFAA, 0x64E2, + 0xDFAB, 0x6509, + 0xDFAC, 0x6525, + 0xDFAD, 0x652E, + 0xDFAE, 0x5F0B, + 0xDFAF, 0x5FD2, + 0xDFB0, 0x7519, + 0xDFB1, 0x5F11, + 0xDFB2, 0x535F, + 0xDFB3, 0x53F1, + 0xDFB4, 0x53FD, + 0xDFB5, 0x53E9, + 0xDFB6, 0x53E8, + 0xDFB7, 0x53FB, + 0xDFB8, 0x5412, + 0xDFB9, 0x5416, + 0xDFBA, 0x5406, + 0xDFBB, 0x544B, + 0xDFBF, 0x5456, + 0xDFC0, 0x5443, + 0xDFC1, 0x5421, + 0xDFC2, 0x5457, + 0xDFC3, 0x5459, + 0xDFC4, 0x5423, + 0xDFC5, 0x5432, + 0xDFC6, 0x5482, + 0xDFC7, 0x5494, + 0xDFC8, 0x5477, + 0xDFC9, 0x5471, + 0xDFCA, 0x5464, + 0xDFCD, 0x5484, + 0xDFCE, 0x5476, + 0xDFCF, 0x5466, + 0xDFD0, 0x549D, + 0xDFD1, 0x54D0, + 0xDFD2, 0x54AD, + 0xDFD3, 0x54C2, + 0xDFD4, 0x54B4, + 0xDFD5, 0x54D2, + 0xDFD6, 0x54A7, + 0xDFD7, 0x54A6, + 0xDFDA, 0x5472, + 0xDFDB, 0x54A3, + 0xDFDC, 0x54D5, + 0xDFDD, 0x54BB, + 0xDFDE, 0x54BF, + 0xDFDF, 0x54CC, + 0xDFE2, 0x54DC, + 0xDFE5, 0x54A4, + 0xDFE6, 0x54DD, + 0xDFE7, 0x54CF, + 0xDFE8, 0x54DE, + 0xDFE9, 0x551B, + 0xDFEA, 0x54E7, + 0xDFEB, 0x5520, + 0xDFEC, 0x54FD, + 0xDFED, 0x5514, + 0xDFEE, 0x54F3, + 0xDFF1, 0x550F, + 0xDFF2, 0x5511, + 0xDFF3, 0x5527, + 0xDFF4, 0x552A, + 0xDFF5, 0x5567, + 0xDFF6, 0x558F, + 0xDFF7, 0x55B5, + 0xDFF8, 0x5549, + 0xDFF9, 0x556D, + 0xDFFA, 0x5541, + 0xDFFB, 0x5555, + 0xDFFC, 0x553F, + 0xDFFD, 0x5550, + 0xDFFE, 0x553C, + 0xE042, 0x90C6, + 0xE048, 0x90D2, + 0xE057, 0x90EC, + 0xE058, 0x90EE, + 0xE067, 0x9103, + 0xE080, 0x911D, + 0xE08F, 0x9130, + 0xE0A0, 0x9144, + 0xE0A1, 0x5537, + 0xE0A2, 0x5556, + 0xE0A6, 0x5533, + 0xE0A7, 0x5530, + 0xE0A8, 0x555C, + 0xE0A9, 0x558B, + 0xE0AA, 0x55D2, + 0xE0AB, 0x5583, + 0xE0AC, 0x55B1, + 0xE0AD, 0x55B9, + 0xE0AE, 0x5588, + 0xE0AF, 0x5581, + 0xE0B0, 0x559F, + 0xE0B1, 0x557E, + 0xE0B2, 0x55D6, + 0xE0B3, 0x5591, + 0xE0B4, 0x557B, + 0xE0B5, 0x55DF, + 0xE0B8, 0x5594, + 0xE0B9, 0x5599, + 0xE0BA, 0x55EA, + 0xE0BB, 0x55F7, + 0xE0BC, 0x55C9, + 0xE0BD, 0x561F, + 0xE0BE, 0x55D1, + 0xE0C1, 0x55D4, + 0xE0C2, 0x55E6, + 0xE0C3, 0x55DD, + 0xE0C4, 0x55C4, + 0xE0C5, 0x55EF, + 0xE0C6, 0x55E5, + 0xE0CB, 0x55E8, + 0xE0CC, 0x55F5, + 0xE0CD, 0x55E4, + 0xE0CE, 0x8F94, + 0xE0CF, 0x561E, + 0xE0D0, 0x5608, + 0xE0D1, 0x560C, + 0xE0D2, 0x5601, + 0xE0D3, 0x5624, + 0xE0D4, 0x5623, + 0xE0D5, 0x55FE, + 0xE0D6, 0x5600, + 0xE0D7, 0x5627, + 0xE0D8, 0x562D, + 0xE0D9, 0x5658, + 0xE0DA, 0x5639, + 0xE0DB, 0x5657, + 0xE0DC, 0x562C, + 0xE0DD, 0x564D, + 0xE0DE, 0x5662, + 0xE0DF, 0x5659, + 0xE0E0, 0x565C, + 0xE0E1, 0x564C, + 0xE0E2, 0x5654, + 0xE0E3, 0x5686, + 0xE0E4, 0x5664, + 0xE0E5, 0x5671, + 0xE0E6, 0x566B, + 0xE0E9, 0x5685, + 0xE0EA, 0x5693, + 0xE0EB, 0x56AF, + 0xE0EC, 0x56D4, + 0xE0ED, 0x56D7, + 0xE0EE, 0x56DD, + 0xE0EF, 0x56E1, + 0xE0F0, 0x56F5, + 0xE0F1, 0x56EB, + 0xE0F2, 0x56F9, + 0xE0F3, 0x56FF, + 0xE0F4, 0x5704, + 0xE0F5, 0x570A, + 0xE0F6, 0x5709, + 0xE0F7, 0x571C, + 0xE0F8, 0x5E0F, + 0xE0F9, 0x5E19, + 0xE0FA, 0x5E14, + 0xE0FB, 0x5E11, + 0xE0FC, 0x5E31, + 0xE140, 0x9145, + 0xE143, 0x9151, + 0xE151, 0x916B, + 0xE152, 0x916D, + 0xE153, 0x9173, + 0xE15C, 0x9186, + 0xE15D, 0x9188, + 0xE15E, 0x918A, + 0xE17E, 0x91BB, + 0xE18B, 0x91C8, + 0xE18C, 0x91CB, + 0xE18D, 0x91D0, + 0xE1A1, 0x5E37, + 0xE1A2, 0x5E44, + 0xE1A3, 0x5E54, + 0xE1A4, 0x5E5B, + 0xE1A5, 0x5E5E, + 0xE1A6, 0x5E61, + 0xE1A7, 0x5C8C, + 0xE1A8, 0x5C7A, + 0xE1A9, 0x5C8D, + 0xE1AA, 0x5C90, + 0xE1AB, 0x5C96, + 0xE1AC, 0x5C88, + 0xE1AF, 0x5C91, + 0xE1B0, 0x5C9A, + 0xE1B1, 0x5C9C, + 0xE1B2, 0x5CB5, + 0xE1B3, 0x5CA2, + 0xE1B4, 0x5CBD, + 0xE1B5, 0x5CAC, + 0xE1B6, 0x5CAB, + 0xE1B7, 0x5CB1, + 0xE1B8, 0x5CA3, + 0xE1B9, 0x5CC1, + 0xE1BA, 0x5CB7, + 0xE1BB, 0x5CC4, + 0xE1BC, 0x5CD2, + 0xE1BD, 0x5CE4, + 0xE1BE, 0x5CCB, + 0xE1BF, 0x5CE5, + 0xE1C2, 0x5D27, + 0xE1C3, 0x5D26, + 0xE1C4, 0x5D2E, + 0xE1C5, 0x5D24, + 0xE1C6, 0x5D1E, + 0xE1C7, 0x5D06, + 0xE1C8, 0x5D1B, + 0xE1C9, 0x5D58, + 0xE1CA, 0x5D3E, + 0xE1CB, 0x5D34, + 0xE1CC, 0x5D3D, + 0xE1CD, 0x5D6C, + 0xE1CE, 0x5D5B, + 0xE1CF, 0x5D6F, + 0xE1D0, 0x5D5D, + 0xE1D1, 0x5D6B, + 0xE1D2, 0x5D4B, + 0xE1D3, 0x5D4A, + 0xE1D4, 0x5D69, + 0xE1D5, 0x5D74, + 0xE1D6, 0x5D82, + 0xE1D7, 0x5D99, + 0xE1D8, 0x5D9D, + 0xE1D9, 0x8C73, + 0xE1DA, 0x5DB7, + 0xE1DB, 0x5DC5, + 0xE1DC, 0x5F73, + 0xE1DD, 0x5F77, + 0xE1DE, 0x5F82, + 0xE1DF, 0x5F87, + 0xE1E0, 0x5F89, + 0xE1E1, 0x5F8C, + 0xE1E2, 0x5F95, + 0xE1E3, 0x5F99, + 0xE1E4, 0x5F9C, + 0xE1E5, 0x5FA8, + 0xE1E6, 0x5FAD, + 0xE1E7, 0x5FB5, + 0xE1E8, 0x5FBC, + 0xE1E9, 0x8862, + 0xE1EA, 0x5F61, + 0xE1EB, 0x72AD, + 0xE1EC, 0x72B0, + 0xE1ED, 0x72B4, + 0xE1F0, 0x72C3, + 0xE1F1, 0x72C1, + 0xE1F2, 0x72CE, + 0xE1F3, 0x72CD, + 0xE1F4, 0x72D2, + 0xE1F5, 0x72E8, + 0xE1F6, 0x72EF, + 0xE1F7, 0x72E9, + 0xE1F8, 0x72F2, + 0xE1F9, 0x72F4, + 0xE1FA, 0x72F7, + 0xE1FB, 0x7301, + 0xE1FC, 0x72F3, + 0xE1FD, 0x7303, + 0xE1FE, 0x72FA, + 0xE2A1, 0x72FB, + 0xE2A2, 0x7317, + 0xE2A3, 0x7313, + 0xE2A4, 0x7321, + 0xE2A5, 0x730A, + 0xE2A6, 0x731E, + 0xE2A7, 0x731D, + 0xE2A8, 0x7315, + 0xE2A9, 0x7322, + 0xE2AA, 0x7339, + 0xE2AB, 0x7325, + 0xE2AC, 0x732C, + 0xE2AD, 0x7338, + 0xE2AE, 0x7331, + 0xE2AF, 0x7350, + 0xE2B0, 0x734D, + 0xE2B1, 0x7357, + 0xE2B2, 0x7360, + 0xE2B3, 0x736C, + 0xE2B4, 0x736F, + 0xE2B5, 0x737E, + 0xE2B6, 0x821B, + 0xE2B7, 0x5925, + 0xE2B8, 0x98E7, + 0xE2B9, 0x5924, + 0xE2BA, 0x5902, + 0xE2BB, 0x9963, + 0xE2C2, 0x9974, + 0xE2C3, 0x9977, + 0xE2C4, 0x997D, + 0xE2C5, 0x9980, + 0xE2C6, 0x9984, + 0xE2C7, 0x9987, + 0xE2C8, 0x998A, + 0xE2C9, 0x998D, + 0xE2CF, 0x5E80, + 0xE2D0, 0x5E91, + 0xE2D1, 0x5E8B, + 0xE2D2, 0x5E96, + 0xE2D3, 0x5EA5, + 0xE2D4, 0x5EA0, + 0xE2D5, 0x5EB9, + 0xE2D6, 0x5EB5, + 0xE2D7, 0x5EBE, + 0xE2D8, 0x5EB3, + 0xE2D9, 0x8D53, + 0xE2DA, 0x5ED2, + 0xE2DB, 0x5ED1, + 0xE2DC, 0x5EDB, + 0xE2DD, 0x5EE8, + 0xE2DE, 0x5EEA, + 0xE2DF, 0x81BA, + 0xE2E0, 0x5FC4, + 0xE2E1, 0x5FC9, + 0xE2E2, 0x5FD6, + 0xE2E3, 0x5FCF, + 0xE2E4, 0x6003, + 0xE2E5, 0x5FEE, + 0xE2E6, 0x6004, + 0xE2E7, 0x5FE1, + 0xE2E8, 0x5FE4, + 0xE2E9, 0x5FFE, + 0xE2EC, 0x5FEA, + 0xE2ED, 0x5FED, + 0xE2EE, 0x5FF8, + 0xE2EF, 0x6019, + 0xE2F0, 0x6035, + 0xE2F1, 0x6026, + 0xE2F2, 0x601B, + 0xE2F3, 0x600F, + 0xE2F4, 0x600D, + 0xE2F5, 0x6029, + 0xE2F6, 0x602B, + 0xE2F7, 0x600A, + 0xE2F8, 0x603F, + 0xE2F9, 0x6021, + 0xE2FC, 0x607B, + 0xE2FD, 0x607A, + 0xE2FE, 0x6042, + 0xE3A1, 0x606A, + 0xE3A2, 0x607D, + 0xE3A3, 0x6096, + 0xE3A4, 0x609A, + 0xE3A5, 0x60AD, + 0xE3A6, 0x609D, + 0xE3A7, 0x6083, + 0xE3A8, 0x6092, + 0xE3A9, 0x608C, + 0xE3AA, 0x609B, + 0xE3AB, 0x60EC, + 0xE3AC, 0x60BB, + 0xE3AD, 0x60B1, + 0xE3AE, 0x60DD, + 0xE3AF, 0x60D8, + 0xE3B0, 0x60C6, + 0xE3B1, 0x60DA, + 0xE3B2, 0x60B4, + 0xE3B3, 0x6120, + 0xE3B4, 0x6126, + 0xE3B5, 0x6115, + 0xE3B6, 0x6123, + 0xE3B7, 0x60F4, + 0xE3B8, 0x6100, + 0xE3B9, 0x610E, + 0xE3BA, 0x612B, + 0xE3BB, 0x614A, + 0xE3BC, 0x6175, + 0xE3BD, 0x61AC, + 0xE3BE, 0x6194, + 0xE3BF, 0x61A7, + 0xE3C0, 0x61B7, + 0xE3C1, 0x61D4, + 0xE3C2, 0x61F5, + 0xE3C3, 0x5FDD, + 0xE3C4, 0x96B3, + 0xE3C5, 0x95E9, + 0xE3C6, 0x95EB, + 0xE3C7, 0x95F1, + 0xE3C8, 0x95F3, + 0xE3CB, 0x95FC, + 0xE3CC, 0x95FE, + 0xE3CF, 0x9606, + 0xE3D0, 0x9608, + 0xE3D5, 0x960F, + 0xE3D6, 0x9612, + 0xE3DC, 0x4E2C, + 0xE3DD, 0x723F, + 0xE3DE, 0x6215, + 0xE3DF, 0x6C35, + 0xE3E0, 0x6C54, + 0xE3E1, 0x6C5C, + 0xE3E2, 0x6C4A, + 0xE3E3, 0x6CA3, + 0xE3E4, 0x6C85, + 0xE3E5, 0x6C90, + 0xE3E6, 0x6C94, + 0xE3E7, 0x6C8C, + 0xE3EA, 0x6C74, + 0xE3EB, 0x6C76, + 0xE3EC, 0x6C86, + 0xE3ED, 0x6CA9, + 0xE3EE, 0x6CD0, + 0xE3EF, 0x6CD4, + 0xE3F0, 0x6CAD, + 0xE3F3, 0x6CF1, + 0xE3F4, 0x6CD7, + 0xE3F5, 0x6CB2, + 0xE3F6, 0x6CE0, + 0xE3F7, 0x6CD6, + 0xE3F8, 0x6CFA, + 0xE3F9, 0x6CEB, + 0xE3FA, 0x6CEE, + 0xE3FB, 0x6CB1, + 0xE3FC, 0x6CD3, + 0xE3FD, 0x6CEF, + 0xE3FE, 0x6CFE, + 0xE4A1, 0x6D39, + 0xE4A2, 0x6D27, + 0xE4A3, 0x6D0C, + 0xE4A4, 0x6D43, + 0xE4A5, 0x6D48, + 0xE4A6, 0x6D07, + 0xE4A7, 0x6D04, + 0xE4A8, 0x6D19, + 0xE4A9, 0x6D0E, + 0xE4AA, 0x6D2B, + 0xE4AB, 0x6D4D, + 0xE4AC, 0x6D2E, + 0xE4AD, 0x6D35, + 0xE4AE, 0x6D1A, + 0xE4AF, 0x6D4F, + 0xE4B0, 0x6D52, + 0xE4B1, 0x6D54, + 0xE4B2, 0x6D33, + 0xE4B3, 0x6D91, + 0xE4B4, 0x6D6F, + 0xE4B5, 0x6D9E, + 0xE4B6, 0x6DA0, + 0xE4B7, 0x6D5E, + 0xE4BA, 0x6D5C, + 0xE4BB, 0x6D60, + 0xE4BC, 0x6D7C, + 0xE4BD, 0x6D63, + 0xE4BE, 0x6E1A, + 0xE4BF, 0x6DC7, + 0xE4C0, 0x6DC5, + 0xE4C1, 0x6DDE, + 0xE4C2, 0x6E0E, + 0xE4C3, 0x6DBF, + 0xE4C4, 0x6DE0, + 0xE4C5, 0x6E11, + 0xE4C6, 0x6DE6, + 0xE4C7, 0x6DDD, + 0xE4C8, 0x6DD9, + 0xE4C9, 0x6E16, + 0xE4CA, 0x6DAB, + 0xE4CB, 0x6E0C, + 0xE4CC, 0x6DAE, + 0xE4CD, 0x6E2B, + 0xE4CE, 0x6E6E, + 0xE4CF, 0x6E4E, + 0xE4D0, 0x6E6B, + 0xE4D1, 0x6EB2, + 0xE4D2, 0x6E5F, + 0xE4D3, 0x6E86, + 0xE4D6, 0x6E32, + 0xE4D7, 0x6E25, + 0xE4D8, 0x6E44, + 0xE4D9, 0x6EDF, + 0xE4DA, 0x6EB1, + 0xE4DB, 0x6E98, + 0xE4DC, 0x6EE0, + 0xE4DD, 0x6F2D, + 0xE4DE, 0x6EE2, + 0xE4DF, 0x6EA5, + 0xE4E0, 0x6EA7, + 0xE4E1, 0x6EBD, + 0xE4E2, 0x6EBB, + 0xE4E3, 0x6EB7, + 0xE4E4, 0x6ED7, + 0xE4E5, 0x6EB4, + 0xE4E6, 0x6ECF, + 0xE4E7, 0x6E8F, + 0xE4E8, 0x6EC2, + 0xE4E9, 0x6E9F, + 0xE4EA, 0x6F62, + 0xE4ED, 0x6F24, + 0xE4EE, 0x6F15, + 0xE4EF, 0x6EF9, + 0xE4F0, 0x6F2F, + 0xE4F1, 0x6F36, + 0xE4F2, 0x6F4B, + 0xE4F3, 0x6F74, + 0xE4F4, 0x6F2A, + 0xE4F5, 0x6F09, + 0xE4F6, 0x6F29, + 0xE4F7, 0x6F89, + 0xE4F8, 0x6F8D, + 0xE4F9, 0x6F8C, + 0xE4FA, 0x6F78, + 0xE4FB, 0x6F72, + 0xE4FC, 0x6F7C, + 0xE4FD, 0x6F7A, + 0xE4FE, 0x6FD1, + 0xE5A0, 0x936B, + 0xE5A1, 0x6FC9, + 0xE5A2, 0x6FA7, + 0xE5A3, 0x6FB9, + 0xE5A4, 0x6FB6, + 0xE5A5, 0x6FC2, + 0xE5A6, 0x6FE1, + 0xE5A7, 0x6FEE, + 0xE5A8, 0x6FDE, + 0xE5A9, 0x6FE0, + 0xE5AA, 0x6FEF, + 0xE5AB, 0x701A, + 0xE5AC, 0x7023, + 0xE5AD, 0x701B, + 0xE5AE, 0x7039, + 0xE5AF, 0x7035, + 0xE5B0, 0x704F, + 0xE5B1, 0x705E, + 0xE5B2, 0x5B80, + 0xE5B3, 0x5B84, + 0xE5B4, 0x5B95, + 0xE5B5, 0x5B93, + 0xE5B6, 0x5BA5, + 0xE5B7, 0x5BB8, + 0xE5B8, 0x752F, + 0xE5B9, 0x9A9E, + 0xE5BA, 0x6434, + 0xE5BB, 0x5BE4, + 0xE5BC, 0x5BEE, + 0xE5BD, 0x8930, + 0xE5BE, 0x5BF0, + 0xE5BF, 0x8E47, + 0xE5C0, 0x8B07, + 0xE5C1, 0x8FB6, + 0xE5C2, 0x8FD3, + 0xE5C3, 0x8FD5, + 0xE5C4, 0x8FE5, + 0xE5C5, 0x8FEE, + 0xE5C6, 0x8FE4, + 0xE5C7, 0x8FE9, + 0xE5C8, 0x8FE6, + 0xE5C9, 0x8FF3, + 0xE5CA, 0x8FE8, + 0xE5CB, 0x9005, + 0xE5CC, 0x9004, + 0xE5CD, 0x900B, + 0xE5CE, 0x9026, + 0xE5CF, 0x9011, + 0xE5D0, 0x900D, + 0xE5D1, 0x9016, + 0xE5D2, 0x9021, + 0xE5D5, 0x902D, + 0xE5D6, 0x902F, + 0xE5D7, 0x9044, + 0xE5DA, 0x9050, + 0xE5DB, 0x9068, + 0xE5DC, 0x9058, + 0xE5DD, 0x9062, + 0xE5DE, 0x905B, + 0xE5DF, 0x66B9, + 0xE5E0, 0x9074, + 0xE5E1, 0x907D, + 0xE5E2, 0x9082, + 0xE5E3, 0x9088, + 0xE5E4, 0x9083, + 0xE5E5, 0x908B, + 0xE5E6, 0x5F50, + 0xE5E7, 0x5F57, + 0xE5E8, 0x5F56, + 0xE5E9, 0x5F58, + 0xE5EA, 0x5C3B, + 0xE5EB, 0x54AB, + 0xE5EC, 0x5C50, + 0xE5ED, 0x5C59, + 0xE5EE, 0x5B71, + 0xE5EF, 0x5C63, + 0xE5F0, 0x5C66, + 0xE5F1, 0x7FBC, + 0xE5F2, 0x5F2A, + 0xE5F3, 0x5F29, + 0xE5F4, 0x5F2D, + 0xE5F5, 0x8274, + 0xE5F6, 0x5F3C, + 0xE5F7, 0x9B3B, + 0xE5F8, 0x5C6E, + 0xE5F9, 0x5981, + 0xE5FA, 0x5983, + 0xE5FB, 0x598D, + 0xE5FE, 0x59A3, + 0xE6A1, 0x5997, + 0xE6A2, 0x59CA, + 0xE6A3, 0x59AB, + 0xE6A4, 0x599E, + 0xE6A5, 0x59A4, + 0xE6A6, 0x59D2, + 0xE6A7, 0x59B2, + 0xE6A8, 0x59AF, + 0xE6A9, 0x59D7, + 0xE6AA, 0x59BE, + 0xE6AD, 0x59DD, + 0xE6AE, 0x5A08, + 0xE6AF, 0x59E3, + 0xE6B0, 0x59D8, + 0xE6B1, 0x59F9, + 0xE6B2, 0x5A0C, + 0xE6B3, 0x5A09, + 0xE6B4, 0x5A32, + 0xE6B5, 0x5A34, + 0xE6B6, 0x5A11, + 0xE6B7, 0x5A23, + 0xE6B8, 0x5A13, + 0xE6B9, 0x5A40, + 0xE6BA, 0x5A67, + 0xE6BB, 0x5A4A, + 0xE6BC, 0x5A55, + 0xE6BD, 0x5A3C, + 0xE6BE, 0x5A62, + 0xE6BF, 0x5A75, + 0xE6C0, 0x80EC, + 0xE6C1, 0x5AAA, + 0xE6C2, 0x5A9B, + 0xE6C3, 0x5A77, + 0xE6C4, 0x5A7A, + 0xE6C5, 0x5ABE, + 0xE6C6, 0x5AEB, + 0xE6C7, 0x5AB2, + 0xE6C8, 0x5AD2, + 0xE6C9, 0x5AD4, + 0xE6CA, 0x5AB8, + 0xE6CB, 0x5AE0, + 0xE6CC, 0x5AE3, + 0xE6CD, 0x5AF1, + 0xE6CE, 0x5AD6, + 0xE6CF, 0x5AE6, + 0xE6D0, 0x5AD8, + 0xE6D1, 0x5ADC, + 0xE6D2, 0x5B09, + 0xE6D3, 0x5B17, + 0xE6D4, 0x5B16, + 0xE6D5, 0x5B32, + 0xE6D6, 0x5B37, + 0xE6D7, 0x5B40, + 0xE6D8, 0x5C15, + 0xE6D9, 0x5C1C, + 0xE6DA, 0x5B5A, + 0xE6DB, 0x5B65, + 0xE6DC, 0x5B73, + 0xE6DD, 0x5B51, + 0xE6DE, 0x5B53, + 0xE6DF, 0x5B62, + 0xE6E0, 0x9A75, + 0xE6E3, 0x9A7A, + 0xE6E4, 0x9A7F, + 0xE6E5, 0x9A7D, + 0xE6E8, 0x9A85, + 0xE6E9, 0x9A88, + 0xE6EA, 0x9A8A, + 0xE6EB, 0x9A90, + 0xE6EE, 0x9A96, + 0xE6EF, 0x9A98, + 0xE6F7, 0x9AA5, + 0xE6F8, 0x9AA7, + 0xE6F9, 0x7E9F, + 0xE6FA, 0x7EA1, + 0xE6FB, 0x7EA3, + 0xE6FC, 0x7EA5, + 0xE7A1, 0x7EAD, + 0xE7A2, 0x7EB0, + 0xE7A3, 0x7EBE, + 0xE7A7, 0x7EC9, + 0xE7AA, 0x7ED0, + 0xE7AB, 0x7ED4, + 0xE7AC, 0x7ED7, + 0xE7AD, 0x7EDB, + 0xE7B0, 0x7EE8, + 0xE7B1, 0x7EEB, + 0xE7B6, 0x7F0D, + 0xE7B7, 0x7EF6, + 0xE7BA, 0x7EFE, + 0xE7C2, 0x7F0F, + 0xE7C5, 0x7F17, + 0xE7C6, 0x7F19, + 0xE7C7, 0x7F1C, + 0xE7C8, 0x7F1B, + 0xE7C9, 0x7F1F, + 0xE7DA, 0x7F35, + 0xE7DB, 0x5E7A, + 0xE7DC, 0x757F, + 0xE7DD, 0x5DDB, + 0xE7DE, 0x753E, + 0xE7DF, 0x9095, + 0xE7E0, 0x738E, + 0xE7E1, 0x7391, + 0xE7E2, 0x73AE, + 0xE7E3, 0x73A2, + 0xE7E4, 0x739F, + 0xE7E5, 0x73CF, + 0xE7E6, 0x73C2, + 0xE7E7, 0x73D1, + 0xE7E8, 0x73B7, + 0xE7E9, 0x73B3, + 0xE7EA, 0x73C0, + 0xE7EB, 0x73C9, + 0xE7EC, 0x73C8, + 0xE7ED, 0x73E5, + 0xE7EE, 0x73D9, + 0xE7EF, 0x987C, + 0xE7F0, 0x740A, + 0xE7F1, 0x73E9, + 0xE7F2, 0x73E7, + 0xE7F3, 0x73DE, + 0xE7F4, 0x73BA, + 0xE7F5, 0x73F2, + 0xE7F6, 0x740F, + 0xE7F7, 0x742A, + 0xE7F8, 0x745B, + 0xE7F9, 0x7426, + 0xE7FA, 0x7425, + 0xE7FB, 0x7428, + 0xE7FC, 0x7430, + 0xE7FD, 0x742E, + 0xE7FE, 0x742C, + 0xE895, 0x9491, + 0xE896, 0x9496, + 0xE897, 0x9498, + 0xE898, 0x94C7, + 0xE899, 0x94CF, + 0xE89C, 0x94DA, + 0xE89D, 0x94E6, + 0xE89E, 0x94FB, + 0xE89F, 0x951C, + 0xE8A0, 0x9520, + 0xE8A1, 0x741B, + 0xE8A2, 0x741A, + 0xE8A3, 0x7441, + 0xE8A4, 0x745C, + 0xE8A5, 0x7457, + 0xE8A6, 0x7455, + 0xE8A7, 0x7459, + 0xE8A8, 0x7477, + 0xE8A9, 0x746D, + 0xE8AA, 0x747E, + 0xE8AB, 0x749C, + 0xE8AC, 0x748E, + 0xE8AF, 0x7487, + 0xE8B0, 0x748B, + 0xE8B1, 0x749E, + 0xE8B4, 0x7490, + 0xE8B5, 0x74A7, + 0xE8B6, 0x74D2, + 0xE8B7, 0x74BA, + 0xE8BB, 0x674C, + 0xE8BC, 0x6753, + 0xE8BD, 0x675E, + 0xE8BE, 0x6748, + 0xE8BF, 0x6769, + 0xE8C0, 0x67A5, + 0xE8C1, 0x6787, + 0xE8C2, 0x676A, + 0xE8C3, 0x6773, + 0xE8C4, 0x6798, + 0xE8C5, 0x67A7, + 0xE8C6, 0x6775, + 0xE8C7, 0x67A8, + 0xE8C8, 0x679E, + 0xE8C9, 0x67AD, + 0xE8CA, 0x678B, + 0xE8CB, 0x6777, + 0xE8CC, 0x677C, + 0xE8CD, 0x67F0, + 0xE8CE, 0x6809, + 0xE8CF, 0x67D8, + 0xE8D0, 0x680A, + 0xE8D1, 0x67E9, + 0xE8D2, 0x67B0, + 0xE8D3, 0x680C, + 0xE8D4, 0x67D9, + 0xE8D5, 0x67B5, + 0xE8D6, 0x67DA, + 0xE8D7, 0x67B3, + 0xE8D8, 0x67DD, + 0xE8D9, 0x6800, + 0xE8DA, 0x67C3, + 0xE8DB, 0x67B8, + 0xE8DC, 0x67E2, + 0xE8DD, 0x680E, + 0xE8DE, 0x67C1, + 0xE8DF, 0x67FD, + 0xE8E4, 0x684E, + 0xE8E5, 0x6862, + 0xE8E6, 0x6844, + 0xE8E7, 0x6864, + 0xE8E8, 0x6883, + 0xE8E9, 0x681D, + 0xE8EA, 0x6855, + 0xE8EB, 0x6866, + 0xE8EC, 0x6841, + 0xE8ED, 0x6867, + 0xE8EE, 0x6840, + 0xE8EF, 0x683E, + 0xE8F0, 0x684A, + 0xE8F1, 0x6849, + 0xE8F2, 0x6829, + 0xE8F3, 0x68B5, + 0xE8F4, 0x688F, + 0xE8F5, 0x6874, + 0xE8F6, 0x6877, + 0xE8F7, 0x6893, + 0xE8F8, 0x686B, + 0xE8F9, 0x68C2, + 0xE8FA, 0x696E, + 0xE8FB, 0x68FC, + 0xE8FE, 0x68F9, + 0xE940, 0x9527, + 0xE941, 0x9533, + 0xE942, 0x953D, + 0xE943, 0x9543, + 0xE944, 0x9548, + 0xE945, 0x954B, + 0xE946, 0x9555, + 0xE947, 0x955A, + 0xE948, 0x9560, + 0xE949, 0x956E, + 0xE9A1, 0x6924, + 0xE9A2, 0x68F0, + 0xE9A3, 0x690B, + 0xE9A4, 0x6901, + 0xE9A5, 0x6957, + 0xE9A6, 0x68E3, + 0xE9A7, 0x6910, + 0xE9A8, 0x6971, + 0xE9A9, 0x6939, + 0xE9AA, 0x6960, + 0xE9AB, 0x6942, + 0xE9AC, 0x695D, + 0xE9AD, 0x6984, + 0xE9AE, 0x696B, + 0xE9AF, 0x6980, + 0xE9B0, 0x6998, + 0xE9B1, 0x6978, + 0xE9B2, 0x6934, + 0xE9B3, 0x69CC, + 0xE9B6, 0x69CE, + 0xE9B7, 0x6989, + 0xE9B8, 0x6966, + 0xE9B9, 0x6963, + 0xE9BA, 0x6979, + 0xE9BB, 0x699B, + 0xE9BC, 0x69A7, + 0xE9BD, 0x69BB, + 0xE9BE, 0x69AB, + 0xE9BF, 0x69AD, + 0xE9C0, 0x69D4, + 0xE9C1, 0x69B1, + 0xE9C2, 0x69C1, + 0xE9C3, 0x69CA, + 0xE9C4, 0x69DF, + 0xE9C5, 0x6995, + 0xE9C6, 0x69E0, + 0xE9C7, 0x698D, + 0xE9C8, 0x69FF, + 0xE9C9, 0x6A2F, + 0xE9CA, 0x69ED, + 0xE9CD, 0x6A65, + 0xE9CE, 0x69F2, + 0xE9CF, 0x6A44, + 0xE9D0, 0x6A3E, + 0xE9D1, 0x6AA0, + 0xE9D2, 0x6A50, + 0xE9D3, 0x6A5B, + 0xE9D4, 0x6A35, + 0xE9D5, 0x6A8E, + 0xE9D6, 0x6A79, + 0xE9D7, 0x6A3D, + 0xE9D8, 0x6A28, + 0xE9D9, 0x6A58, + 0xE9DA, 0x6A7C, + 0xE9DB, 0x6A91, + 0xE9DC, 0x6A90, + 0xE9DD, 0x6AA9, + 0xE9DE, 0x6A97, + 0xE9DF, 0x6AAB, + 0xE9E0, 0x7337, + 0xE9E1, 0x7352, + 0xE9E4, 0x6B87, + 0xE9E5, 0x6B84, + 0xE9E8, 0x6B8D, + 0xE9EB, 0x6BA1, + 0xE9EC, 0x6BAA, + 0xE9ED, 0x8F6B, + 0xE9EE, 0x8F6D, + 0xE9F4, 0x8F78, + 0xE9F5, 0x8F77, + 0xE9F8, 0x8F7C, + 0xE9F9, 0x8F7E, + 0xE9FC, 0x8F84, + 0xE9FD, 0x8F87, + 0xE9FE, 0x8F8B, + 0xEA5C, 0x95EC, + 0xEA5D, 0x95FF, + 0xEA5E, 0x9607, + 0xEA5F, 0x9613, + 0xEA60, 0x9618, + 0xEA61, 0x961B, + 0xEA62, 0x961E, + 0xEA63, 0x9620, + 0xEA74, 0x963E, + 0xEA75, 0x9641, + 0xEA76, 0x9643, + 0xEA77, 0x964A, + 0xEA86, 0x9660, + 0xEA87, 0x9663, + 0xEA8A, 0x966B, + 0xEA90, 0x9673, + 0xEA9E, 0x9687, + 0xEAA4, 0x8F98, + 0xEAA5, 0x8F9A, + 0xEAA6, 0x8ECE, + 0xEAA7, 0x620B, + 0xEAA8, 0x6217, + 0xEAA9, 0x621B, + 0xEAAA, 0x621F, + 0xEAAB, 0x6222, + 0xEAAC, 0x6221, + 0xEAAD, 0x6225, + 0xEAAE, 0x6224, + 0xEAAF, 0x622C, + 0xEAB0, 0x81E7, + 0xEAB1, 0x74EF, + 0xEAB2, 0x74F4, + 0xEAB3, 0x74FF, + 0xEAB4, 0x750F, + 0xEAB5, 0x7511, + 0xEAB6, 0x7513, + 0xEAB7, 0x6534, + 0xEABB, 0x660A, + 0xEABC, 0x6619, + 0xEABD, 0x6772, + 0xEABE, 0x6603, + 0xEABF, 0x6615, + 0xEAC0, 0x6600, + 0xEAC1, 0x7085, + 0xEAC2, 0x66F7, + 0xEAC3, 0x661D, + 0xEAC4, 0x6634, + 0xEAC5, 0x6631, + 0xEAC6, 0x6636, + 0xEAC7, 0x6635, + 0xEAC8, 0x8006, + 0xEAC9, 0x665F, + 0xEACA, 0x6654, + 0xEACB, 0x6641, + 0xEACC, 0x664F, + 0xEACD, 0x6656, + 0xEACE, 0x6661, + 0xEACF, 0x6657, + 0xEAD0, 0x6677, + 0xEAD1, 0x6684, + 0xEAD2, 0x668C, + 0xEAD3, 0x66A7, + 0xEAD4, 0x669D, + 0xEAD5, 0x66BE, + 0xEAD8, 0x66E6, + 0xEAD9, 0x66E9, + 0xEADC, 0x8D36, + 0xEADD, 0x8D3B, + 0xEADE, 0x8D3D, + 0xEADF, 0x8D40, + 0xEAE4, 0x8D47, + 0xEAE5, 0x8D4D, + 0xEAE6, 0x8D55, + 0xEAE7, 0x8D59, + 0xEAE8, 0x89C7, + 0xEAF0, 0x726E, + 0xEAF1, 0x729F, + 0xEAF2, 0x725D, + 0xEAF3, 0x7266, + 0xEAF4, 0x726F, + 0xEAF7, 0x7284, + 0xEAF8, 0x728B, + 0xEAF9, 0x728D, + 0xEAFA, 0x728F, + 0xEAFB, 0x7292, + 0xEAFC, 0x6308, + 0xEAFD, 0x6332, + 0xEAFE, 0x63B0, + 0xEB40, 0x968C, + 0xEB41, 0x968E, + 0xEB63, 0x96BF, + 0xEB66, 0x96C8, + 0xEB7E, 0x96EB, + 0xEB88, 0x96F8, + 0xEB8D, 0x96FF, + 0xEB90, 0x9705, + 0xEB9E, 0x971D, + 0xEBA1, 0x643F, + 0xEBA2, 0x64D8, + 0xEBA3, 0x8004, + 0xEBA4, 0x6BEA, + 0xEBA5, 0x6BF3, + 0xEBA6, 0x6BFD, + 0xEBA7, 0x6BF5, + 0xEBA8, 0x6BF9, + 0xEBA9, 0x6C05, + 0xEBAA, 0x6C07, + 0xEBAB, 0x6C06, + 0xEBAC, 0x6C0D, + 0xEBAD, 0x6C15, + 0xEBB1, 0x6C21, + 0xEBB2, 0x6C29, + 0xEBB3, 0x6C24, + 0xEBB4, 0x6C2A, + 0xEBB5, 0x6C32, + 0xEBB6, 0x6535, + 0xEBB7, 0x6555, + 0xEBB8, 0x656B, + 0xEBB9, 0x724D, + 0xEBBA, 0x7252, + 0xEBBB, 0x7256, + 0xEBBC, 0x7230, + 0xEBBD, 0x8662, + 0xEBBE, 0x5216, + 0xEBBF, 0x809F, + 0xEBC0, 0x809C, + 0xEBC1, 0x8093, + 0xEBC2, 0x80BC, + 0xEBC3, 0x670A, + 0xEBC4, 0x80BD, + 0xEBC5, 0x80B1, + 0xEBC6, 0x80AB, + 0xEBC7, 0x80AD, + 0xEBC8, 0x80B4, + 0xEBC9, 0x80B7, + 0xEBCE, 0x80DB, + 0xEBCF, 0x80C2, + 0xEBD0, 0x80C4, + 0xEBD1, 0x80D9, + 0xEBD2, 0x80CD, + 0xEBD3, 0x80D7, + 0xEBD4, 0x6710, + 0xEBD5, 0x80DD, + 0xEBD6, 0x80EB, + 0xEBD7, 0x80F1, + 0xEBD8, 0x80F4, + 0xEBD9, 0x80ED, + 0xEBDC, 0x80F2, + 0xEBDD, 0x80FC, + 0xEBDE, 0x6715, + 0xEBDF, 0x8112, + 0xEBE0, 0x8C5A, + 0xEBE1, 0x8136, + 0xEBE2, 0x811E, + 0xEBE3, 0x812C, + 0xEBE4, 0x8118, + 0xEBE5, 0x8132, + 0xEBE6, 0x8148, + 0xEBE7, 0x814C, + 0xEBE8, 0x8153, + 0xEBE9, 0x8174, + 0xEBEC, 0x8171, + 0xEBED, 0x8160, + 0xEBEE, 0x8169, + 0xEBF1, 0x816D, + 0xEBF2, 0x8167, + 0xEBF3, 0x584D, + 0xEBF4, 0x5AB5, + 0xEBF5, 0x8188, + 0xEBF6, 0x8182, + 0xEBF7, 0x8191, + 0xEBF8, 0x6ED5, + 0xEBF9, 0x81A3, + 0xEBFA, 0x81AA, + 0xEBFB, 0x81CC, + 0xEBFC, 0x6726, + 0xEBFD, 0x81CA, + 0xEBFE, 0x81BB, + 0xEC4D, 0x9731, + 0xEC6E, 0x975A, + 0xEC71, 0x975F, + 0xEC80, 0x9772, + 0xEC81, 0x9775, + 0xEC94, 0x978C, + 0xEC98, 0x9793, + 0xECA1, 0x81C1, + 0xECA2, 0x81A6, + 0xECA3, 0x6B24, + 0xECA4, 0x6B37, + 0xECA5, 0x6B39, + 0xECA6, 0x6B43, + 0xECA7, 0x6B46, + 0xECA8, 0x6B59, + 0xECAC, 0x98D5, + 0xECAF, 0x6BB3, + 0xECB0, 0x5F40, + 0xECB1, 0x6BC2, + 0xECB2, 0x89F3, + 0xECB3, 0x6590, + 0xECB4, 0x9F51, + 0xECB5, 0x6593, + 0xECB6, 0x65BC, + 0xECB7, 0x65C6, + 0xECB8, 0x65C4, + 0xECB9, 0x65C3, + 0xECBA, 0x65CC, + 0xECBB, 0x65CE, + 0xECBC, 0x65D2, + 0xECBD, 0x65D6, + 0xECBE, 0x7080, + 0xECBF, 0x709C, + 0xECC0, 0x7096, + 0xECC1, 0x709D, + 0xECC2, 0x70BB, + 0xECC3, 0x70C0, + 0xECC4, 0x70B7, + 0xECC5, 0x70AB, + 0xECC6, 0x70B1, + 0xECC7, 0x70E8, + 0xECC8, 0x70CA, + 0xECC9, 0x7110, + 0xECCA, 0x7113, + 0xECCB, 0x7116, + 0xECCC, 0x712F, + 0xECCD, 0x7131, + 0xECCE, 0x7173, + 0xECCF, 0x715C, + 0xECD0, 0x7168, + 0xECD1, 0x7145, + 0xECD2, 0x7172, + 0xECD3, 0x714A, + 0xECD4, 0x7178, + 0xECD5, 0x717A, + 0xECD6, 0x7198, + 0xECD7, 0x71B3, + 0xECD8, 0x71B5, + 0xECD9, 0x71A8, + 0xECDA, 0x71A0, + 0xECDB, 0x71E0, + 0xECDC, 0x71D4, + 0xECDD, 0x71E7, + 0xECDE, 0x71F9, + 0xECDF, 0x721D, + 0xECE0, 0x7228, + 0xECE1, 0x706C, + 0xECE2, 0x7118, + 0xECE3, 0x7166, + 0xECE4, 0x71B9, + 0xECE5, 0x623E, + 0xECE6, 0x623D, + 0xECE7, 0x6243, + 0xECEA, 0x793B, + 0xECEB, 0x7940, + 0xECEC, 0x7946, + 0xECED, 0x7949, + 0xECF0, 0x7953, + 0xECF1, 0x795A, + 0xECF2, 0x7962, + 0xECF3, 0x7957, + 0xECF4, 0x7960, + 0xECF5, 0x796F, + 0xECF6, 0x7967, + 0xECF7, 0x797A, + 0xECF8, 0x7985, + 0xECF9, 0x798A, + 0xECFA, 0x799A, + 0xECFB, 0x79A7, + 0xECFC, 0x79B3, + 0xECFD, 0x5FD1, + 0xECFE, 0x5FD0, + 0xED4B, 0x97AC, + 0xED4C, 0x97AE, + 0xED4F, 0x97B3, + 0xED82, 0x97E8, + 0xED88, 0x97F4, + 0xEDA1, 0x603C, + 0xEDA2, 0x605D, + 0xEDA3, 0x605A, + 0xEDA4, 0x6067, + 0xEDA5, 0x6041, + 0xEDA6, 0x6059, + 0xEDA7, 0x6063, + 0xEDA8, 0x60AB, + 0xEDA9, 0x6106, + 0xEDAA, 0x610D, + 0xEDAB, 0x615D, + 0xEDAC, 0x61A9, + 0xEDAD, 0x619D, + 0xEDAE, 0x61CB, + 0xEDAF, 0x61D1, + 0xEDB0, 0x6206, + 0xEDB1, 0x8080, + 0xEDB2, 0x807F, + 0xEDB3, 0x6C93, + 0xEDB4, 0x6CF6, + 0xEDB5, 0x6DFC, + 0xEDB6, 0x77F6, + 0xEDB7, 0x77F8, + 0xEDB8, 0x7800, + 0xEDB9, 0x7809, + 0xEDBC, 0x7811, + 0xEDBD, 0x65AB, + 0xEDBE, 0x782D, + 0xEDC4, 0x781F, + 0xEDC5, 0x783C, + 0xEDC6, 0x7825, + 0xEDC7, 0x782C, + 0xEDC8, 0x7823, + 0xEDC9, 0x7829, + 0xEDCA, 0x784E, + 0xEDCB, 0x786D, + 0xEDCE, 0x7826, + 0xEDCF, 0x7850, + 0xEDD0, 0x7847, + 0xEDD1, 0x784C, + 0xEDD2, 0x786A, + 0xEDD3, 0x789B, + 0xEDD4, 0x7893, + 0xEDD5, 0x789A, + 0xEDD6, 0x7887, + 0xEDD7, 0x789C, + 0xEDD8, 0x78A1, + 0xEDD9, 0x78A3, + 0xEDDA, 0x78B2, + 0xEDDB, 0x78B9, + 0xEDDC, 0x78A5, + 0xEDDD, 0x78D4, + 0xEDDE, 0x78D9, + 0xEDDF, 0x78C9, + 0xEDE0, 0x78EC, + 0xEDE1, 0x78F2, + 0xEDE2, 0x7905, + 0xEDE3, 0x78F4, + 0xEDE4, 0x7913, + 0xEDE5, 0x7924, + 0xEDE6, 0x791E, + 0xEDE7, 0x7934, + 0xEDE8, 0x9F9B, + 0xEDE9, 0x9EF9, + 0xEDEC, 0x76F1, + 0xEDED, 0x7704, + 0xEDEE, 0x770D, + 0xEDEF, 0x76F9, + 0xEDF2, 0x771A, + 0xEDF3, 0x7722, + 0xEDF4, 0x7719, + 0xEDF5, 0x772D, + 0xEDF6, 0x7726, + 0xEDF7, 0x7735, + 0xEDF8, 0x7738, + 0xEDFB, 0x7747, + 0xEDFC, 0x7743, + 0xEDFD, 0x775A, + 0xEDFE, 0x7768, + 0xEEA1, 0x7762, + 0xEEA2, 0x7765, + 0xEEA3, 0x777F, + 0xEEA4, 0x778D, + 0xEEA5, 0x777D, + 0xEEA6, 0x7780, + 0xEEA7, 0x778C, + 0xEEA8, 0x7791, + 0xEEAB, 0x77B0, + 0xEEAC, 0x77B5, + 0xEEAD, 0x77BD, + 0xEEAE, 0x753A, + 0xEEAF, 0x7540, + 0xEEB0, 0x754E, + 0xEEB1, 0x754B, + 0xEEB2, 0x7548, + 0xEEB3, 0x755B, + 0xEEB4, 0x7572, + 0xEEB5, 0x7579, + 0xEEB6, 0x7583, + 0xEEB7, 0x7F58, + 0xEEB8, 0x7F61, + 0xEEB9, 0x7F5F, + 0xEEBA, 0x8A48, + 0xEEBB, 0x7F68, + 0xEEBC, 0x7F74, + 0xEEBD, 0x7F71, + 0xEEBE, 0x7F79, + 0xEEBF, 0x7F81, + 0xEEC0, 0x7F7E, + 0xEEC1, 0x76CD, + 0xEEC2, 0x76E5, + 0xEEC3, 0x8832, + 0xEEC7, 0x948B, + 0xEEC8, 0x948A, + 0xEECD, 0x9494, + 0xEECE, 0x9497, + 0xEECF, 0x9495, + 0xEED5, 0x94AB, + 0xEED6, 0x94AA, + 0xEED7, 0x94AD, + 0xEED8, 0x94AC, + 0xEEDB, 0x94B2, + 0xEEDC, 0x94B4, + 0xEEE4, 0x94BF, + 0xEEE5, 0x94C4, + 0xEEF3, 0x94D9, + 0xEEF4, 0x94D8, + 0xEEF5, 0x94DB, + 0xEEF9, 0x94E2, + 0xEEFE, 0x94EA, + 0xEF46, 0x988B, + 0xEF47, 0x988E, + 0xEF48, 0x9892, + 0xEF49, 0x9895, + 0xEF4A, 0x9899, + 0xEF4B, 0x98A3, + 0xEF74, 0x98D4, + 0xEFA1, 0x94E9, + 0xEFA2, 0x94EB, + 0xEFA8, 0x94F7, + 0xEFA9, 0x94F9, + 0xEFAC, 0x94FF, + 0xEFAD, 0x9503, + 0xEFAE, 0x9502, + 0xEFBB, 0x9518, + 0xEFBC, 0x951B, + 0xEFC0, 0x9522, + 0xEFC3, 0x9529, + 0xEFC4, 0x952C, + 0xEFC7, 0x9534, + 0xEFCB, 0x953C, + 0xEFCE, 0x9542, + 0xEFCF, 0x9535, + 0xEFD3, 0x9549, + 0xEFD4, 0x954C, + 0xEFDE, 0x955B, + 0xEFE1, 0x955D, + 0xEFED, 0x956F, + 0xEFF1, 0x953A, + 0xEFF2, 0x77E7, + 0xEFF3, 0x77EC, + 0xEFF4, 0x96C9, + 0xEFF5, 0x79D5, + 0xEFF6, 0x79ED, + 0xEFF7, 0x79E3, + 0xEFF8, 0x79EB, + 0xEFF9, 0x7A06, + 0xEFFA, 0x5D47, + 0xEFFB, 0x7A03, + 0xEFFC, 0x7A02, + 0xEFFD, 0x7A1E, + 0xEFFE, 0x7A14, + 0xF097, 0x9964, + 0xF098, 0x9966, + 0xF099, 0x9973, + 0xF09C, 0x997B, + 0xF09D, 0x997E, + 0xF0A0, 0x9989, + 0xF0A1, 0x7A39, + 0xF0A2, 0x7A37, + 0xF0A3, 0x7A51, + 0xF0A4, 0x9ECF, + 0xF0A5, 0x99A5, + 0xF0A6, 0x7A70, + 0xF0A7, 0x7688, + 0xF0A8, 0x768E, + 0xF0A9, 0x7693, + 0xF0AA, 0x7699, + 0xF0AB, 0x76A4, + 0xF0AC, 0x74DE, + 0xF0AD, 0x74E0, + 0xF0AE, 0x752C, + 0xF0AF, 0x9E20, + 0xF0B0, 0x9E22, + 0xF0B6, 0x9E32, + 0xF0B7, 0x9E31, + 0xF0B8, 0x9E36, + 0xF0B9, 0x9E38, + 0xF0BA, 0x9E37, + 0xF0BD, 0x9E3E, + 0xF0C0, 0x9E44, + 0xF0C7, 0x9E4E, + 0xF0C8, 0x9E51, + 0xF0C9, 0x9E55, + 0xF0CA, 0x9E57, + 0xF0CE, 0x9E5E, + 0xF0CF, 0x9E63, + 0xF0D7, 0x9E71, + 0xF0D8, 0x9E6D, + 0xF0D9, 0x9E73, + 0xF0DA, 0x7592, + 0xF0DB, 0x7594, + 0xF0DC, 0x7596, + 0xF0DD, 0x75A0, + 0xF0DE, 0x759D, + 0xF0DF, 0x75AC, + 0xF0E0, 0x75A3, + 0xF0E3, 0x75B8, + 0xF0E4, 0x75C4, + 0xF0E5, 0x75B1, + 0xF0E6, 0x75B0, + 0xF0E7, 0x75C3, + 0xF0E8, 0x75C2, + 0xF0E9, 0x75D6, + 0xF0EA, 0x75CD, + 0xF0EB, 0x75E3, + 0xF0EC, 0x75E8, + 0xF0ED, 0x75E6, + 0xF0EE, 0x75E4, + 0xF0EF, 0x75EB, + 0xF0F0, 0x75E7, + 0xF0F1, 0x7603, + 0xF0F2, 0x75F1, + 0xF0F3, 0x75FC, + 0xF0F4, 0x75FF, + 0xF0F5, 0x7610, + 0xF0F6, 0x7600, + 0xF0F7, 0x7605, + 0xF0F8, 0x760C, + 0xF0F9, 0x7617, + 0xF0FA, 0x760A, + 0xF0FB, 0x7625, + 0xF0FC, 0x7618, + 0xF0FD, 0x7615, + 0xF0FE, 0x7619, + 0xF140, 0x998C, + 0xF141, 0x998E, + 0xF1A1, 0x761B, + 0xF1A2, 0x763C, + 0xF1A3, 0x7622, + 0xF1A4, 0x7620, + 0xF1A5, 0x7640, + 0xF1A6, 0x762D, + 0xF1A7, 0x7630, + 0xF1A8, 0x763F, + 0xF1A9, 0x7635, + 0xF1AA, 0x7643, + 0xF1AB, 0x763E, + 0xF1AC, 0x7633, + 0xF1AD, 0x764D, + 0xF1AE, 0x765E, + 0xF1AF, 0x7654, + 0xF1B0, 0x765C, + 0xF1B1, 0x7656, + 0xF1B2, 0x766B, + 0xF1B3, 0x766F, + 0xF1B4, 0x7FCA, + 0xF1B5, 0x7AE6, + 0xF1B8, 0x7A80, + 0xF1B9, 0x7A86, + 0xF1BA, 0x7A88, + 0xF1BB, 0x7A95, + 0xF1BC, 0x7AA6, + 0xF1BD, 0x7AA0, + 0xF1BE, 0x7AAC, + 0xF1BF, 0x7AA8, + 0xF1C0, 0x7AAD, + 0xF1C1, 0x7AB3, + 0xF1C2, 0x8864, + 0xF1C3, 0x8869, + 0xF1C4, 0x8872, + 0xF1C5, 0x887D, + 0xF1C6, 0x887F, + 0xF1C7, 0x8882, + 0xF1C8, 0x88A2, + 0xF1C9, 0x88C6, + 0xF1CA, 0x88B7, + 0xF1CB, 0x88BC, + 0xF1CC, 0x88C9, + 0xF1CD, 0x88E2, + 0xF1CE, 0x88CE, + 0xF1CF, 0x88E3, + 0xF1D0, 0x88E5, + 0xF1D1, 0x88F1, + 0xF1D2, 0x891A, + 0xF1D3, 0x88FC, + 0xF1D4, 0x88E8, + 0xF1D5, 0x88FE, + 0xF1D6, 0x88F0, + 0xF1D7, 0x8921, + 0xF1D8, 0x8919, + 0xF1D9, 0x8913, + 0xF1DA, 0x891B, + 0xF1DB, 0x890A, + 0xF1DC, 0x8934, + 0xF1DD, 0x892B, + 0xF1DE, 0x8936, + 0xF1DF, 0x8941, + 0xF1E0, 0x8966, + 0xF1E1, 0x897B, + 0xF1E2, 0x758B, + 0xF1E3, 0x80E5, + 0xF1E4, 0x76B2, + 0xF1E5, 0x76B4, + 0xF1E6, 0x77DC, + 0xF1E7, 0x8012, + 0xF1E8, 0x8014, + 0xF1E9, 0x8016, + 0xF1EA, 0x801C, + 0xF1EB, 0x8020, + 0xF1EC, 0x8022, + 0xF1F0, 0x8029, + 0xF1F1, 0x8028, + 0xF1F2, 0x8031, + 0xF1F3, 0x800B, + 0xF1F4, 0x8035, + 0xF1F5, 0x8043, + 0xF1F6, 0x8046, + 0xF1F7, 0x804D, + 0xF1F8, 0x8052, + 0xF1F9, 0x8069, + 0xF1FA, 0x8071, + 0xF1FB, 0x8983, + 0xF1FC, 0x9878, + 0xF1FD, 0x9880, + 0xF1FE, 0x9883, + 0xF2A1, 0x9889, + 0xF2A4, 0x988F, + 0xF2A5, 0x9894, + 0xF2AE, 0x864D, + 0xF2AF, 0x8654, + 0xF2B0, 0x866C, + 0xF2B1, 0x866E, + 0xF2B2, 0x867F, + 0xF2B3, 0x867A, + 0xF2B4, 0x867C, + 0xF2B5, 0x867B, + 0xF2B6, 0x86A8, + 0xF2B7, 0x868D, + 0xF2B8, 0x868B, + 0xF2B9, 0x86AC, + 0xF2BA, 0x869D, + 0xF2BB, 0x86A7, + 0xF2BC, 0x86A3, + 0xF2BD, 0x86AA, + 0xF2BE, 0x8693, + 0xF2BF, 0x86A9, + 0xF2C0, 0x86B6, + 0xF2C1, 0x86C4, + 0xF2C2, 0x86B5, + 0xF2C3, 0x86CE, + 0xF2C4, 0x86B0, + 0xF2C5, 0x86BA, + 0xF2C6, 0x86B1, + 0xF2C7, 0x86AF, + 0xF2C8, 0x86C9, + 0xF2C9, 0x86CF, + 0xF2CA, 0x86B4, + 0xF2CB, 0x86E9, + 0xF2CE, 0x86ED, + 0xF2CF, 0x86F3, + 0xF2D0, 0x86D0, + 0xF2D1, 0x8713, + 0xF2D2, 0x86DE, + 0xF2D3, 0x86F4, + 0xF2D4, 0x86DF, + 0xF2D5, 0x86D8, + 0xF2D6, 0x86D1, + 0xF2D7, 0x8703, + 0xF2D8, 0x8707, + 0xF2D9, 0x86F8, + 0xF2DA, 0x8708, + 0xF2DB, 0x870A, + 0xF2DC, 0x870D, + 0xF2DD, 0x8709, + 0xF2DE, 0x8723, + 0xF2DF, 0x873B, + 0xF2E0, 0x871E, + 0xF2E1, 0x8725, + 0xF2E2, 0x872E, + 0xF2E3, 0x871A, + 0xF2E4, 0x873E, + 0xF2E5, 0x8748, + 0xF2E6, 0x8734, + 0xF2E7, 0x8731, + 0xF2E8, 0x8729, + 0xF2E9, 0x8737, + 0xF2EA, 0x873F, + 0xF2EB, 0x8782, + 0xF2EC, 0x8722, + 0xF2EF, 0x877B, + 0xF2F0, 0x8760, + 0xF2F1, 0x8770, + 0xF2F2, 0x874C, + 0xF2F3, 0x876E, + 0xF2F4, 0x878B, + 0xF2F5, 0x8753, + 0xF2F6, 0x8763, + 0xF2F7, 0x877C, + 0xF2F8, 0x8764, + 0xF2F9, 0x8759, + 0xF2FA, 0x8765, + 0xF2FB, 0x8793, + 0xF2FC, 0x87AF, + 0xF2FD, 0x87A8, + 0xF2FE, 0x87D2, + 0xF352, 0x9A72, + 0xF353, 0x9A83, + 0xF354, 0x9A89, + 0xF359, 0x9A99, + 0xF35A, 0x9AA6, + 0xF366, 0x9AB9, + 0xF367, 0x9ABB, + 0xF376, 0x9AD2, + 0xF382, 0x9AE0, + 0xF38B, 0x9AEC, + 0xF38C, 0x9AEE, + 0xF396, 0x9AFA, + 0xF3A1, 0x87C6, + 0xF3A2, 0x8788, + 0xF3A3, 0x8785, + 0xF3A4, 0x87AD, + 0xF3A5, 0x8797, + 0xF3A6, 0x8783, + 0xF3A7, 0x87AB, + 0xF3A8, 0x87E5, + 0xF3A9, 0x87AC, + 0xF3AA, 0x87B5, + 0xF3AB, 0x87B3, + 0xF3AC, 0x87CB, + 0xF3AD, 0x87D3, + 0xF3AE, 0x87BD, + 0xF3AF, 0x87D1, + 0xF3B0, 0x87C0, + 0xF3B1, 0x87CA, + 0xF3B2, 0x87DB, + 0xF3B3, 0x87EA, + 0xF3B4, 0x87E0, + 0xF3B5, 0x87EE, + 0xF3B6, 0x8816, + 0xF3B7, 0x8813, + 0xF3B8, 0x87FE, + 0xF3B9, 0x880A, + 0xF3BA, 0x881B, + 0xF3BB, 0x8821, + 0xF3BC, 0x8839, + 0xF3BD, 0x883C, + 0xF3BE, 0x7F36, + 0xF3BF, 0x7F42, + 0xF3C2, 0x8210, + 0xF3C3, 0x7AFA, + 0xF3C4, 0x7AFD, + 0xF3C5, 0x7B08, + 0xF3C8, 0x7B15, + 0xF3C9, 0x7B0A, + 0xF3CA, 0x7B2B, + 0xF3CB, 0x7B0F, + 0xF3CC, 0x7B47, + 0xF3CD, 0x7B38, + 0xF3CE, 0x7B2A, + 0xF3CF, 0x7B19, + 0xF3D0, 0x7B2E, + 0xF3D1, 0x7B31, + 0xF3D2, 0x7B20, + 0xF3D3, 0x7B25, + 0xF3D4, 0x7B24, + 0xF3D5, 0x7B33, + 0xF3D6, 0x7B3E, + 0xF3D7, 0x7B1E, + 0xF3D8, 0x7B58, + 0xF3D9, 0x7B5A, + 0xF3DA, 0x7B45, + 0xF3DB, 0x7B75, + 0xF3DC, 0x7B4C, + 0xF3DD, 0x7B5D, + 0xF3DE, 0x7B60, + 0xF3DF, 0x7B6E, + 0xF3E0, 0x7B7B, + 0xF3E1, 0x7B62, + 0xF3E2, 0x7B72, + 0xF3E3, 0x7B71, + 0xF3E4, 0x7B90, + 0xF3E7, 0x7BB8, + 0xF3E8, 0x7BAC, + 0xF3E9, 0x7B9D, + 0xF3EA, 0x7BA8, + 0xF3EB, 0x7B85, + 0xF3EC, 0x7BAA, + 0xF3ED, 0x7B9C, + 0xF3EE, 0x7BA2, + 0xF3EF, 0x7BAB, + 0xF3F0, 0x7BB4, + 0xF3F1, 0x7BD1, + 0xF3F2, 0x7BC1, + 0xF3F3, 0x7BCC, + 0xF3F4, 0x7BDD, + 0xF3F5, 0x7BDA, + 0xF3F8, 0x7BEA, + 0xF3F9, 0x7C0C, + 0xF3FA, 0x7BFE, + 0xF3FB, 0x7BFC, + 0xF3FC, 0x7C0F, + 0xF3FD, 0x7C16, + 0xF3FE, 0x7C0B, + 0xF440, 0x9B07, + 0xF471, 0x9B46, + 0xF475, 0x9B4E, + 0xF476, 0x9B50, + 0xF4A1, 0x7C1F, + 0xF4A2, 0x7C2A, + 0xF4A3, 0x7C26, + 0xF4A4, 0x7C38, + 0xF4A5, 0x7C41, + 0xF4A6, 0x7C40, + 0xF4A7, 0x81FE, + 0xF4AA, 0x8204, + 0xF4AB, 0x81EC, + 0xF4AC, 0x8844, + 0xF4B0, 0x822D, + 0xF4B1, 0x822F, + 0xF4B2, 0x8228, + 0xF4B3, 0x822B, + 0xF4B4, 0x8238, + 0xF4B5, 0x823B, + 0xF4B8, 0x823E, + 0xF4B9, 0x8244, + 0xF4BA, 0x8249, + 0xF4BB, 0x824B, + 0xF4BC, 0x824F, + 0xF4BD, 0x825A, + 0xF4BE, 0x825F, + 0xF4BF, 0x8268, + 0xF4C0, 0x887E, + 0xF4C1, 0x8885, + 0xF4C2, 0x8888, + 0xF4C3, 0x88D8, + 0xF4C4, 0x88DF, + 0xF4C5, 0x895E, + 0xF4C6, 0x7F9D, + 0xF4C7, 0x7F9F, + 0xF4C8, 0x7FA7, + 0xF4CB, 0x7FB2, + 0xF4CC, 0x7C7C, + 0xF4CD, 0x6549, + 0xF4CE, 0x7C91, + 0xF4CF, 0x7C9D, + 0xF4D0, 0x7C9C, + 0xF4D1, 0x7C9E, + 0xF4D2, 0x7CA2, + 0xF4D3, 0x7CB2, + 0xF4D6, 0x7CC1, + 0xF4D7, 0x7CC7, + 0xF4DA, 0x7CC8, + 0xF4DB, 0x7CC5, + 0xF4DC, 0x7CD7, + 0xF4DD, 0x7CE8, + 0xF4DE, 0x826E, + 0xF4DF, 0x66A8, + 0xF4E0, 0x7FBF, + 0xF4E1, 0x7FCE, + 0xF4E2, 0x7FD5, + 0xF4E3, 0x7FE5, + 0xF4E4, 0x7FE1, + 0xF4E5, 0x7FE6, + 0xF4E6, 0x7FE9, + 0xF4E7, 0x7FEE, + 0xF4E8, 0x7FF3, + 0xF4E9, 0x7CF8, + 0xF4EA, 0x7D77, + 0xF4EB, 0x7DA6, + 0xF4EC, 0x7DAE, + 0xF4ED, 0x7E47, + 0xF4EE, 0x7E9B, + 0xF4EF, 0x9EB8, + 0xF4F0, 0x9EB4, + 0xF4F1, 0x8D73, + 0xF4F2, 0x8D84, + 0xF4F3, 0x8D94, + 0xF4F4, 0x8D91, + 0xF4F5, 0x8DB1, + 0xF4F6, 0x8D67, + 0xF4F7, 0x8D6D, + 0xF4F8, 0x8C47, + 0xF4F9, 0x8C49, + 0xF4FA, 0x914A, + 0xF4FB, 0x9150, + 0xF4FE, 0x9164, + 0xF5A1, 0x9162, + 0xF5A2, 0x9161, + 0xF5A3, 0x9170, + 0xF5A4, 0x9169, + 0xF5A5, 0x916F, + 0xF5A8, 0x9172, + 0xF5A9, 0x9174, + 0xF5AA, 0x9179, + 0xF5AB, 0x918C, + 0xF5AC, 0x9185, + 0xF5AD, 0x9190, + 0xF5AE, 0x918D, + 0xF5AF, 0x9191, + 0xF5B2, 0x91AA, + 0xF5B6, 0x91B5, + 0xF5B7, 0x91B4, + 0xF5B8, 0x91BA, + 0xF5B9, 0x8C55, + 0xF5BA, 0x9E7E, + 0xF5BB, 0x8DB8, + 0xF5BC, 0x8DEB, + 0xF5BD, 0x8E05, + 0xF5BE, 0x8E59, + 0xF5BF, 0x8E69, + 0xF5C0, 0x8DB5, + 0xF5C1, 0x8DBF, + 0xF5C2, 0x8DBC, + 0xF5C3, 0x8DBA, + 0xF5C4, 0x8DC4, + 0xF5C7, 0x8DDA, + 0xF5C8, 0x8DDE, + 0xF5CB, 0x8DDB, + 0xF5CC, 0x8DC6, + 0xF5CD, 0x8DEC, + 0xF5D0, 0x8DE3, + 0xF5D1, 0x8DF9, + 0xF5D2, 0x8DFB, + 0xF5D3, 0x8DE4, + 0xF5D4, 0x8E09, + 0xF5D5, 0x8DFD, + 0xF5D6, 0x8E14, + 0xF5D7, 0x8E1D, + 0xF5D8, 0x8E1F, + 0xF5D9, 0x8E2C, + 0xF5DA, 0x8E2E, + 0xF5DB, 0x8E23, + 0xF5DC, 0x8E2F, + 0xF5DD, 0x8E3A, + 0xF5DE, 0x8E40, + 0xF5DF, 0x8E39, + 0xF5E0, 0x8E35, + 0xF5E1, 0x8E3D, + 0xF5E2, 0x8E31, + 0xF5E3, 0x8E49, + 0xF5E8, 0x8E4A, + 0xF5E9, 0x8E70, + 0xF5EA, 0x8E76, + 0xF5EB, 0x8E7C, + 0xF5EC, 0x8E6F, + 0xF5ED, 0x8E74, + 0xF5EE, 0x8E85, + 0xF5EF, 0x8E8F, + 0xF5F0, 0x8E94, + 0xF5F1, 0x8E90, + 0xF5F2, 0x8E9C, + 0xF5F3, 0x8E9E, + 0xF5F4, 0x8C78, + 0xF5F5, 0x8C82, + 0xF5F6, 0x8C8A, + 0xF5F7, 0x8C85, + 0xF5F8, 0x8C98, + 0xF5F9, 0x8C94, + 0xF5FA, 0x659B, + 0xF5FB, 0x89D6, + 0xF5FC, 0x89DE, + 0xF5FD, 0x89DA, + 0xF5FE, 0x89DC, + 0xF6A1, 0x89E5, + 0xF6A2, 0x89EB, + 0xF6A3, 0x89EF, + 0xF6A4, 0x8A3E, + 0xF6A5, 0x8B26, + 0xF6A6, 0x9753, + 0xF6A7, 0x96E9, + 0xF6A8, 0x96F3, + 0xF6A9, 0x96EF, + 0xF6AA, 0x9706, + 0xF6AB, 0x9701, + 0xF6AC, 0x9708, + 0xF6AD, 0x970F, + 0xF6AE, 0x970E, + 0xF6AF, 0x972A, + 0xF6B0, 0x972D, + 0xF6B1, 0x9730, + 0xF6B2, 0x973E, + 0xF6B3, 0x9F80, + 0xF6B4, 0x9F83, + 0xF6BB, 0x9F8C, + 0xF6BC, 0x9EFE, + 0xF6BD, 0x9F0B, + 0xF6BE, 0x9F0D, + 0xF6BF, 0x96B9, + 0xF6C2, 0x96CE, + 0xF6C3, 0x96D2, + 0xF6C4, 0x77BF, + 0xF6C5, 0x96E0, + 0xF6C6, 0x928E, + 0xF6C7, 0x92AE, + 0xF6C8, 0x92C8, + 0xF6C9, 0x933E, + 0xF6CA, 0x936A, + 0xF6CB, 0x93CA, + 0xF6CC, 0x938F, + 0xF6CD, 0x943E, + 0xF6CE, 0x946B, + 0xF6CF, 0x9C7F, + 0xF6D0, 0x9C82, + 0xF6D5, 0x7A23, + 0xF6D6, 0x9C8B, + 0xF6D7, 0x9C8E, + 0xF6EA, 0x9CAB, + 0xF780, 0x9C7B, + 0xF783, 0x9C80, + 0xF788, 0x9C8C, + 0xF789, 0x9C8F, + 0xF78A, 0x9C93, + 0xF78F, 0x9C9D, + 0xF790, 0x9CAA, + 0xF791, 0x9CAC, + 0xF792, 0x9CAF, + 0xF793, 0x9CB9, + 0xF7AE, 0x9CDF, + 0xF7AF, 0x9CE2, + 0xF7B0, 0x977C, + 0xF7B1, 0x9785, + 0xF7B4, 0x9794, + 0xF7B5, 0x97AF, + 0xF7B6, 0x97AB, + 0xF7B7, 0x97A3, + 0xF7B8, 0x97B2, + 0xF7B9, 0x97B4, + 0xF7BA, 0x9AB1, + 0xF7BB, 0x9AB0, + 0xF7BC, 0x9AB7, + 0xF7BD, 0x9E58, + 0xF7BE, 0x9AB6, + 0xF7BF, 0x9ABA, + 0xF7C0, 0x9ABC, + 0xF7C1, 0x9AC1, + 0xF7C2, 0x9AC0, + 0xF7C3, 0x9AC5, + 0xF7C4, 0x9AC2, + 0xF7C7, 0x9AD1, + 0xF7C8, 0x9B45, + 0xF7C9, 0x9B43, + 0xF7CA, 0x9B47, + 0xF7CB, 0x9B49, + 0xF7CC, 0x9B48, + 0xF7CD, 0x9B4D, + 0xF7CE, 0x9B51, + 0xF7CF, 0x98E8, + 0xF7D0, 0x990D, + 0xF7D1, 0x992E, + 0xF7D2, 0x9955, + 0xF7D3, 0x9954, + 0xF7D4, 0x9ADF, + 0xF7D5, 0x9AE1, + 0xF7D6, 0x9AE6, + 0xF7D7, 0x9AEF, + 0xF7D8, 0x9AEB, + 0xF7D9, 0x9AFB, + 0xF7DA, 0x9AED, + 0xF7DB, 0x9AF9, + 0xF7DC, 0x9B08, + 0xF7DD, 0x9B0F, + 0xF7DE, 0x9B13, + 0xF7DF, 0x9B1F, + 0xF7E0, 0x9B23, + 0xF7E3, 0x7E3B, + 0xF7E4, 0x9E82, + 0xF7E7, 0x9E8B, + 0xF7E8, 0x9E92, + 0xF7E9, 0x93D6, + 0xF7EA, 0x9E9D, + 0xF7EB, 0x9E9F, + 0xF7EF, 0x9EE0, + 0xF7F0, 0x9EDF, + 0xF7F1, 0x9EE2, + 0xF7F2, 0x9EE9, + 0xF7F3, 0x9EE7, + 0xF7F4, 0x9EE5, + 0xF7F5, 0x9EEA, + 0xF7F6, 0x9EEF, + 0xF7F7, 0x9F22, + 0xF7F8, 0x9F2C, + 0xF7F9, 0x9F2F, + 0xF7FA, 0x9F39, + 0xF7FB, 0x9F37, + 0xF7FE, 0x9F44, + 0xFB5C, 0x9E24, + 0xFB5D, 0x9E27, + 0xFB5E, 0x9E2E, + 0xFB5F, 0x9E30, + 0xFB60, 0x9E34, + 0xFB63, 0x9E40, + 0xFB64, 0x9E4D, + 0xFB65, 0x9E50, + 0xFB69, 0x9E56, + 0xFB6A, 0x9E59, + 0xFB6B, 0x9E5D, + 0xFB70, 0x9E65, + 0xFB73, 0x9E72, + 0xFB7E, 0x9E80, + 0xFB80, 0x9E81, + 0xFB96, 0x9E9E, + 0xFC4E, 0x9EBC, + 0xFC5B, 0x9ED0, + 0xFC63, 0x9EDE, + 0xFC64, 0x9EE1, + 0xFC67, 0x9EE6, + 0xFC68, 0x9EE8, + 0xFC76, 0x9EFA, + 0xFC77, 0x9EFD, + 0xFC85, 0x9F0C, + 0xFC86, 0x9F0F, + 0xFC8C, 0x9F18, + 0xFC93, 0x9F21, + 0xFD45, 0x9F38, + 0xFD46, 0x9F3A, + 0xFD47, 0x9F3C, + 0xFD9C, 0xF92C, + 0xFD9D, 0xF979, + 0xFD9E, 0xF995, + 0xFD9F, 0xF9E7, + 0xFDA0, 0xF9F1, + 0xFE44, 0xFA11, + 0xFE47, 0xFA18, // }}} +}; +#endif +#if 0 +static const unsigned short _gbk2utf16_3[] = +{ + 0x8141, 0x8143, 0x4E04, // {{{ + 0x8147, 0x8149, 0x4E1F, + 0x814D, 0x814E, 0x4E2E, + 0x8154, 0x8156, 0x4E40, + 0x815D, 0x815E, 0x4E5A, + 0x815F, 0x8162, 0x4E62, + 0x8163, 0x8164, 0x4E67, + 0x8165, 0x816A, 0x4E6A, + 0x816C, 0x8175, 0x4E74, + 0x8176, 0x817C, 0x4E7F, + 0x8181, 0x8182, 0x4E96, + 0x8184, 0x8186, 0x4E9C, + 0x8189, 0x818B, 0x4EAF, + 0x818D, 0x8190, 0x4EB6, + 0x8191, 0x8193, 0x4EBC, + 0x8196, 0x8197, 0x4ECF, + 0x8199, 0x819B, 0x4EDA, + 0x819E, 0x819F, 0x4EE6, + 0x81A1, 0x81A3, 0x4EED, + 0x81A6, 0x81A8, 0x4EF8, + 0x81AC, 0x81B2, 0x4F02, + 0x81B3, 0x81B4, 0x4F0B, + 0x81B5, 0x81B9, 0x4F12, + 0x81BA, 0x81BB, 0x4F1C, + 0x81BE, 0x81BF, 0x4F28, + 0x81C0, 0x81C2, 0x4F2C, + 0x81C9, 0x81CD, 0x4F3E, + 0x81CE, 0x81CF, 0x4F44, + 0x81D0, 0x81D5, 0x4F47, + 0x81D9, 0x81DA, 0x4F61, + 0x81DD, 0x81DE, 0x4F6A, + 0x81DF, 0x81E0, 0x4F6D, + 0x81E1, 0x81E2, 0x4F71, + 0x81E4, 0x81E7, 0x4F77, + 0x81E9, 0x81EB, 0x4F80, + 0x81EC, 0x81EE, 0x4F85, + 0x81F3, 0x81F4, 0x4F92, + 0x81F5, 0x81F6, 0x4F95, + 0x81F7, 0x81F9, 0x4F98, + 0x81FB, 0x81FC, 0x4F9E, + 0x81FD, 0x81FE, 0x4FA1, + 0x8243, 0x8247, 0x4FB0, + 0x8248, 0x8250, 0x4FB6, + 0x8251, 0x8253, 0x4FC0, + 0x8254, 0x8257, 0x4FC6, + 0x8258, 0x825A, 0x4FCB, + 0x825B, 0x825F, 0x4FD2, + 0x8264, 0x8265, 0x4FE4, + 0x8267, 0x8268, 0x4FEB, + 0x826B, 0x826E, 0x4FF4, + 0x8270, 0x8272, 0x4FFB, + 0x8273, 0x827E, 0x4FFF, + 0x8282, 0x8283, 0x5010, + 0x8285, 0x8287, 0x5015, + 0x8289, 0x828A, 0x501D, + 0x828C, 0x828E, 0x5022, + 0x8291, 0x829B, 0x502F, + 0x829E, 0x82A1, 0x503F, + 0x82A2, 0x82A4, 0x5044, + 0x82A5, 0x82A7, 0x5049, + 0x82A9, 0x82AD, 0x5050, + 0x82AE, 0x82B1, 0x5056, + 0x82B3, 0x82BA, 0x505D, + 0x82BB, 0x82C0, 0x5066, + 0x82C1, 0x82C9, 0x506D, + 0x82CA, 0x82CC, 0x5078, + 0x82CD, 0x82CE, 0x507C, + 0x82CF, 0x82D2, 0x5081, + 0x82D3, 0x82D4, 0x5086, + 0x82D5, 0x82D8, 0x5089, + 0x82D9, 0x82ED, 0x508E, + 0x82F0, 0x82F1, 0x50AA, + 0x82F2, 0x82F6, 0x50AD, + 0x82F7, 0x82FD, 0x50B3, + 0x8340, 0x8351, 0x50BD, + 0x8352, 0x8357, 0x50D0, + 0x8358, 0x835A, 0x50D7, + 0x835B, 0x8365, 0x50DB, + 0x8366, 0x8369, 0x50E8, + 0x836A, 0x836D, 0x50EF, + 0x836F, 0x8373, 0x50F6, + 0x8374, 0x837D, 0x50FC, + 0x8380, 0x8381, 0x5109, + 0x8382, 0x8387, 0x510C, + 0x8388, 0x8395, 0x5113, + 0x8396, 0x83B2, 0x5122, + 0x83B7, 0x83B9, 0x514E, + 0x83BA, 0x83BB, 0x5152, + 0x83BC, 0x83BE, 0x5157, + 0x83C0, 0x83C4, 0x515D, + 0x83C5, 0x83C6, 0x5163, + 0x83C7, 0x83C8, 0x5166, + 0x83C9, 0x83CA, 0x5169, + 0x83CE, 0x83CF, 0x517E, + 0x83D0, 0x83D1, 0x5183, + 0x83D2, 0x83D3, 0x5186, + 0x83D4, 0x83D5, 0x518A, + 0x83D6, 0x83D9, 0x518E, + 0x83DA, 0x83DB, 0x5193, + 0x83DE, 0x83E0, 0x519D, + 0x83E3, 0x83E7, 0x51A6, + 0x83E8, 0x83E9, 0x51AD, + 0x83EB, 0x83ED, 0x51B8, + 0x83EE, 0x83EF, 0x51BE, + 0x83F0, 0x83F2, 0x51C1, + 0x83F6, 0x83F7, 0x51CD, + 0x83F9, 0x83FE, 0x51D2, + 0x8440, 0x8442, 0x51D8, + 0x8444, 0x8445, 0x51DE, + 0x8446, 0x8447, 0x51E2, + 0x8448, 0x844D, 0x51E5, + 0x8450, 0x8451, 0x51F1, + 0x8455, 0x8456, 0x5204, + 0x8458, 0x8459, 0x520B, + 0x845A, 0x845B, 0x520F, + 0x845C, 0x845E, 0x5213, + 0x8460, 0x8461, 0x521E, + 0x8462, 0x8464, 0x5221, + 0x8465, 0x8467, 0x5225, + 0x846B, 0x846C, 0x5231, + 0x846D, 0x846E, 0x5234, + 0x8471, 0x8476, 0x5244, + 0x8478, 0x8479, 0x524E, + 0x847A, 0x847B, 0x5252, + 0x847D, 0x847E, 0x5257, + 0x8480, 0x8482, 0x5259, + 0x8484, 0x8485, 0x525F, + 0x8486, 0x8488, 0x5262, + 0x848B, 0x848E, 0x526B, + 0x848F, 0x8490, 0x5270, + 0x8491, 0x849A, 0x5273, + 0x849D, 0x84A1, 0x5283, + 0x84A2, 0x84A8, 0x5289, + 0x84A9, 0x84AA, 0x5291, + 0x84AB, 0x84B1, 0x5294, + 0x84B3, 0x84B6, 0x52A4, + 0x84B7, 0x84B9, 0x52AE, + 0x84BA, 0x84C3, 0x52B4, + 0x84C4, 0x84C6, 0x52C0, + 0x84C7, 0x84C9, 0x52C4, + 0x84CC, 0x84CF, 0x52CC, + 0x84D1, 0x84D3, 0x52D3, + 0x84D5, 0x84DA, 0x52D9, + 0x84DB, 0x84DE, 0x52E0, + 0x84DF, 0x84E9, 0x52E5, + 0x84EA, 0x84F1, 0x52F1, + 0x84F2, 0x84F4, 0x52FB, + 0x84F5, 0x84F8, 0x5301, + 0x84FA, 0x84FD, 0x5309, + 0x8540, 0x8543, 0x5311, + 0x8545, 0x8546, 0x531B, + 0x8547, 0x8548, 0x531E, + 0x854A, 0x854B, 0x5324, + 0x854C, 0x854E, 0x5327, + 0x854F, 0x8551, 0x532B, + 0x8552, 0x855B, 0x532F, + 0x855C, 0x855D, 0x533C, + 0x8562, 0x8564, 0x534B, + 0x8567, 0x8568, 0x5358, + 0x856E, 0x856F, 0x536C, + 0x8573, 0x8576, 0x537B, + 0x8577, 0x8578, 0x5380, + 0x857A, 0x857B, 0x5387, + 0x857D, 0x857E, 0x538E, + 0x8580, 0x8584, 0x5390, + 0x8585, 0x8586, 0x5396, + 0x8588, 0x8589, 0x539B, + 0x858B, 0x858C, 0x53A0, + 0x858F, 0x8592, 0x53AA, + 0x8593, 0x8599, 0x53AF, + 0x859A, 0x859D, 0x53B7, + 0x859E, 0x85A0, 0x53BC, + 0x85A2, 0x85A6, 0x53C3, + 0x85A7, 0x85A9, 0x53CE, + 0x85AA, 0x85AB, 0x53D2, + 0x85AE, 0x85B0, 0x53DC, + 0x85B1, 0x85B2, 0x53E1, + 0x85B6, 0x85B8, 0x53FE, + 0x85BE, 0x85C0, 0x5418, + 0x85C3, 0x85C4, 0x5424, + 0x85C8, 0x85C9, 0x5436, + 0x85CD, 0x85CE, 0x5441, + 0x85CF, 0x85D0, 0x5444, + 0x85D3, 0x85D6, 0x544C, + 0x85D9, 0x85DD, 0x545D, + 0x85E1, 0x85E8, 0x5469, + 0x85EA, 0x85EB, 0x5479, + 0x85EC, 0x85ED, 0x547E, + 0x85F1, 0x85F4, 0x5487, + 0x85F8, 0x85F9, 0x5497, + 0x85FB, 0x85FE, 0x549E, + 0x8645, 0x8647, 0x54B5, + 0x8648, 0x8649, 0x54B9, + 0x864E, 0x864F, 0x54CA, + 0x8653, 0x8657, 0x54E0, + 0x8658, 0x8659, 0x54EB, + 0x865A, 0x865C, 0x54EF, + 0x865D, 0x8662, 0x54F4, + 0x8666, 0x8669, 0x5502, + 0x866B, 0x866F, 0x550A, + 0x8670, 0x8671, 0x5512, + 0x8672, 0x8677, 0x5515, + 0x8678, 0x867B, 0x551C, + 0x867D, 0x867E, 0x5525, + 0x8680, 0x8681, 0x5528, + 0x8685, 0x8687, 0x5534, + 0x8688, 0x868B, 0x5538, + 0x8690, 0x8691, 0x5547, + 0x8692, 0x8696, 0x554B, + 0x8697, 0x869A, 0x5551, + 0x869B, 0x869F, 0x5557, + 0x86A0, 0x86A3, 0x555D, + 0x86A4, 0x86A5, 0x5562, + 0x86A6, 0x86A7, 0x5568, + 0x86A9, 0x86AE, 0x556F, + 0x86AF, 0x86B0, 0x5579, + 0x86B3, 0x86B4, 0x5585, + 0x86B5, 0x86B7, 0x558C, + 0x86B9, 0x86BA, 0x5592, + 0x86BB, 0x86BD, 0x5595, + 0x86BE, 0x86BF, 0x559A, + 0x86C1, 0x86C7, 0x55A0, + 0x86C8, 0x86D0, 0x55A8, + 0x86D7, 0x86DB, 0x55BF, + 0x86DC, 0x86DE, 0x55C6, + 0x86DF, 0x86E0, 0x55CA, + 0x86E1, 0x86E3, 0x55CE, + 0x86E5, 0x86E9, 0x55D7, + 0x86EF, 0x86F0, 0x55ED, + 0x86F1, 0x86F2, 0x55F0, + 0x86F5, 0x86F9, 0x55F8, + 0x86FB, 0x86FE, 0x5602, + 0x8740, 0x8741, 0x5606, + 0x8742, 0x8743, 0x560A, + 0x8745, 0x874C, 0x5610, + 0x874D, 0x874E, 0x5619, + 0x874F, 0x8750, 0x561C, + 0x8751, 0x8753, 0x5620, + 0x8754, 0x8755, 0x5625, + 0x8756, 0x8759, 0x5628, + 0x875A, 0x875C, 0x562E, + 0x875F, 0x8760, 0x5637, + 0x8762, 0x8764, 0x563C, + 0x8765, 0x8770, 0x5640, + 0x8771, 0x8775, 0x564F, + 0x8776, 0x8777, 0x5655, + 0x8778, 0x8779, 0x565A, + 0x877A, 0x877E, 0x565D, + 0x8781, 0x8783, 0x5665, + 0x8784, 0x8787, 0x566D, + 0x8788, 0x878B, 0x5672, + 0x878C, 0x878F, 0x5677, + 0x8790, 0x8797, 0x567D, + 0x8798, 0x879E, 0x5687, + 0x879F, 0x87A1, 0x5690, + 0x87A2, 0x87B0, 0x5694, + 0x87B1, 0x87BB, 0x56A4, + 0x87BC, 0x87C2, 0x56B0, + 0x87C3, 0x87C6, 0x56B8, + 0x87C7, 0x87D3, 0x56BD, + 0x87D4, 0x87DC, 0x56CB, + 0x87DD, 0x87DE, 0x56D5, + 0x87DF, 0x87E0, 0x56D8, + 0x87E3, 0x87E8, 0x56E5, + 0x87EA, 0x87EB, 0x56EE, + 0x87EC, 0x87ED, 0x56F2, + 0x87EE, 0x87F0, 0x56F6, + 0x87F1, 0x87F2, 0x56FB, + 0x87F3, 0x87F5, 0x5700, + 0x87F8, 0x87FE, 0x570B, + 0x8840, 0x8849, 0x5712, + 0x884A, 0x884B, 0x571D, + 0x884C, 0x884E, 0x5720, + 0x884F, 0x8852, 0x5724, + 0x8854, 0x8855, 0x5731, + 0x8856, 0x885A, 0x5734, + 0x885B, 0x885C, 0x573C, + 0x885F, 0x8862, 0x5743, + 0x8863, 0x8864, 0x5748, + 0x8866, 0x886A, 0x5752, + 0x886B, 0x886C, 0x5758, + 0x886D, 0x886E, 0x5762, + 0x8873, 0x8875, 0x5770, + 0x8876, 0x8877, 0x5774, + 0x8878, 0x887A, 0x5778, + 0x887B, 0x887E, 0x577D, + 0x8881, 0x8884, 0x5787, + 0x8885, 0x8889, 0x578D, + 0x888A, 0x8890, 0x5794, + 0x8891, 0x8894, 0x579C, + 0x8899, 0x889B, 0x57AF, + 0x889D, 0x889F, 0x57B5, + 0x88A0, 0x88A8, 0x57B9, + 0x88A9, 0x88AF, 0x57C4, + 0x88B0, 0x88B1, 0x57CC, + 0x88B2, 0x88B3, 0x57D0, + 0x88B5, 0x88B6, 0x57D6, + 0x88B7, 0x88B8, 0x57DB, + 0x88BA, 0x88BC, 0x57E1, + 0x88BD, 0x88C4, 0x57E5, + 0x88C6, 0x88C9, 0x57F0, + 0x88CA, 0x88CC, 0x57F5, + 0x88CD, 0x88CE, 0x57FB, + 0x88CF, 0x88D0, 0x57FE, + 0x88D2, 0x88D4, 0x5803, + 0x88D5, 0x88D7, 0x5808, + 0x88D9, 0x88DB, 0x580E, + 0x88DC, 0x88DE, 0x5812, + 0x88DF, 0x88E1, 0x5816, + 0x88E2, 0x88E5, 0x581A, + 0x88E7, 0x88E8, 0x5822, + 0x88E9, 0x88ED, 0x5825, + 0x88EE, 0x88F2, 0x582B, + 0x88F3, 0x88F6, 0x5831, + 0x88F7, 0x88FE, 0x5836, + 0x8940, 0x8945, 0x583E, + 0x8946, 0x894C, 0x5845, + 0x894D, 0x894F, 0x584E, + 0x8950, 0x8951, 0x5852, + 0x8952, 0x8954, 0x5855, + 0x8955, 0x8959, 0x5859, + 0x895A, 0x895F, 0x585F, + 0x8960, 0x8964, 0x5866, + 0x8965, 0x8975, 0x586D, + 0x8979, 0x897B, 0x5886, + 0x897C, 0x897E, 0x588A, + 0x8980, 0x8984, 0x588D, + 0x8985, 0x8989, 0x5894, + 0x898A, 0x898C, 0x589B, + 0x898D, 0x8994, 0x58A0, + 0x8995, 0x89A6, 0x58AA, + 0x89A7, 0x89AA, 0x58BD, + 0x89AB, 0x89AD, 0x58C2, + 0x89AE, 0x89B8, 0x58C6, + 0x89B9, 0x89BB, 0x58D2, + 0x89BC, 0x89C9, 0x58D6, + 0x89CA, 0x89CF, 0x58E5, + 0x89D2, 0x89D3, 0x58F1, + 0x89D4, 0x89D5, 0x58F4, + 0x89D6, 0x89D7, 0x58F7, + 0x89D8, 0x89DF, 0x58FA, + 0x89E1, 0x89E2, 0x5905, + 0x89E3, 0x89E7, 0x5908, + 0x89E9, 0x89EC, 0x5910, + 0x89ED, 0x89EE, 0x5917, + 0x89F0, 0x89F1, 0x591D, + 0x89F2, 0x89F5, 0x5920, + 0x89FA, 0x89FB, 0x5932, + 0x89FC, 0x89FD, 0x5935, + 0x8A40, 0x8A43, 0x593D, + 0x8A45, 0x8A46, 0x5945, + 0x8A48, 0x8A49, 0x594C, + 0x8A4B, 0x8A4C, 0x5952, + 0x8A4E, 0x8A52, 0x595B, + 0x8A54, 0x8A55, 0x5963, + 0x8A56, 0x8A62, 0x5966, + 0x8A65, 0x8A67, 0x597A, + 0x8A68, 0x8A6A, 0x597E, + 0x8A6D, 0x8A6E, 0x598B, + 0x8A6F, 0x8A72, 0x598E, + 0x8A73, 0x8A74, 0x5994, + 0x8A76, 0x8A79, 0x599A, + 0x8A7A, 0x8A7D, 0x599F, + 0x8A81, 0x8A82, 0x59AC, + 0x8A83, 0x8A84, 0x59B0, + 0x8A85, 0x8A8A, 0x59B3, + 0x8A8C, 0x8A8D, 0x59BC, + 0x8A8E, 0x8A94, 0x59BF, + 0x8A95, 0x8A97, 0x59C7, + 0x8A98, 0x8A9B, 0x59CC, + 0x8A9C, 0x8A9D, 0x59D5, + 0x8AA0, 0x8AA4, 0x59DE, + 0x8AA6, 0x8AA7, 0x59E6, + 0x8AA8, 0x8AAA, 0x59E9, + 0x8AAB, 0x8AB6, 0x59ED, + 0x8AB8, 0x8ABA, 0x59FC, + 0x8ABD, 0x8ABE, 0x5A0A, + 0x8ABF, 0x8AC2, 0x5A0D, + 0x8AC4, 0x8AC7, 0x5A14, + 0x8AC8, 0x8ACA, 0x5A19, + 0x8ACB, 0x8ACC, 0x5A1D, + 0x8ACD, 0x8ACE, 0x5A21, + 0x8AD0, 0x8AD2, 0x5A26, + 0x8AD3, 0x8AD9, 0x5A2A, + 0x8ADC, 0x8AE0, 0x5A37, + 0x8AE1, 0x8AE3, 0x5A3D, + 0x8AE4, 0x8AE8, 0x5A41, + 0x8AE9, 0x8AEA, 0x5A47, + 0x8AEB, 0x8AF4, 0x5A4B, + 0x8AF5, 0x8AF8, 0x5A56, + 0x8AF9, 0x8AFE, 0x5A5B, + 0x8B41, 0x8B44, 0x5A63, + 0x8B45, 0x8B46, 0x5A68, + 0x8B47, 0x8B4F, 0x5A6B, + 0x8B50, 0x8B51, 0x5A78, + 0x8B52, 0x8B55, 0x5A7B, + 0x8B56, 0x8B67, 0x5A80, + 0x8B68, 0x8B6E, 0x5A93, + 0x8B6F, 0x8B7C, 0x5A9C, + 0x8B7D, 0x8B7E, 0x5AAB, + 0x8B80, 0x8B84, 0x5AAD, + 0x8B86, 0x8B87, 0x5AB6, + 0x8B88, 0x8B8C, 0x5AB9, + 0x8B8D, 0x8B8E, 0x5ABF, + 0x8B8F, 0x8B94, 0x5AC3, + 0x8B95, 0x8B96, 0x5ACA, + 0x8B97, 0x8B9B, 0x5ACD, + 0x8B9F, 0x8BA1, 0x5AD9, + 0x8BA2, 0x8BA4, 0x5ADD, + 0x8BA6, 0x8BA7, 0x5AE4, + 0x8BA8, 0x8BA9, 0x5AE7, + 0x8BAB, 0x8BAF, 0x5AEC, + 0x8BB0, 0x8BC6, 0x5AF2, + 0x8BC7, 0x8BD2, 0x5B0A, + 0x8BD3, 0x8BEC, 0x5B18, + 0x8BEE, 0x8BEF, 0x5B35, + 0x8BF0, 0x8BF7, 0x5B38, + 0x8BF8, 0x8BFE, 0x5B41, + 0x8C40, 0x8C47, 0x5B48, + 0x8C4B, 0x8C4C, 0x5B60, + 0x8C4D, 0x8C4E, 0x5B67, + 0x8C50, 0x8C52, 0x5B6D, + 0x8C55, 0x8C58, 0x5B76, + 0x8C59, 0x8C5A, 0x5B7B, + 0x8C5B, 0x8C5C, 0x5B7E, + 0x8C60, 0x8C61, 0x5B8D, + 0x8C62, 0x8C64, 0x5B90, + 0x8C68, 0x8C6A, 0x5BA7, + 0x8C6B, 0x8C6E, 0x5BAC, + 0x8C6F, 0x8C70, 0x5BB1, + 0x8C72, 0x8C74, 0x5BBA, + 0x8C75, 0x8C76, 0x5BC0, + 0x8C78, 0x8C7B, 0x5BC8, + 0x8C7C, 0x8C7E, 0x5BCD, + 0x8C81, 0x8C89, 0x5BD4, + 0x8C8B, 0x8C8C, 0x5BE2, + 0x8C8D, 0x8C8E, 0x5BE6, + 0x8C8F, 0x8C93, 0x5BE9, + 0x8C95, 0x8C9B, 0x5BF1, + 0x8C9C, 0x8C9D, 0x5BFD, + 0x8C9F, 0x8CA0, 0x5C02, + 0x8CA2, 0x8CA3, 0x5C07, + 0x8CA4, 0x8CA7, 0x5C0B, + 0x8CA9, 0x8CAA, 0x5C12, + 0x8CAE, 0x8CB1, 0x5C1E, + 0x8CB4, 0x8CB7, 0x5C28, + 0x8CB8, 0x8CBB, 0x5C2D, + 0x8CBC, 0x8CBD, 0x5C32, + 0x8CBE, 0x8CC0, 0x5C35, + 0x8CC1, 0x8CC2, 0x5C43, + 0x8CC3, 0x8CC4, 0x5C46, + 0x8CC5, 0x8CC6, 0x5C4C, + 0x8CC7, 0x8CC9, 0x5C52, + 0x8CCA, 0x8CCC, 0x5C56, + 0x8CCD, 0x8CD0, 0x5C5A, + 0x8CD4, 0x8CDA, 0x5C67, + 0x8CDC, 0x8CE2, 0x5C72, + 0x8CE3, 0x8CE6, 0x5C7B, + 0x8CE8, 0x8CEC, 0x5C83, + 0x8CED, 0x8CEF, 0x5C89, + 0x8CF0, 0x8CF1, 0x5C8E, + 0x8CF2, 0x8CF3, 0x5C92, + 0x8CF5, 0x8CF9, 0x5C9D, + 0x8CFA, 0x8CFE, 0x5CA4, + 0x8D41, 0x8D43, 0x5CAE, + 0x8D47, 0x8D4A, 0x5CB9, + 0x8D4D, 0x8D4E, 0x5CC2, + 0x8D4F, 0x8D54, 0x5CC5, + 0x8D55, 0x8D5A, 0x5CCC, + 0x8D5B, 0x8D60, 0x5CD3, + 0x8D61, 0x8D67, 0x5CDA, + 0x8D68, 0x8D69, 0x5CE2, + 0x8D6C, 0x8D6D, 0x5CEB, + 0x8D6E, 0x8D6F, 0x5CEE, + 0x8D70, 0x8D79, 0x5CF1, + 0x8D7A, 0x8D7E, 0x5CFC, + 0x8D81, 0x8D82, 0x5D04, + 0x8D83, 0x8D88, 0x5D08, + 0x8D89, 0x8D8D, 0x5D0F, + 0x8D8F, 0x8D92, 0x5D17, + 0x8D93, 0x8D94, 0x5D1C, + 0x8D95, 0x8D99, 0x5D1F, + 0x8D9C, 0x8D9E, 0x5D2A, + 0x8D9F, 0x8DA3, 0x5D2F, + 0x8DA4, 0x8DAB, 0x5D35, + 0x8DAC, 0x8DB3, 0x5D3F, + 0x8DB4, 0x8DB5, 0x5D48, + 0x8DB6, 0x8DC0, 0x5D4D, + 0x8DC1, 0x8DC2, 0x5D59, + 0x8DC4, 0x8DCE, 0x5D5E, + 0x8DD0, 0x8DD1, 0x5D6D, + 0x8DD2, 0x8DD5, 0x5D70, + 0x8DD6, 0x8DE2, 0x5D75, + 0x8DE3, 0x8DF8, 0x5D83, + 0x8DF9, 0x8DFB, 0x5D9A, + 0x8DFC, 0x8DFE, 0x5D9E, + 0x8E40, 0x8E55, 0x5DA1, + 0x8E56, 0x8E62, 0x5DB8, + 0x8E63, 0x8E69, 0x5DC6, + 0x8E6A, 0x8E76, 0x5DCE, + 0x8E78, 0x8E79, 0x5DDF, + 0x8E7A, 0x8E7B, 0x5DE3, + 0x8E7D, 0x8E7E, 0x5DEC, + 0x8E81, 0x8E82, 0x5DF5, + 0x8E83, 0x8E87, 0x5DF8, + 0x8E88, 0x8E89, 0x5DFF, + 0x8E8C, 0x8E8E, 0x5E09, + 0x8E8F, 0x8E90, 0x5E0D, + 0x8E91, 0x8E92, 0x5E12, + 0x8E94, 0x8E9B, 0x5E1E, + 0x8E9C, 0x8EA0, 0x5E28, + 0x8EA1, 0x8EA2, 0x5E2F, + 0x8EA3, 0x8EA7, 0x5E32, + 0x8EA8, 0x8EA9, 0x5E39, + 0x8EAA, 0x8EAD, 0x5E3E, + 0x8EAF, 0x8EB4, 0x5E46, + 0x8EB5, 0x8EBB, 0x5E4D, + 0x8EBC, 0x8EC0, 0x5E56, + 0x8EC1, 0x8EC2, 0x5E5C, + 0x8EC3, 0x8EC4, 0x5E5F, + 0x8EC5, 0x8ED3, 0x5E63, + 0x8ED8, 0x8EDA, 0x5E81, + 0x8EDC, 0x8EDD, 0x5E88, + 0x8EDE, 0x8EE0, 0x5E8C, + 0x8EE5, 0x8EE8, 0x5EA1, + 0x8EE9, 0x8EED, 0x5EA8, + 0x8EEE, 0x8EF2, 0x5EAE, + 0x8EF4, 0x8EF7, 0x5EBA, + 0x8EF8, 0x8EFE, 0x5EBF, + 0x8F40, 0x8F42, 0x5EC6, + 0x8F43, 0x8F48, 0x5ECB, + 0x8F49, 0x8F4A, 0x5ED4, + 0x8F4B, 0x8F4E, 0x5ED7, + 0x8F4F, 0x8F5A, 0x5EDC, + 0x8F5C, 0x8F64, 0x5EEB, + 0x8F66, 0x8F67, 0x5EF8, + 0x8F68, 0x8F6A, 0x5EFB, + 0x8F6B, 0x8F6D, 0x5F05, + 0x8F6F, 0x8F71, 0x5F0C, + 0x8F76, 0x8F77, 0x5F19, + 0x8F78, 0x8F7A, 0x5F1C, + 0x8F7B, 0x8F7E, 0x5F21, + 0x8F81, 0x8F82, 0x5F2B, + 0x8F85, 0x8F8B, 0x5F32, + 0x8F8D, 0x8F8F, 0x5F3D, + 0x8F90, 0x8F9E, 0x5F41, + 0x8FA1, 0x8FA4, 0x5F59, + 0x8FA5, 0x8FA7, 0x5F5E, + 0x8FAA, 0x8FAB, 0x5F67, + 0x8FAD, 0x8FAE, 0x5F6E, + 0x8FB0, 0x8FB2, 0x5F74, + 0x8FB5, 0x8FB7, 0x5F7D, + 0x8FBA, 0x8FBC, 0x5F8D, + 0x8FBE, 0x8FBF, 0x5F93, + 0x8FC1, 0x8FC2, 0x5F9A, + 0x8FC3, 0x8FC6, 0x5F9D, + 0x8FC7, 0x8FCC, 0x5FA2, + 0x8FCE, 0x8FCF, 0x5FAB, + 0x8FD0, 0x8FD5, 0x5FAF, + 0x8FD7, 0x8FDA, 0x5FB8, + 0x8FDB, 0x8FDF, 0x5FBE, + 0x8FE0, 0x8FE1, 0x5FC7, + 0x8FE2, 0x8FE3, 0x5FCA, + 0x8FE5, 0x8FE7, 0x5FD3, + 0x8FE8, 0x8FEA, 0x5FDA, + 0x8FEB, 0x8FEC, 0x5FDE, + 0x8FED, 0x8FEE, 0x5FE2, + 0x8FEF, 0x8FF0, 0x5FE5, + 0x8FF1, 0x8FF2, 0x5FE8, + 0x8FF4, 0x8FF5, 0x5FEF, + 0x8FF6, 0x8FF8, 0x5FF2, + 0x8FF9, 0x8FFA, 0x5FF6, + 0x8FFB, 0x8FFC, 0x5FF9, + 0x9040, 0x9041, 0x6008, + 0x9042, 0x9043, 0x600B, + 0x9044, 0x9045, 0x6010, + 0x9047, 0x9048, 0x6017, + 0x904A, 0x904B, 0x601E, + 0x904C, 0x904E, 0x6022, + 0x904F, 0x9051, 0x602C, + 0x9052, 0x9056, 0x6030, + 0x9057, 0x905B, 0x6036, + 0x905C, 0x905D, 0x603D, + 0x905F, 0x9065, 0x6044, + 0x9067, 0x9068, 0x604E, + 0x906A, 0x906B, 0x6053, + 0x906C, 0x906E, 0x6056, + 0x906F, 0x9070, 0x605B, + 0x9071, 0x9074, 0x605E, + 0x9075, 0x9076, 0x6065, + 0x9078, 0x9079, 0x6071, + 0x907A, 0x907B, 0x6074, + 0x9080, 0x9081, 0x6081, + 0x9082, 0x9085, 0x6085, + 0x9086, 0x9087, 0x608A, + 0x9088, 0x908B, 0x608E, + 0x908E, 0x9090, 0x6097, + 0x9093, 0x9094, 0x60A1, + 0x9095, 0x9096, 0x60A4, + 0x9098, 0x9099, 0x60A9, + 0x909D, 0x909F, 0x60B5, + 0x90A0, 0x90A1, 0x60B9, + 0x90A2, 0x90A9, 0x60BD, + 0x90AA, 0x90AC, 0x60C7, + 0x90AD, 0x90B1, 0x60CC, + 0x90B2, 0x90B4, 0x60D2, + 0x90B5, 0x90B6, 0x60D6, + 0x90BA, 0x90BE, 0x60E1, + 0x90C0, 0x90C1, 0x60F1, + 0x90C3, 0x90C4, 0x60F7, + 0x90C5, 0x90C9, 0x60FB, + 0x90CA, 0x90CD, 0x6102, + 0x90CF, 0x90D1, 0x610A, + 0x90D2, 0x90D6, 0x6110, + 0x90D7, 0x90DA, 0x6116, + 0x90DB, 0x90DE, 0x611B, + 0x90DF, 0x90E0, 0x6121, + 0x90E2, 0x90E4, 0x6128, + 0x90E5, 0x90F7, 0x612C, + 0x90F8, 0x90FE, 0x6140, + 0x9144, 0x9145, 0x614F, + 0x9146, 0x9148, 0x6152, + 0x9149, 0x914F, 0x6156, + 0x9150, 0x9153, 0x615E, + 0x9154, 0x9157, 0x6163, + 0x9158, 0x915E, 0x6169, + 0x915F, 0x9162, 0x6171, + 0x9164, 0x9176, 0x6178, + 0x9177, 0x9178, 0x618C, + 0x9179, 0x917D, 0x618F, + 0x9180, 0x9186, 0x6196, + 0x9187, 0x918F, 0x619E, + 0x9190, 0x9191, 0x61AA, + 0x9192, 0x919B, 0x61AD, + 0x919C, 0x91A1, 0x61B8, + 0x91A2, 0x91A4, 0x61BF, + 0x91A5, 0x91A9, 0x61C3, + 0x91AB, 0x91AF, 0x61CC, + 0x91B1, 0x91C1, 0x61D5, + 0x91C2, 0x91CF, 0x61E7, + 0x91D0, 0x91D8, 0x61F6, + 0x91D9, 0x91DE, 0x6200, + 0x91E1, 0x91E2, 0x6213, + 0x91E4, 0x91E6, 0x621C, + 0x91E9, 0x91EC, 0x6226, + 0x91EF, 0x91F2, 0x622F, + 0x91F3, 0x91F4, 0x6235, + 0x91F5, 0x91F9, 0x6238, + 0x91FB, 0x91FD, 0x6244, + 0x9240, 0x9241, 0x624F, + 0x9242, 0x9244, 0x6255, + 0x9245, 0x9246, 0x6259, + 0x9247, 0x924D, 0x625C, + 0x924E, 0x924F, 0x6264, + 0x9251, 0x9252, 0x6271, + 0x9253, 0x9254, 0x6274, + 0x9255, 0x9256, 0x6277, + 0x9257, 0x9258, 0x627A, + 0x925A, 0x925C, 0x6281, + 0x925D, 0x9260, 0x6285, + 0x9261, 0x9266, 0x628B, + 0x9269, 0x926B, 0x629C, + 0x926D, 0x926E, 0x62A6, + 0x926F, 0x9270, 0x62A9, + 0x9271, 0x9274, 0x62AD, + 0x9275, 0x9277, 0x62B2, + 0x9278, 0x927A, 0x62B6, + 0x927D, 0x927E, 0x62C0, + 0x9285, 0x9286, 0x62DD, + 0x9287, 0x9288, 0x62E0, + 0x928A, 0x928B, 0x62EA, + 0x928F, 0x9292, 0x62F8, + 0x9294, 0x9297, 0x6303, + 0x9298, 0x929B, 0x630A, + 0x929C, 0x929D, 0x630F, + 0x929E, 0x92A1, 0x6312, + 0x92A2, 0x92A4, 0x6317, + 0x92A6, 0x92A7, 0x6326, + 0x92A9, 0x92AB, 0x632C, + 0x92AC, 0x92AD, 0x6330, + 0x92AE, 0x92B3, 0x6333, + 0x92B4, 0x92B5, 0x633B, + 0x92B6, 0x92B9, 0x633E, + 0x92BB, 0x92BC, 0x6347, + 0x92BE, 0x92C1, 0x6351, + 0x92C2, 0x92C9, 0x6356, + 0x92CB, 0x92CD, 0x6364, + 0x92CF, 0x92D1, 0x636A, + 0x92D2, 0x92D3, 0x636F, + 0x92D4, 0x92D7, 0x6372, + 0x92D8, 0x92D9, 0x6378, + 0x92DA, 0x92DD, 0x637C, + 0x92DF, 0x92E2, 0x6383, + 0x92E6, 0x92E8, 0x6393, + 0x92EA, 0x92F0, 0x6399, + 0x92F6, 0x92F7, 0x63B1, + 0x92F8, 0x92F9, 0x63B5, + 0x92FD, 0x92FE, 0x63BF, + 0x9340, 0x9342, 0x63C1, + 0x9344, 0x9345, 0x63C7, + 0x9346, 0x9348, 0x63CA, + 0x934A, 0x934C, 0x63D3, + 0x934D, 0x9353, 0x63D7, + 0x9356, 0x935A, 0x63E4, + 0x935B, 0x935C, 0x63EB, + 0x935D, 0x9360, 0x63EE, + 0x9364, 0x9367, 0x63F9, + 0x9369, 0x936A, 0x6403, + 0x936B, 0x936F, 0x6406, + 0x9370, 0x9371, 0x640D, + 0x9372, 0x9373, 0x6411, + 0x9374, 0x9379, 0x6415, + 0x937C, 0x937E, 0x6422, + 0x9381, 0x9383, 0x6427, + 0x9385, 0x938A, 0x642E, + 0x938B, 0x938F, 0x6435, + 0x9390, 0x9391, 0x643B, + 0x9394, 0x9395, 0x6442, + 0x9397, 0x939D, 0x644B, + 0x939F, 0x93A1, 0x6455, + 0x93A2, 0x93A6, 0x6459, + 0x93A7, 0x93AE, 0x645F, + 0x93B0, 0x93B2, 0x646A, + 0x93B3, 0x93BC, 0x646E, + 0x93BD, 0x93C3, 0x647B, + 0x93C6, 0x93CE, 0x6488, + 0x93CF, 0x93D0, 0x6493, + 0x93D1, 0x93D2, 0x6497, + 0x93D3, 0x93D6, 0x649A, + 0x93D7, 0x93DB, 0x649F, + 0x93DC, 0x93DF, 0x64A5, + 0x93E0, 0x93E1, 0x64AA, + 0x93E3, 0x93E6, 0x64B1, + 0x93EA, 0x93EC, 0x64BD, + 0x93EE, 0x93EF, 0x64C3, + 0x93F0, 0x93F6, 0x64C6, + 0x93F9, 0x93FC, 0x64D3, + 0x93FD, 0x93FE, 0x64D9, + 0x9440, 0x9442, 0x64DB, + 0x9443, 0x9445, 0x64DF, + 0x9448, 0x9460, 0x64E7, + 0x9461, 0x9468, 0x6501, + 0x9469, 0x9470, 0x650A, + 0x9471, 0x9475, 0x6513, + 0x9476, 0x947E, 0x6519, + 0x9480, 0x9482, 0x6522, + 0x9483, 0x9487, 0x6526, + 0x9488, 0x9489, 0x652C, + 0x948A, 0x948D, 0x6530, + 0x9490, 0x9491, 0x653C, + 0x9492, 0x9496, 0x6540, + 0x9497, 0x9498, 0x6546, + 0x9499, 0x949A, 0x654A, + 0x949B, 0x949C, 0x654D, + 0x949E, 0x94A0, 0x6552, + 0x94A1, 0x94A2, 0x6557, + 0x94A5, 0x94A7, 0x655F, + 0x94A8, 0x94A9, 0x6564, + 0x94AA, 0x94AD, 0x6567, + 0x94AE, 0x94B0, 0x656D, + 0x94B3, 0x94B4, 0x6575, + 0x94B5, 0x94C3, 0x6578, + 0x94C4, 0x94C6, 0x6588, + 0x94C7, 0x94C9, 0x658D, + 0x94CB, 0x94CD, 0x6594, + 0x94D0, 0x94D1, 0x659D, + 0x94D3, 0x94D4, 0x65A2, + 0x94DA, 0x94E1, 0x65B1, + 0x94E2, 0x94E3, 0x65BA, + 0x94E4, 0x94E6, 0x65BE, + 0x94E8, 0x94EB, 0x65C7, + 0x94ED, 0x94EE, 0x65D0, + 0x94EF, 0x94F1, 0x65D3, + 0x94F2, 0x94F9, 0x65D8, + 0x94FB, 0x94FC, 0x65E3, + 0x94FD, 0x94FE, 0x65EA, + 0x9540, 0x9543, 0x65F2, + 0x9544, 0x9545, 0x65F8, + 0x9546, 0x954A, 0x65FB, + 0x954C, 0x954D, 0x6604, + 0x954E, 0x9550, 0x6607, + 0x9553, 0x9555, 0x6610, + 0x9556, 0x9558, 0x6616, + 0x9559, 0x955B, 0x661A, + 0x955D, 0x9560, 0x6621, + 0x9562, 0x9565, 0x6629, + 0x9568, 0x9569, 0x6632, + 0x956A, 0x956E, 0x6637, + 0x9570, 0x9571, 0x663F, + 0x9573, 0x9579, 0x6644, + 0x957A, 0x957B, 0x664D, + 0x957C, 0x957D, 0x6650, + 0x9581, 0x9584, 0x665B, + 0x9586, 0x9587, 0x6662, + 0x958A, 0x958E, 0x6669, + 0x958F, 0x9591, 0x6671, + 0x9593, 0x9594, 0x6678, + 0x9595, 0x9597, 0x667B, + 0x9598, 0x959A, 0x667F, + 0x959C, 0x959D, 0x6685, + 0x959E, 0x95A1, 0x6688, + 0x95A2, 0x95A5, 0x668D, + 0x95A6, 0x95A9, 0x6692, + 0x95AA, 0x95AE, 0x6698, + 0x95AF, 0x95B7, 0x669E, + 0x95B8, 0x95BC, 0x66A9, + 0x95BD, 0x95C1, 0x66AF, + 0x95C2, 0x95C5, 0x66B5, + 0x95C6, 0x95C9, 0x66BA, + 0x95CA, 0x95E3, 0x66BF, + 0x95E5, 0x95EC, 0x66DE, + 0x95ED, 0x95EE, 0x66E7, + 0x95EF, 0x95F4, 0x66EA, + 0x95F6, 0x95F7, 0x66F5, + 0x95F9, 0x95FA, 0x66FA, + 0x95FC, 0x95FE, 0x6701, + 0x9640, 0x9643, 0x6704, + 0x9645, 0x9646, 0x670E, + 0x9647, 0x9649, 0x6711, + 0x964B, 0x964D, 0x6718, + 0x9650, 0x9655, 0x6720, + 0x965A, 0x965B, 0x6732, + 0x965C, 0x965F, 0x6736, + 0x9660, 0x9661, 0x673B, + 0x9662, 0x9663, 0x673E, + 0x9665, 0x9666, 0x6744, + 0x9668, 0x9669, 0x674A, + 0x966C, 0x966D, 0x6754, + 0x966E, 0x9672, 0x6757, + 0x9674, 0x9676, 0x6762, + 0x9677, 0x9678, 0x6766, + 0x9679, 0x967A, 0x676B, + 0x9680, 0x9683, 0x6778, + 0x9686, 0x9687, 0x6782, + 0x9688, 0x9689, 0x6785, + 0x968C, 0x968F, 0x678C, + 0x9690, 0x9693, 0x6791, + 0x9697, 0x9699, 0x679F, + 0x969F, 0x96A0, 0x67B1, + 0x96A2, 0x96A9, 0x67B9, + 0x96AB, 0x96B4, 0x67C5, + 0x96B5, 0x96B7, 0x67D5, + 0x96BB, 0x96BC, 0x67E3, + 0x96BD, 0x96BF, 0x67E6, + 0x96C0, 0x96C1, 0x67EA, + 0x96C2, 0x96C3, 0x67ED, + 0x96C5, 0x96CC, 0x67F5, + 0x96CE, 0x96D1, 0x6801, + 0x96D6, 0x96D7, 0x6814, + 0x96D8, 0x96DC, 0x6818, + 0x96DD, 0x96DF, 0x681E, + 0x96E0, 0x96E6, 0x6822, + 0x96E7, 0x96ED, 0x682B, + 0x96EE, 0x96F0, 0x6834, + 0x96F1, 0x96F2, 0x683A, + 0x96F9, 0x96FE, 0x6856, + 0x9740, 0x9743, 0x685C, + 0x9745, 0x974C, 0x686C, + 0x974E, 0x9756, 0x6878, + 0x9759, 0x9760, 0x6887, + 0x9761, 0x9763, 0x6890, + 0x9764, 0x9766, 0x6894, + 0x9767, 0x9770, 0x6898, + 0x9771, 0x9773, 0x68A3, + 0x9774, 0x9777, 0x68A9, + 0x9779, 0x977A, 0x68B1, + 0x977C, 0x977E, 0x68B6, + 0x9780, 0x9786, 0x68B9, + 0x9788, 0x978D, 0x68C3, + 0x9790, 0x9793, 0x68CE, + 0x9794, 0x9795, 0x68D3, + 0x9796, 0x9797, 0x68D6, + 0x9799, 0x979D, 0x68DB, + 0x979E, 0x979F, 0x68E1, + 0x97A0, 0x97A9, 0x68E4, + 0x97AB, 0x97AD, 0x68F2, + 0x97AE, 0x97B0, 0x68F6, + 0x97B2, 0x97B5, 0x68FD, + 0x97B6, 0x97B8, 0x6902, + 0x97B9, 0x97BD, 0x6906, + 0x97C1, 0x97CC, 0x6913, + 0x97CD, 0x97CF, 0x6921, + 0x97D0, 0x97D7, 0x6925, + 0x97D8, 0x97D9, 0x692E, + 0x97DA, 0x97DC, 0x6931, + 0x97DD, 0x97E0, 0x6935, + 0x97E1, 0x97E3, 0x693A, + 0x97E5, 0x97E6, 0x6940, + 0x97E7, 0x97F7, 0x6943, + 0x97F8, 0x97F9, 0x6955, + 0x97FA, 0x97FB, 0x6958, + 0x97FC, 0x97FD, 0x695B, + 0x9840, 0x9841, 0x6961, + 0x9842, 0x9843, 0x6964, + 0x9844, 0x9847, 0x6967, + 0x9848, 0x9849, 0x696C, + 0x984A, 0x984B, 0x696F, + 0x984C, 0x9850, 0x6972, + 0x9851, 0x9852, 0x697A, + 0x9853, 0x9855, 0x697D, + 0x9859, 0x985B, 0x698A, + 0x985C, 0x9861, 0x698E, + 0x9862, 0x9863, 0x6996, + 0x9864, 0x9865, 0x6999, + 0x9866, 0x986F, 0x699D, + 0x9870, 0x9871, 0x69A9, + 0x9873, 0x9875, 0x69AE, + 0x9876, 0x9877, 0x69B2, + 0x9878, 0x9879, 0x69B5, + 0x987A, 0x987C, 0x69B8, + 0x987D, 0x987E, 0x69BC, + 0x9880, 0x9882, 0x69BE, + 0x9883, 0x988A, 0x69C2, + 0x988E, 0x9890, 0x69D1, + 0x9891, 0x9896, 0x69D5, + 0x9897, 0x9899, 0x69DC, + 0x989A, 0x98A5, 0x69E1, + 0x98A6, 0x98A9, 0x69EE, + 0x98AA, 0x98B3, 0x69F3, + 0x98B5, 0x98BE, 0x6A00, + 0x98BF, 0x98CA, 0x6A0B, + 0x98CB, 0x98D0, 0x6A19, + 0x98D2, 0x98D7, 0x6A22, + 0x98D9, 0x98DC, 0x6A2B, + 0x98DE, 0x98E0, 0x6A32, + 0x98E1, 0x98E7, 0x6A36, + 0x98E8, 0x98EC, 0x6A3F, + 0x98ED, 0x98EE, 0x6A45, + 0x98EF, 0x98F6, 0x6A48, + 0x98F7, 0x98FD, 0x6A51, + 0x9940, 0x9944, 0x6A5C, + 0x9945, 0x9947, 0x6A62, + 0x9948, 0x9952, 0x6A66, + 0x9953, 0x9959, 0x6A72, + 0x995A, 0x995B, 0x6A7A, + 0x995C, 0x995E, 0x6A7D, + 0x995F, 0x9961, 0x6A81, + 0x9962, 0x996A, 0x6A85, + 0x996C, 0x9970, 0x6A92, + 0x9971, 0x9978, 0x6A98, + 0x9979, 0x997E, 0x6AA1, + 0x9980, 0x9981, 0x6AA7, + 0x9983, 0x99F5, 0x6AAD, + 0x99F6, 0x99F7, 0x6B25, + 0x99F8, 0x99FE, 0x6B28, + 0x9A40, 0x9A42, 0x6B2F, + 0x9A43, 0x9A46, 0x6B33, + 0x9A48, 0x9A4A, 0x6B3B, + 0x9A4B, 0x9A4E, 0x6B3F, + 0x9A4F, 0x9A50, 0x6B44, + 0x9A52, 0x9A53, 0x6B4A, + 0x9A54, 0x9A5F, 0x6B4D, + 0x9A60, 0x9A67, 0x6B5A, + 0x9A68, 0x9A69, 0x6B68, + 0x9A6A, 0x9A77, 0x6B6B, + 0x9A79, 0x9A7C, 0x6B7D, + 0x9A81, 0x9A84, 0x6B8E, + 0x9A85, 0x9A86, 0x6B94, + 0x9A87, 0x9A89, 0x6B97, + 0x9A8A, 0x9A8E, 0x6B9C, + 0x9A8F, 0x9A96, 0x6BA2, + 0x9A97, 0x9A9E, 0x6BAB, + 0x9AA0, 0x9AA6, 0x6BB8, + 0x9AA8, 0x9AA9, 0x6BC3, + 0x9AAA, 0x9AAE, 0x6BC6, + 0x9AB1, 0x9AB2, 0x6BD0, + 0x9AB5, 0x9AB9, 0x6BDC, + 0x9ABA, 0x9AC1, 0x6BE2, + 0x9AC2, 0x9AC4, 0x6BEC, + 0x9AC5, 0x9AC7, 0x6BF0, + 0x9AC9, 0x9ACB, 0x6BF6, + 0x9ACC, 0x9ACE, 0x6BFA, + 0x9ACF, 0x9AD5, 0x6BFE, + 0x9AD6, 0x9ADA, 0x6C08, + 0x9ADE, 0x9AE0, 0x6C1C, + 0x9AE4, 0x9AE6, 0x6C2B, + 0x9AE9, 0x9AEA, 0x6C36, + 0x9AEB, 0x9AEE, 0x6C39, + 0x9AEF, 0x9AF0, 0x6C3E, + 0x9AF1, 0x9AF3, 0x6C43, + 0x9AF5, 0x9AF9, 0x6C4B, + 0x9AFA, 0x9AFC, 0x6C51, + 0x9B40, 0x9B41, 0x6C59, + 0x9B42, 0x9B43, 0x6C62, + 0x9B44, 0x9B46, 0x6C65, + 0x9B47, 0x9B4B, 0x6C6B, + 0x9B4F, 0x9B50, 0x6C77, + 0x9B51, 0x9B53, 0x6C7A, + 0x9B54, 0x9B55, 0x6C7F, + 0x9B58, 0x9B59, 0x6C8A, + 0x9B5A, 0x9B5B, 0x6C8D, + 0x9B5C, 0x9B5D, 0x6C91, + 0x9B5E, 0x9B61, 0x6C95, + 0x9B63, 0x9B65, 0x6C9C, + 0x9B6A, 0x9B6B, 0x6CAF, + 0x9B6C, 0x9B6F, 0x6CB4, + 0x9B71, 0x9B74, 0x6CC0, + 0x9B75, 0x9B77, 0x6CC6, + 0x9B79, 0x9B7B, 0x6CCD, + 0x9B7C, 0x9B7D, 0x6CD1, + 0x9B80, 0x9B81, 0x6CD9, + 0x9B82, 0x9B83, 0x6CDC, + 0x9B86, 0x9B87, 0x6CE6, + 0x9B89, 0x9B8A, 0x6CEC, + 0x9B8E, 0x9B8F, 0x6CFF, + 0x9B90, 0x9B91, 0x6D02, + 0x9B92, 0x9B93, 0x6D05, + 0x9B94, 0x9B96, 0x6D08, + 0x9B98, 0x9B9A, 0x6D0F, + 0x9B9B, 0x9B9E, 0x6D13, + 0x9BA0, 0x9BA1, 0x6D1C, + 0x9BA2, 0x9BA7, 0x6D1F, + 0x9BA9, 0x9BAA, 0x6D28, + 0x9BAB, 0x9BAC, 0x6D2C, + 0x9BAD, 0x9BAE, 0x6D2F, + 0x9BB0, 0x9BB2, 0x6D36, + 0x9BB4, 0x9BB5, 0x6D3F, + 0x9BBB, 0x9BBE, 0x6D55, + 0x9BC2, 0x9BC3, 0x6D61, + 0x9BC4, 0x9BC5, 0x6D64, + 0x9BC6, 0x9BC7, 0x6D67, + 0x9BC8, 0x9BCA, 0x6D6B, + 0x9BCB, 0x9BCE, 0x6D70, + 0x9BCF, 0x9BD0, 0x6D75, + 0x9BD1, 0x9BD3, 0x6D79, + 0x9BD4, 0x9BD8, 0x6D7D, + 0x9BD9, 0x9BDA, 0x6D83, + 0x9BDB, 0x9BDC, 0x6D86, + 0x9BDD, 0x9BDE, 0x6D8A, + 0x9BE0, 0x9BE1, 0x6D8F, + 0x9BE3, 0x9BE7, 0x6D96, + 0x9BEB, 0x9BEC, 0x6DAC, + 0x9BED, 0x9BEE, 0x6DB0, + 0x9BEF, 0x9BF0, 0x6DB3, + 0x9BF1, 0x9BF2, 0x6DB6, + 0x9BF3, 0x9BF8, 0x6DB9, + 0x9BF9, 0x9BFB, 0x6DC1, + 0x9BFC, 0x9BFE, 0x6DC8, + 0x9C40, 0x9C43, 0x6DCD, + 0x9C44, 0x9C47, 0x6DD2, + 0x9C49, 0x9C4B, 0x6DDA, + 0x9C4D, 0x9C4E, 0x6DE2, + 0x9C50, 0x9C53, 0x6DE7, + 0x9C55, 0x9C56, 0x6DEF, + 0x9C58, 0x9C5A, 0x6DF4, + 0x9C5D, 0x9C64, 0x6DFD, + 0x9C65, 0x9C68, 0x6E06, + 0x9C6B, 0x9C6C, 0x6E12, + 0x9C6E, 0x9C6F, 0x6E18, + 0x9C70, 0x9C71, 0x6E1B, + 0x9C72, 0x9C73, 0x6E1E, + 0x9C75, 0x9C77, 0x6E26, + 0x9C7B, 0x9C7C, 0x6E30, + 0x9C80, 0x9C81, 0x6E36, + 0x9C83, 0x9C8A, 0x6E3B, + 0x9C8B, 0x9C92, 0x6E45, + 0x9C93, 0x9C96, 0x6E4F, + 0x9C99, 0x9C9A, 0x6E59, + 0x9C9B, 0x9C9D, 0x6E5C, + 0x9C9E, 0x9CA8, 0x6E60, + 0x9CA9, 0x9CAA, 0x6E6C, + 0x9CAB, 0x9CB9, 0x6E6F, + 0x9CBA, 0x9CBC, 0x6E80, + 0x9CBE, 0x9CBF, 0x6E87, + 0x9CC0, 0x9CC4, 0x6E8A, + 0x9CC5, 0x9CCB, 0x6E91, + 0x9CCC, 0x9CCE, 0x6E99, + 0x9CCF, 0x9CD0, 0x6E9D, + 0x9CD1, 0x9CD2, 0x6EA0, + 0x9CD3, 0x9CD4, 0x6EA3, + 0x9CD6, 0x9CD7, 0x6EA8, + 0x9CD8, 0x9CDB, 0x6EAB, + 0x9CDF, 0x9CE0, 0x6EB8, + 0x9CE2, 0x9CE4, 0x6EBE, + 0x9CE5, 0x9CE8, 0x6EC3, + 0x9CE9, 0x9CEB, 0x6EC8, + 0x9CEC, 0x9CEE, 0x6ECC, + 0x9CF2, 0x9CF3, 0x6ED8, + 0x9CF4, 0x9CF6, 0x6EDB, + 0x9CF9, 0x9CFE, 0x6EEA, + 0x9D40, 0x9D43, 0x6EF0, + 0x9D44, 0x9D47, 0x6EF5, + 0x9D48, 0x9D4F, 0x6EFA, + 0x9D50, 0x9D52, 0x6F03, + 0x9D53, 0x9D54, 0x6F07, + 0x9D55, 0x9D59, 0x6F0A, + 0x9D5A, 0x9D5C, 0x6F10, + 0x9D5D, 0x9D66, 0x6F16, + 0x9D67, 0x9D69, 0x6F21, + 0x9D6A, 0x9D6D, 0x6F25, + 0x9D72, 0x9D73, 0x6F34, + 0x9D74, 0x9D7A, 0x6F37, + 0x9D7B, 0x9D7E, 0x6F3F, + 0x9D80, 0x9D82, 0x6F43, + 0x9D83, 0x9D85, 0x6F48, + 0x9D87, 0x9D90, 0x6F4E, + 0x9D91, 0x9D93, 0x6F59, + 0x9D95, 0x9D97, 0x6F5F, + 0x9D98, 0x9D9A, 0x6F63, + 0x9D9B, 0x9DA0, 0x6F67, + 0x9DA1, 0x9DA3, 0x6F6F, + 0x9DA5, 0x9DA7, 0x6F75, + 0x9DAA, 0x9DB0, 0x6F7D, + 0x9DB1, 0x9DB3, 0x6F85, + 0x9DB4, 0x9DB5, 0x6F8A, + 0x9DB6, 0x9DC2, 0x6F8F, + 0x9DC3, 0x9DC6, 0x6F9D, + 0x9DC7, 0x9DCB, 0x6FA2, + 0x9DCC, 0x9DD6, 0x6FA8, + 0x9DD7, 0x9DD8, 0x6FB4, + 0x9DD9, 0x9DDA, 0x6FB7, + 0x9DDB, 0x9DE0, 0x6FBA, + 0x9DE2, 0x9DE7, 0x6FC3, + 0x9DE8, 0x9DEE, 0x6FCA, + 0x9DEF, 0x9DF9, 0x6FD3, + 0x9DFB, 0x9DFE, 0x6FE2, + 0x9E40, 0x9E47, 0x6FE6, + 0x9E48, 0x9E68, 0x6FF0, + 0x9E69, 0x9E70, 0x7012, + 0x9E71, 0x9E77, 0x701C, + 0x9E78, 0x9E7E, 0x7024, + 0x9E80, 0x9E89, 0x702B, + 0x9E8A, 0x9E8C, 0x7036, + 0x9E8D, 0x9E9E, 0x703A, + 0x9E9F, 0x9EA0, 0x704D, + 0x9EA1, 0x9EAE, 0x7050, + 0x9EAF, 0x9EBA, 0x705F, + 0x9EBC, 0x9EBF, 0x7071, + 0x9EC1, 0x9EC3, 0x7079, + 0x9EC5, 0x9EC8, 0x7081, + 0x9EC9, 0x9ECB, 0x7086, + 0x9ECC, 0x9ECE, 0x708B, + 0x9ECF, 0x9ED1, 0x708F, + 0x9ED3, 0x9ED4, 0x7097, + 0x9ED5, 0x9ED6, 0x709A, + 0x9ED7, 0x9EE3, 0x709E, + 0x9EE6, 0x9EE8, 0x70B4, + 0x9EEA, 0x9EEB, 0x70BE, + 0x9EEC, 0x9EEF, 0x70C4, + 0x9EF1, 0x9EFD, 0x70CB, + 0x9F40, 0x9F42, 0x70DC, + 0x9F43, 0x9F46, 0x70E0, + 0x9F4A, 0x9F50, 0x70F0, + 0x9F52, 0x9F54, 0x70FA, + 0x9F55, 0x9F5F, 0x70FE, + 0x9F60, 0x9F64, 0x710B, + 0x9F65, 0x9F66, 0x7111, + 0x9F69, 0x9F73, 0x711B, + 0x9F74, 0x9F7B, 0x7127, + 0x9F7C, 0x9F7E, 0x7132, + 0x9F81, 0x9F8E, 0x7137, + 0x9F8F, 0x9F92, 0x7146, + 0x9F95, 0x9FA1, 0x714F, + 0x9FA3, 0x9FA7, 0x715F, + 0x9FA9, 0x9FAD, 0x7169, + 0x9FAE, 0x9FB0, 0x716F, + 0x9FB1, 0x9FB4, 0x7174, + 0x9FB6, 0x9FB7, 0x717B, + 0x9FB8, 0x9FBD, 0x717E, + 0x9FBE, 0x9FC2, 0x7185, + 0x9FC3, 0x9FC6, 0x718B, + 0x9FC7, 0x9FCA, 0x7190, + 0x9FCB, 0x9FCD, 0x7195, + 0x9FCE, 0x9FD2, 0x719A, + 0x9FD3, 0x9FD9, 0x71A1, + 0x9FDA, 0x9FDC, 0x71A9, + 0x9FDD, 0x9FE2, 0x71AD, + 0x9FE4, 0x9FE6, 0x71B6, + 0x9FE7, 0x9FEF, 0x71BA, + 0x9FF0, 0x9FF9, 0x71C4, + 0x9FFA, 0x9FFE, 0x71CF, + 0xA040, 0xA049, 0x71D6, + 0xA04A, 0xA04D, 0x71E1, + 0xA04F, 0xA054, 0x71E8, + 0xA055, 0xA05E, 0x71EF, + 0xA05F, 0xA06A, 0x71FA, + 0xA06B, 0xA07E, 0x7207, + 0xA080, 0xA081, 0x721B, + 0xA082, 0xA08B, 0x721E, + 0xA08E, 0xA090, 0x722D, + 0xA091, 0xA093, 0x7232, + 0xA097, 0xA09D, 0x7240, + 0xA09E, 0xA0A0, 0x7249, + 0xA0A1, 0xA0A4, 0x724E, + 0xA0A5, 0xA0A7, 0x7253, + 0xA0A8, 0xA0A9, 0x7257, + 0xA0AE, 0xA0B0, 0x7263, + 0xA0B2, 0xA0B5, 0x726A, + 0xA0B6, 0xA0B7, 0x7270, + 0xA0B8, 0xA0B9, 0x7273, + 0xA0BA, 0xA0BC, 0x7276, + 0xA0BD, 0xA0BF, 0x727B, + 0xA0C0, 0xA0C1, 0x7282, + 0xA0C2, 0xA0C6, 0x7285, + 0xA0C9, 0xA0CA, 0x7290, + 0xA0CB, 0xA0D6, 0x7293, + 0xA0D7, 0xA0E2, 0x72A0, + 0xA0E4, 0xA0E6, 0x72B1, + 0xA0E8, 0xA0EE, 0x72BA, + 0xA0EF, 0xA0F1, 0x72C5, + 0xA0F2, 0xA0F5, 0x72C9, + 0xA0F8, 0xA0FB, 0x72D3, + 0xA0FD, 0xA0FE, 0x72DA, + 0xA1A1, 0xA1A3, 0x3000, + 0xA1AE, 0xA1AF, 0x2018, + 0xA1B0, 0xA1B1, 0x201C, + 0xA1B2, 0xA1B3, 0x3014, + 0xA1B4, 0xA1BB, 0x3008, + 0xA1BC, 0xA1BD, 0x3016, + 0xA1BE, 0xA1BF, 0x3010, + 0xA1C4, 0xA1C5, 0x2227, + 0xA1DA, 0xA1DB, 0x226E, + 0xA1DC, 0xA1DD, 0x2264, + 0xA1E4, 0xA1E5, 0x2032, + 0xA1E9, 0xA1EA, 0xFFE0, + 0xA1FB, 0xA1FC, 0x2190, + 0xA2A1, 0xA2AA, 0x2170, + 0xA2B1, 0xA2C4, 0x2488, + 0xA2C5, 0xA2D8, 0x2474, + 0xA2D9, 0xA2E2, 0x2460, + 0xA2E5, 0xA2EE, 0x3220, + 0xA2F1, 0xA2FC, 0x2160, + 0xA3A1, 0xA3A3, 0xFF01, + 0xA3A5, 0xA3FD, 0xFF05, + 0xA4A1, 0xA4F3, 0x3041, + 0xA5A1, 0xA5F6, 0x30A1, + 0xA6A1, 0xA6B1, 0x0391, + 0xA6B2, 0xA6B8, 0x03A3, + 0xA6C1, 0xA6D1, 0x03B1, + 0xA6D2, 0xA6D8, 0x03C3, + 0xA6E0, 0xA6E1, 0xFE35, + 0xA6E2, 0xA6E3, 0xFE39, + 0xA6E4, 0xA6E5, 0xFE3F, + 0xA6E6, 0xA6E7, 0xFE3D, + 0xA6E8, 0xA6EB, 0xFE41, + 0xA6EE, 0xA6EF, 0xFE3B, + 0xA6F0, 0xA6F1, 0xFE37, + 0xA6F4, 0xA6F5, 0xFE33, + 0xA7A1, 0xA7A6, 0x0410, + 0xA7A8, 0xA7C1, 0x0416, + 0xA7D1, 0xA7D6, 0x0430, + 0xA7D8, 0xA7F1, 0x0436, + 0xA840, 0xA841, 0x02CA, + 0xA849, 0xA84C, 0x2196, + 0xA851, 0xA852, 0x2266, + 0xA854, 0xA877, 0x2550, + 0xA878, 0xA87E, 0x2581, + 0xA880, 0xA887, 0x2588, + 0xA888, 0xA88A, 0x2593, + 0xA88B, 0xA88C, 0x25BC, + 0xA88D, 0xA890, 0x25E2, + 0xA894, 0xA895, 0x301D, + 0xA8C5, 0xA8E9, 0x3105, + 0xA940, 0xA948, 0x3021, + 0xA94A, 0xA94B, 0x338E, + 0xA94C, 0xA94E, 0x339C, + 0xA952, 0xA953, 0x33D1, + 0xA961, 0xA962, 0x309B, + 0xA963, 0xA964, 0x30FD, + 0xA966, 0xA967, 0x309D, + 0xA968, 0xA971, 0xFE49, + 0xA972, 0xA975, 0xFE54, + 0xA976, 0xA97E, 0xFE59, + 0xA980, 0xA984, 0xFE62, + 0xA985, 0xA988, 0xFE68, + 0xA9A4, 0xA9EF, 0x2500, + 0xAA40, 0xAA41, 0x72DC, + 0xAA43, 0xAA48, 0x72E2, + 0xAA49, 0xAA4A, 0x72EA, + 0xAA4B, 0xAA4C, 0x72F5, + 0xAA4E, 0xAA51, 0x72FD, + 0xAA53, 0xAA58, 0x7304, + 0xAA59, 0xAA5B, 0x730B, + 0xAA5C, 0xAA5F, 0x730F, + 0xAA61, 0xAA63, 0x7318, + 0xAA64, 0xAA65, 0x731F, + 0xAA66, 0xAA67, 0x7323, + 0xAA68, 0xAA6A, 0x7326, + 0xAA6C, 0xAA6D, 0x732F, + 0xAA6E, 0xAA6F, 0x7332, + 0xAA70, 0xAA71, 0x7335, + 0xAA72, 0xAA75, 0x733A, + 0xAA76, 0xAA7E, 0x7340, + 0xAA80, 0xAA83, 0x7349, + 0xAA84, 0xAA85, 0x734E, + 0xAA87, 0xAA8A, 0x7353, + 0xAA8B, 0xAA92, 0x7358, + 0xAA93, 0xAA9D, 0x7361, + 0xAA9F, 0xAAA0, 0x7370, + 0xAB40, 0xAB4B, 0x7372, + 0xAB4C, 0xAB50, 0x737F, + 0xAB51, 0xAB52, 0x7385, + 0xAB55, 0xAB56, 0x738C, + 0xAB57, 0xAB58, 0x738F, + 0xAB59, 0xAB5C, 0x7392, + 0xAB5D, 0xAB60, 0x7397, + 0xAB61, 0xAB63, 0x739C, + 0xAB64, 0xAB65, 0x73A0, + 0xAB66, 0xAB6B, 0x73A3, + 0xAB6D, 0xAB6E, 0x73AC, + 0xAB70, 0xAB72, 0x73B4, + 0xAB73, 0xAB74, 0x73B8, + 0xAB75, 0xAB78, 0x73BC, + 0xAB7A, 0xAB7E, 0x73C3, + 0xAB80, 0xAB81, 0x73CB, + 0xAB83, 0xAB89, 0x73D2, + 0xAB8A, 0xAB8D, 0x73DA, + 0xAB8F, 0xAB92, 0x73E1, + 0xAB95, 0xAB97, 0x73EA, + 0xAB98, 0xAB9B, 0x73EE, + 0xAB9C, 0xABA0, 0x73F3, + 0xAC40, 0xAC4A, 0x73F8, + 0xAC4C, 0xAC4D, 0x7407, + 0xAC4E, 0xAC51, 0x740B, + 0xAC52, 0xAC5A, 0x7411, + 0xAC5B, 0xAC60, 0x741C, + 0xAC61, 0xAC62, 0x7423, + 0xAC68, 0xAC69, 0x7431, + 0xAC6A, 0xAC6E, 0x7437, + 0xAC6F, 0xAC72, 0x743D, + 0xAC73, 0xAC7E, 0x7442, + 0xAC80, 0xAC86, 0x744E, + 0xAC8A, 0xAC96, 0x7460, + 0xAC97, 0xAC98, 0x746E, + 0xAC99, 0xAC9D, 0x7471, + 0xAC9E, 0xACA0, 0x7478, + 0xAD40, 0xAD42, 0x747B, + 0xAD45, 0xAD47, 0x7484, + 0xAD48, 0xAD4A, 0x7488, + 0xAD4B, 0xAD4C, 0x748C, + 0xAD4E, 0xAD58, 0x7491, + 0xAD5A, 0xAD61, 0x749F, + 0xAD62, 0xAD71, 0x74AA, + 0xAD72, 0xAD7E, 0x74BB, + 0xAD80, 0xAD89, 0x74C8, + 0xAD8A, 0xAD92, 0x74D3, + 0xAD97, 0xAD9D, 0x74E7, + 0xAD9E, 0xADA0, 0x74F0, + 0xAE42, 0xAE48, 0x74F8, + 0xAE49, 0xAE4C, 0x7500, + 0xAE4D, 0xAE54, 0x7505, + 0xAE58, 0xAE5B, 0x7514, + 0xAE5D, 0xAE5E, 0x751D, + 0xAE5F, 0xAE63, 0x7520, + 0xAE64, 0xAE65, 0x7526, + 0xAE6B, 0xAE6C, 0x753C, + 0xAE6E, 0xAE71, 0x7541, + 0xAE72, 0xAE73, 0x7546, + 0xAE74, 0xAE75, 0x7549, + 0xAE77, 0xAE7A, 0x7550, + 0xAE7B, 0xAE7E, 0x7555, + 0xAE80, 0xAE87, 0x755D, + 0xAE88, 0xAE8A, 0x7567, + 0xAE8B, 0xAE91, 0x756B, + 0xAE93, 0xAE95, 0x7575, + 0xAE96, 0xAE9A, 0x757A, + 0xAE9B, 0xAE9D, 0x7580, + 0xAE9E, 0xAE9F, 0x7584, + 0xAF40, 0xAF42, 0x7588, + 0xAF43, 0xAF45, 0x758C, + 0xAF4A, 0xAF4B, 0x759B, + 0xAF4E, 0xAF52, 0x75A6, + 0xAF54, 0xAF55, 0x75B6, + 0xAF56, 0xAF57, 0x75BA, + 0xAF58, 0xAF5A, 0x75BF, + 0xAF5C, 0xAF5D, 0x75CB, + 0xAF5E, 0xAF61, 0x75CE, + 0xAF64, 0xAF65, 0x75D9, + 0xAF66, 0xAF67, 0x75DC, + 0xAF68, 0xAF6A, 0x75DF, + 0xAF6D, 0xAF70, 0x75EC, + 0xAF71, 0xAF72, 0x75F2, + 0xAF73, 0xAF76, 0x75F5, + 0xAF77, 0xAF78, 0x75FA, + 0xAF79, 0xAF7A, 0x75FD, + 0xAF7D, 0xAF7E, 0x7606, + 0xAF80, 0xAF81, 0x7608, + 0xAF83, 0xAF85, 0x760D, + 0xAF86, 0xAF89, 0x7611, + 0xAF8C, 0xAF8E, 0x761C, + 0xAF91, 0xAF92, 0x7627, + 0xAF94, 0xAF95, 0x762E, + 0xAF96, 0xAF97, 0x7631, + 0xAF98, 0xAF99, 0x7636, + 0xAF9A, 0xAF9C, 0x7639, + 0xAF9E, 0xAF9F, 0x7641, + 0xB040, 0xB046, 0x7645, + 0xB047, 0xB04C, 0x764E, + 0xB04E, 0xB052, 0x7657, + 0xB054, 0xB057, 0x765F, + 0xB058, 0xB05E, 0x7664, + 0xB05F, 0xB061, 0x766C, + 0xB062, 0xB069, 0x7670, + 0xB06A, 0xB06B, 0x7679, + 0xB06D, 0xB06F, 0x767F, + 0xB072, 0xB073, 0x7689, + 0xB074, 0xB075, 0x768C, + 0xB076, 0xB077, 0x768F, + 0xB079, 0xB07A, 0x7694, + 0xB07B, 0xB07C, 0x7697, + 0xB07D, 0xB07E, 0x769A, + 0xB080, 0xB087, 0x769C, + 0xB088, 0xB090, 0x76A5, + 0xB091, 0xB092, 0x76AF, + 0xB094, 0xB09D, 0x76B5, + 0xB09E, 0xB09F, 0x76C0, + 0xB143, 0xB144, 0x76CB, + 0xB147, 0xB148, 0x76D9, + 0xB149, 0xB14B, 0x76DC, + 0xB14C, 0xB150, 0x76E0, + 0xB151, 0xB158, 0x76E6, + 0xB15B, 0xB15D, 0x76F5, + 0xB15E, 0xB15F, 0x76FA, + 0xB161, 0xB162, 0x76FF, + 0xB163, 0xB164, 0x7702, + 0xB165, 0xB166, 0x7705, + 0xB169, 0xB173, 0x770E, + 0xB174, 0xB177, 0x771B, + 0xB179, 0xB17B, 0x7723, + 0xB17D, 0xB17E, 0x772A, + 0xB182, 0xB186, 0x7730, + 0xB189, 0xB18B, 0x773D, + 0xB18D, 0xB18F, 0x7744, + 0xB190, 0xB197, 0x7748, + 0xB198, 0xB19F, 0x7752, + 0xB1E6, 0xB1E7, 0x8FA8, + 0xB240, 0xB243, 0x775D, + 0xB246, 0xB247, 0x7769, + 0xB248, 0xB253, 0x776D, + 0xB254, 0xB256, 0x777A, + 0xB257, 0xB259, 0x7781, + 0xB25A, 0xB25F, 0x7786, + 0xB260, 0xB261, 0x778F, + 0xB262, 0xB26D, 0x7793, + 0xB26F, 0xB270, 0x77A3, + 0xB274, 0xB276, 0x77AD, + 0xB277, 0xB278, 0x77B1, + 0xB27A, 0xB27E, 0x77B6, + 0xB282, 0xB28E, 0x77C0, + 0xB28F, 0xB297, 0x77CE, + 0xB298, 0xB29A, 0x77D8, + 0xB29B, 0xB29F, 0x77DD, + 0xB343, 0xB346, 0x77EF, + 0xB347, 0xB348, 0x77F4, + 0xB34A, 0xB34D, 0x77F9, + 0xB34E, 0xB353, 0x7803, + 0xB354, 0xB355, 0x780A, + 0xB356, 0xB358, 0x780E, + 0xB35E, 0xB360, 0x7820, + 0xB363, 0xB364, 0x782A, + 0xB365, 0xB366, 0x782E, + 0xB367, 0xB369, 0x7831, + 0xB36A, 0xB36B, 0x7835, + 0xB36E, 0xB371, 0x7841, + 0xB373, 0xB376, 0x7848, + 0xB37A, 0xB37B, 0x7853, + 0xB37C, 0xB37E, 0x7858, + 0xB380, 0xB381, 0x785B, + 0xB382, 0xB38D, 0x785E, + 0xB38E, 0xB395, 0x786F, + 0xB396, 0xB399, 0x7878, + 0xB39A, 0xB3A0, 0x787D, + 0xB440, 0xB442, 0x7884, + 0xB444, 0xB445, 0x788A, + 0xB446, 0xB447, 0x788F, + 0xB449, 0xB44B, 0x7894, + 0xB44D, 0xB44E, 0x789D, + 0xB453, 0xB45A, 0x78A8, + 0xB45B, 0xB45E, 0x78B5, + 0xB45F, 0xB462, 0x78BA, + 0xB463, 0xB464, 0x78BF, + 0xB465, 0xB467, 0x78C2, + 0xB468, 0xB46A, 0x78C6, + 0xB46B, 0xB46E, 0x78CC, + 0xB46F, 0xB471, 0x78D1, + 0xB472, 0xB474, 0x78D6, + 0xB475, 0xB47E, 0x78DA, + 0xB480, 0xB483, 0x78E4, + 0xB484, 0xB486, 0x78E9, + 0xB487, 0xB48B, 0x78ED, + 0xB48D, 0xB48E, 0x78F5, + 0xB48F, 0xB490, 0x78F8, + 0xB491, 0xB496, 0x78FB, + 0xB497, 0xB499, 0x7902, + 0xB49A, 0xB4A0, 0x7906, + 0xB540, 0xB545, 0x790D, + 0xB546, 0xB54F, 0x7914, + 0xB550, 0xB554, 0x791F, + 0xB555, 0xB563, 0x7925, + 0xB564, 0xB568, 0x7935, + 0xB56B, 0xB56E, 0x7942, + 0xB570, 0xB578, 0x794A, + 0xB579, 0xB57A, 0x7954, + 0xB57B, 0xB57C, 0x7958, + 0xB582, 0xB585, 0x7969, + 0xB587, 0xB58D, 0x7970, + 0xB58F, 0xB593, 0x797B, + 0xB594, 0xB595, 0x7982, + 0xB596, 0xB599, 0x7986, + 0xB59A, 0xB59D, 0x798B, + 0xB59E, 0xB5A0, 0x7990, + 0xB640, 0xB646, 0x7993, + 0xB647, 0xB652, 0x799B, + 0xB653, 0xB65D, 0x79A8, + 0xB65E, 0xB662, 0x79B4, + 0xB666, 0xB667, 0x79C4, + 0xB668, 0xB669, 0x79C7, + 0xB66C, 0xB66E, 0x79CE, + 0xB66F, 0xB670, 0x79D3, + 0xB671, 0xB672, 0x79D6, + 0xB673, 0xB678, 0x79D9, + 0xB679, 0xB67B, 0x79E0, + 0xB682, 0xB688, 0x79F1, + 0xB689, 0xB68A, 0x79F9, + 0xB68C, 0xB68D, 0x79FE, + 0xB68F, 0xB690, 0x7A04, + 0xB691, 0xB694, 0x7A07, + 0xB696, 0xB69A, 0x7A0F, + 0xB69B, 0xB69C, 0x7A15, + 0xB69D, 0xB69E, 0x7A18, + 0xB69F, 0xB6A0, 0x7A1B, + 0xB742, 0xB743, 0x7A21, + 0xB744, 0xB752, 0x7A24, + 0xB753, 0xB755, 0x7A34, + 0xB759, 0xB75E, 0x7A40, + 0xB75F, 0xB768, 0x7A47, + 0xB769, 0xB76D, 0x7A52, + 0xB76E, 0xB77E, 0x7A58, + 0xB780, 0xB786, 0x7A69, + 0xB787, 0xB789, 0x7A71, + 0xB78B, 0xB78E, 0x7A7B, + 0xB792, 0xB795, 0x7A89, + 0xB796, 0xB798, 0x7A8E, + 0xB799, 0xB79A, 0x7A93, + 0xB79B, 0xB79D, 0x7A99, + 0xB79F, 0xB7A0, 0x7AA1, + 0xB840, 0xB841, 0x7AA3, + 0xB843, 0xB845, 0x7AA9, + 0xB846, 0xB84A, 0x7AAE, + 0xB84B, 0xB855, 0x7AB4, + 0xB856, 0xB860, 0x7AC0, + 0xB861, 0xB86A, 0x7ACC, + 0xB86B, 0xB86C, 0x7AD7, + 0xB86D, 0xB870, 0x7ADA, + 0xB871, 0xB872, 0x7AE1, + 0xB874, 0xB879, 0x7AE7, + 0xB87B, 0xB87E, 0x7AF0, + 0xB880, 0xB884, 0x7AF4, + 0xB885, 0xB886, 0x7AFB, + 0xB888, 0xB88A, 0x7B00, + 0xB88E, 0xB890, 0x7B0C, + 0xB892, 0xB893, 0x7B12, + 0xB894, 0xB896, 0x7B16, + 0xB898, 0xB899, 0x7B1C, + 0xB89B, 0xB89D, 0x7B21, + 0xB940, 0xB941, 0x7B2F, + 0xB943, 0xB946, 0x7B34, + 0xB94A, 0xB94F, 0x7B3F, + 0xB953, 0xB954, 0x7B4D, + 0xB95A, 0xB95B, 0x7B5E, + 0xB95D, 0xB967, 0x7B63, + 0xB968, 0xB969, 0x7B6F, + 0xB96A, 0xB96B, 0x7B73, + 0xB96F, 0xB970, 0x7B7C, + 0xB972, 0xB975, 0x7B81, + 0xB976, 0xB97C, 0x7B86, + 0xB97D, 0xB97E, 0x7B8E, + 0xB980, 0xB982, 0x7B91, + 0xB984, 0xB987, 0x7B98, + 0xB988, 0xB98A, 0x7B9E, + 0xB98B, 0xB98D, 0x7BA3, + 0xB98E, 0xB990, 0x7BAE, + 0xB991, 0xB992, 0x7BB2, + 0xB993, 0xB995, 0x7BB5, + 0xB996, 0xB99D, 0x7BB9, + 0xB99E, 0xB9A0, 0x7BC2, + 0xBA41, 0xBA44, 0x7BC8, + 0xBA45, 0xBA48, 0x7BCD, + 0xBA4A, 0xBA4E, 0x7BD4, + 0xBA4F, 0xBA50, 0x7BDB, + 0xBA51, 0xBA53, 0x7BDE, + 0xBA54, 0xBA56, 0x7BE2, + 0xBA57, 0xBA59, 0x7BE7, + 0xBA5A, 0xBA5C, 0x7BEB, + 0xBA5D, 0xBA5E, 0x7BEF, + 0xBA5F, 0xBA63, 0x7BF2, + 0xBA64, 0xBA67, 0x7BF8, + 0xBA69, 0xBA70, 0x7BFF, + 0xBA71, 0xBA73, 0x7C08, + 0xBA74, 0xBA75, 0x7C0D, + 0xBA76, 0xBA7B, 0x7C10, + 0xBA7C, 0xBA7E, 0x7C17, + 0xBA80, 0xBA84, 0x7C1A, + 0xBA85, 0xBA8A, 0x7C20, + 0xBA8B, 0xBA8C, 0x7C28, + 0xBA8D, 0xBA99, 0x7C2B, + 0xBA9A, 0xBA9F, 0x7C39, + 0xBB40, 0xBB49, 0x7C43, + 0xBB4A, 0xBB6E, 0x7C4E, + 0xBB6F, 0xBB74, 0x7C75, + 0xBB75, 0xBB7E, 0x7C7E, + 0xBB81, 0xBB87, 0x7C8A, + 0xBB88, 0xBB89, 0x7C93, + 0xBB8B, 0xBB8D, 0x7C99, + 0xBB8E, 0xBB8F, 0x7CA0, + 0xBB91, 0xBB94, 0x7CA6, + 0xBB95, 0xBB97, 0x7CAB, + 0xBB98, 0xBB99, 0x7CAF, + 0xBB9A, 0xBB9E, 0x7CB4, + 0xBB9F, 0xBBA0, 0x7CBA, + 0xBC40, 0xBC41, 0x7CBF, + 0xBC42, 0xBC44, 0x7CC2, + 0xBC48, 0xBC4E, 0x7CCE, + 0xBC50, 0xBC51, 0x7CDA, + 0xBC52, 0xBC53, 0x7CDD, + 0xBC54, 0xBC5A, 0x7CE1, + 0xBC5B, 0xBC60, 0x7CE9, + 0xBC61, 0xBC68, 0x7CF0, + 0xBC69, 0xBC6A, 0x7CF9, + 0xBC6B, 0xBC78, 0x7CFC, + 0xBC79, 0xBC7E, 0x7D0B, + 0xBC80, 0xBC8E, 0x7D11, + 0xBC90, 0xBC93, 0x7D23, + 0xBC94, 0xBC96, 0x7D28, + 0xBC97, 0xBC99, 0x7D2C, + 0xBC9A, 0xBCA0, 0x7D30, + 0xBD40, 0xBD76, 0x7D37, + 0xBD77, 0xBD7E, 0x7D6F, + 0xBD80, 0xBDA0, 0x7D78, + 0xBE40, 0xBE4C, 0x7D99, + 0xBE4D, 0xBE53, 0x7DA7, + 0xBE54, 0xBE7E, 0x7DAF, + 0xBE80, 0xBEA0, 0x7DDA, + 0xBF40, 0xBF7E, 0x7DFB, + 0xBF81, 0xBF85, 0x7E3C, + 0xBF86, 0xBF8A, 0x7E42, + 0xBF8B, 0xBFA0, 0x7E48, + 0xC040, 0xC063, 0x7E5E, + 0xC064, 0xC07B, 0x7E83, + 0xC07C, 0xC07E, 0x7E9C, + 0xC082, 0xC083, 0x7EBB, + 0xC08D, 0xC093, 0x7F3B, + 0xC095, 0xC09E, 0x7F46, + 0xC09F, 0xC0A0, 0x7F52, + 0xC142, 0xC145, 0x7F5B, + 0xC147, 0xC14B, 0x7F63, + 0xC14C, 0xC14E, 0x7F6B, + 0xC14F, 0xC150, 0x7F6F, + 0xC152, 0xC155, 0x7F75, + 0xC156, 0xC159, 0x7F7A, + 0xC15A, 0xC15B, 0x7F7F, + 0xC15C, 0xC163, 0x7F82, + 0xC166, 0xC16A, 0x7F8F, + 0xC16B, 0xC16F, 0x7F95, + 0xC170, 0xC171, 0x7F9B, + 0xC173, 0xC174, 0x7FA2, + 0xC175, 0xC176, 0x7FA5, + 0xC177, 0xC17D, 0x7FA8, + 0xC180, 0xC184, 0x7FB3, + 0xC185, 0xC186, 0x7FBA, + 0xC189, 0xC18B, 0x7FC2, + 0xC18C, 0xC18F, 0x7FC6, + 0xC192, 0xC196, 0x7FCF, + 0xC197, 0xC198, 0x7FD6, + 0xC199, 0xC19E, 0x7FD9, + 0xC19F, 0xC1A0, 0x7FE2, + 0xC241, 0xC242, 0x7FE7, + 0xC243, 0xC246, 0x7FEA, + 0xC249, 0xC24F, 0x7FF4, + 0xC250, 0xC252, 0x7FFD, + 0xC254, 0xC257, 0x8007, + 0xC258, 0xC259, 0x800E, + 0xC25C, 0xC25D, 0x801A, + 0xC25E, 0xC260, 0x801D, + 0xC262, 0xC263, 0x8023, + 0xC264, 0xC269, 0x802B, + 0xC26C, 0xC26D, 0x8039, + 0xC270, 0xC271, 0x8040, + 0xC272, 0xC273, 0x8044, + 0xC274, 0xC276, 0x8047, + 0xC277, 0xC27A, 0x804E, + 0xC27C, 0xC27E, 0x8055, + 0xC281, 0xC28E, 0x805B, + 0xC28F, 0xC294, 0x806B, + 0xC295, 0xC2A0, 0x8072, + 0xC341, 0xC342, 0x8081, + 0xC346, 0xC34B, 0x808D, + 0xC34C, 0xC34D, 0x8094, + 0xC352, 0xC354, 0x80A6, + 0xC358, 0xC359, 0x80B5, + 0xC35A, 0xC35B, 0x80B8, + 0xC35E, 0xC362, 0x80C7, + 0xC363, 0xC369, 0x80CF, + 0xC36B, 0xC36C, 0x80DF, + 0xC36D, 0xC36E, 0x80E2, + 0xC375, 0xC378, 0x80FE, + 0xC379, 0xC37B, 0x8103, + 0xC37C, 0xC37D, 0x8107, + 0xC384, 0xC386, 0x811B, + 0xC387, 0xC393, 0x811F, + 0xC394, 0xC395, 0x812D, + 0xC397, 0xC399, 0x8133, + 0xC39B, 0xC39F, 0x8139, + 0xC440, 0xC445, 0x8140, + 0xC448, 0xC44A, 0x814D, + 0xC44C, 0xC44E, 0x8156, + 0xC44F, 0xC453, 0x815B, + 0xC454, 0xC457, 0x8161, + 0xC45A, 0xC45C, 0x816A, + 0xC45E, 0xC45F, 0x8172, + 0xC460, 0xC463, 0x8175, + 0xC465, 0xC469, 0x8183, + 0xC46B, 0xC46E, 0x818B, + 0xC470, 0xC475, 0x8192, + 0xC476, 0xC477, 0x8199, + 0xC478, 0xC47C, 0x819E, + 0xC47D, 0xC47E, 0x81A4, + 0xC482, 0xC489, 0x81AB, + 0xC48A, 0xC48F, 0x81B4, + 0xC490, 0xC493, 0x81BC, + 0xC494, 0xC495, 0x81C4, + 0xC496, 0xC498, 0x81C7, + 0xC49A, 0xC4A0, 0x81CD, + 0xC540, 0xC54E, 0x81D4, + 0xC54F, 0xC551, 0x81E4, + 0xC552, 0xC553, 0x81E8, + 0xC555, 0xC559, 0x81EE, + 0xC55A, 0xC55F, 0x81F5, + 0xC563, 0xC567, 0x8207, + 0xC568, 0xC569, 0x820E, + 0xC56C, 0xC571, 0x8215, + 0xC574, 0xC577, 0x8224, + 0xC57C, 0xC57D, 0x823C, + 0xC580, 0xC583, 0x8240, + 0xC584, 0xC585, 0x8245, + 0xC588, 0xC58A, 0x824C, + 0xC58B, 0xC592, 0x8250, + 0xC594, 0xC597, 0x825B, + 0xC598, 0xC59F, 0x8260, + 0xC640, 0xC643, 0x826A, + 0xC645, 0xC648, 0x8275, + 0xC649, 0xC64A, 0x827B, + 0xC64B, 0xC64C, 0x8280, + 0xC64E, 0xC650, 0x8285, + 0xC654, 0xC657, 0x8293, + 0xC658, 0xC659, 0x829A, + 0xC65C, 0xC65D, 0x82A2, + 0xC660, 0xC661, 0x82B5, + 0xC662, 0xC664, 0x82BA, + 0xC665, 0xC666, 0x82BF, + 0xC667, 0xC668, 0x82C2, + 0xC669, 0xC66A, 0x82C5, + 0xC66E, 0xC66F, 0x82D9, + 0xC672, 0xC675, 0x82E7, + 0xC676, 0xC678, 0x82EC, + 0xC67A, 0xC67B, 0x82F2, + 0xC67C, 0xC67D, 0x82F5, + 0xC681, 0xC685, 0x82FC, + 0xC686, 0xC687, 0x830A, + 0xC68A, 0xC68B, 0x8312, + 0xC68D, 0xC68E, 0x8318, + 0xC68F, 0xC698, 0x831D, + 0xC699, 0xC69A, 0x8329, + 0xC740, 0xC741, 0x833E, + 0xC742, 0xC743, 0x8341, + 0xC744, 0xC745, 0x8344, + 0xC747, 0xC74B, 0x834A, + 0xC74D, 0xC751, 0x8355, + 0xC754, 0xC75A, 0x8370, + 0xC75B, 0xC75C, 0x8379, + 0xC75D, 0xC763, 0x837E, + 0xC764, 0xC765, 0x8387, + 0xC766, 0xC769, 0x838A, + 0xC76A, 0xC76C, 0x838F, + 0xC76D, 0xC770, 0x8394, + 0xC771, 0xC772, 0x8399, + 0xC775, 0xC77B, 0x83A1, + 0xC77C, 0xC77E, 0x83AC, + 0xC783, 0xC784, 0x83BE, + 0xC785, 0xC787, 0x83C2, + 0xC789, 0xC78A, 0x83C8, + 0xC78C, 0xC78D, 0x83CD, + 0xC78E, 0xC791, 0x83D0, + 0xC794, 0xC796, 0x83D9, + 0xC798, 0xC79A, 0x83E2, + 0xC79B, 0xC79D, 0x83E6, + 0xC79E, 0xC7A0, 0x83EB, + 0xC840, 0xC841, 0x83EE, + 0xC842, 0xC846, 0x83F3, + 0xC847, 0xC849, 0x83FA, + 0xC84A, 0xC84C, 0x83FE, + 0xC84F, 0xC852, 0x8407, + 0xC854, 0xC859, 0x8412, + 0xC85A, 0xC85C, 0x8419, + 0xC85D, 0xC862, 0x841E, + 0xC863, 0xC86A, 0x8429, + 0xC86B, 0xC870, 0x8432, + 0xC871, 0xC873, 0x8439, + 0xC874, 0xC87B, 0x843E, + 0xC87C, 0xC87E, 0x8447, + 0xC880, 0xC886, 0x844A, + 0xC887, 0xC88B, 0x8452, + 0xC88D, 0xC890, 0x845D, + 0xC892, 0xC896, 0x8464, + 0xC898, 0xC89A, 0x846E, + 0xC89F, 0xC8A0, 0x847B, + 0xC940, 0xC944, 0x847D, + 0xC945, 0xC948, 0x8483, + 0xC94B, 0xC952, 0x848F, + 0xC954, 0xC955, 0x849A, + 0xC956, 0xC959, 0x849D, + 0xC95A, 0xC966, 0x84A2, + 0xC967, 0xC968, 0x84B0, + 0xC96A, 0xC96C, 0x84B5, + 0xC96D, 0xC96E, 0x84BB, + 0xC971, 0xC972, 0x84C2, + 0xC973, 0xC976, 0x84C5, + 0xC977, 0xC978, 0x84CB, + 0xC979, 0xC97A, 0x84CE, + 0xC97C, 0xC97D, 0x84D4, + 0xC980, 0xC984, 0x84D8, + 0xC986, 0xC987, 0x84E1, + 0xC989, 0xC98D, 0x84E7, + 0xC98E, 0xC990, 0x84ED, + 0xC991, 0xC99B, 0x84F1, + 0xC99C, 0xC99D, 0x84FD, + 0xC99E, 0xC9A0, 0x8500, + 0xC9E0, 0xC9E1, 0x820C, + 0xCA40, 0xCA48, 0x8503, + 0xCA49, 0xCA4C, 0x850D, + 0xCA4E, 0xCA50, 0x8514, + 0xCA51, 0xCA52, 0x8518, + 0xCA53, 0xCA56, 0x851B, + 0xCA58, 0xCA60, 0x8522, + 0xCA61, 0xCA6A, 0x852D, + 0xCA6B, 0xCA6F, 0x853E, + 0xCA70, 0xCA73, 0x8544, + 0xCA74, 0xCA7E, 0x854B, + 0xCA80, 0xCA81, 0x8557, + 0xCA82, 0xCA85, 0x855A, + 0xCA86, 0xCA8A, 0x855F, + 0xCA8B, 0xCA8D, 0x8565, + 0xCA8E, 0xCA96, 0x8569, + 0xCA98, 0xCA9B, 0x8575, + 0xCA9C, 0xCA9D, 0x857C, + 0xCA9E, 0xCAA0, 0x857F, + 0xCB40, 0xCB41, 0x8582, + 0xCB43, 0xCB49, 0x8588, + 0xCB4A, 0xCB54, 0x8590, + 0xCB55, 0xCB5B, 0x859D, + 0xCB5C, 0xCB5E, 0x85A5, + 0xCB60, 0xCB62, 0x85AB, + 0xCB63, 0xCB68, 0x85B1, + 0xCB6A, 0xCB70, 0x85BA, + 0xCB71, 0xCB77, 0x85C2, + 0xCB78, 0xCB7C, 0x85CA, + 0xCB7D, 0xCB7E, 0x85D1, + 0xCB81, 0xCB86, 0x85D6, + 0xCB87, 0xCB8D, 0x85DD, + 0xCB8E, 0xCB91, 0x85E5, + 0xCB92, 0xCBA0, 0x85EA, + 0xCC40, 0xCC41, 0x85F9, + 0xCC42, 0xCC44, 0x85FC, + 0xCC45, 0xCC49, 0x8600, + 0xCC4A, 0xCC54, 0x8606, + 0xCC55, 0xCC58, 0x8612, + 0xCC59, 0xCC68, 0x8617, + 0xCC6A, 0xCC77, 0x862A, + 0xCC78, 0xCC7A, 0x8639, + 0xCC7B, 0xCC7E, 0x863D, + 0xCC80, 0xCC8B, 0x8641, + 0xCC8C, 0xCC8D, 0x8652, + 0xCC8E, 0xCC92, 0x8655, + 0xCC93, 0xCC95, 0x865B, + 0xCC96, 0xCC98, 0x865F, + 0xCC99, 0xCCA0, 0x8663, + 0xCD41, 0xCD42, 0x866F, + 0xCD43, 0xCD49, 0x8672, + 0xCD4A, 0xCD50, 0x8683, + 0xCD51, 0xCD55, 0x868E, + 0xCD57, 0xCD5C, 0x8696, + 0xCD5D, 0xCD61, 0x869E, + 0xCD62, 0xCD63, 0x86A5, + 0xCD65, 0xCD66, 0x86AD, + 0xCD67, 0xCD68, 0x86B2, + 0xCD69, 0xCD6B, 0x86B7, + 0xCD6C, 0xCD70, 0x86BB, + 0xCD71, 0xCD73, 0x86C1, + 0xCD76, 0xCD77, 0x86CC, + 0xCD78, 0xCD79, 0x86D2, + 0xCD7A, 0xCD7C, 0x86D5, + 0xCD81, 0xCD84, 0x86E0, + 0xCD85, 0xCD88, 0x86E5, + 0xCD89, 0xCD8B, 0x86EA, + 0xCD8D, 0xCD8F, 0x86F5, + 0xCD90, 0xCD93, 0x86FA, + 0xCD96, 0xCD98, 0x8704, + 0xCD99, 0xCD9A, 0x870B, + 0xCD9B, 0xCD9E, 0x870E, + 0xCE43, 0xCE44, 0x871F, + 0xCE46, 0xCE48, 0x8726, + 0xCE49, 0xCE4C, 0x872A, + 0xCE4D, 0xCE4E, 0x872F, + 0xCE4F, 0xCE50, 0x8732, + 0xCE51, 0xCE52, 0x8735, + 0xCE53, 0xCE55, 0x8738, + 0xCE56, 0xCE57, 0x873C, + 0xCE58, 0xCE5E, 0x8740, + 0xCE5F, 0xCE60, 0x874A, + 0xCE62, 0xCE65, 0x874F, + 0xCE66, 0xCE68, 0x8754, + 0xCE6A, 0xCE6F, 0x875A, + 0xCE70, 0xCE71, 0x8761, + 0xCE72, 0xCE79, 0x8766, + 0xCE7B, 0xCE7D, 0x8771, + 0xCE80, 0xCE83, 0x8777, + 0xCE84, 0xCE86, 0x877F, + 0xCE88, 0xCE89, 0x8786, + 0xCE8A, 0xCE8B, 0x8789, + 0xCE8D, 0xCE91, 0x878E, + 0xCE92, 0xCE94, 0x8794, + 0xCE95, 0xCE9B, 0x8798, + 0xCE9C, 0xCEA0, 0x87A0, + 0xCF40, 0xCF42, 0x87A5, + 0xCF43, 0xCF44, 0x87A9, + 0xCF46, 0xCF48, 0x87B0, + 0xCF4A, 0xCF4D, 0x87B6, + 0xCF4E, 0xCF4F, 0x87BB, + 0xCF50, 0xCF51, 0x87BE, + 0xCF52, 0xCF56, 0x87C1, + 0xCF57, 0xCF59, 0x87C7, + 0xCF5A, 0xCF5E, 0x87CC, + 0xCF5F, 0xCF65, 0x87D4, + 0xCF66, 0xCF69, 0x87DC, + 0xCF6A, 0xCF6D, 0x87E1, + 0xCF6E, 0xCF71, 0x87E6, + 0xCF72, 0xCF74, 0x87EB, + 0xCF75, 0xCF7E, 0x87EF, + 0xCF80, 0xCF83, 0x87FA, + 0xCF84, 0xCF87, 0x87FF, + 0xCF88, 0xCF8D, 0x8804, + 0xCF8E, 0xCF95, 0x880B, + 0xCF97, 0xCF9A, 0x8817, + 0xCF9B, 0xCF9F, 0x881C, + 0xD040, 0xD04D, 0x8824, + 0xD04E, 0xD053, 0x8833, + 0xD054, 0xD055, 0x883A, + 0xD056, 0xD058, 0x883D, + 0xD059, 0xD05B, 0x8841, + 0xD05C, 0xD061, 0x8846, + 0xD062, 0xD067, 0x884E, + 0xD068, 0xD069, 0x8855, + 0xD06B, 0xD071, 0x885A, + 0xD072, 0xD073, 0x8866, + 0xD078, 0xD07B, 0x8873, + 0xD07C, 0xD07E, 0x8878, + 0xD080, 0xD081, 0x887B, + 0xD084, 0xD085, 0x8886, + 0xD086, 0xD087, 0x8889, + 0xD089, 0xD08C, 0x888E, + 0xD08D, 0xD08F, 0x8893, + 0xD090, 0xD094, 0x8897, + 0xD095, 0xD099, 0x889D, + 0xD09B, 0xD0A0, 0x88A5, + 0xD141, 0xD143, 0x88AE, + 0xD144, 0xD148, 0x88B2, + 0xD149, 0xD14C, 0x88B8, + 0xD14D, 0xD150, 0x88BD, + 0xD151, 0xD152, 0x88C3, + 0xD153, 0xD154, 0x88C7, + 0xD155, 0xD158, 0x88CA, + 0xD159, 0xD15B, 0x88CF, + 0xD15D, 0xD15E, 0x88D6, + 0xD15F, 0xD163, 0x88DA, + 0xD164, 0xD165, 0x88E0, + 0xD166, 0xD167, 0x88E6, + 0xD168, 0xD16E, 0x88E9, + 0xD170, 0xD172, 0x88F5, + 0xD173, 0xD174, 0x88FA, + 0xD176, 0xD178, 0x88FF, + 0xD179, 0xD17E, 0x8903, + 0xD181, 0xD185, 0x890B, + 0xD187, 0xD18B, 0x8914, + 0xD18C, 0xD190, 0x891C, + 0xD191, 0xD193, 0x8922, + 0xD194, 0xD197, 0x8926, + 0xD198, 0xD19B, 0x892C, + 0xD19C, 0xD19E, 0x8931, + 0xD240, 0xD248, 0x8938, + 0xD249, 0xD24A, 0x8942, + 0xD24B, 0xD263, 0x8945, + 0xD264, 0xD269, 0x8960, + 0xD26A, 0xD27D, 0x8967, + 0xD280, 0xD281, 0x897D, + 0xD284, 0xD285, 0x8984, + 0xD286, 0xD2A0, 0x8987, + 0xD340, 0xD35E, 0x89A2, + 0xD361, 0xD363, 0x89D3, + 0xD364, 0xD366, 0x89D7, + 0xD369, 0xD36C, 0x89DF, + 0xD36E, 0xD371, 0x89E7, + 0xD372, 0xD374, 0x89EC, + 0xD375, 0xD377, 0x89F0, + 0xD378, 0xD37E, 0x89F4, + 0xD380, 0xD384, 0x89FB, + 0xD385, 0xD38A, 0x8A01, + 0xD38B, 0xD3A0, 0x8A08, + 0xD3A9, 0xD3AA, 0x8424, + 0xD440, 0xD45F, 0x8A1E, + 0xD460, 0xD468, 0x8A3F, + 0xD469, 0xD47E, 0x8A49, + 0xD480, 0xD499, 0x8A5F, + 0xD49A, 0xD4A0, 0x8A7A, + 0xD540, 0xD547, 0x8A81, + 0xD548, 0xD54F, 0x8A8B, + 0xD550, 0xD57E, 0x8A94, + 0xD580, 0xD5A0, 0x8AC3, + 0xD640, 0xD662, 0x8AE4, + 0xD663, 0xD67E, 0x8B08, + 0xD680, 0xD681, 0x8B24, + 0xD682, 0xD6A0, 0x8B27, + 0xD6C1, 0xD6C2, 0x81F3, + 0xD740, 0xD75F, 0x8B46, + 0xD760, 0xD764, 0x8B67, + 0xD765, 0xD77E, 0x8B6D, + 0xD780, 0xD798, 0x8B87, + 0xD840, 0xD848, 0x8C38, + 0xD849, 0xD84C, 0x8C42, + 0xD84E, 0xD84F, 0x8C4A, + 0xD850, 0xD857, 0x8C4D, + 0xD858, 0xD85B, 0x8C56, + 0xD85C, 0xD861, 0x8C5B, + 0xD862, 0xD868, 0x8C63, + 0xD869, 0xD86F, 0x8C6C, + 0xD870, 0xD873, 0x8C74, + 0xD874, 0xD87A, 0x8C7B, + 0xD87B, 0xD87C, 0x8C83, + 0xD87D, 0xD87E, 0x8C86, + 0xD882, 0xD888, 0x8C8D, + 0xD889, 0xD88B, 0x8C95, + 0xD88C, 0xD8A0, 0x8C99, + 0xD8DB, 0xD8DC, 0x523F, + 0xD940, 0xD97E, 0x8CAE, + 0xD980, 0xD9A0, 0x8CED, + 0xDA40, 0xDA4E, 0x8D0E, + 0xDA50, 0xDA51, 0x8D51, + 0xDA55, 0xDA57, 0x8D68, + 0xDA59, 0xDA5A, 0x8D6E, + 0xDA5B, 0xDA5C, 0x8D71, + 0xDA5D, 0xDA65, 0x8D78, + 0xDA66, 0xDA67, 0x8D82, + 0xDA68, 0xDA6B, 0x8D86, + 0xDA6C, 0xDA70, 0x8D8C, + 0xDA71, 0xDA72, 0x8D92, + 0xDA73, 0xDA7C, 0x8D95, + 0xDA7D, 0xDA7E, 0x8DA0, + 0xDA81, 0xDA8D, 0x8DA4, + 0xDA8F, 0xDA90, 0x8DB6, + 0xDA94, 0xDA96, 0x8DC0, + 0xDA98, 0xDA9B, 0x8DC7, + 0xDA9E, 0xDAA0, 0x8DD2, + 0xDAA6, 0xDAA7, 0x8BA6, + 0xDAA9, 0xDAAA, 0x8BB4, + 0xDAAC, 0xDAAD, 0x8BC2, + 0xDAB1, 0xDAB3, 0x8BD2, + 0xDAB5, 0xDAB6, 0x8BD8, + 0xDAB8, 0xDAB9, 0x8BDF, + 0xDABB, 0xDABC, 0x8BE8, + 0xDAC3, 0xDAC4, 0x8BFF, + 0xDACA, 0xDACB, 0x8C11, + 0xDACC, 0xDACE, 0x8C14, + 0xDAD3, 0xDAD5, 0x8C1F, + 0xDAD8, 0xDAD9, 0x8C2A, + 0xDADA, 0xDADB, 0x8C2E, + 0xDADC, 0xDADD, 0x8C32, + 0xDADE, 0xDADF, 0x8C35, + 0xDB41, 0xDB42, 0x8DD8, + 0xDB44, 0xDB46, 0x8DE0, + 0xDB47, 0xDB49, 0x8DE5, + 0xDB4B, 0xDB4C, 0x8DED, + 0xDB4D, 0xDB4F, 0x8DF0, + 0xDB53, 0xDB59, 0x8DFE, + 0xDB5A, 0xDB5C, 0x8E06, + 0xDB5E, 0xDB5F, 0x8E0D, + 0xDB60, 0xDB63, 0x8E10, + 0xDB64, 0xDB6B, 0x8E15, + 0xDB6C, 0xDB6D, 0x8E20, + 0xDB6E, 0xDB72, 0x8E24, + 0xDB76, 0xDB78, 0x8E32, + 0xDB79, 0xDB7B, 0x8E36, + 0xDB7C, 0xDB7D, 0x8E3B, + 0xDB82, 0xDB83, 0x8E45, + 0xDB84, 0xDB88, 0x8E4C, + 0xDB89, 0xDB8E, 0x8E53, + 0xDB8F, 0xDB9A, 0x8E5A, + 0xDB9B, 0xDB9C, 0x8E67, + 0xDB9D, 0xDB9E, 0x8E6A, + 0xDBBE, 0xDBBF, 0x52AC, + 0xDBDC, 0xDBDD, 0x572E, + 0xDC42, 0xDC46, 0x8E77, + 0xDC47, 0xDC48, 0x8E7D, + 0xDC4A, 0xDC4C, 0x8E82, + 0xDC4E, 0xDC54, 0x8E88, + 0xDC55, 0xDC57, 0x8E91, + 0xDC58, 0xDC5E, 0x8E95, + 0xDC60, 0xDC6B, 0x8E9F, + 0xDC6C, 0xDC6D, 0x8EAD, + 0xDC6E, 0xDC6F, 0x8EB0, + 0xDC70, 0xDC76, 0x8EB3, + 0xDC77, 0xDC7E, 0x8EBB, + 0xDC80, 0xDC8A, 0x8EC3, + 0xDC8B, 0xDCA0, 0x8ECF, + 0xDCC8, 0xDCC9, 0x82CB, + 0xDCE3, 0xDCE4, 0x8314, + 0xDCE9, 0xDCEA, 0x835B, + 0xDD40, 0xDD7E, 0x8EE5, + 0xDD80, 0xDDA0, 0x8F24, + 0xDDA6, 0xDDA7, 0x836D, + 0xDDAA, 0xDDAB, 0x83B3, + 0xDDCE, 0xDDCF, 0x83F8, + 0xDDDB, 0xDDDC, 0x8487, + 0xDE40, 0xDE60, 0x8F45, + 0xDE66, 0xDE68, 0x8FA0, + 0xDE69, 0xDE6C, 0x8FA4, + 0xDE6E, 0xDE71, 0x8FAC, + 0xDE72, 0xDE75, 0x8FB2, + 0xDE76, 0xDE77, 0x8FB7, + 0xDE78, 0xDE7A, 0x8FBA, + 0xDE7B, 0xDE7C, 0x8FBF, + 0xDE80, 0xDE84, 0x8FC9, + 0xDE87, 0xDE88, 0x8FD6, + 0xDE8A, 0xDE8B, 0x8FE0, + 0xDE90, 0xDE91, 0x8FF1, + 0xDE92, 0xDE94, 0x8FF4, + 0xDE95, 0xDE97, 0x8FFA, + 0xDE98, 0xDE99, 0x8FFE, + 0xDE9A, 0xDE9B, 0x9007, + 0xDF42, 0xDF44, 0x9023, + 0xDF45, 0xDF4A, 0x9027, + 0xDF4B, 0xDF4F, 0x9030, + 0xDF51, 0xDF52, 0x9039, + 0xDF54, 0xDF55, 0x903F, + 0xDF57, 0xDF58, 0x9045, + 0xDF59, 0xDF5D, 0x9048, + 0xDF5F, 0xDF61, 0x9054, + 0xDF62, 0xDF63, 0x9059, + 0xDF64, 0xDF69, 0x905C, + 0xDF6B, 0xDF6C, 0x9066, + 0xDF6D, 0xDF70, 0x9069, + 0xDF71, 0xDF75, 0x906F, + 0xDF76, 0xDF7C, 0x9076, + 0xDF80, 0xDF83, 0x9084, + 0xDF84, 0xDF85, 0x9089, + 0xDF86, 0xDF8A, 0x908C, + 0xDF91, 0xDF93, 0x909E, + 0xDF94, 0xDF95, 0x90A4, + 0xDF96, 0xDF98, 0x90A7, + 0xDF9D, 0xDF9E, 0x90BC, + 0xDF9F, 0xDFA0, 0x90BF, + 0xDFA2, 0xDFA3, 0x64B7, + 0xDFBC, 0xDFBE, 0x5452, + 0xDFCB, 0xDFCC, 0x549A, + 0xDFD8, 0xDFD9, 0x54D3, + 0xDFE0, 0xDFE1, 0x54D9, + 0xDFE3, 0xDFE4, 0x54A9, + 0xDFEF, 0xDFF0, 0x5522, + 0xE040, 0xE041, 0x90C2, + 0xE043, 0xE044, 0x90C8, + 0xE045, 0xE047, 0x90CB, + 0xE049, 0xE04B, 0x90D4, + 0xE04C, 0xE04E, 0x90D8, + 0xE04F, 0xE051, 0x90DE, + 0xE052, 0xE054, 0x90E3, + 0xE055, 0xE056, 0x90E9, + 0xE059, 0xE05C, 0x90F0, + 0xE05D, 0xE05F, 0x90F5, + 0xE060, 0xE063, 0x90F9, + 0xE064, 0xE066, 0x90FF, + 0xE068, 0xE07B, 0x9105, + 0xE07C, 0xE07E, 0x911A, + 0xE081, 0xE083, 0x911F, + 0xE084, 0xE08E, 0x9124, + 0xE090, 0xE096, 0x9132, + 0xE097, 0xE09F, 0x913A, + 0xE0A3, 0xE0A5, 0x5575, + 0xE0B6, 0xE0B7, 0x55BD, + 0xE0BF, 0xE0C0, 0x55EB, + 0xE0C7, 0xE0C8, 0x55F2, + 0xE0C9, 0xE0CA, 0x55CC, + 0xE0E7, 0xE0E8, 0x567B, + 0xE0FD, 0xE0FE, 0x5E3B, + 0xE141, 0xE142, 0x9147, + 0xE144, 0xE147, 0x9153, + 0xE148, 0xE149, 0x9158, + 0xE14A, 0xE14B, 0x915B, + 0xE14C, 0xE14D, 0x915F, + 0xE14E, 0xE150, 0x9166, + 0xE154, 0xE156, 0x917A, + 0xE157, 0xE15B, 0x9180, + 0xE15F, 0xE160, 0x918E, + 0xE161, 0xE167, 0x9193, + 0xE168, 0xE16D, 0x919C, + 0xE16E, 0xE173, 0x91A4, + 0xE174, 0xE175, 0x91AB, + 0xE176, 0xE179, 0x91B0, + 0xE17A, 0xE17D, 0x91B6, + 0xE180, 0xE18A, 0x91BC, + 0xE18E, 0xE197, 0x91D2, + 0xE198, 0xE1A0, 0x91DD, + 0xE1AD, 0xE1AE, 0x5C98, + 0xE1C0, 0xE1C1, 0x5D02, + 0xE1EE, 0xE1EF, 0x72B7, + 0xE240, 0xE27E, 0x91E6, + 0xE280, 0xE2A0, 0x9225, + 0xE2BC, 0xE2C1, 0x9967, + 0xE2CA, 0xE2CB, 0x9990, + 0xE2CC, 0xE2CE, 0x9993, + 0xE2EA, 0xE2EB, 0x6005, + 0xE2FA, 0xE2FB, 0x6078, + 0xE340, 0xE36D, 0x9246, + 0xE36E, 0xE37E, 0x9275, + 0xE380, 0xE387, 0x9286, + 0xE388, 0xE3A0, 0x928F, + 0xE3C9, 0xE3CA, 0x95F5, + 0xE3CD, 0xE3CE, 0x9603, + 0xE3D1, 0xE3D4, 0x960A, + 0xE3D7, 0xE3D9, 0x9615, + 0xE3DA, 0xE3DB, 0x9619, + 0xE3E8, 0xE3E9, 0x6C68, + 0xE3F1, 0xE3F2, 0x6CF7, + 0xE440, 0xE445, 0x92A8, + 0xE446, 0xE45E, 0x92AF, + 0xE45F, 0xE47E, 0x92C9, + 0xE480, 0xE4A0, 0x92E9, + 0xE4B8, 0xE4B9, 0x6D93, + 0xE4D4, 0xE4D5, 0x6E53, + 0xE4EB, 0xE4EC, 0x6F46, + 0xE540, 0xE573, 0x930A, + 0xE574, 0xE57E, 0x933F, + 0xE580, 0xE59F, 0x934A, + 0xE5D3, 0xE5D4, 0x9035, + 0xE5D8, 0xE5D9, 0x9051, + 0xE5FC, 0xE5FD, 0x59A9, + 0xE640, 0xE662, 0x936C, + 0xE663, 0xE67E, 0x9390, + 0xE680, 0xE69D, 0x93AC, + 0xE69E, 0xE6A0, 0x93CB, + 0xE6AB, 0xE6AC, 0x5A05, + 0xE6E1, 0xE6E2, 0x9A77, + 0xE6E6, 0xE6E7, 0x9A80, + 0xE6EC, 0xE6ED, 0x9A92, + 0xE6F0, 0xE6F2, 0x9A9B, + 0xE6F3, 0xE6F4, 0x9A9F, + 0xE6F5, 0xE6F6, 0x9AA2, + 0xE6FD, 0xE6FE, 0x7EA8, + 0xE740, 0xE747, 0x93CE, + 0xE748, 0xE77E, 0x93D7, + 0xE780, 0xE7A0, 0x940E, + 0xE7A4, 0xE7A6, 0x7EC0, + 0xE7A8, 0xE7A9, 0x7ECB, + 0xE7AE, 0xE7AF, 0x7EE0, + 0xE7B2, 0xE7B3, 0x7EEE, + 0xE7B4, 0xE7B5, 0x7EF1, + 0xE7B8, 0xE7B9, 0x7EFA, + 0xE7BB, 0xE7BD, 0x7F01, + 0xE7BE, 0xE7BF, 0x7F07, + 0xE7C0, 0xE7C1, 0x7F0B, + 0xE7C3, 0xE7C4, 0x7F11, + 0xE7CA, 0xE7D0, 0x7F21, + 0xE7D1, 0xE7D4, 0x7F2A, + 0xE7D5, 0xE7D9, 0x7F2F, + 0xE840, 0xE84E, 0x942F, + 0xE84F, 0xE87A, 0x943F, + 0xE87B, 0xE87E, 0x946C, + 0xE880, 0xE894, 0x9470, + 0xE89A, 0xE89B, 0x94D3, + 0xE8AD, 0xE8AE, 0x7480, + 0xE8B2, 0xE8B3, 0x74A8, + 0xE8B8, 0xE8BA, 0x97EA, + 0xE8E0, 0xE8E1, 0x6832, + 0xE8E2, 0xE8E3, 0x6860, + 0xE8FC, 0xE8FD, 0x691F, + 0xE94A, 0xE94B, 0x9574, + 0xE94C, 0xE953, 0x9577, + 0xE954, 0xE97E, 0x9580, + 0xE980, 0xE9A0, 0x95AB, + 0xE9B4, 0xE9B5, 0x6987, + 0xE9CB, 0xE9CC, 0x6A17, + 0xE9E2, 0xE9E3, 0x6B81, + 0xE9E6, 0xE9E7, 0x6B92, + 0xE9E9, 0xE9EA, 0x6B9A, + 0xE9EF, 0xE9F1, 0x8F71, + 0xE9F2, 0xE9F3, 0x8F75, + 0xE9F6, 0xE9F7, 0x8F79, + 0xE9FA, 0xE9FB, 0x8F81, + 0xEA40, 0xEA5B, 0x95CC, + 0xEA64, 0xEA6A, 0x9623, + 0xEA6B, 0xEA6D, 0x962B, + 0xEA6E, 0xEA6F, 0x962F, + 0xEA70, 0xEA73, 0x9637, + 0xEA78, 0xEA79, 0x964E, + 0xEA7A, 0xEA7C, 0x9651, + 0xEA7D, 0xEA7E, 0x9656, + 0xEA80, 0xEA82, 0x9658, + 0xEA83, 0xEA85, 0x965C, + 0xEA88, 0xEA89, 0x9665, + 0xEA8B, 0xEA8F, 0x966D, + 0xEA91, 0xEA9D, 0x9678, + 0xEA9F, 0xEAA0, 0x9689, + 0xEAA1, 0xEAA3, 0x8F8D, + 0xEAB8, 0xEABA, 0x65EE, + 0xEAD6, 0xEAD7, 0x66DB, + 0xEADA, 0xEADB, 0x8D32, + 0xEAE0, 0xEAE1, 0x8D45, + 0xEAE2, 0xEAE3, 0x8D48, + 0xEAE9, 0xEAEB, 0x89CA, + 0xEAEC, 0xEAEF, 0x89CE, + 0xEAF5, 0xEAF6, 0x727E, + 0xEB42, 0xEB44, 0x9691, + 0xEB45, 0xEB46, 0x9695, + 0xEB47, 0xEB48, 0x969A, + 0xEB49, 0xEB52, 0x969D, + 0xEB53, 0xEB5A, 0x96A8, + 0xEB5B, 0xEB5C, 0x96B1, + 0xEB5D, 0xEB5E, 0x96B4, + 0xEB5F, 0xEB60, 0x96B7, + 0xEB61, 0xEB62, 0x96BA, + 0xEB64, 0xEB65, 0x96C2, + 0xEB67, 0xEB68, 0x96CA, + 0xEB69, 0xEB6A, 0x96D0, + 0xEB6B, 0xEB6C, 0x96D3, + 0xEB6D, 0xEB76, 0x96D6, + 0xEB77, 0xEB7D, 0x96E1, + 0xEB80, 0xEB82, 0x96EC, + 0xEB83, 0xEB85, 0x96F0, + 0xEB86, 0xEB87, 0x96F4, + 0xEB89, 0xEB8C, 0x96FA, + 0xEB8E, 0xEB8F, 0x9702, + 0xEB91, 0xEB93, 0x970A, + 0xEB94, 0xEB96, 0x9710, + 0xEB97, 0xEB98, 0x9714, + 0xEB99, 0xEB9D, 0x9717, + 0xEB9F, 0xEBA0, 0x971F, + 0xEBAE, 0xEBB0, 0x6C18, + 0xEBCA, 0xEBCD, 0x80E7, + 0xEBDA, 0xEBDB, 0x810D, + 0xEBEA, 0xEBEB, 0x8159, + 0xEBEF, 0xEBF0, 0x817C, + 0xEC40, 0xEC48, 0x9721, + 0xEC49, 0xEC4A, 0x972B, + 0xEC4B, 0xEC4C, 0x972E, + 0xEC4E, 0xEC52, 0x9733, + 0xEC53, 0xEC56, 0x973A, + 0xEC57, 0xEC69, 0x973F, + 0xEC6A, 0xEC6B, 0x9754, + 0xEC6C, 0xEC6D, 0x9757, + 0xEC6F, 0xEC70, 0x975C, + 0xEC72, 0xEC73, 0x9763, + 0xEC74, 0xEC76, 0x9766, + 0xEC77, 0xEC7E, 0x976A, + 0xEC82, 0xEC86, 0x9777, + 0xEC87, 0xEC8E, 0x977D, + 0xEC8F, 0xEC93, 0x9786, + 0xEC95, 0xEC97, 0x978E, + 0xEC99, 0xEC9B, 0x9795, + 0xEC9C, 0xECA0, 0x9799, + 0xECA9, 0xECAB, 0x98D1, + 0xECAD, 0xECAE, 0x98D9, + 0xECE8, 0xECE9, 0x6248, + 0xECEE, 0xECEF, 0x795B, + 0xED40, 0xED41, 0x979E, + 0xED42, 0xED43, 0x97A1, + 0xED44, 0xED4A, 0x97A4, + 0xED4D, 0xED4E, 0x97B0, + 0xED50, 0xED7E, 0x97B5, + 0xED80, 0xED81, 0x97E4, + 0xED83, 0xED87, 0x97EE, + 0xED89, 0xEDA0, 0x97F7, + 0xEDBA, 0xEDBB, 0x7817, + 0xEDBF, 0xEDC0, 0x781C, + 0xEDC1, 0xEDC3, 0x7839, + 0xEDCC, 0xEDCD, 0x7856, + 0xEDEA, 0xEDEB, 0x9EFB, + 0xEDF0, 0xEDF1, 0x7707, + 0xEDF9, 0xEDFA, 0x7750, + 0xEE40, 0xEE7E, 0x980F, + 0xEE80, 0xEEA0, 0x984E, + 0xEEA9, 0xEEAA, 0x779F, + 0xEEC4, 0xEEC6, 0x9485, + 0xEEC9, 0xEECA, 0x948C, + 0xEECB, 0xEECC, 0x948F, + 0xEED0, 0xEED2, 0x949A, + 0xEED3, 0xEED4, 0x94A3, + 0xEED9, 0xEEDA, 0x94AF, + 0xEEDD, 0xEEE1, 0x94B6, + 0xEEE2, 0xEEE3, 0x94BC, + 0xEEE6, 0xEEEC, 0x94C8, + 0xEEED, 0xEEEF, 0x94D0, + 0xEEF0, 0xEEF2, 0x94D5, + 0xEEF6, 0xEEF8, 0x94DE, + 0xEEFA, 0xEEFB, 0x94E4, + 0xEEFC, 0xEEFD, 0x94E7, + 0xEF40, 0xEF45, 0x986F, + 0xEF4C, 0xEF71, 0x98A8, + 0xEF72, 0xEF73, 0x98CF, + 0xEF75, 0xEF76, 0x98D6, + 0xEF77, 0xEF79, 0x98DB, + 0xEF7A, 0xEF7E, 0x98E0, + 0xEF80, 0xEF81, 0x98E5, + 0xEF82, 0xEFA0, 0x98E9, + 0xEFA3, 0xEFA4, 0x94EE, + 0xEFA5, 0xEFA7, 0x94F3, + 0xEFAA, 0xEFAB, 0x94FC, + 0xEFAF, 0xEFB0, 0x9506, + 0xEFB1, 0xEFB2, 0x9509, + 0xEFB3, 0xEFB5, 0x950D, + 0xEFB6, 0xEFBA, 0x9512, + 0xEFBD, 0xEFBF, 0x951D, + 0xEFC1, 0xEFC2, 0x952A, + 0xEFC5, 0xEFC6, 0x9531, + 0xEFC8, 0xEFCA, 0x9536, + 0xEFCC, 0xEFCD, 0x953E, + 0xEFD0, 0xEFD2, 0x9544, + 0xEFD5, 0xEFD6, 0x954E, + 0xEFD7, 0xEFD9, 0x9552, + 0xEFDA, 0xEFDD, 0x9556, + 0xEFDF, 0xEFE0, 0x955E, + 0xEFE2, 0xEFE3, 0x9561, + 0xEFE4, 0xEFEC, 0x9564, + 0xEFEE, 0xEFF0, 0x9571, + 0xF040, 0xF044, 0x9908, + 0xF045, 0xF046, 0x990E, + 0xF047, 0xF063, 0x9911, + 0xF064, 0xF07E, 0x992F, + 0xF080, 0xF089, 0x994A, + 0xF08A, 0xF096, 0x9956, + 0xF09A, 0xF09B, 0x9978, + 0xF09E, 0xF09F, 0x9982, + 0xF0B1, 0xF0B5, 0x9E28, + 0xF0BB, 0xF0BC, 0x9E39, + 0xF0BE, 0xF0BF, 0x9E41, + 0xF0C1, 0xF0C4, 0x9E46, + 0xF0C5, 0xF0C6, 0x9E4B, + 0xF0CB, 0xF0CD, 0x9E5A, + 0xF0D0, 0xF0D6, 0x9E66, + 0xF0E1, 0xF0E2, 0x75B3, + 0xF142, 0xF14C, 0x999A, + 0xF14D, 0xF14E, 0x99A6, + 0xF14F, 0xF17E, 0x99A9, + 0xF180, 0xF1A0, 0x99D9, + 0xF1B6, 0xF1B7, 0x7A78, + 0xF1ED, 0xF1EF, 0x8025, + 0xF240, 0xF27E, 0x99FA, + 0xF280, 0xF2A0, 0x9A39, + 0xF2A2, 0xF2A3, 0x988C, + 0xF2A6, 0xF2A7, 0x989A, + 0xF2A8, 0xF2A9, 0x989E, + 0xF2AA, 0xF2AB, 0x98A1, + 0xF2AC, 0xF2AD, 0x98A5, + 0xF2CC, 0xF2CD, 0x86F1, + 0xF2ED, 0xF2EE, 0x877D, + 0xF340, 0xF351, 0x9A5A, + 0xF355, 0xF356, 0x9A8D, + 0xF357, 0xF358, 0x9A94, + 0xF35B, 0xF361, 0x9AA9, + 0xF362, 0xF365, 0x9AB2, + 0xF368, 0xF36A, 0x9ABD, + 0xF36B, 0xF36C, 0x9AC3, + 0xF36D, 0xF371, 0x9AC6, + 0xF372, 0xF375, 0x9ACD, + 0xF377, 0xF37A, 0x9AD4, + 0xF37B, 0xF37E, 0x9AD9, + 0xF380, 0xF381, 0x9ADD, + 0xF383, 0xF386, 0x9AE2, + 0xF387, 0xF38A, 0x9AE7, + 0xF38D, 0xF395, 0x9AF0, + 0xF397, 0xF39D, 0x9AFC, + 0xF39E, 0xF3A0, 0x9B04, + 0xF3C0, 0xF3C1, 0x7F44, + 0xF3C6, 0xF3C7, 0x7B03, + 0xF3E5, 0xF3E6, 0x7BA6, + 0xF3F6, 0xF3F7, 0x7BE5, + 0xF441, 0xF446, 0x9B09, + 0xF447, 0xF449, 0x9B10, + 0xF44A, 0xF454, 0x9B14, + 0xF455, 0xF457, 0x9B20, + 0xF458, 0xF462, 0x9B24, + 0xF463, 0xF464, 0x9B30, + 0xF465, 0xF46C, 0x9B33, + 0xF46D, 0xF470, 0x9B3D, + 0xF472, 0xF474, 0x9B4A, + 0xF477, 0xF478, 0x9B52, + 0xF479, 0xF47E, 0x9B55, + 0xF480, 0xF4A0, 0x9B5B, + 0xF4A8, 0xF4A9, 0x8201, + 0xF4AD, 0xF4AF, 0x8221, + 0xF4B6, 0xF4B7, 0x8233, + 0xF4C9, 0xF4CA, 0x7FAF, + 0xF4D4, 0xF4D5, 0x7CBC, + 0xF4D8, 0xF4D9, 0x7CCC, + 0xF4FC, 0xF4FD, 0x914E, + 0xF540, 0xF57E, 0x9B7C, + 0xF580, 0xF5A0, 0x9BBB, + 0xF5A6, 0xF5A7, 0x917D, + 0xF5B0, 0xF5B1, 0x91A2, + 0xF5B3, 0xF5B5, 0x91AD, + 0xF5C5, 0xF5C6, 0x8DD6, + 0xF5C9, 0xF5CA, 0x8DCE, + 0xF5CE, 0xF5CF, 0x8DF7, + 0xF5E4, 0xF5E5, 0x8E41, + 0xF5E6, 0xF5E7, 0x8E51, + 0xF640, 0xF67E, 0x9BDC, + 0xF680, 0xF6A0, 0x9C1B, + 0xF6B5, 0xF6BA, 0x9F85, + 0xF6C0, 0xF6C1, 0x96BC, + 0xF6D1, 0xF6D4, 0x9C85, + 0xF6D8, 0xF6DA, 0x9C90, + 0xF6DB, 0xF6DC, 0x9C94, + 0xF6DD, 0xF6DE, 0x9C9A, + 0xF6DF, 0xF6E4, 0x9C9E, + 0xF6E5, 0xF6E9, 0x9CA5, + 0xF6EB, 0xF6EC, 0x9CAD, + 0xF6ED, 0xF6F4, 0x9CB0, + 0xF6F5, 0xF6F8, 0x9CBA, + 0xF6F9, 0xF6FC, 0x9CC4, + 0xF6FD, 0xF6FE, 0x9CCA, + 0xF740, 0xF77E, 0x9C3C, + 0xF781, 0xF782, 0x9C7D, + 0xF784, 0xF785, 0x9C83, + 0xF786, 0xF787, 0x9C89, + 0xF78B, 0xF78E, 0x9C96, + 0xF794, 0xF798, 0x9CBE, + 0xF799, 0xF79A, 0x9CC8, + 0xF79B, 0xF79C, 0x9CD1, + 0xF79D, 0xF79E, 0x9CDA, + 0xF79F, 0xF7A0, 0x9CE0, + 0xF7A1, 0xF7A5, 0x9CCC, + 0xF7A6, 0xF7A8, 0x9CD3, + 0xF7A9, 0xF7AB, 0x9CD7, + 0xF7AC, 0xF7AD, 0x9CDC, + 0xF7B2, 0xF7B3, 0x9791, + 0xF7C5, 0xF7C6, 0x9ACB, + 0xF7E1, 0xF7E2, 0x9EBD, + 0xF7E5, 0xF7E6, 0x9E87, + 0xF7EC, 0xF7EE, 0x9EDB, + 0xF7FC, 0xF7FD, 0x9F3D, + 0xF840, 0xF87E, 0x9CE3, + 0xF880, 0xF8A0, 0x9D22, + 0xF940, 0xF97E, 0x9D43, + 0xF980, 0xF9A0, 0x9D82, + 0xFA40, 0xFA7E, 0x9DA3, + 0xFA80, 0xFAA0, 0x9DE2, + 0xFB40, 0xFB5B, 0x9E03, + 0xFB61, 0xFB62, 0x9E3B, + 0xFB66, 0xFB68, 0x9E52, + 0xFB6C, 0xFB6F, 0x9E5F, + 0xFB71, 0xFB72, 0x9E6E, + 0xFB74, 0xFB7D, 0x9E74, + 0xFB81, 0xFB84, 0x9E83, + 0xFB85, 0xFB86, 0x9E89, + 0xFB87, 0xFB8C, 0x9E8C, + 0xFB8D, 0xFB95, 0x9E94, + 0xFB97, 0xFB9C, 0x9EA0, + 0xFB9D, 0xFBA0, 0x9EA7, + 0xFC40, 0xFC48, 0x9EAB, + 0xFC49, 0xFC4B, 0x9EB5, + 0xFC4C, 0xFC4D, 0x9EB9, + 0xFC4F, 0xFC53, 0x9EBF, + 0xFC54, 0xFC57, 0x9EC5, + 0xFC58, 0xFC5A, 0x9ECA, + 0xFC5C, 0xFC5D, 0x9ED2, + 0xFC5E, 0xFC60, 0x9ED5, + 0xFC61, 0xFC62, 0x9ED9, + 0xFC65, 0xFC66, 0x9EE3, + 0xFC69, 0xFC6C, 0x9EEB, + 0xFC6D, 0xFC75, 0x9EF0, + 0xFC78, 0xFC7E, 0x9EFF, + 0xFC80, 0xFC84, 0x9F06, + 0xFC87, 0xFC88, 0x9F11, + 0xFC89, 0xFC8B, 0x9F14, + 0xFC8D, 0xFC92, 0x9F1A, + 0xFC94, 0xFC9C, 0x9F23, + 0xFC9D, 0xFC9E, 0x9F2D, + 0xFC9F, 0xFCA0, 0x9F30, + 0xFD40, 0xFD44, 0x9F32, + 0xFD48, 0xFD4C, 0x9F3F, + 0xFD4D, 0xFD57, 0x9F45, + 0xFD58, 0xFD7E, 0x9F52, + 0xFD80, 0xFD85, 0x9F79, + 0xFD86, 0xFD87, 0x9F81, + 0xFD88, 0xFD93, 0x9F8D, + 0xFD94, 0xFD96, 0x9F9C, + 0xFD97, 0xFD9B, 0x9FA1, + 0xFE40, 0xFE43, 0xFA0C, + 0xFE45, 0xFE46, 0xFA13, + 0xFE48, 0xFE4A, 0xFA1F, + 0xFE4B, 0xFE4C, 0xFA23, + 0xFE4D, 0xFE4F, 0xFA27, + 0xFE50, 0xFEA0, 0xE815, // }}} +}; +#endif + + +#endif /* ! ASM_FILE */ #endif /* ! GRUB_SHARED_HEADER */ diff --git a/stage2/stage2.c b/stage2/stage2.c index 677babad..36329730 100644 --- a/stage2/stage2.c +++ b/stage2/stage2.c @@ -1,4 +1,4 @@ -/* +/* * GRUB -- GRand Unified Bootloader * Copyright (C) 2000,2001,2002,2004,2005 Free Software Foundation, Inc. * @@ -21,55 +21,30 @@ #include /* indicates whether or not the next char printed will be highlighted */ -unsigned long is_highlight = 0; - -/* preset_menu is defined in asm.S */ -#define preset_menu *(const char **)0x307FFC - -static unsigned long preset_menu_offset; +unsigned int is_highlight = 0; +static int open_preset_menu (void); static int -open_preset_menu (void) +open_preset_menu (void) //打开预置菜单 { - if (! use_preset_menu) - return 0; + if (! use_preset_menu) //如果不存在预置菜单 + return 0; //返回0 - if (preset_menu != (const char *)0x800) - goto lzma; - - preset_menu_offset = 0; - return 1;//preset_menu != 0; - -lzma: - return grub_open ("(md)0x880+0x200"); + return grub_open (preset_menu); //打开压缩菜单 位置0x110000 最大尺寸0x40000=256k } +static int read_from_preset_menu (char *buf, int max_len); static int -read_from_preset_menu (char *buf, int max_len) +read_from_preset_menu (char *buf, int max_len) //从预设菜单读取(缓存,尺寸) { - int len; - - if (! use_preset_menu) //if (preset_menu == 0) - return 0; - - if (preset_menu != (const char *)0x800) - goto lzma; - len = grub_strlen (preset_menu + preset_menu_offset); - - if (len > max_len) - len = max_len; - - grub_memmove (buf, preset_menu + preset_menu_offset, len); - preset_menu_offset += len; - - return len; + if (! use_preset_menu) //如果不存在预置菜单 + return 0; -lzma: - return grub_read ((unsigned long long)(unsigned int)buf, max_len, 0xedde0d90); + return grub_read ((unsigned long long)(grub_size_t)buf, max_len, 0xedde0d90); } #define MENU_BOX_X ((menu_border.menu_box_x > 2) ? menu_border.menu_box_x : 2) -#define MENU_BOX_W ((menu_border.menu_box_w && menu_border.menu_box_w < (current_term->chars_per_line - MENU_BOX_X - 1)) ? menu_border.menu_box_w : (current_term->chars_per_line - MENU_BOX_X - 1)) +#define MENU_BOX_W ((menu_border.menu_box_w && menu_border.menu_box_w < (current_term->chars_per_line - MENU_BOX_X - 1)) ? menu_border.menu_box_w : (current_term->chars_per_line - MENU_BOX_X * 2)) //UEFI固件的右上角(0x2510)是宽字符 #define MENU_BOX_Y (menu_border.menu_box_y) #define MENU_KEYHELP_Y_OFFSET ((menu_border.menu_keyhelp_y_offset < 5) ? menu_border.menu_keyhelp_y_offset : 0) /* window height */ @@ -83,38 +58,49 @@ read_from_preset_menu (char *buf, int max_len) #define MENU_HELP_E (menu_border.menu_help_x ? (menu_border.menu_help_w ? (menu_border.menu_help_x + menu_border.menu_help_w) : (current_term->chars_per_line - MENU_HELP_X)) : (MENU_BOX_E + 1)) #define NUM_LINE_ENTRYHELP ((MENU_KEYHELP_Y_OFFSET == 0) ? 4 : MENU_KEYHELP_Y_OFFSET) // -static long temp_entryno; +static int temp_entryno; static short temp_num; -static char * *titles; /* title array, point to 256 strings. */ -extern int (*hotkey_func)(char *titles,int flags,int flags1); +static char * *titles; /* title array, point to 256 strings. 标题数组,指向256个字符串*/ static unsigned short *title_boot; static int default_help_message_destoyed = 1; extern int num_text_char(char *p); -/* - unsigned char disp_ul; - unsigned char disp_ur; - unsigned char disp_ll; - unsigned char disp_lr; - unsigned char disp_horiz; - unsigned char disp_vert; - unsigned char menu_box_x; // line start - unsigned char menu_box_w; // line width - unsigned char menu_box_y; // first line number - unsigned char menu_box_h; - unsigned char menu_box_b; - unsigned char border_w; - unsigned char menu_help_x; - unsigned char menu_help_w; - unsigned char menu_keyhelp_y_offset; -*/ struct border menu_border = {218,191,192,217,196,179,2,0,2,0,0,2,0,0,0}; /* console */ -//struct border menu_border = {20,21,22,19,15,14,2,0,2,0,0}; /* graphics */ +char* print_color_characters (char *message, unsigned char *character, unsigned long long *color64_back, unsigned int *color_back); +char* +print_color_characters (char *message, unsigned char *character, unsigned long long *color64_back, unsigned int *color_back) +{ + if (message[2] == ']') + { + current_color_64bit = *color64_back; + current_color = *color_back; + message += 3; + *character = *(message); + } + else if ((message[3] | 0x20) == 'x') + { + unsigned long long ull; + message += 2; + if (safe_parse_maxint((char **)&message,&ull) && *message == ']') + { + *color_back = current_color; + *color64_back = current_color_64bit; + current_color_64bit = ull; + current_color = color_64_to_8 (current_color_64bit); + *character = *(++message); + } + } + return message; +} + +static void print_help_message (const char *message,int flags); static void print_help_message (const char *message,int flags) { grub_u32_t j,x,k; grub_u8_t c = *message; int start_offcet = 0; + unsigned long long current_color_64bit_back; + unsigned int current_color_back; if (flags==2) { @@ -123,7 +109,7 @@ static void print_help_message (const char *message,int flags) if (MENU_BOX_B + 1 + j > current_term->max_lines) return; gotoxy (MENU_HELP_X, MENU_BOX_B + 1 + j); - for (x = MENU_HELP_X; x < MENU_HELP_E; x++) + for (x = MENU_HELP_X; x < (grub_u32_t)MENU_HELP_E; x++) grub_putchar (' ', 255); } } @@ -158,47 +144,49 @@ static void print_help_message (const char *message,int flags) start_offcet = MENU_HELP_X + ((MENU_HELP_E - MENU_HELP_X - num_text_char((char *)message))>>1); else if((menu_tab & 0x40) && flags==1) { -// start_offcet = current_term->chars_per_line - MENU_HELP_X - num_text_char((char *)message); start_offcet = MENU_HELP_E - num_text_char((char *)message); if(start_offcet= start_offcet) + if (c && c != '\n' && fontx >= (grub_u32_t)start_offcet) { - if (fontx == MENU_HELP_E - 1) + if (fontx == (grub_u32_t)MENU_HELP_E - (grub_u32_t)1) if (c > 0x7F && !(menu_tab & 0x40)) { grub_putchar (' ', 255); continue; } + //处理菜单项注释中的彩色字符 + if (*(unsigned short*)message == 0x5B24)//$[ + message = print_color_characters ((char *)message,&c,¤t_color_64bit_back,¤t_color_back); grub_putchar (c, 255); c = *(++message); } else grub_putchar (' ', 255); } - for (x = fontx; x < MENU_HELP_E; x++) + for (x = fontx; x < (grub_u32_t)MENU_HELP_E; x++) grub_putchar (' ', 255); } } } } +static void print_default_help_message (char *config_entries); static void print_default_help_message (char *config_entries) { grub_u32_t i; - char buff[256]; +// char buff[256]; + char *buff = grub_malloc (256); -if (menu_tab & 0x20) + if (menu_tab & 0x20) i = grub_sprintf (buff,"\n按↑和↓选择菜单。"); else - i = grub_sprintf (buff,"\nUse the %c and %c keys to highlight an entry.", - (unsigned long)(unsigned char)DISP_UP, (unsigned long)(unsigned char)DISP_DOWN); - + i = grub_sprintf (buff,"\nUse the ↑ and ↓ keys to highlight an entry."); if (! auth && password_buf) { if (menu_tab & 0x20) @@ -225,21 +213,31 @@ if (menu_tab & 0x20) "or ESC to go back to the main menu."))); } if(keyhelp_color) - current_color_64bit = keyhelp_color; + { + if (!(splashimage_loaded & 2)) + { + current_color_64bit = keyhelp_color | (console_color_64bit[COLOR_STATE_NORMAL] & 0x00ffffff00000000); + } + else + current_color_64bit = keyhelp_color; + current_term->setcolorstate (color_64_to_8 (current_color_64bit) | 0x100); + } print_help_message(buff,0); default_help_message_destoyed = 0; + grub_free (buff); } - // ADDED By STEVE6375 -static unsigned int num_entries; +static int num_entries; + +static char *get_entry (char *list, int num); static char * get_entry (char *list, int num) { int i; if (list == (char *)titles) - return num < num_entries ? titles[num] : 0; + return num < num_entries ? titles[num] : (int)0; for (i = 0; i < num && *list; i++) { @@ -251,6 +249,7 @@ get_entry (char *list, int num) static char ntext[256]; +static void clean_entry (char *text); static void clean_entry (char *text) { @@ -258,7 +257,9 @@ clean_entry (char *text) //(void) strcpy (ntext, text); for (i = 0; i < 255 && text[i]; ++i) { - if (text[i] < 32 || text[i] > 127) + int a = (int)(char)text[i]; +// if (text[i] < (char)32 || text[i] > (char)127) + if (a < (int)32 || a > (int)127) ntext[i] = 32; else ntext[i] = text[i]; @@ -267,6 +268,7 @@ clean_entry (char *text) return; } +static int checkvalue (void); static int checkvalue (void) { @@ -286,7 +288,7 @@ checkvalue (void) return value; } - +static int myatoi (void); static int myatoi (void) { @@ -306,17 +308,16 @@ myatoi (void) return value; } } - // printf ("Mv%dMv",value); return value; } // END OF STEVE6375 ADDED CODE - +int num_text_char(char *p); int num_text_char(char *p) { int i=0; - unsigned long un16=0; + unsigned int un16=0; for(;*p && *p != '\n' && *p != '\r';) { @@ -332,7 +333,7 @@ num_text_char(char *p) continue; }else if((*p & 0xf0) == 0xe0) { - un16=(long)(*p & 0xf)<<12 | (long)(*(p+1) & 0x3f)<<6 | (long)(*(p+2) & 0x3f); + un16=(int)(*p & 0xf)<<12 | (int)(*(p+1) & 0x3f)<<6 | (int)(*(p+2) & 0x3f); if(un16 >= 0x4e00 && un16 <= 0x9fff) i+=2; else @@ -345,11 +346,11 @@ num_text_char(char *p) } /* Print an entry in a line of the menu box. */ -extern char menu_cfg[]; -extern unsigned char menu_num_ctrl[]; -int use_phys_base; +char menu_cfg[2]; +unsigned char menu_num_ctrl[4]; char graphic_file_shift[32]; +static void print_entry (int y, int highlight,int entryno, char *config_entries); static void print_entry (int y, int highlight,int entryno, char *config_entries) { @@ -358,23 +359,29 @@ print_entry (int y, int highlight,int entryno, char *config_entries) char *entry = get_entry (config_entries, entryno); int start_offcet = 0; int end_offcet = 0; + int first_brackets = 0; if (current_term->setcolorstate) current_term->setcolorstate (highlight ? COLOR_STATE_HIGHLIGHT : COLOR_STATE_NORMAL); + unsigned long long clo64_back = current_color_64bit; + unsigned int clo_back = current_color; + unsigned long long clo64_tmp; + unsigned int clo_tmp; is_highlight = highlight; if (graphic_type) { - char tmp[128]; +// char tmp[128]; int file_len=grub_strlen(graphic_file); int www = (font_w * MENU_BOX_W) / graphic_list; - int graphic_x_offset, graphic_y_offset; - int text_y_offset = MENU_BOX_Y+((y-MENU_BOX_Y)*((graphic_high+row_space+font_h+line_spacing-1)/(font_h+line_spacing))/graphic_list); + int graphic_x_offset, graphic_y_offset, text_x_offset; + int text_y_offset = MENU_BOX_Y + + (((y-MENU_BOX_Y)/graphic_list) * (graphic_high+row_space) + (graphic_high-font_h)/2) / (font_h+line_spacing); graphic_x_offset = font_w*MENU_BOX_X+((y-MENU_BOX_Y)%graphic_list)*(www); if (graphic_type & 0x10) - graphic_y_offset = (font_h+line_spacing)*text_y_offset-(graphic_high/2-(font_h+line_spacing)/2); + graphic_y_offset = (font_h+line_spacing)*text_y_offset - (graphic_high-font_h)/2; else graphic_y_offset = font_h*MENU_BOX_Y+((y-MENU_BOX_Y)/graphic_list)*(graphic_high+row_space); @@ -385,6 +392,7 @@ print_entry (int y, int highlight,int entryno, char *config_entries) } else { + char *tmp = grub_malloc (128); graphic_file[file_len-6] = ((entryno + graphic_file_shift[entryno]) / 10) | 0x30; graphic_file[file_len-5] = ((entryno + graphic_file_shift[entryno]) % 10) | 0x30; sprintf(tmp,"--offset=%d=%d=%d %s",0,graphic_x_offset,graphic_y_offset,graphic_file); @@ -392,13 +400,17 @@ print_entry (int y, int highlight,int entryno, char *config_entries) graphic_enable = 1; splashimage_func(tmp,1); graphic_enable = 0; + use_phys_base=0; + grub_free (tmp); if ((graphic_type & 4) && highlight) rectangle(graphic_x_offset,graphic_y_offset,graphic_wide,graphic_high,3); } c = *entry; if (graphic_type & 0x10) { - gotoxy ((graphic_x_offset + graphic_wide + font_w -1)/font_w, text_y_offset); + text_x_offset = (graphic_x_offset + graphic_wide + font_w -1) / (font_w + font_spacing); + end_offcet = MENU_BOX_E - ((www - graphic_wide) / (font_w + font_spacing)) - text_x_offset; + gotoxy (text_x_offset, text_y_offset); goto graphic_mixing; } else @@ -410,17 +422,18 @@ print_entry (int y, int highlight,int entryno, char *config_entries) end_offcet = 1; if (highlight) menu_num_ctrl[2] = entryno; - if (*(unsigned short *)0x8308) +// if (*(unsigned short *)IMG(0x8308)) + if (*(unsigned short *)IMG(0x82c8)) { if(!(menu_tab & 0x40)) { gotoxy (MENU_BOX_X - 1, y); - grub_putchar(highlight ? menu_cfg[0] : ' ', 255); + grub_putchar(highlight ? (menu_num_ctrl[2] = entryno, menu_cfg[0]) : ' ', 255); } else { gotoxy (MENU_BOX_E - 1, y); - grub_putchar(highlight ? menu_cfg[1] : ' ', 255); + grub_putchar(highlight ? (menu_num_ctrl[2] = entryno,menu_cfg[1]) : ' ', 255); } } graphic_mixing: @@ -475,15 +488,59 @@ print_entry (int y, int highlight,int entryno, char *config_entries) for (x = fontx; x < MENU_BOX_E - end_offcet; x = fontx) { - unsigned int ret; + int ret; ret = MENU_BOX_E - x - end_offcet; if (c && c != '\n' /* && x <= MENU_BOX_W*/ && x >= start_offcet) { - +hotkey_start: + if (hotkey_func && hotkey_color_64bit) + { + if (c == '^') + { + c = *(++entry); + goto color; + } + else if (first_brackets == 0 && c == '[') + { + first_brackets = 1; + goto color_no; + } + else if (first_brackets == 1 && c == ']') + { + first_brackets = 2; + goto color_no; + } + else if (first_brackets == 0 || first_brackets == 2) + { + first_brackets = 2; + goto color_no; + } +color: + clo64_tmp = current_color_64bit; + clo_tmp = current_color; + current_color_64bit = hotkey_color_64bit; + current_color = hotkey_color; + if (current_term == term_table) + console_setcolorstate (current_color | 0x100); + ret = grub_putchar ((unsigned char)c, ret); + current_color_64bit = clo64_tmp; + current_color = clo_tmp; + if (current_term == term_table) + current_term->setcolorstate (current_color | 0x100); + goto hotkey_end; + } +color_no: + //处理菜单项中的彩色字符 + if (*(unsigned short*)entry == 0x5B24)//$[ + { + entry = print_color_characters (entry,&c,&clo64_back,&clo_back); + goto hotkey_start; + } ret = grub_putchar ((unsigned char)c, ret); +hotkey_end: //is_highlight = 0; - if ((long)ret < 0) + if (ret < (int)0) { c = 0; continue; @@ -494,16 +551,14 @@ print_entry (int y, int highlight,int entryno, char *config_entries) { if (!(menu_tab & 0x10)) { - unsigned long long clo = current_color_64bit; + clo64_tmp = current_color_64bit; if(splashimage_loaded & 2) current_color_64bit = 0; else if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_NORMAL); ret = grub_putchar (' ', ret); - current_color_64bit = clo; -// if ((long)ret < 0) -// break; + current_color_64bit = clo64_tmp; } else grub_putchar (' ', ret); @@ -525,13 +580,10 @@ print_entry (int y, int highlight,int entryno, char *config_entries) default_help_message_destoyed = 1; print_help_message(entry,1); } -// else if (default_help_message_destoyed) else { if(!(menu_border.menu_keyhelp_y_offset) && !(menu_tab & 4)) { -// if (current_term->setcolorstate) -// current_term->setcolorstate (COLOR_STATE_HELPTEXT); if (default_help_message_destoyed) print_default_help_message (config_entries); } @@ -544,11 +596,11 @@ print_entry (int y, int highlight,int entryno, char *config_entries) } /* Print entries in the menu box. */ +static void print_entries (int first, int entryno, char *menu_entries); static void print_entries (int first, int entryno, char *menu_entries) { int i; - //int main_menu = (menu_entries == (char *)titles); gotoxy (MENU_BOX_E, MENU_BOX_Y); @@ -559,31 +611,15 @@ print_entries (int first, int entryno, char *menu_entries) if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_BORDER); if (first) - grub_putchar (DISP_UP, 255); + console_print_unicode (DISP_UP, 255); else - grub_putchar (DISP_VERT, 255); + console_print_unicode (DISP_VERT, 255); } - //if (main_menu || *menu_entries) - // menu_entries = get_entry (menu_entries, first); if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_NORMAL); for (i = 0; i < MENU_BOX_H/*size*/; i++) { print_entry (MENU_BOX_Y + i, entryno == i, first + i, menu_entries); - - // if (main_menu) - // { - //if (menu_entries) - //{ - // if ((++first) < 256) - // menu_entries = titles[first]; - // else - // menu_entries = 0; - //} - //continue; - // } - // if (*menu_entries) - //while (*(menu_entries++)); } #ifdef SUPPORT_GRAPHICS @@ -596,15 +632,16 @@ print_entries (int first, int entryno, char *menu_entries) current_term->setcolorstate (COLOR_STATE_BORDER); char *last_entry = get_entry(menu_entries,first+MENU_BOX_H); if (last_entry && *last_entry) - grub_putchar (DISP_DOWN, 255); + console_print_unicode (DISP_DOWN, 255); else - grub_putchar (DISP_VERT, 255); + console_print_unicode (DISP_VERT, 255); if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_STANDARD); } gotoxy (MENU_BOX_E, MENU_BOX_Y + entryno); /* XXX: Why? */ } +static void print_entries_raw (int size, int first, char *menu_entries); static void print_entries_raw (int size, int first, char *menu_entries) { @@ -636,6 +673,7 @@ extern int checkrange_func (char *arg1, int flags); /* Run an entry from the script SCRIPT. HEAP is used for the command-line buffer. If an error occurs, return non-zero, otherwise return zero. */ +static int run_script (char *script, char *heap); static int run_script (char *script, char *heap) { @@ -645,12 +683,8 @@ run_script (char *script, char *heap) char cmd_add[16]; char *menu_bat; char *p; -// char *arg; -// grub_error_t errnum_old;//2010-12-16 /* Initialize the data. */ - //saved_drive = boot_drive; - //saved_partition = install_partition; current_drive = GRUB_INVALID_DRIVE; count_lines = -1; @@ -658,106 +692,82 @@ run_script (char *script, char *heap) kernel_type = KERNEL_TYPE_NONE; errnum = 0; errorcheck = 1; /* errorcheck on */ - if (grub_memcmp (cur_entry, "!BAT", 4) == 0) { - while (1) - { - while (*cur_entry++); - if (! *cur_entry) - break; - *(cur_entry - 1) = 0x0a; - } - menu_bat = (char *)grub_malloc(cur_entry - script + 10 + 512); - if (menu_bat == NULL) - return 0; - p = (char *)(((int)menu_bat + 511) & ~511); - grub_memmove (p, script, cur_entry - script); - grub_sprintf (cmd_add, "(md)%d+%d", (int)p >> 9, ((cur_entry - script + 10 + 511) & ~511) >> 9); - command_func (cmd_add, BUILTIN_SCRIPT); - grub_free(menu_bat); - - if (errnum >= 1000) - { - errnum=ERR_NONE; - return 0; - } - if (errnum && errorcheck) - goto ppp; + while (1) + { + while (*cur_entry++); + if (! *cur_entry) + break; + *(cur_entry - 1) = 0x0a; + } +// menu_bat = (char *)grub_malloc(cur_entry - script + 10 + 512); + menu_bat = (char *)grub_memalign(512, cur_entry - script + 10 + 512); //对齐分配内存 + if (menu_bat == NULL) + return 0; +// p = (char *)(((grub_size_t)menu_bat + 511) & ~511); + p = menu_bat; + grub_memmove (p, script, cur_entry - script); + grub_sprintf (cmd_add, "(md)%d+%d", (grub_size_t)p >> 9, ((cur_entry - script + 10 + 511) & ~511) >> 9); + command_func (cmd_add, BUILTIN_SCRIPT); + grub_free(menu_bat); + menu_bat = 0; + if (errnum >= 1000) + { + errnum=ERR_NONE; + return 0; + } + if (errnum && errorcheck) + goto ppp; - /* If any kernel is not loaded, just exit successfully. */ - if (kernel_type == KERNEL_TYPE_NONE) - return 0; /* return to main menu. */ - /* Otherwise, the command boot is run implicitly. */ - grub_sprintf (cmd_add, "boot", 5); - run_line (cmd_add , BUILTIN_SCRIPT); - goto ppp; + /* If any kernel is not loaded, just exit successfully. */ + if (kernel_type == KERNEL_TYPE_NONE) + return 0; /* return to main menu. */ + /* Otherwise, the command boot is run implicitly. */ + grub_sprintf (cmd_add, "boot", 5); + run_line (cmd_add , BUILTIN_SCRIPT); + + goto ppp; } while (1) - { - if (errnum == MAX_ERR_NUM) + { + if (errnum == MAX_ERR_NUM) { errnum=ERR_NONE; return 0; } - if (errnum && errorcheck) - break; - -// errnum_old = errnum; //2010-12-16 - /* Copy the first string in CUR_ENTRY to HEAP. */ -// errnum = ERR_NONE;//2010-12-16 - old_entry = cur_entry; - while (*cur_entry++) - ; - - grub_memmove (heap, old_entry, (int) cur_entry - (int) old_entry); - if (! *heap) - { - /* If there is no more command in SCRIPT... */ - - /* If any kernel is not loaded, just exit successfully. */ - if (kernel_type == KERNEL_TYPE_NONE) - return 0; /* return to main menu. */ - - /* Otherwise, the command boot is run implicitly. */ - grub_memmove (heap, "boot", 5); - } + if (errnum && errorcheck) + break; - /* Find a builtin. */ - builtin = find_command (heap); - if (! builtin) - { - grub_printf ("%s\n", old_entry); - continue; - } -/* now command echoing is considered no use for a successful command. */ -// if (! (builtin->flags & BUILTIN_NO_ECHO)) -// grub_printf ("%s\n", old_entry); + old_entry = cur_entry; + while (*cur_entry++) + ; -/*comment by chenall on 2010-12-16,will do it in run_line*/ -#if 0 - /* If BUILTIN cannot be run in the command-line, skip it. */ - if ((int)builtin != -1 && ! (builtin->flags & BUILTIN_CMDLINE)) - { - errnum = ERR_UNRECOGNIZED; - continue; - } + grub_memmove (heap, old_entry, (grub_size_t) cur_entry - (grub_size_t) old_entry); + if (! *heap) + { + /* If there is no more command in SCRIPT... */ + /* If any kernel is not loaded, just exit successfully. */ + if (kernel_type == KERNEL_TYPE_NONE) + return 0; /* return to main menu. */ - /* Invalidate the cache, because the user may exchange removable - disks. */ - buf_drive = -1; + /* Otherwise, the command boot is run implicitly. */ + grub_memmove (heap, "boot", 5); + } - if ((int)builtin != -1) - if ((builtin->func) == errnum_func || (builtin->func) == checkrange_func) - errnum = errnum_old; + /* Find a builtin. */ + builtin = find_command (heap); + if (! builtin) + { + grub_printf ("%s\n", old_entry); + continue; + } + run_line (heap , BUILTIN_SCRIPT); - /* find && and || */ -#endif - run_line (heap , BUILTIN_SCRIPT); - if (! *old_entry) /* HEAP holds the implicit BOOT command */ - break; - } /* while (1) */ + if (! *old_entry) /* HEAP holds the implicit BOOT command */ + break; + } /* while (1) */ ppp: kernel_type = KERNEL_TYPE_NONE; @@ -765,63 +775,122 @@ run_script (char *script, char *heap) /* If a fallback entry is defined, don't prompt a user's intervention. */ if (fallback_entryno < 0) - { -#if 0 - if (! (builtin->flags & BUILTIN_NO_ECHO)) - grub_printf ("%s\n", heap); -#endif - print_error (); + { + print_error (); - grub_printf ("\nPress any key to continue..."); - (void) getkey (); - } + grub_printf ("\nPress any key to continue..."); + (void) getkey (); + } errnum = ERR_NONE; return 1; /* use fallback. */ } -unsigned short beep_buf[256]; +void clear_delay_display (int entryno); +void +clear_delay_display (int entryno) +{ + if (grub_timeout >= 0) + { + if (current_term->setcolorstate) + current_term->setcolorstate (COLOR_STATE_HELPTEXT); + if (current_term->flags & TERM_DUMB) + grub_putchar ('\r', 255); + + if(timeout_x || timeout_y) + gotoxy (timeout_x,timeout_y); + else + { + if(!(menu_tab & 0x40)) + gotoxy (MENU_BOX_E - 2, MENU_BOX_Y + entryno); + else + gotoxy (MENU_BOX_X - 1, MENU_BOX_Y + entryno); + } + + if(timeout_color) + { + current_term->setcolorstate (COLOR_STATE_NORMAL); + if ((timeout_color & 0xffffffff00000000) == 0) + current_color_64bit = timeout_color | (current_color_64bit & 0xffffffff00000000); + else + current_color_64bit = timeout_color; + } + else if (current_term->setcolorstate) + current_term->setcolorstate (COLOR_STATE_HIGHLIGHT); + + grub_printf(" "); + if (current_term->setcolorstate) + current_term->setcolorstate (COLOR_STATE_HELPTEXT); + + grub_timeout = -1; + timeout_enable = 0; + fallback_entryno = -1; + if (! (current_term->flags & TERM_DUMB)) + gotoxy (MENU_BOX_E, MENU_BOX_Y + entryno); + } +} + int new_menu; +int new_hotkey; int color_counting; int password_x; +unsigned char timeout_enable = 0; +int time0 = 0, time1 = 0; static int fallbacked_entries; static int old_c; static int old_c_count; static int old_c_count_end; + +void timeout_refresh(void); +void timeout_refresh(void) +{ + time0++; + if (time0 == 1000) + { + time0 = 0; + time1++; + } +} + +static void run_menu (char *menu_entries, char *config_entries, /*int num_entries,*/ char *heap, int entryno); static void run_menu (char *menu_entries, char *config_entries, /*int num_entries,*/ char *heap, int entryno) { - int c = 0, time1, time2 = -1, first_entry = 0; + int i, /*time1,*/ time2 = -1, first_entry = 0; + unsigned short c; char *cur_entry = 0; char *pass_config = 0; color_counting = 0; -// struct term_entry *prev_term = NULL; - /* * Main loop for menu UI. */ - if (password_buf)//Make sure that PASSWORD is NUL-terminated. - pass_config = wee_skip_to(password_buf,SKIP_WITH_TERMINATE); + if (password_buf)//Make sure that PASSWORD is NUL-terminated. + pass_config = wee_skip_to(password_buf,SKIP_WITH_TERMINATE); /* clear keyboard buffer before boot */ - while (console_checkkey () == 0x1c0d) console_getkey (); + while ((unsigned short)console_checkkey () == 0x000d); restart1: //clear temp_num when restart menu temp_num = 0; font_spacing = menu_font_spacing; line_spacing = menu_line_spacing; + if (graphics_mode > 0xff) //含字符间隙时,需重新计算 2023-02-22 + { + current_term->max_lines = current_y_resolution / (font_h + line_spacing); + current_term->chars_per_line = current_x_resolution / (font_w + font_spacing); + } /* Dumb terminal always use all entries for display invariant for TERM_DUMB: first_entry == 0 */ if (! (current_term->flags & TERM_DUMB)) + { + if (entryno > MENU_BOX_H - 1) { - if (entryno > MENU_BOX_H - 1) - { - first_entry += entryno - (MENU_BOX_H - 1); - entryno = MENU_BOX_H - 1; - } + first_entry += entryno - (MENU_BOX_H - 1); + entryno = MENU_BOX_H - 1; } + } /* If the timeout was expired or wasn't set, force to show the menu interface. */ @@ -831,53 +900,57 @@ run_menu (char *menu_entries, char *config_entries, /*int num_entries,*/ char *h cls(); /* If SHOW_MENU is false, don't display the menu until a key-press. */ if (! show_menu) + { + /* Get current time. */ +// while ((time1 = getrtsecs ()) == 0xFF) +// ; + if (grub_timeout >= 0) + timeout_enable = 1; + + while (1) { - /* Get current time. */ - while ((time1 = getrtsecs ()) == 0xFF) - ; - - while (1) - { - /* Unhide the menu on any keypress. */ - if (checkkey () != -1 /*&& ASCII_CHAR (getkey ()) == '\e'*/) + /* Unhide the menu on any keypress. */ + if ((i = checkkey ()) != (int)-1 /*&& ASCII_CHAR (getkey ()) == '\e'*/) { - c = getkey();/* eat the key */ + c = i; if (silent_hiddenmenu > 1) { - if (c != silent_hiddenmenu) - goto boot_entry; - if (password_buf) + if (c != silent_hiddenmenu) + goto boot_entry; + if (password_buf) { - if (check_password (password_buf, password_type)) - { - grub_printf ("auth failed!\n"); - grub_timeout = 5; - continue; - } - if (*pass_config) - { - strcpy(config_file,pass_config); - auth = 0; - return; - } - auth = 1; + if (check_password (password_buf, password_type)) + { + grub_printf ("auth failed!\n"); + grub_timeout = 5; + continue; + } + if (*pass_config) + { + strcpy(config_file,pass_config); + auth = 0; + return; + } + auth = 1; } } grub_timeout = -1; + timeout_enable = 0; show_menu = 1; break; } - /* If GRUB_TIMEOUT is expired, boot the default entry. */ - if (grub_timeout >=0 - && (time1 = getrtsecs ()) != time2 + /* If GRUB_TIMEOUT is expired, boot the default entry. */ + if (grub_timeout >=0 +// && (time1 = getrtsecs ()) != time2 + && time1 != time2 /* && time1 != 0xFF */) { if (grub_timeout <= 0) - { - grub_timeout = -1; - goto boot_entry; - } + { +// grub_timeout = -1; + goto boot_entry; + } time2 = time1; grub_timeout--; @@ -885,12 +958,12 @@ run_menu (char *menu_entries, char *config_entries, /*int num_entries,*/ char *h /* Print a message. */ if (! silent_hiddenmenu) { - grub_printf ("\rPress any key to enter the menu... %d ", - grub_timeout); + grub_printf ("\rPress any key to enter the menu... %d ", + grub_timeout); } } - } } + } if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_NORMAL); @@ -902,16 +975,12 @@ run_menu (char *menu_entries, char *config_entries, /*int num_entries,*/ char *h /* Only display the menu if the user wants to see it. */ if (show_menu) - { - cls (); - if (!(menu_tab & 0x80)) - init_page (); - //setcursor (0); - + { + cls (); + if (!(menu_tab & 0x80)) + init_page (); if (graphics_inited && graphics_mode > 0xff)/*vbe mode call rectangle_func*/ { - int i,j; - char y; unsigned long long col = current_color_64bit; for (i=0; i<16; i++) { @@ -920,105 +989,134 @@ run_menu (char *menu_entries, char *config_entries, /*int num_entries,*/ char *h current_color_64bit = DrawBox[i].color; rectangle(DrawBox[i].start_x, DrawBox[i].start_y, DrawBox[i].horiz, DrawBox[i].vert, DrawBox[i].linewidth); } - - if (num_string) - { - for (j=0; j<16; j++) - { - if (strings[j].enable == 0) - continue; - if (strings[j].start_y < 0) - y = strings[j].start_y + current_term->max_lines; - else - y = strings[j].start_y; - gotoxy (strings[j].start_x, y); - current_term->setcolorstate (COLOR_STATE_NORMAL); - if ((strings[j].color & 0xffffffff00000000) == 0) - current_color_64bit = strings[j].color | (current_color_64bit & 0xffffffff00000000); - else - current_color_64bit = strings[j].color | 0x1000000000000000; - grub_printf("%s",strings[j].string); - } - } current_color_64bit = col; } + + if (num_string) + { + int j; + char y; + char *p; + unsigned long long current_color_64bit_back; + unsigned int current_color_back; + grub_u8_t c1; + for (j=0; j<16; j++) + { + if (strings[j].enable == 0) + continue; + if (strings[j].start_y < 0) + y = strings[j].start_y + current_term->max_lines; + else + y = strings[j].start_y; + gotoxy (strings[j].start_x, y); + + if (!(strings[j].color & 0xffffffff00000000)) + { + if (!(splashimage_loaded & 2)) + current_color_64bit = strings[j].color | (console_color_64bit[COLOR_STATE_NORMAL] & 0xffffffff00000000); + else + current_color_64bit = strings[j].color | (current_color_64bit & 0xffffffff00000000); + } + else + current_color_64bit = strings[j].color | 0x1000000000000000; + + current_term->setcolorstate (color_64_to_8 (current_color_64bit & 0x00ffffffffffffff) | 0x100); + + p = strings[j].string; + while(*p) + { + //处理字符串中的彩色字符 + if (*(unsigned short*)p == 0x5B24)//$[ + p = print_color_characters (p,&c1,¤t_color_64bit_back,¤t_color_back); + else + c1 = *(p); + grub_putchar (c1, 255); //123 4456 778 + p++; + } +// grub_printf("%s",strings[j].string); + current_term->setcolorstate (COLOR_STATE_NORMAL); + } + } - if (current_term->flags & TERM_DUMB) - print_entries_raw (num_entries, first_entry, menu_entries); - else /* print border */ - #ifdef SUPPORT_GRAPHICS - if (graphics_inited && graphics_mode > 0xff)/*vbe mode call rectangle_func*/ - { - if (current_term->setcolorstate) - current_term->setcolorstate (COLOR_STATE_BORDER); - unsigned long x,y,w,h,i,j; - i = font_w + font_spacing; - j = font_h + line_spacing; - x = (MENU_BOX_X - 2) * i + (i>>1); - y = (MENU_BOX_Y)*j-(j>>1); - w = (MENU_BOX_W + 2) * i; - if (graphic_type) - h = (graphic_high+row_space) * graphic_row; - else - h = (MENU_BOX_H + 1) * j; - rectangle(x,y,w,h,menu_border.border_w); - } - else - #endif - { - int i; - - if (current_term->setcolorstate) - current_term->setcolorstate (COLOR_STATE_BORDER); + if (current_term->flags & TERM_DUMB) + print_entries_raw (num_entries, first_entry, menu_entries); + else /* print border */ +#ifdef SUPPORT_GRAPHICS + if (graphics_inited && graphics_mode > 0xff)/*vbe mode call rectangle_func*/ + { + if (current_term->setcolorstate) + current_term->setcolorstate (COLOR_STATE_BORDER); + unsigned int x,y,w,h,j; + i = font_w + font_spacing; + j = font_h + line_spacing; + x = (MENU_BOX_X - 2) * i + (i>>1); + y = (MENU_BOX_Y)*j-(j>>1); + if (menu_border.menu_box_w) //如果设置了w,保持 2023-02-22 + w = (MENU_BOX_W + 2) * i; + else //否则,重新计数。因为含间隙字符时,水平像素处以i可能有余数,导致菜单框右边偏大 + w = current_x_resolution - (x<<1); + if (graphic_type) + h = (graphic_high+row_space) * graphic_row; + else + h = (MENU_BOX_H + 1) * j; + rectangle(x,y,w,h,menu_border.border_w); + } + else +#endif + { + if (current_term->setcolorstate) + current_term->setcolorstate (COLOR_STATE_BORDER); - /* upper-left corner */ - gotoxy (MENU_BOX_X - 2, MENU_BOX_Y - 1); - grub_putchar (DISP_UL, 255); + /* upper-left corner */ + gotoxy (MENU_BOX_X - 2, MENU_BOX_Y - 1); + console_print_unicode (DISP_UL, 255); - /* top horizontal line */ - for (i = 0; i < MENU_BOX_W + 1; i++) - grub_putchar (DISP_HORIZ, 255); + /* top horizontal line */ + for (i = 0; i < MENU_BOX_W + 1; i++) + console_print_unicode (DISP_HORIZ, 255); - /* upper-right corner */ - grub_putchar (DISP_UR, 255); + /* upper-right corner */ + console_print_unicode (DISP_UR, 255); - for (i = 0; i < MENU_BOX_H; i++) + for (i = 0; i < MENU_BOX_H; i++) { /* left vertical line */ gotoxy (MENU_BOX_X - 2, MENU_BOX_Y + i); - grub_putchar (DISP_VERT, 255); + console_print_unicode (DISP_VERT, 255); /* right vertical line */ gotoxy (MENU_BOX_E, MENU_BOX_Y + i); - grub_putchar (DISP_VERT, 255); + console_print_unicode (DISP_VERT, 255); } - /* lower-left corner */ - gotoxy (MENU_BOX_X - 2, MENU_BOX_Y + MENU_BOX_H); - grub_putchar (DISP_LL, 255); + /* lower-left corner */ + gotoxy (MENU_BOX_X - 2, MENU_BOX_Y + MENU_BOX_H); + console_print_unicode (DISP_LL, 255); - /* bottom horizontal line */ - for (i = 0; i < MENU_BOX_W + 1; i++) - grub_putchar (DISP_HORIZ, 255); + /* bottom horizontal line */ + for (i = 0; i < MENU_BOX_W + 1; i++) + console_print_unicode (DISP_HORIZ, 255); - /* lower-right corner */ - grub_putchar (DISP_LR, 255); - } + /* lower-right corner */ + console_print_unicode (DISP_LR, 255); + } - if (current_term->setcolorstate) - current_term->setcolorstate (COLOR_STATE_HELPTEXT); + if (current_term->setcolorstate) + current_term->setcolorstate (COLOR_STATE_HELPTEXT); if (!(menu_tab & 4)) print_default_help_message (config_entries); - if (current_term->flags & TERM_DUMB) - grub_printf ("\n\nThe selected entry is %d ", entryno); - else - print_entries (first_entry, entryno, menu_entries); - } - if (menu_init_script_file[0] != 0 ) - command_func(menu_init_script_file,BUILTIN_MENU); + if (current_term->flags & TERM_DUMB) + grub_printf ("\n\nThe selected entry is %d ", entryno); + else + print_entries (first_entry, entryno, menu_entries); + } + if (menu_init_script_file[0] != 0 ) + command_func(menu_init_script_file,BUILTIN_MENU); /* XX using RT clock now, need to initialize value */ - while ((time1 = getrtsecs()) == 0xFF); +// while ((time1 = getrtsecs()) == 0xFF); + if (grub_timeout >= 0) + timeout_enable = 1; old_c = 0; old_c_count = 0; @@ -1026,1303 +1124,712 @@ run_menu (char *menu_entries, char *config_entries, /*int num_entries,*/ char *h temp_entryno = 0; /* Initialize to NULL just in case... */ cur_entry = NULL; + while (1) + { + /* Initialize to NULL just in case... */ +// if (grub_timeout >= 0 && (time1 = getrtsecs()) != time2 /* && time1 != 0xFF */) + if (grub_timeout >= 0 && time1 != time2 /* && time1 != 0xFF */) { - /* Initialize to NULL just in case... */ - //cur_entry = NULL; - //cur_entry = menu_entries; /* for modified menu */ - - if (grub_timeout >= 0 && (time1 = getrtsecs()) != time2 /* && time1 != 0xFF */) - { - if (grub_timeout <= 0) + if (grub_timeout <= 0) { grub_timeout = -1; + timeout_enable = 0; break; } - /* else not booting yet! */ - time2 = time1; + /* else not booting yet! */ + time2 = time1; - if (current_term->setcolorstate) + if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_HELPTEXT); - if (current_term->flags & TERM_DUMB) - grub_printf ("\r Entry %d will be booted automatically in %d seconds. ", - entryno, grub_timeout); - else + if (current_term->flags & TERM_DUMB) + grub_printf ("\r Entry %d will be booted automatically in %d seconds. ", entryno, grub_timeout); + else { -// unsigned long x; -// unsigned long ret; -// unsigned char tmp_buf[512]; -// unsigned char *p; -// unsigned char ch = ' '; - -// grub_sprintf ((char*)tmp_buf, " The highlighted entry will be booted automatically in %d seconds.", grub_timeout); -// gotoxy (0, MENU_BOX_B + 5); -// p = tmp_buf; -// for (x = 0; x < current_term->chars_per_line; x = fontx) -// { -// if (ch >= ' ') -// ch = *p++; -// ret = current_term->chars_per_line - x; -// ret = grub_putchar ((ch >= ' ' ? ch : ' '), ret); -// if ((long)ret < 0) -// break; -// } - if(timeout_x || timeout_y) - gotoxy (timeout_x,timeout_y); - else - { - if(!(menu_tab & 0x40)) - gotoxy (MENU_BOX_E - 2, MENU_BOX_Y + entryno); - else - gotoxy (MENU_BOX_X - 1, MENU_BOX_Y + entryno); - } - - if(timeout_color) - { - current_term->setcolorstate (COLOR_STATE_NORMAL); - if ((timeout_color & 0xffffffff00000000) == 0) - current_color_64bit = timeout_color | (current_color_64bit & 0xffffffff00000000); - else - current_color_64bit = timeout_color; - } - else - if (current_term->setcolorstate) - current_term->setcolorstate (COLOR_STATE_HIGHLIGHT); + if(timeout_x || timeout_y) + gotoxy (timeout_x,timeout_y); + else + { + if(!(menu_tab & 0x40)) + gotoxy (MENU_BOX_E - 2, MENU_BOX_Y + entryno); + else + gotoxy (MENU_BOX_X - 1, MENU_BOX_Y + entryno); + } + + if(timeout_color) + { + if (!(timeout_color & 0xffffffff00000000)) + { + if (!(splashimage_loaded & 2)) + current_color_64bit = timeout_color | (console_color_64bit[COLOR_STATE_NORMAL] & 0xffffffff00000000); + else + current_color_64bit = timeout_color; + } + else + current_color_64bit = timeout_color | 0x1000000000000000; + + current_term->setcolorstate (color_64_to_8 (current_color_64bit & 0x00ffffffffffffff) | 0x100); + } + else + if (current_term->setcolorstate) + current_term->setcolorstate (COLOR_STATE_HIGHLIGHT); grub_printf("%2d",grub_timeout); - if (current_term->setcolorstate) + + if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_HELPTEXT); - gotoxy (MENU_BOX_E, MENU_BOX_Y + entryno); + gotoxy (MENU_BOX_E, MENU_BOX_Y + entryno); } - grub_timeout--; - } - - if (grub_timeout >= 0) - { - defer(1); - if (animated_enable) - animated(); - if (beep_enable) - beep_func((char *)beep_buf,1); - if (DateTime_enable) - DateTime_refresh(); - } - /* Check for a keypress, however if TIMEOUT has been expired - (GRUB_TIMEOUT == -1) relax in GETKEY even if no key has been - pressed. - This avoids polling (relevant in the grub-shell and later on - in grub if interrupt driven I/O is done). */ - if (checkkey () >= 0 || grub_timeout < 0) - { - /* Key was pressed, show which entry is selected before GETKEY, + grub_timeout--; + } +#if 0 + if (grub_timeout >= 0) + { + defer(1); + if (animated_enable) + animated(); + if (DateTime_enable) + DateTime_refresh(); + } +#endif + /* Check for a keypress, however if TIMEOUT has been expired + (GRUB_TIMEOUT == -1) relax in GETKEY even if no key has been pressed. + This avoids polling (relevant in the grub-shell and later on + in grub if interrupt driven I/O is done). */ + if ((i = checkkey ()) >= 0 || grub_timeout < 0) + { + /* Key was pressed, show which entry is selected before GETKEY, since we're comming in here also on GRUB_TIMEOUT == -1 and hang in GETKEY */ - if (current_term->flags & TERM_DUMB) - grub_printf ("\r Highlighted entry is %d: ", entryno); - if (config_entries && hotkey_func) - { - putchar_hooked = (unsigned char*)0x800; - //0x4b40 flags HK, - c = hotkey_func(0,-1,(0x4B40<<16)|(first_entry << 8) | entryno); - putchar_hooked = 0; - - if (beep_enable) + if (current_term->flags & TERM_DUMB) + grub_printf ("\r Highlighted entry is %d: ", entryno); + + if (i < 0) + i = getkey (); + else + clear_delay_display (entryno); + c = i; + if (config_entries && hotkey_func) { - beep_enable = 0; - beep_play = 0; - beep_frequency = 0; - console_beep(); - } - - if (c == -1) + //由于checkkey后,uefi键盘缓存已经清除,只能保存和使用其返回值i + i = (*hotkey_func)(0,-1,(0x4B40<<16)|(first_entry << 8) | entryno,i); +// putchar_hooked = 0; + c = i; + if (i == -1) goto restart1; - if (c>>16) - { - temp_entryno = (long)(unsigned char)(c>>16); - if (c & 1<<30) - goto check_update; - entryno = temp_entryno; - first_entry = 0; - goto boot_entry; - } - } - else - c = /*ASCII_CHAR*/ (getkey ()); - - if (beep_enable) - { - beep_enable = 0; - beep_play = 0; - beep_frequency = 0; - console_beep(); - } - - if (! old_c_count_end) - { - if (old_c == 0) - old_c = c; - if (c == old_c && old_c_count < 0x7FFFFFFF) - old_c_count++; - if (c != old_c) - { - old_c_count_end = 1; - } - } - - if (grub_timeout >= 0) + if (i>>16) + { + temp_entryno = (int)(unsigned char)(i>>16); + if (i & 1<<30) + goto check_update; + entryno = temp_entryno; + first_entry = 0; + goto boot_entry; + } + } + if (! old_c_count_end) + { + if (old_c == 0) + old_c = c; + if (c == old_c && old_c_count < 0x7FFFFFFF) + old_c_count++; + if (c != old_c) + old_c_count_end = 1; + } +#if 0 + if (grub_timeout >= 0) { -// unsigned long x; - if (current_term->setcolorstate) - current_term->setcolorstate (COLOR_STATE_HELPTEXT); + current_term->setcolorstate (COLOR_STATE_HELPTEXT); if (current_term->flags & TERM_DUMB) - grub_putchar ('\r', 255); -// else -// gotoxy (0, MENU_BOX_B + 5); -// for (x = 0; x < current_term->chars_per_line; x++) -// { -// grub_putchar (' ', 255); -// } - if(timeout_x || timeout_y) - gotoxy (timeout_x,timeout_y); - else - { - if(!(menu_tab & 0x40)) - gotoxy (MENU_BOX_E - 2, MENU_BOX_Y + entryno); - else - gotoxy (MENU_BOX_X - 1, MENU_BOX_Y + entryno); - } - - if(timeout_color) - { - current_term->setcolorstate (COLOR_STATE_NORMAL); - if ((timeout_color & 0xffffffff00000000) == 0) - current_color_64bit = timeout_color | (current_color_64bit & 0xffffffff00000000); - else - current_color_64bit = timeout_color; - } - else - if (current_term->setcolorstate) - current_term->setcolorstate (COLOR_STATE_HIGHLIGHT); - - grub_printf(" "); - if (current_term->setcolorstate) - current_term->setcolorstate (COLOR_STATE_HELPTEXT); - - grub_timeout = -1; - fallback_entryno = -1; - if (! (current_term->flags & TERM_DUMB)) - gotoxy (MENU_BOX_E, MENU_BOX_Y + entryno); - } - - if (num_entries == 0) - { - first_entry = entryno = 0; - goto done_key_handling; - } - - if (c==0x3c00) - { - if (animated_type) - animated_enable ^= 1; - animated_enable_backup = animated_enable; - goto restart1; - } - - /* We told them above (at least in SUPPORT_SERIAL) to use - '^' or 'v' so accept these keys. */ - if (c == KEY_UP/*16*/ || c == KEY_LEFT || ((char)c) == '^') - { - temp_entryno = 0; - if (current_term->flags & TERM_DUMB) - { - if (entryno > 0) - entryno--; - } - else - { - if (c == KEY_UP) - { - temp_entryno = first_entry + entryno; - for (;;) - { - temp_entryno = (temp_entryno + num_entries - 1) % num_entries; - if (temp_entryno == first_entry + entryno) - goto done_key_handling; - cur_entry = get_entry (menu_entries, temp_entryno); - if (*cur_entry != 0x08) - goto check_update; - } - } - - if (entryno > 0) - { - //cur_entry = get_entry (menu_entries, first_entry + entryno); - /* un-highlight the current entry */ - print_entry (MENU_BOX_Y + entryno, 0, first_entry + entryno, menu_entries); - --entryno; - //cur_entry = get_entry (menu_entries, first_entry + entryno); - /* highlight the previous entry */ - print_entry (MENU_BOX_Y + entryno, 1, first_entry + entryno, menu_entries); - } - else if (first_entry > 0) - { - first_entry--; - print_entries (first_entry, entryno, menu_entries); - } - else /* loop forward to END */ - { - temp_entryno = num_entries - 1; - goto check_update; - } - } - } - else if ((c == KEY_DOWN/*14*/ || c == KEY_RIGHT || ((char)c) == 'v' || (!old_c_count_end && c == old_c && old_c_count >= 8)) - /* && first_entry + entryno + 1 < num_entries */) - { - temp_entryno = 0; - if (current_term->flags & TERM_DUMB) - { - if (first_entry + entryno + 1 < num_entries) - entryno++; - } - else - { - if (c == KEY_DOWN) - { - temp_entryno = first_entry + entryno; - for (;;) - { - temp_entryno = (temp_entryno + 1) % num_entries; - if (temp_entryno == first_entry + entryno) - goto done_key_handling; - cur_entry = get_entry (menu_entries, temp_entryno); - if (*cur_entry != 0x08) - goto check_update; - } - } - - if (first_entry + entryno + 1 >= num_entries) - { - temp_entryno = 0; /* loop backward to HOME */ - goto check_update; - } - if (entryno < MENU_BOX_H - 1) - { - //cur_entry = get_entry (menu_entries, first_entry + entryno); - /* un-highlight the current entry */ - print_entry (MENU_BOX_Y + entryno, 0, first_entry + entryno, menu_entries); - //entryno++; - //cur_entry = get_entry (menu_entries, first_entry + entryno); - /* highlight the next entry */ - ++entryno; - print_entry (MENU_BOX_Y + entryno, 1, first_entry + entryno, menu_entries); - } - else if (num_entries > MENU_BOX_H + first_entry) - { - first_entry++; - print_entries (first_entry, entryno, menu_entries); - } - } - } - else if (c == KEY_PPAGE/*7*/) - { - /* Page Up */ - temp_entryno = 0; - first_entry -= MENU_BOX_H; - if (first_entry < 0) - { - entryno += first_entry; - first_entry = 0; - if (entryno < 0) - entryno = 0; - } - print_entries (first_entry, entryno, menu_entries); - } - else if (c == KEY_NPAGE/*3*/) - { - /* Page Down */ - temp_entryno = 0; - first_entry += MENU_BOX_H; - if (first_entry + entryno + 1 >= num_entries) - { - first_entry = num_entries - MENU_BOX_H; - if (first_entry < 0) - first_entry = 0; - entryno = num_entries - first_entry - 1; - } - print_entries (first_entry, entryno, menu_entries); - } - else if ( ((char)c) >= '0' && ((char)c) <= '9') - { - temp_num *= 10; - temp_num += ((char)c) - '0'; -// if (temp_entryno >= num_entries) -// temp_entryno = num_entries - 1; - if (temp_num >= num_entries) /* too big an entryno */ - { - temp_num = ((char)c - '0'>= num_entries)?0:(char)c - '0'; - } - temp_entryno = temp_num; - if (temp_entryno != 0 || (char)c == '0') - { - - + grub_putchar ('\r', 255); + if(timeout_x || timeout_y) + gotoxy (timeout_x,timeout_y); + else + { + if(!(menu_tab & 0x40)) + gotoxy (MENU_BOX_E - 2, MENU_BOX_Y + entryno); + else + gotoxy (MENU_BOX_X - 1, MENU_BOX_Y + entryno); + } + current_term->setcolorstate (COLOR_STATE_NORMAL); + grub_printf(" "); + if (current_term->setcolorstate) + current_term->setcolorstate (COLOR_STATE_HELPTEXT); + + grub_timeout = -1; + fallback_entryno = -1; + if (! (current_term->flags & TERM_DUMB)) + gotoxy (MENU_BOX_E, MENU_BOX_Y + entryno); + } +#else + clear_delay_display (entryno); +#endif + if (num_entries == 0) + { + first_entry = entryno = 0; + goto done_key_handling; + } + + if (c==0x3c00) + { + if (animated_type) + animated_enable ^= 1; + animated_enable_backup = animated_enable; + goto restart1; + } + /* We told them above (at least in SUPPORT_SERIAL) to use + '^' or 'v' so accept these keys. */ + if (c == KEY_UP/*16*/ || c == KEY_LEFT || ((char)c) == '^') + { + temp_entryno = 0; + if (current_term->flags & TERM_DUMB) + { + if (entryno > 0) + entryno--; + } + else + { + if (c == KEY_UP) + { + temp_entryno = first_entry + entryno; + for (;;) + { + temp_entryno = (temp_entryno + num_entries - 1) % num_entries; + if (temp_entryno == first_entry + entryno) + goto done_key_handling; + cur_entry = get_entry (menu_entries, temp_entryno); + if (*cur_entry != 0x08) + goto check_update; + } + } + + if (entryno > 0) + { + //cur_entry = get_entry (menu_entries, first_entry + entryno); + /* un-highlight the current entry */ + print_entry (MENU_BOX_Y + entryno, 0, first_entry + entryno, menu_entries); + --entryno; + //cur_entry = get_entry (menu_entries, first_entry + entryno); + /* highlight the previous entry */ + print_entry (MENU_BOX_Y + entryno, 1, first_entry + entryno, menu_entries); + } + else if (first_entry > 0) + { + first_entry--; + print_entries (first_entry, entryno, menu_entries); + } + else /* loop forward to END */ + { + temp_entryno = num_entries - 1; + goto check_update; + } + } + } + else if ((c == KEY_DOWN/*14*/ || c == KEY_RIGHT || ((char)c) == 'v' || (!old_c_count_end && c == old_c && old_c_count >= 8)) + /* && first_entry + entryno + 1 < num_entries */) + { + temp_entryno = 0; + if (current_term->flags & TERM_DUMB) + { + if (first_entry + entryno + 1 < num_entries) + entryno++; + } + else + { + if (c == KEY_DOWN) + { + temp_entryno = first_entry + entryno; + for (;;) + { + temp_entryno = (temp_entryno + 1) % num_entries; + if (temp_entryno == first_entry + entryno) + goto done_key_handling; + cur_entry = get_entry (menu_entries, temp_entryno); + if (*cur_entry != 0x08) + goto check_update; + } + } + + if (first_entry + entryno + 1 >= num_entries) + { + temp_entryno = 0; /* loop backward to HOME */ + goto check_update; + } + if (entryno < MENU_BOX_H - 1) + { + //cur_entry = get_entry (menu_entries, first_entry + entryno); + /* un-highlight the current entry */ + print_entry (MENU_BOX_Y + entryno, 0, first_entry + entryno, menu_entries); + /* highlight the next entry */ + ++entryno; + print_entry (MENU_BOX_Y + entryno, 1, first_entry + entryno, menu_entries); + } + else if ((int)num_entries > MENU_BOX_H + first_entry) + { + first_entry++; + print_entries (first_entry, entryno, menu_entries); + } + } + } + else if (c == KEY_PPAGE/*7*/) + { + /* Page Up */ + temp_entryno = 0; + first_entry -= MENU_BOX_H; + if (first_entry < 0) + { + entryno += first_entry; + first_entry = 0; + if (entryno < 0) + entryno = 0; + } + print_entries (first_entry, entryno, menu_entries); + } + else if (c == KEY_NPAGE/*3*/) + { + /* Page Down */ + temp_entryno = 0; + first_entry += MENU_BOX_H; + if (first_entry + entryno + 1 >= num_entries) + { + first_entry = num_entries - MENU_BOX_H; + if (first_entry < 0) + first_entry = 0; + entryno = num_entries - first_entry - 1; + } + print_entries (first_entry, entryno, menu_entries); + } + else if ( ((char)c) >= '0' && ((char)c) <= '9') + { + temp_num *= 10; + temp_num += ((char)c) - '0'; + if (temp_num >= num_entries) /* too big an entryno */ + temp_num = ((char)c - '0'>= num_entries)?0:(char)c - '0'; + temp_entryno = temp_num; + if (temp_entryno != 0 || (char)c == '0') + { // temp_entryno has users number - check if it matches a title number // If menu items are numbered then there must be no unnumbered items in the first few entries // e.g. if you have 35 menu items, then menu entries 0 - 3 must all numbered - otherwise double-digit user entry will not work - e.g. 34 will not work - int j; - if (menu_num_ctrl[0]) - { - if (menu_num_ctrl[0] == 1) - { - j = temp_num; - while(title_boot[j+1]<=temp_num) - { - ++j; - } - if (title_boot[j] == temp_num) - temp_entryno = j; - } - } - else - { - for (j = 0; j < num_entries; ++j) - { - // grub_printf("TE%d C%dC A%dATE%s ",temp_entryno,checkvalue (get_entry (menu_entries,j) ),myatoi (get_entry (menu_entries,j)),get_entry(menu_entries,j)); - clean_entry (get_entry (menu_entries, j)); - if (checkvalue () > 0 && myatoi () == temp_entryno) - { - temp_entryno = j; - j = num_entries; - } - } - } + int j; + if (menu_num_ctrl[0]) + { + if (menu_num_ctrl[0] == 1) + { + j = temp_num; + while(title_boot[j+1]<=temp_num) + ++j; + if (title_boot[j] == temp_num) + temp_entryno = j; + } + } + else + { + for (j = 0; j < num_entries; ++j) + { + clean_entry (get_entry (menu_entries, j)); + if (checkvalue () > 0 && myatoi () == temp_entryno) + { + temp_entryno = j; + j = num_entries; + } + } + } check_update: - if (temp_entryno != first_entry + entryno) - { - /* check if entry temp_entryno is out of the screen */ - if (temp_entryno < first_entry || temp_entryno >= first_entry + MENU_BOX_H) - { - first_entry = (temp_entryno / MENU_BOX_H) * MENU_BOX_H; - entryno = temp_entryno % MENU_BOX_H; - print_entries (first_entry, entryno, menu_entries); - } else { - /* entry temp_entryno is on the screen, its relative entry number is - * (temp_entryno - first_entry) */ - //cur_entry = get_entry (menu_entries, first_entry + entryno); - /* un-highlight the current entry */ - print_entry (MENU_BOX_Y + entryno, 0, first_entry + entryno, menu_entries); - entryno = temp_entryno - first_entry; - //cur_entry = get_entry (menu_entries, temp_entryno); - /* highlight entry temp_entryno */ - print_entry (MENU_BOX_Y + entryno, 1, temp_entryno, menu_entries); - } - } - } - if (temp_entryno >= num_entries) - temp_entryno = 0; - } - else if (c == KEY_HOME/*1*/) - { - temp_entryno = 0; - goto check_update; - } - else if (c == KEY_END/*5*/) - { - temp_entryno = num_entries - 1; - goto check_update; - } - else - temp_entryno = 0; + if (temp_entryno != first_entry + entryno) + { + /* check if entry temp_entryno is out of the screen */ + if (temp_entryno < first_entry || temp_entryno >= first_entry + MENU_BOX_H) + { + first_entry = (temp_entryno / MENU_BOX_H) * MENU_BOX_H; + entryno = temp_entryno % MENU_BOX_H; + print_entries (first_entry, entryno, menu_entries); + } else { + /* entry temp_entryno is on the screen, its relative entry number is + * (temp_entryno - first_entry) */ + print_entry (MENU_BOX_Y + entryno, 0, first_entry + entryno, menu_entries); + entryno = temp_entryno - first_entry; + /* highlight entry temp_entryno */ + print_entry (MENU_BOX_Y + entryno, 1, temp_entryno, menu_entries); + } + } + } + if (temp_entryno >= num_entries) + temp_entryno = 0; + } + else if (c == KEY_HOME/*1*/) + { + temp_entryno = 0; + goto check_update; + } + else if (c == KEY_END/*5*/) + { + temp_entryno = num_entries - 1; + goto check_update; + } + else + temp_entryno = 0; done_key_handling: + if (current_term->setcolorstate) + current_term->setcolorstate (COLOR_STATE_HEADING); - if (current_term->setcolorstate) - current_term->setcolorstate (COLOR_STATE_HEADING); - -// if (debug > 0) -// { -// gotoxy (MENU_BOX_E - 4, MENU_BOX_Y - 2); -// grub_printf ("%3d ", (first_entry + entryno)); -// } - gotoxy (MENU_BOX_E, MENU_BOX_Y + entryno); - - if (current_term->setcolorstate) - current_term->setcolorstate (COLOR_STATE_STANDARD); - - if (!old_c_count_end && c == old_c && (old_c_count >= 30 || (old_c_count >= 8 && c != KEY_DOWN /*&& c != KEY_RIGHT*/ && c != KEY_UP /*&& c != KEY_LEFT*/))) - grub_timeout = 5; - - cur_entry = NULL; + gotoxy (MENU_BOX_E, MENU_BOX_Y + entryno); - if (config_entries) - { - if ((((char)c) == '\n') || (((char)c) == '\r') || (((char)c) == 'b') || (((char)c) == '#') || (((char)c) == '*')) - break; - } - else - { - if ((((char)c) == 'd') || (((char)c) == 'o') || (((char)c) == 'O')) - { - if (! (current_term->flags & TERM_DUMB)) - print_entry (MENU_BOX_Y + entryno, 0,first_entry + entryno, menu_entries); - - /* insert after is almost exactly like insert before */ - if (((char)c) == 'o') - { - /* But `o' differs from `O', since it may causes - the menu screen to scroll up. */ - if (num_entries > 0) - { - if (entryno < MENU_BOX_H - 1 || (current_term->flags & TERM_DUMB)) - entryno++; - else - first_entry++; - } - - c = 'O'; - } - - cur_entry = get_entry (menu_entries, first_entry + entryno); - - if (((char)c) == 'O') - { - grub_memmove (cur_entry + 2, cur_entry, ((int) heap) - ((int) cur_entry)); - - cur_entry[0] = ' '; - cur_entry[1] = 0; - - heap += 2; - - /*if (first_entry + entryno == num_entries - 1) - { - cur_entry[2] = 0; - heap++; - }*/ - - num_entries++; - } - else if (num_entries > 0) - { - char *ptr = get_entry (menu_entries, first_entry + entryno + 1); - - grub_memmove (cur_entry, ptr, ((int) heap) - ((int) ptr)); - heap -= (((int) ptr) - ((int) cur_entry)); - - num_entries--; - - if (/*entryno >= num_entries && */entryno > 0) - entryno--; - else if (first_entry/* && num_entries < MENU_BOX_H + first_entry*/) - first_entry--; - } - - if (current_term->flags & TERM_DUMB) - { - grub_putchar ('\n', 255); - grub_putchar ('\n', 255); - print_entries_raw (num_entries, first_entry, menu_entries); - } - else if (num_entries > 0) - print_entries (first_entry, entryno, menu_entries); - else - print_entry (MENU_BOX_Y, 0, first_entry + entryno, menu_entries); - } + if (current_term->setcolorstate) + current_term->setcolorstate (COLOR_STATE_STANDARD); - cur_entry = menu_entries; - if (((char)c) == 27) - return; - if (((char)c) == 'b') - break; - } + if (!old_c_count_end && c == old_c && (old_c_count >= 30 || (old_c_count >= 8 && c != KEY_DOWN /*&& c != KEY_RIGHT*/ && c != KEY_UP /*&& c != KEY_LEFT*/))) + grub_timeout = 5; - if (! auth && password_buf) - { - if (((char)c) == 'p') - { - /* Do password check here! */ - if (current_term->flags & TERM_DUMB) - grub_printf ("\r "); - else - { - if (MENU_BOX_B + 1 > current_term->max_lines) - gotoxy (MENU_HELP_X, MENU_BOX_H); - else - gotoxy (MENU_HELP_X, (MENU_HELP_X ? MENU_BOX_B : (MENU_BOX_B + 1))); - } - - password_x = MENU_HELP_X; - if (current_term->setcolorstate) - current_term->setcolorstate (COLOR_STATE_HELPTEXT); + cur_entry = NULL; - if (! check_password (password_buf, password_type)) - { - /* If *pass_config is NUL, then allow the user to use - privileged instructions, otherwise, load - another configuration file. */ - if (*pass_config) - { - strcpy(config_file,pass_config); - /* Make sure that the user will not have - authority in the next configuration. */ - auth = 0; - return; - } - else - { - /* Now the user is superhuman. */ - auth = 1; - goto restart1; - } - } - else - { - grub_printf ("Failed! Press any key to continue..."); - getkey (); - goto restart1; - } - } - } - else - { - //if (((char)c) == 'e' && c != 0xE065) /* repulse GigaByte Key-E attack */ - if ( c == 0x1265) /* repulse GigaByte Key-E attack */ - { - int new_num_entries = 0, i = 0; - char *new_heap; - font_spacing = 0; - line_spacing = 0; - - if (num_entries == 0) - { - first_entry = entryno = 0; - cur_entry = get_entry (menu_entries, 0); - grub_memmove (cur_entry + 2, cur_entry, ((int) heap) - ((int) cur_entry)); - - cur_entry[0] = ' '; - cur_entry[1] = 0; - - heap += 2; - - /*if (first_entry + entryno == num_entries - 1) - { - cur_entry[2] = 0; - heap++; - }*/ - - num_entries++; - } - - // while (first_entry + entryno >= num_entries) - // { - // if (entryno > 0) - // entryno--; - // else - // first_entry--; - // } - - if (config_entries) - { - new_heap = heap; - //cur_entry = get_entry (config_entries, first_entry + entryno, 1); - cur_entry = titles[first_entry + entryno]; - while (*cur_entry++); /* the first entry */ - } - else - { - /* safe area! */ - new_heap = heap + NEW_HEAPSIZE + 1; - cur_entry = get_entry (menu_entries, first_entry + entryno); - } - - do - { - while ((*(new_heap++) = cur_entry[i++]) != 0); - new_num_entries++; - } - while (config_entries && cur_entry[i]); - - /* this only needs to be done if config_entries is non-NULL, - but it doesn't hurt to do it always */ - *(new_heap++) = 0; - - if (config_entries && new_num_entries) - { - int old_num_entries = num_entries; - unsigned char graphic_type_back = graphic_type; - graphic_type = 0; - num_entries = new_num_entries; - run_menu (heap, NULL, /*new_num_entries,*/ new_heap, 0); /* recursive!! */ - num_entries = old_num_entries; - graphic_type = graphic_type_back; - goto restart1; - } - //else - { - animated_enable_backup = animated_enable; - animated_enable = 0; - setcursor (1); /* show cursor and disable splashimage */ - cls (); - print_cmdline_message (0); - - new_heap = heap + NEW_HEAPSIZE + 1; - - saved_drive = boot_drive; - saved_partition = install_partition; - current_drive = GRUB_INVALID_DRIVE; - - get_cmdline_str.prompt = (unsigned char*)PACKAGE " edit> "; - get_cmdline_str.maxlen = NEW_HEAPSIZE + 1; - get_cmdline_str.echo_char = 0; - get_cmdline_str.readline = 1; - get_cmdline_str.cmdline= (unsigned char*)new_heap; - if (! get_cmdline ()) - { - int j = 0; - - /* get length of new command */ - while (new_heap[j++]) - ; - - if (j < 2) - { - j = 2; - new_heap[0] = ' '; - new_heap[1] = 0; - } - - /* align rest of commands properly */ - grub_memmove (cur_entry + j, cur_entry + i, (int) heap - ((int) cur_entry + i)); - - /* copy command to correct area */ - grub_memmove (cur_entry, new_heap, j); - - heap += (j - i); - if (first_entry + entryno == num_entries - 1) - { - cur_entry[j] = 0; - heap++; - } - } - } + if (config_entries) + { + if ((((char)c) == '\n') || (((char)c) == '\r') || (((char)c) == 'b') || (((char)c) == '#') || (((char)c) == '*')) + break; + } + else + { + if ((((char)c) == 'd') || (((char)c) == 'o') || (((char)c) == 'O')) + { + if (! (current_term->flags & TERM_DUMB)) + print_entry (MENU_BOX_Y + entryno, 0,first_entry + entryno, menu_entries); + + /* insert after is almost exactly like insert before */ + if (((char)c) == 'o') + { + /* But `o' differs from `O', since it may causes + the menu screen to scroll up. */ + if (num_entries > 0) + { + if (entryno < MENU_BOX_H - 1 || (current_term->flags & TERM_DUMB)) + entryno++; + else + first_entry++; + } + c = 'O'; + } + + cur_entry = get_entry (menu_entries, first_entry + entryno); + + if (((char)c) == 'O') + { + grub_memmove (cur_entry + 2, cur_entry, ((grub_size_t) heap) - ((grub_size_t) cur_entry)); + cur_entry[0] = ' '; + cur_entry[1] = 0; + heap += 2; + num_entries++; + } + else if (num_entries > 0) + { + char *ptr = get_entry (menu_entries, first_entry + entryno + 1); + + grub_memmove (cur_entry, ptr, ((grub_size_t) heap) - ((grub_size_t) ptr)); + heap -= (((grub_size_t) ptr) - ((grub_size_t) cur_entry)); + + num_entries--; + + if (/*entryno >= num_entries && */entryno > 0) + entryno--; + else if (first_entry/* && num_entries < MENU_BOX_H + first_entry*/) + first_entry--; + } + + if (current_term->flags & TERM_DUMB) + { + grub_putchar ('\n', 255); + grub_putchar ('\n', 255); + print_entries_raw (num_entries, first_entry, menu_entries); + } + else if (num_entries > 0) + print_entries (first_entry, entryno, menu_entries); + else + print_entry (MENU_BOX_Y, 0, first_entry + entryno, menu_entries); + } + + cur_entry = menu_entries; + if (((char)c) == 27) + return; + if (((char)c) == 'b') + break; + } - goto restart1; - } - if (((char)c) == 'c') - { - font_spacing = 0; - line_spacing = 0; - animated_enable_backup = animated_enable; - animated_enable = 0; - setcursor (1); - cls (); - enter_cmdline (heap, 0); - goto restart1; - } - } - } - } - - /* Attempt to boot an entry. */ - - boot_entry: + if (! auth && password_buf) + { + if (((char)c) == 'p') + { + /* Do password check here! */ + if (current_term->flags & TERM_DUMB) + grub_printf ("\r "); + else + { + if (MENU_BOX_B + 1 > current_term->max_lines) + gotoxy (MENU_HELP_X, MENU_BOX_H); + else + gotoxy (MENU_HELP_X, (MENU_HELP_X ? MENU_BOX_B : (MENU_BOX_B + 1))); + } + + password_x = MENU_HELP_X; + if (current_term->setcolorstate) + current_term->setcolorstate (COLOR_STATE_HELPTEXT); + + if (! check_password (password_buf, password_type)) + { + /* If *pass_config is NUL, then allow the user to use + privileged instructions, otherwise, load + another configuration file. */ + if (*pass_config) + { + strcpy(config_file,pass_config); + /* Make sure that the user will not have + authority in the next configuration. */ + auth = 0; + return; + } + else + { + /* Now the user is superhuman. */ + auth = 1; + goto restart1; + } + } + else + { + grub_printf ("Failed! Press any key to continue..."); + getkey (); + goto restart1; + } + } + } + else + { + if (((char)c) == 'e' && c != 0xE065) /* repulse GigaByte Key-E attack */ + //if ( c == 0x1265) /* repulse GigaByte Key-E attack */ + { + int new_num_entries = 0; + i = 0; + char *new_heap; + font_spacing = menu_font_spacing; //恢复图形模式时需要 2023-02-22 + line_spacing = menu_line_spacing; + font_spacing = 0; + line_spacing = 0; + + if (num_entries == 0) + { + first_entry = entryno = 0; + cur_entry = get_entry (menu_entries, 0); + grub_memmove (cur_entry + 2, cur_entry, ((grub_size_t) heap) - ((grub_size_t) cur_entry)); + + cur_entry[0] = ' '; + cur_entry[1] = 0; + heap += 2; + num_entries++; + } + + if (config_entries) + { + new_heap = heap; + cur_entry = titles[first_entry + entryno]; + while (*cur_entry++); /* the first entry */ + } + else + { + /* safe area! */ + new_heap = heap + NEW_HEAPSIZE + 1; + cur_entry = get_entry (menu_entries, first_entry + entryno); + } + + do + { + while ((*(new_heap++) = cur_entry[i++]) != 0); + new_num_entries++; + } + while (config_entries && cur_entry[i]); + + /* this only needs to be done if config_entries is non-NULL, + but it doesn't hurt to do it always */ + *(new_heap++) = 0; + + if (config_entries && new_num_entries) + { + int old_num_entries = num_entries; + unsigned char graphic_type_back = graphic_type; + graphic_type = 0; + num_entries = new_num_entries; + run_menu (heap, NULL, /*new_num_entries,*/ new_heap, 0); /* recursive!! */ + num_entries = old_num_entries; + graphic_type = graphic_type_back; + goto restart1; + } + + { + animated_enable_backup = animated_enable; + animated_enable = 0; + setcursor (1); /* show cursor and disable splashimage */ + if (current_term->setcolorstate) + current_term->setcolorstate (COLOR_STATE_STANDARD); + cls (); + print_cmdline_message (0); + new_heap = heap + NEW_HEAPSIZE + 1; + current_drive = GRUB_INVALID_DRIVE; + get_cmdline_str.prompt = (unsigned char*)PACKAGE " edit> "; + get_cmdline_str.maxlen = NEW_HEAPSIZE + 1; + get_cmdline_str.echo_char = 0; + get_cmdline_str.readline = 1; + get_cmdline_str.cmdline= (unsigned char*)new_heap; + if (! get_cmdline ()) + { + int j = 0; + + /* get length of new command */ + while (new_heap[j++]) + ; + + if (j < 2) + { + j = 2; + new_heap[0] = ' '; + new_heap[1] = 0; + } + + /* align rest of commands properly */ + grub_memmove (cur_entry + j, cur_entry + i, (grub_size_t) heap - ((grub_size_t) cur_entry + i)); + + /* copy command to correct area */ + grub_memmove (cur_entry, new_heap, j); + + heap += (j - i); + if (first_entry + entryno == num_entries - 1) + { + cur_entry[j] = 0; + heap++; + } + } + } + + goto restart1; + } + if (((char)c) == 'c') + { + font_spacing = menu_font_spacing; //恢复图形模式时需要 2023-02-22 + line_spacing = menu_line_spacing; + font_spacing = 0; + line_spacing = 0; + animated_enable_backup = animated_enable; + animated_enable = 0; + setcursor (1); + if (current_term->setcolorstate) + current_term->setcolorstate (COLOR_STATE_STANDARD); + cls (); + enter_cmdline (heap, 0); + goto restart1; + } + } + }//if ((i = checkkey ()) >= 0 || grub_timeout < 0) + }//while (1) + /* Attempt to boot an entry. */ +boot_entry: + grub_timeout = -1; + timeout_enable = 0; + if (ext_timer) + { + grub_free (ext_timer); + ext_timer = 0; + } + setcursor (1); /* show cursor and disable splashimage */ animated_enable_backup = animated_enable; animated_enable = 0; - setcursor (1); /* show cursor and disable splashimage */ + if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_STANDARD); cls (); -// /* if our terminal needed initialization, we should shut it down -// * before booting the kernel, but we want to save what it was so -// * we can come back if needed */ -// prev_term = current_term; -//// if (current_term->shutdown) -//// { -//// (*current_term->shutdown)(); -//// current_term = term_table; /* assumption: console is first */ -//// } + font_spacing = menu_font_spacing; //恢复图形模式时需要 2023-02-22 + line_spacing = menu_line_spacing; font_spacing = 0; line_spacing = 0; fallbacked_entries = 0; while (1) + { + if (debug > 0) { - if (debug > 0) - { - if (config_entries) - { - char *p; - - p = get_entry (menu_entries, first_entry + entryno); - //printf (" Booting \'%s\'\n\n", (((*p) & 0xF0) ? p : ++p)); - if (! ((*p) & 0xF0)) - p++; - //(for Issue 123)changed by chenall 2013-04-19 also translate variables for booting message. - #if 0 - unsigned char ch; - grub_putstr (" Booting "); - while ((*p) && (ch = *p++) && ch != '\n') grub_putchar (ch, 255); - grub_putchar ('\n', 255); - grub_putchar ('\n', 255); - #else - char *p_t = (char *)SCRATCHADDR; - while(*p && *p != '\n') - *p_t++ = *p++; - *p_t++ = 0; - expand_var ((char *)SCRATCHADDR, p_t, 0x400); - printf (" Booting \'%s\'\n\n",p_t); - #endif - } - else - printf (" Booting command-list\n\n"); - } - - /* Set CURRENT_ENTRYNO for the command "savedefault". */ - current_entryno = first_entry + entryno; - - if (! cur_entry) - { - //cur_entry = get_entry (config_entries, first_entry + entryno, 1); - cur_entry = titles[current_entryno]; - while (*cur_entry++); - } - - if (current_entryno >= num_entries)//Max entries - break; - - if (! run_script (cur_entry, heap)) - break; - if (fallback_entryno < 0) - break; - cur_entry = NULL; - first_entry = 0; - entryno = fallback_entries[fallback_entryno]; - fallback_entryno++; - if (fallback_entryno >= MAX_FALLBACK_ENTRIES || fallback_entries[fallback_entryno] < 0) - fallback_entryno = -1; - fallbacked_entries++; - if (fallbacked_entries > num_entries * num_entries * 4) - { - printf ("\nEndless fallback loop detected(entry=%d)! Press any key to exit...", current_entryno); - (void) getkey (); - break; - } - } - -// /* if we get back here, we should go back to what our term was before */ -// current_term = prev_term; -// if (current_term->startup) -// /* if our terminal fails to initialize, fall back to console since -// * it should always work */ -// if ((*current_term->startup)() == 0) -// current_term = term_table; /* we know that console is first */ - show_menu = 1; - goto restart1; -} - -// #define GFX_DEBUG - -#ifdef SUPPORT_GFX - -/* kernel + (grub-)module options */ -#define GFX_CMD_BUF_SIZE 512 - -/* command line separator char */ -#define GFX_CMD_SEP 1 - -/* - * Search cpio archive for gfx file. - */ -static unsigned find_file (unsigned char *buf, unsigned len, - unsigned *gfx_file_start, unsigned *file_len, - unsigned *code_start) -{ - unsigned i, fname_len; - - *gfx_file_start = 0; - - for(i = 0; i < len;) - { - if((len - i) >= 0x1a && (buf[i] + (buf[i + 1] << 8)) == 0x71c7) + if (config_entries) { - fname_len = *(unsigned short *) (buf + i + 20); - *file_len = *(unsigned short *) (buf + i + 24) + (*(unsigned short *) (buf + i + 22) << 16); - i += 26 + fname_len; - i = ((i + 1) & ~1); - if (*(unsigned *) (buf + i) == 0x0b2d97f00) /* magic id */ - { - int v = buf[i + 4]; - - *code_start = *(unsigned *) (buf + i + 8); - *gfx_file_start = i; - if ((v>=5) && (v <= 7)) /* version 5 - 7 */ - return 1; - else if (v == 8) /* version 8 */ - return 2; - } - i += *file_len; - i = ((i + 1) & ~1); + char *p; + + p = get_entry (menu_entries, first_entry + entryno); + if (! ((*p) & 0xF0)) + p++; + char *p_t = (char *)SCRATCHADDR; + while(*p && *p != '\n') + *p_t++ = *p++; + *p_t++ = 0; + expand_var ((char *)SCRATCHADDR, p_t, 0x400); + printf (" Booting \'%s\'\n\n",p_t); } - else - break; - } - - return 0; -} - -#define MIN_GFX_FREE 0x1000 - -#define SC_BOOTLOADER 0 -#define SC_FAILSAFE 3 -#define SC_SYSCONFIG_SIZE 4 -#define SC_BOOTLOADER_SEG 8 -#define SC_XMEM_0 24 -#define SC_XMEM_1 26 -#define SC_XMEM_2 28 -#define SC_XMEM_3 30 -#define SC_FILE 32 -#define SC_ARCHIVE_START 36 -#define SC_ARCHIVE_END 40 -#define SC_MEM0_START 44 -#define SC_MEM0_END 48 - -unsigned long gfx_drive, gfx_partition; - -/* - * Does normally not return. - */ -static void -run_graphics_menu (char *menu_entries, char *config_entries, /*int num_entries,*/ - char *heap, int entryno) -{ - unsigned char *buf, *buf_ext; - unsigned buf_size, buf_ext_size, code_start = 0, file_start; - char *cfg; - int i, j, max_len, gfx_file_size, verbose; - int selected_entry; - gfx_data_v1_t *gfx1; - gfx_data_v2_t *gfx2; - //char *cmd_buf; - unsigned mem0_start, mem0_end, file_len = 0; - int version; - unsigned long tmp_drive, tmp_partition; - - /* - * check gfx_data_t struct offsets for consistency; gcc will optimize away - * the whole block - */ - - /* dummy function to make ld fail */ - { - extern void wrong_struct_size(void); - #define gfx_ofs_check(a) if(gfx_ofs_v1_##a != (char *) &gfx1->a - (char *) &gfx1->ok) wrong_struct_size(); - gfx_ofs_check(ok); - gfx_ofs_check(mem_start); - gfx_ofs_check(mem_cur); - gfx_ofs_check(mem_max); - gfx_ofs_check(code_seg); - gfx_ofs_check(jmp_table); - gfx_ofs_check(sys_cfg); - gfx_ofs_check(cmdline); - gfx_ofs_check(cmdline_len); - gfx_ofs_check(menu_list); - gfx_ofs_check(menu_default_entry); - gfx_ofs_check(menu_entries); - gfx_ofs_check(menu_entry_len); - gfx_ofs_check(args_list); - gfx_ofs_check(args_entry_len); - gfx_ofs_check(timeout); - gfx_ofs_check(mem_file); - gfx_ofs_check(mem_align); - #undef gfx_ofs_check - - #define gfx_ofs_check(a) if(gfx_ofs_v2_##a != (char *) &gfx2->a - (char *) &gfx2->ok) wrong_struct_size(); - gfx_ofs_check(ok); - gfx_ofs_check(code_seg); - gfx_ofs_check(jmp_table); - gfx_ofs_check(sys_cfg); - gfx_ofs_check(cmdline); - gfx_ofs_check(cmdline_len); - gfx_ofs_check(menu_list); - gfx_ofs_check(menu_default_entry); - gfx_ofs_check(menu_entries); - gfx_ofs_check(menu_entry_len); - gfx_ofs_check(args_list); - gfx_ofs_check(args_entry_len); - gfx_ofs_check(timeout); - #undef gfx_ofs_check - } - - if(!num_entries) return; - - kernel_type = KERNEL_TYPE_NONE; - - gfx1 = (gfx_data_v1_t *) (heap = (char *)0x50000); - heap = (char *) (((unsigned) heap + sizeof (*gfx1) + 0xF) & ~0xF); - gfx2 = (gfx_data_v2_t *) heap; - heap += sizeof *gfx2; - memset((char *) gfx1, 0, (char *) heap - (char *) gfx1); - - //verbose = (*(unsigned char *) 0x417) & 3 ? 1 : 0; /* SHIFT pressed */ - verbose = (debug > 1); - - /* setup command line edit buffer */ - - gfx1->cmdline_len = gfx2->cmdline_len = 256; - gfx1->cmdline = gfx2->cmdline = heap; - heap += gfx1->cmdline_len; - memset(gfx1->cmdline, 0, gfx1->cmdline_len); - - //cmd_buf = heap; - heap += GFX_CMD_BUF_SIZE; - - /* setup menu entries */ - - for (i = max_len = 0; i < num_entries; i++) - { - char ch; - char *str = get_entry(menu_entries, i); - - j = 0; - /* ending at LF, the start of help message */ - while ((ch = *str++) && ch != '\n') - j++; - - if (max_len < j) - max_len = j; - } - - if (!max_len) return; - - gfx1->menu_entry_len = gfx2->menu_entry_len = max_len; - gfx1->menu_entries = gfx2->menu_entries = num_entries; - - gfx1->menu_list = gfx2->menu_list = heap; - heap += gfx1->menu_entry_len * gfx1->menu_entries; - - memset(gfx1->menu_list, 0, gfx1->menu_entry_len * gfx1->menu_entries); - - for(i = 0; i < (int) gfx1->menu_entries; i++) - { - char ch; - char *dest = gfx1->menu_list + i * gfx1->menu_entry_len; - char *src = get_entry(menu_entries, i); - - /* Skip the leading '\t'. */ - src++; - - /* ending at LF, the start of help message */ - while ((ch = *src++) && ch != '\n') - *dest++ = ch; - *dest = 0; - } - - gfx1->menu_default_entry = gfx2->menu_default_entry = gfx1->menu_list + entryno * gfx1->menu_entry_len; - - gfx1->args_entry_len = gfx2->args_entry_len = 1; - gfx1->args_list = gfx2->args_list = heap; - heap += gfx1->args_entry_len * gfx1->menu_entries; - memset(gfx1->args_list, 0, gfx1->args_entry_len * gfx1->menu_entries); - - /* use 1MB starting at 4MB as file buffer */ - buf_ext = (unsigned char *) (4 << 20); - buf_ext_size = 1 << 20; - - /* must be 16-byte aligned */ - buf = (unsigned char *) (((unsigned) heap + 0xf) & ~0xf); - - buf_size = ((*((unsigned short *)0x413)) << 10) - (unsigned) buf; - buf_size &= ~0xf; - - mem0_start = (unsigned) buf; - mem0_end = mem0_start + buf_size; - -#ifdef GFX_DEBUG - if (verbose) - { - printf("low memory 0x%x - 0x%x (%d bytes)\n", mem0_start, mem0_end, buf_size); - } -#endif - - /* read the file */ - tmp_drive = saved_drive; - tmp_partition = saved_partition; - saved_drive = gfx_drive; - saved_partition = gfx_partition; - if (!grub_open(graphics_file)) - { - if (verbose) - printf("%s: file not found\n", graphics_file); - - saved_drive = tmp_drive; - saved_partition = tmp_partition; - return; - } - - gfx_file_size = grub_read ((unsigned long long)(unsigned int)(char *)buf_ext, buf_ext_size, 0xedde0d90); - - grub_close(); - - saved_drive = tmp_drive; - saved_partition = tmp_partition; - - if (gfx_file_size <= 0) - { - if (verbose) - printf("%s: read error\n", graphics_file); - - return; - } - -#ifdef GFX_DEBUG - if (verbose) - { - printf("%s: %d bytes (%d bytes left)\n", graphics_file, gfx_file_size, (buf_ext_size - gfx_file_size)); - } -#endif - - /* locate file inside cpio archive */ - if (!(version = find_file(buf_ext, gfx_file_size, &file_start, &file_len, &code_start))) - { - if (verbose) - printf("%s: invalid file format\n", graphics_file); - - return; + else + printf (" Booting command-list\n\n"); } -#ifdef GFX_DEBUG - if (verbose) + /* Set CURRENT_ENTRYNO for the command "savedefault". */ + current_entryno = first_entry + entryno; + if (! cur_entry) { - printf("init: start 0x%x, len %d; code offset 0x%x\n", file_start, file_len, code_start); + cur_entry = titles[current_entryno]; + while (*cur_entry++); } -#endif - - if (version == 1) - { - unsigned u; - - if (gfx_file_size + MIN_GFX_FREE + 0xf >= (int) buf_size) - { - if (verbose) - printf("not enough free memory: %d extra bytes need\n", (gfx_file_size + MIN_GFX_FREE - buf_size)); - - return; - } - - memcpy ((void *) buf, (void *) buf_ext, gfx_file_size); - - gfx1->sys_cfg[0] = 2; /* bootloader: grub */ - gfx1->timeout = grub_timeout >= 0 ? grub_timeout : 0; - - gfx1->mem_start = (unsigned) buf; - gfx1->mem_max = gfx1->mem_start + buf_size; - - gfx1->mem_cur = gfx1->mem_start + - ((gfx_file_size + 0x0f + 3) & ~3); /* align it */ - - /* align it */ - u = (-(code_start + gfx1->mem_start + file_start)) & 0x0f; - gfx1->mem_align = gfx1->mem_start + u; - gfx1->mem_file = gfx1->mem_align + file_start; - if (u) - { - memcpy((void *) gfx1->mem_align, (void *) gfx1->mem_start, gfx_file_size); - } - - code_start += gfx1->mem_file; - gfx1->code_seg = code_start >> 4; - - for (i = 0; (unsigned) i < sizeof gfx1->jmp_table / sizeof *gfx1->jmp_table; i++) - { - gfx1->jmp_table[i] = (gfx1->code_seg << 16) + ((unsigned short *) code_start)[i]; - } - - if (gfx_init_v1 (gfx1)) - { - if (verbose) - printf("graphics initialization failed\n"); - - return; - } - - gfx_setup_menu_v1 (gfx1); - i = gfx_input_v1 (gfx1, &selected_entry); - gfx_done_v1 (gfx1); - } - else - { - if (file_len - code_start + MIN_GFX_FREE > buf_size) - { - if (verbose) - printf("not enough free memory: %d extra bytes need\n", (file_len - code_start + MIN_GFX_FREE - buf_size)); - - return; - } - - gfx2->sys_cfg[SC_BOOTLOADER] = 2; /* bootloader: grub */ - gfx2->sys_cfg[SC_SYSCONFIG_SIZE] = 52; /* config data size */ - *(unsigned short *) (gfx2->sys_cfg + SC_BOOTLOADER_SEG) = (unsigned) gfx2 >> 4; /* segment */ - gfx2->sys_cfg[SC_XMEM_0] = 0x21; /* 1MB @ 2MB */ - gfx2->sys_cfg[SC_XMEM_1] = 0x41; /* 1MB @ 4MB */ - gfx2->sys_cfg[SC_FAILSAFE] = verbose; - gfx2->timeout = grub_timeout >= 0 ? grub_timeout : 0; - - memcpy((void *) buf, (void *) (buf_ext + file_start + code_start), file_len - code_start); - - mem0_start += file_len - code_start; - mem0_start = (mem0_start + 3) & ~3; /* align */ - - /* init interface to graphics functions */ - - *(unsigned *) (gfx2->sys_cfg + SC_FILE) = (unsigned) buf_ext + file_start; - *(unsigned *) (gfx2->sys_cfg + SC_ARCHIVE_START) = (unsigned) buf_ext; - *(unsigned *) (gfx2->sys_cfg + SC_ARCHIVE_END) = (unsigned) buf_ext + gfx_file_size; - *(unsigned *) (gfx2->sys_cfg + SC_MEM0_START) = mem0_start; - *(unsigned *) (gfx2->sys_cfg + SC_MEM0_END) = mem0_end; - - gfx2->code_seg = (unsigned) buf >> 4; - -#ifdef GFX_DEBUG - - if (verbose) - { - printf("init 0x%x, archive 0x%x - 0x%x, low mem 0x%x - 0x%x\ncode seg 0x%x\n", - ((unsigned) buf_ext + file_start), - (unsigned) buf_ext, ((unsigned) buf_ext + gfx_file_size), - mem0_start, mem0_end, gfx2->code_seg - ); - } -#endif - - for (i = 0; (unsigned) i < sizeof gfx2->jmp_table / sizeof *gfx2->jmp_table; i++) - { - gfx2->jmp_table[i] = (gfx2->code_seg << 16) + ((unsigned short *) buf)[i]; - } - -#ifdef GFX_DEBUG - if (verbose) - { - for(i = 0; i < 12; i++) - { - printf("%d: 0x%x\n", i, gfx2->jmp_table[i]); - } - for(i = 0; i < gfx2->menu_entries; i++) - { - printf("\"%s\" -- \"%s\"\n", - (gfx2->menu_list + i * gfx2->menu_entry_len), - (gfx2->args_list + i * gfx2->args_entry_len) - ); - } - - printf("default: \"%s\"\n", gfx2->menu_default_entry); - } -#endif - - /* switch to graphics mode */ - if (gfx_init_v2 (gfx2)) - { - if (verbose) - printf("graphics initialization failed\n"); - - return; - } - - gfx_setup_menu_v2 (gfx2); - i = gfx_input_v2 (gfx2, &selected_entry); - gfx_done_v2 (gfx2); - } - - memset ((char *) HISTORY_BUF, 0, HISTORY_BUFLEN); - /* ESC -> show text menu */ - - if (i == 1) + if (current_entryno >= num_entries)//Max entries + break; + if (! run_script (cur_entry, heap)) + break; + if (fallback_entryno < 0) + break; + cur_entry = NULL; + first_entry = 0; + entryno = fallback_entries[fallback_entryno]; + fallback_entryno++; + if (fallback_entryno >= MAX_FALLBACK_ENTRIES || fallback_entries[fallback_entryno] < 0) + fallback_entryno = -1; + fallbacked_entries++; + if (fallbacked_entries > num_entries * num_entries * 4) { - grub_timeout = -1; - return; + printf ("\nEndless fallback loop detected(entry=%d)! Press any key to exit...", current_entryno); + (void) getkey (); + break; } - - //heap = saved_heap; /* free most of the graphics data */ - - // printf("cmdline: >%s<, entry = %d\n", gfx_data->cmdline, selected_entry); - - if (selected_entry < 0 || selected_entry > num_entries) - return; - - /* for 'savedefault' */ - current_entryno = selected_entry; - - cfg = get_entry(menu_entries, selected_entry); - while (*(cfg++)) - ; - - run_script(cfg, heap); + } + show_menu = 1; + goto restart1; } -#endif /* SUPPORT_GFX */ - +static int get_line_from_config (char *cmdline, int max_len, int preset); static int -get_line_from_config (char *cmdline, int max_len, int preset) +get_line_from_config (char *cmdline, int max_len, int preset) //从配置中获取行(命令行,尺寸,是预置菜单) { - unsigned long pos = 0, info = 0;//literal = 0, comment = 0; + unsigned int pos = 0, info = 0;//literal = 0, comment = 0; char c; /* since we're loading it a byte at a time! */ - + while (1) { -#if 0 - /* Skip UTF-8 Byte Order Mark: EF BB BF */ - { - unsigned long menu_offset; - - menu_offset = read_from_file ? filepos : preset_menu_offset; - if (menu_offset == 0) - { - /* read 3 bytes, check UTF-8 Byte Order Mark: EF BB BF */ - if (read_from_file) - { - if (3 != grub_read (&menu_offset, 3)) - { - filepos = 0; - break; - } - if (menu_offset != 0xBFBBEF) - { - filepos = 0; - } - } - else - { - if (3 != read_from_preset_menu (&menu_offset, 3)) - { - preset_menu_offset = 0; - break; - } - if (menu_offset != 0xBFBBEF) - { - preset_menu_offset = 0; - } - } - } - } -#endif - if (preset) { - if (! read_from_preset_menu (&c, 1)) - break; + if (! read_from_preset_menu (&c, 1)) //从预设菜单读取 + break; } else { - if (! grub_read ((unsigned long long)(unsigned int)&c, 1, 0xedde0d90)) + if (! grub_read ((unsigned long long)(grub_size_t)&c, 1, 0xedde0d90)) { if (errnum) { @@ -2333,10 +1840,6 @@ get_line_from_config (char *cmdline, int max_len, int preset) } } - ///* Skip UTF-8 Byte Order Mark: EF BB BF */ - //if ((c & 0x80) && pos < 3) - // continue; - /* Replace CR with LF. */ if (c == '\r') c = '\n'; @@ -2348,34 +1851,10 @@ get_line_from_config (char *cmdline, int max_len, int preset) /* all other non-printable chars are illegal. */ if (c != '\n' && (unsigned char)c < ' ') { - pos = 0; +// pos = 0; 2023-02-11 预置菜单最后一行没有回车符,会出错 break; } -// /* The previous is a backslash, then... */ -// if (info & 1) /* bit 0 for literal */ -// { -// /* If it is a newline, replace it with a space and continue. */ -// if (c == '\n') -// { -// c = ' '; -// -// /* Go back to overwrite a backslash. */ -// if (pos > 0) -// pos--; -// } -// -// info &= 0xFFFFFFFE; //literal = 0; -// } -// -// ///* Replace semi-colon with LF. */ -// //if (c == ';') -// // c = '\n'; -// -// /* translate characters first! */ -// if (c == '\\') -// info |= 1; //literal = 1; - if (info & 2) /* bit 1 for comment */ { if (c == '\n') @@ -2420,9 +1899,6 @@ get_line_from_config (char *cmdline, int max_len, int preset) info &= ~8; // not all hex digit } - // if (!(info & 4) && ((c & 0x80) || pos > 31)) /* bit 2 for argument */ - //break; - if (pos < max_len) { if (!(info & 4) && c == '=') @@ -2439,15 +1915,17 @@ get_line_from_config (char *cmdline, int max_len, int preset) } int config_len; -static char *config_entries, *cur_entry; +static char *cur_entry; +char *CONFIG_ENTRIES; +static void reset (void); static void reset (void) { count_lines = -1; config_len = 0; num_entries = 0; - cur_entry = config_entries; + cur_entry = CONFIG_ENTRIES; /* Initialize the data for the configuration file. */ default_entry = 0; @@ -2455,153 +1933,165 @@ reset (void) fallback_entryno = -1; fallback_entries[0] = -1; grub_timeout = -1; + timeout_enable = 0; menu_num_ctrl[0] = 0; } extern struct builtin builtin_title; -extern struct builtin builtin_graphicsmode; +//extern struct builtin builtin_graphicsmode; extern struct builtin builtin_debug; -static unsigned long attr = 0; +static unsigned int attr = 0; +int font_func (char *arg, int flags); /* This is the starting function in C. */ +void cmain (void); void cmain (void) { - debug = debug_boot + 1; - title_boot = (unsigned short *) init_free_mem_start; - titles = (char * *)(init_free_mem_start + 1024); - config_entries = (char*)init_free_mem_start + 1024 + 256 * sizeof (char *); + //分配菜单内存 + if (!menu_mem) + { + menu_mem = grub_zalloc (0x40e00); //分配内存, 并清零 + menu_mem = (char *)(grub_size_t)(((unsigned long long)(grub_size_t)menu_mem + 511) & 0xfffffffffffffe00); + title_boot = (unsigned short *)menu_mem; + titles = (char * *)(menu_mem + 1024); + CONFIG_ENTRIES = menu_mem + 1024 + 256 * sizeof (char *); + } +// else +// grub_memset (menu_mem, 0, 0x40e00 - 0x200); + //初始化 saved_entryno = 0; new_menu = 0; - /* Never return. */ + new_hotkey = 0; + /* Never return. 永不回头 */ restart2: - reset (); - - /* Here load the configuration file. */ - - if (! use_config_file) - goto done_config_file; - - pxe_restart_config = 0; - -restart_config: - + reset (); //重置 + /* Here load the configuration file. 在这里加载配置文件。*/ +// if (! use_config_file) //如果不使用配置文件,跳转 在asm,configfile_func置1 +// goto done_config_file; + +// pxe_restart_config = 0; +//使用预置菜单重新配置 +//restart_config: { - /* STATE 0: Menu init, i.e., before any title command. - STATE 1: In a title command. - STATE 2: In a entry after a title command. + /* STATE 0: Menu init, i.e., before any title command. 菜单初始化,即在任何标题命令之前 + STATE 1: In a title command. 在标题命令中 + STATE 2: In a entry after a title command. 在标题命令后的条目中 */ + //初始化 int state = 0, prev_config_len = 0, bt = 0; - unsigned long graphicsmode_in_menu_init = 0; - unsigned long debug_in_menu_init = 0; - //char *cmdline; - int is_preset; + int is_preset, flags0; grub_memset (graphic_file_shift, 0, 32); menu_init_script_file[0] = 0; + //打开预置菜单或者配置文件 { int is_opened; - is_preset = is_opened = 0; /* Try command-line menu first if it is specified. */ - //if (preset_menu == (char *)0x0800/*&& ! *config_file*/) - if (use_preset_menu) - { - is_opened = is_preset = open_preset_menu (); - } - if (! is_opened) - { - /* Try config_file */ - if (*config_file) + //如果存在预置菜单,首先尝试使用他。如果成功,则不再打开配置文件 + if (use_preset_menu) //在get_embed置1 (如果grub4efi有内置菜单,则置1) + { + is_opened = is_preset = open_preset_menu (); //打开预置菜单 + } + //如果没有预置菜单或者打开预置菜单失败,则尝试打开配置文件 + if (! is_opened) //如果没有打开预置菜单,尝试使用配置文件 + { + if (*config_file) //如果存在配置文件 { - is_opened = (configfile_opened || grub_open (config_file)); + is_opened = (/*configfile_opened || */grub_open (config_file)); //打开配置文件 configfile_opened=0,而且没有文件设置他 + if (! is_opened) //如果打开配置文件失败,转不使用配置文件 + goto done_config_file; #ifdef FSYS_IPXE - if (is_opened && current_drive == PXE_DRIVE && current_partition == IPXE_PART) - pxe_detect(IPXE_PART,config_file); +// if (is_opened && current_drive == PXE_DRIVE && current_partition == IPXE_PART) +// pxe_detect(IPXE_PART,config_file); #endif } - } + } errnum = 0; - configfile_opened = 0; +// configfile_opened = 0; +#if 0 + //如果没有配置文件,再次尝试打开预置菜单(因为可能use_preset_menu为0) if (! is_opened) - { - if (pxe_restart_config) - goto original_config; - + { +// if (pxe_restart_config) +// goto original_config; /* Try the preset menu. This will succeed at most once, - * because the preset menu will be disabled(see below). */ - is_opened = is_preset = open_preset_menu (); + * because the preset menu will be disabled(see below). */ + //尝试使用预设菜单。这最多只会成功一次,因为预设菜单将被禁用(见下文) + is_opened = is_preset = open_preset_menu (); //打开预置菜单 } - - if (! is_opened) +#endif + if (! is_opened) //如果打开失败,不再处理 goto done_config_file; } - + /* This is necessary, because the menu must be overrided. */ - reset (); - //cmdline = (char *) CMDLINE_BUF; - - putchar_hooked = (unsigned char*)1;/*stop displaying on screen*/ - - while (get_line_from_config ((char *) CMDLINE_BUF, NEW_HEAPSIZE, is_preset)) + //这是必要的,因为菜单必须被覆盖 + reset (); //重置 +#if 1 //值1表示: 从现在开始, 不在屏幕显示任何信息 + putchar_hooked = (unsigned char*)1;/*stop displaying on screen*/ //禁止显示 +#else + putchar_hooked = 0; //允许显示 +#endif + //处理预置菜单或者配置文件 + while (get_line_from_config ((char *) CMDLINE_BUF, NEW_HEAPSIZE, is_preset)) //从配置中获取行 { - struct builtin *builtin = 0; - char *cmdline = (char *) CMDLINE_BUF; - + struct builtin *builtin = 0; + char *cmdline = (char *) CMDLINE_BUF; + flags0 = 0; /* Get the pointer to the builtin structure. */ - if (*cmdline == ':' || *cmdline == '!') - goto sss; - builtin = find_command (cmdline); + //获取指向内置结构的指针 + if (*cmdline == ':' || *cmdline == '!' || *cmdline == '{' || *cmdline == '}') + { +// builtin->flags = 8; + if (builtin) //适应gcc高版本 2023-05-24 + builtin->flags = 8; + flags0 = 8; //适应gcc高版本 2023-05-24 + goto sss; + } + builtin = find_command (cmdline); //查找命令 errnum = 0; - if (! builtin) - /* Unknown command. Just skip now. */ - continue; -sss: - if ((int)builtin != -1 && builtin->flags == 0) /* title command */ + if (! builtin) //如果没有找到,跳过 + continue; /* Unknown command. Just skip now. */ +sss: +// if ((grub_size_t)builtin != (grub_size_t)-1 && builtin->flags == (int)0) /* title command */ + //如果是标题命令 + if ((grub_size_t)builtin != (grub_size_t)-1 && builtin && builtin->flags == (int)0 && flags0 != 8) /* title command */ { + //如果不是内置标题 if (builtin != &builtin_title)/*If title*/ { - unsigned long tmp_filpos; - unsigned long tmp_drive = saved_drive; - unsigned long tmp_partition = saved_partition; + unsigned int tmp_filpos; + unsigned int tmp_drive = saved_drive; + unsigned int tmp_partition = saved_partition; unsigned int rp; cmdline = skip_to(1, cmdline); - /* save original file position. */ - tmp_filpos = (is_preset && preset_menu == (const char *)0x800) ? - preset_menu_offset : filepos; - + //保存原始文件位置 + tmp_filpos = /*(is_preset && preset_menu == (const char *)0x800) ? + preset_menu_offset : */filepos; /* close the already opened file for safety, in case * the builtin->func() below would call * grub_open(). */ - if (! is_preset || preset_menu != (const char *)0x800) - grub_close (); - - if (debug_boot) - { - putchar_hooked = 0; - grub_printf("IFTITLE: %s->",cmdline); - putchar_hooked = (unsigned char*)1; - } - + //为了安全起见,请关闭已打开的文件,以防下面的builtin->func()调用grub_open()。 + grub_close (); //关闭 + //执行命令 rp = builtin->func(cmdline,BUILTIN_IFTITLE); saved_drive = tmp_drive; saved_partition = tmp_partition; current_drive = GRUB_INVALID_DRIVE; buf_drive = -1; - /* re-open the config_file which is still in use by * get_line_from_config(), and restore file position * with the saved value. */ - if (is_preset) - { - open_preset_menu (); - if (preset_menu == (const char *)0x800) - preset_menu_offset = tmp_filpos; - else - filepos = (unsigned long long)tmp_filpos; - } - else + //重新打开get_line_from_config()仍在使用的configfile,并使用保存的值恢复文件位置 + if (is_preset) //如果是预置菜单 + { + open_preset_menu (); //打开预置菜单 + filepos = (unsigned long long)tmp_filpos; + } + else //如果是配置文件 { - if (! grub_open (config_file)) + if (! grub_open (config_file)) //打开配置文件 { printf (" Fatal! Re-open %s failed!\n", config_file); print_error (); @@ -2609,15 +2099,7 @@ cmain (void) filepos = (unsigned long long)tmp_filpos; } - if (debug_boot) - { - putchar_hooked = 0; - grub_printf(" rp=%d\n", rp); - DEBUG_SLEEP - putchar_hooked = (unsigned char*)1; - } - - if (rp) + if (rp) //如果命令执行成功 { cmdline += rp; } @@ -2625,38 +2107,39 @@ cmain (void) { int i; for (i = num_entries + ((state & 0xf) ? 1 : 0); i < 32; i++) - graphic_file_shift[i] += 1; + graphic_file_shift[i] += 1; //图形文件移位 state |= 0x10; continue; } - } - /* Finish the menu init commands or previous menu items. */ + }//if (builtin != &builtin_title) - if (state & 2) + /* Finish the menu init commands or previous menu items. */ + //完成菜单初始化命令或之前的菜单项 + if (state & 2) //如果是步骤2 { /* The next title is found. */ + //找到下一个标题 if (num_entries >= 256) - break; - bt += (config_entries[attr] & 1); - num_entries++; /* an entry is completed. */ - config_entries[config_len++] = 0; /* finish the entry. */ + break; + bt += (CONFIG_ENTRIES[attr] & 1); + num_entries++; /* an entry is completed. 条目已完成*/ + CONFIG_ENTRIES[config_len++] = 0; /* finish the entry. 完成条目*/ prev_config_len = config_len; } - else if (state & 1) /* state == 1 */ + else if (state & 1) //如果是步骤1 { - /* previous is an invalid title, overwrite it. */ + /* previous is an invalid title, overwrite it. 上一个标题无效,请覆盖它*/ config_len = prev_config_len; } - else /* state == 0 */ + else //如果是步骤0 { - /* The first title. So finish the menu init commands. */ - config_entries[config_len++] = 0; + /* The first title. So finish the menu init commands. 第一个标题。因此,完成菜单初始化命令*/ + CONFIG_ENTRIES[config_len++] = 0; } - - /* Reset the state. */ + /* Reset the state. 重置状态*/ state = 1; - /* Copy title into config area. */ + /* Copy title into config area. 将标题复制到配置区域*/ { int len; char *ptr = cmdline; @@ -2667,263 +2150,157 @@ cmain (void) attr = config_len; if (num_entries < 256) { - titles[num_entries] = config_entries + config_len; + titles[num_entries] = CONFIG_ENTRIES + config_len; title_boot[num_entries] = bt; } - config_entries[config_len++] = 0x08; /* attribute byte */ + CONFIG_ENTRIES[config_len++] = 0x08; /* attribute byte */ len = parse_string (ptr); ptr[len] = 0; - while ((config_entries[config_len++] = *(ptr++)) != 0); + while ((CONFIG_ENTRIES[config_len++] = *(ptr++)) != 0); } - } - else if (state & 0x10) /*ignored menu by iftitle*/ + }//if ((grub_size_t)builtin != (grub_size_t)-1 && ..... + else if (state & 0x10) /*ignored menu by iftitle 被iftitle忽略的菜单*/ + { continue; - else if (! state) /* menu init command */ + } + else if (! state) /* menu init command 菜单初始化命令*/ { - if ((int)builtin == -1 || builtin->flags & BUILTIN_MENU) + if ((grub_size_t)builtin == (grub_size_t)-1 || builtin->flags & BUILTIN_MENU) { char *ptr = cmdline; /* Copy menu-specific commands to config area. */ - while ((config_entries[config_len++] = *ptr++) != 0); + while ((CONFIG_ENTRIES[config_len++] = *ptr++) != 0); prev_config_len = config_len; - if (builtin == &builtin_graphicsmode) - graphicsmode_in_menu_init = 1; - if (builtin == &builtin_debug) - debug_in_menu_init = 1; } else - /* Ignored. */ + /* Ignored. 忽视*/ continue; } - else /* menu item command */ + else /* menu item command 菜单项命令*/ { state = 2; - - /* Copy config file data to config area. */ + /* Copy config file data to config area. 将配置文件数据复制到配置区域*/ { char *ptr = cmdline; - while ((config_entries[config_len++] = *ptr++) != 0); + while ((CONFIG_ENTRIES[config_len++] = *ptr++) != 0); prev_config_len = config_len; } - if ((int)builtin != -1) - config_entries[attr] |= !!(builtin->flags & BUILTIN_BOOTING); + if ((grub_size_t)builtin != (grub_size_t)-1) + { + CONFIG_ENTRIES[attr] |= !!(builtin->flags & BUILTIN_BOOTING); + } } } /* while (get_line_from_config()) */ - +//从现在开始, 在屏幕显示信息 putchar_hooked = 0; - /* file must be closed here, because the menu-specific commands * below may also use the GRUB_OPEN command. */ - if (is_preset) - { -#ifdef SUPPORT_GRAPHICS -extern int font_func (char *, int); -extern int graphicsmode_func (char *, int); - //font_func (NULL, 0); /* clear the font */ - /* Since ROM VGA font already loaded in init_bios_info(), we - * should not load it again here. The same as below. - * See issue 160. */ - /* Clear the narrow_char_indicator for the NULL char only. */ -// *(unsigned long *)UNIFONT_START = 0; // Enable next font command. - if (use_preset_menu/* != (const char *)0x800*/) - { - /* load the font embedded in preset menu. */ - char *menu = "(md)4+8"; - - if (preset_menu != (const char *)0x800) - menu = "(md)0x880+0x200"; - if (font_func (menu, 0)) - { - /* font exists, automatically enter graphics mode. */ - if (! graphicsmode_in_menu_init) - { - if (debug_boot) - grub_printf ("\rSwitch to graphics mode ... \r"); - graphicsmode_func ("-1 -1 -1 24:32", 0); - } - } - //font_func (NULL, 0); /* clear the font */ - /* Clear the narrow_char_indicator for the NULL char only. */ -// *(unsigned long *)UNIFONT_START = 0;//Enable next font command. - } -#endif /* SUPPORT_GRAPHICS */ - - if (preset_menu != (const char *)0x800) - grub_close (); - //use_preset_menu = 0; /* Disable preset menu. */ - } - else + //必须在此处关闭文件,因为下面特定于菜单的命令也可能使用GRUB_OPEN命令。 + if (is_preset) + { + if (use_preset_menu/* != (const char *)0x800*/) + { + /* load the font embedded in preset menu. 载入预置菜单中的字体。*/ + if (font_func (preset_menu, 0)) //0 如果字体加载成功 + { + /* font exists, automatically enter graphics mode. 字体存在,自动进入图形模式。*/ + if (! IMAGE_BUFFER) //如果不在图形模式,尝试设置图形模式 + { + graphicsmode_func ("-1 800", 0); + } + menu_tab_ext &= 0xfb; //清除字库已加载标记 + } + } + grub_close (); + } + else { grub_close (); - /* before showing menu, try loading font in the tail of config_file */ -#ifdef SUPPORT_GRAPHICS - extern int font_func (char *, int); - //font_func (NULL, 0); /* clear the font */ - /* Clear the narrow_char_indicator for the NULL char only. */ -// *(unsigned long *)UNIFONT_START = 0; // Enable next font command. - font_func (config_file, 0); - //font_func (NULL, 0); /* clear the font */ - /* Clear the narrow_char_indicator for the NULL char only. */ -// *(unsigned long *)UNIFONT_START = 0; // Enable next font command. -#endif /* SUPPORT_GRAPHICS */ + if (current_drive != 0x21 && font_func (config_file, 0)) + menu_tab_ext &= 0xfb; //清除字库已加载标记 + /* before showing menu, try loading font in the tail of config_file 在显示菜单之前,尝试在configfile的尾部加载字体*/ } - use_preset_menu = 0; /* Disable preset menu. */ - + use_preset_menu = 0; /* Disable preset menu. 禁用预置菜单 */ if (state & 2) { if (num_entries < 256) - num_entries++; /* the last entry is completed. */ + num_entries++; /* the last entry is completed. 最后一个条目已完成 */ } else// if (state) { config_len = prev_config_len; } - /* Finish the last entry or the menu init commands. */ - config_entries[config_len++] = 0; + /* Finish the last entry or the menu init commands. 完成最后一个条目或菜单初始化命令 */ + CONFIG_ENTRIES[config_len++] = 0; title_boot[num_entries] = -1; if (num_entries < 256) titles[num_entries] = 0; - - /* old MENU_BUF is not used any more. So MENU_BUF is a temp area, - * and can be moved to elsewhere. */ + /* old MENU_BUF is not used any more. So MENU_BUF is a temp area, 不再使用旧的MENU_BUF。所以MENU_BUF是一个临时区域,可以移动到其他地方 + * and can be moved to elsewhere. */ - /* config_entries contains these: - * 1. The array of menu init commands. - * 2. The array of menu item commands with leading titles. + /* CONFIG_ENTRIES contains these: CONFIG_ENTRIES包含以下内容: + * 1. The array of menu init commands. 1.菜单初始化命令数组。 + * 2. The array of menu item commands with leading titles. 2.带有前导标题的菜单项命令数组。 */ - /* Display this info if the debug command is not present in the + /* Display this info if the debug command is not present in the 如果调试命令不在菜单init命令集中,则显示此信息。 * menu-init command set. */ - if (debug_boot || ! debug_in_menu_init) - { -#include "grub4dos_version.h" - -#ifdef GRUB4DOS_VERSION - if ((unsigned long)saved_partition == 0xFFFFFF) - printf_debug0 ("\rGRUB4DOS " GRUB4DOS_VERSION - ", root is (0x%X)%s\n", - (unsigned long)saved_drive, - saved_dir); - else - printf_debug0 ("\rGRUB4DOS " GRUB4DOS_VERSION - ", root is (0x%X,%d)%s\n", - (unsigned long)saved_drive, - (unsigned char)(saved_partition >> 16), - saved_dir); -#endif - if (is_preset) - { - if (preset_menu == (const char *)0x800) - printf_debug0 ("\rProcessing the preset-menu ...\n"); - else - printf_debug0 ("\rProcessing the LZMA preset-menu ...\n"); - } - else - printf_debug0 ("\rProcessing menu file %s ...\n", config_file); - DEBUG_SLEEP - } - - /* Run menu-specific commands before any other menu entry commands. */ - + /* Run menu-specific commands before any other menu entry commands. 在任何其他菜单项命令之前运行特定于菜单的命令。 */ { static char *old_entry = NULL; - static char *heap = NULL; heap = config_entries + config_len; - - static int old_debug = 1; + static char *heap = NULL; heap = CONFIG_ENTRIES + config_len; - /* Initialize the data. */ - //saved_drive = boot_drive; - //saved_partition = install_partition; + /* Initialize the data. 初始化数据*/ current_drive = GRUB_INVALID_DRIVE; count_lines = -1; kernel_type = KERNEL_TYPE_NONE; errnum = 0; - while (1) { -// struct builtin *builtin; //2010-12-16 commented by chenall -// char *arg; -// grub_error_t errnum_old;//2010-12-16 commented by chenall - - pxe_restart_config = 0; +// pxe_restart_config = 0; #ifdef SUPPORT_GFX - *graphics_file = 0; +// *graphics_file = 0; #endif - -// errnum_old = errnum;//2010-12-16 commented by chenall -// errnum = 0;//2010-12-16 commented by chenall - - if (debug_boot) { - grub_printf("\r%s\n", cur_entry); - } //DEBUG_SLEEP /* Only uncomment if you want to pause before processing every menu.lst line */ + //仅当您想在处理每个菜单前暂停时才取消注释。第一行 /* Copy the first string in CUR_ENTRY to HEAP. */ + //将CUR_ENTRY中的第一个字符串复制到HEAP。 old_entry = cur_entry; while (*cur_entry++); - grub_memmove (heap, old_entry, (int) cur_entry - (int) old_entry); + grub_memmove (heap, old_entry, (grub_size_t) cur_entry - (grub_size_t) old_entry); if (! *heap) { - /* If there is no more command in SCRIPT... */ - - /* If no kernel is loaded, just exit successfully. */ + /* If there is no more command in SCRIPT... 如果SCRIPT中没有更多命令。*/ + /* If no kernel is loaded, just exit successfully. 如果没有加载内核,只需成功退出*/ if (kernel_type == KERNEL_TYPE_NONE) break; - /* Otherwise, the command boot is run implicitly. */ + /* Otherwise, the command boot is run implicitly. 否则,命令boot将隐式运行。*/ grub_memmove (heap, "boot", 5); } - run_line (heap , BUILTIN_MENU); - /* if the INSERT key was pressed at startup, debug is not allowed to be turned off. */ - if (debug_boot) - if ((unsigned int)debug < 2) /* debug == 0 or 1 */ - { - old_debug = debug; /* save the new debug in old_debug */ - debug = 2; - } - -#ifdef SUPPORT_GFX - if (num_entries && ! errnum && *graphics_file && !password_buf && show_menu && grub_timeout) - { - unsigned long pxe_restart_config_bak = pxe_restart_config; - pxe_restart_config = 1; /* for configfile to work with gfxmenu. */ - - run_graphics_menu((char *)titles, cur_entry, /*num_entries,*/ config_entries + config_len, default_entry); - - pxe_restart_config = pxe_restart_config_bak; /* restore the original value. */ - - } -#endif - - if (pxe_restart_config) - goto restart_config; - -original_config: + /* if the INSERT key was pressed at startup, debug is not allowed to be turned off. */ + //如果在启动时按下了INSERT键,则不允许关闭调试 +// if (pxe_restart_config) +// goto restart_config; +//original_config: if (! *old_entry) break; } /* while (1) */ kernel_type = KERNEL_TYPE_NONE; + } - if (debug_boot) - { - debug = old_debug; /* restore user-specified debug level. */ - printf_debug0 ("\n\nEnd of menu init commands. Press any key to enter command-line or run menu..."); - } - DEBUG_SLEEP - } /* while (1) */ - - /* End of menu-specific commands. */ + /* End of menu-specific commands. 菜单特定命令结束 */ errnum = 0; - - /* Make sure that all fallback entries are valid. */ + /* Make sure that all fallback entries are valid. 确保所有回退条目都有效。*/ if (fallback_entryno >= 0) { int i; @@ -2942,9 +2319,9 @@ extern int graphicsmode_func (char *, int); if (fallback_entries[0] < 0) fallback_entryno = -1; } - /* Check if the default entry is present. Otherwise reset it to fallback if fallback is valid, or to DEFAULT_ENTRY if not. */ + //检查是否存在默认条目。否则,如果回退有效,则将其重置为回退,否则重置为DEFAULT_ENTRY。 if (default_entry >= num_entries) { if (fallback_entryno >= 0) @@ -2957,31 +2334,29 @@ extern int graphicsmode_func (char *, int); else default_entry = 0; } - } - + }//restart_config +//不使用配置文件,或者打开预置菜单以及配置文件失败 done_config_file: - - use_preset_menu = 0; /* Disable the preset menu. */ - - pxe_restart_config = 1; /* pxe_detect will use configfile to run menu */ - - /* go ahead and make sure the terminal is setup */ - if (current_term->startup) - (*current_term->startup)(); + use_preset_menu = 0; /* Disable the preset menu. 禁用预设菜单 */ +// pxe_restart_config = 1; /* pxe_detect will use configfile to run menu pxe_tect将使用configfile运行菜单*/ + /* go ahead and make sure the terminal is setup 继续前进,确保终端的安装 */ +// if (current_term->startup) 无用 2023-06-13 +// (*current_term->startup)(); if (! num_entries) { /* no config file, goto command-line, starting heap from where the config entries would have been stored if there were any. */ - enter_cmdline (config_entries, 1); + //没有配置文件,goto命令行,从哪里开始堆如果有的话,配置条目也会被存储。 + enter_cmdline (CONFIG_ENTRIES, 1); } else { - /* Run menu interface. */ - /* cur_entry point to the first menu item command. */ + /* Run menu interface. 运行菜单界面 */ + /* cur_entry point to the first menu item command. cur_entry指向第一个菜单项命令 */ if (hotkey_func) - hotkey_func(0,0,-1); - run_menu ((char *)titles, cur_entry, /*num_entries,*/ config_entries + config_len, default_entry); + (*hotkey_func)(0,0,-1,0); + run_menu ((char *)titles, cur_entry, /*num_entries,*/ CONFIG_ENTRIES + config_len, default_entry); } goto restart2; } diff --git a/stage2/term.h b/stage2/term.h index dd9d18a1..43c9cf00 100644 --- a/stage2/term.h +++ b/stage2/term.h @@ -20,7 +20,7 @@ #ifndef GRUB_TERM_HEADER #define GRUB_TERM_HEADER 1 - +#include "shared.h" /* These are used to represent the various color states we use */ typedef enum { @@ -60,12 +60,223 @@ typedef enum /* Set when the terminal needs to be initialized. */ #define TERM_NEED_INIT (1 << 16) +#if 0 +//#ifdef SUPPORT_SERIAL +unsigned int serial_putchar (unsigned int c, unsigned int max_width); +int serial_checkkey (void); +int serial_getkey (void); +int serial_getxy (void); +void serial_gotoxy (int x, int y); +void serial_cls (void); +void serial_setcolorstate (color_state state); +//#endif +#endif + +#if 0 +//#ifdef SUPPORT_HERCULES +unsigned int hercules_putchar (unsigned int c, unsigned int max_width); +int hercules_getxy (void); +void hercules_gotoxy (int x, int y); +void hercules_cls (void); +unsigned int hercules_setcursor (unsigned int on); +//#endif +#endif + +#ifdef SUPPORT_GRAPHICS +extern unsigned int foreground, background, graphics_inited; + +void graphics_set_splash(char *splashfile); +int set_videomode (int mode); +unsigned int graphics_putchar (unsigned int c, unsigned int max_width); +int graphics_getxy(void); +void graphics_gotoxy(int x, int y); +void graphics_cls(void); +int graphics_init(void); +void graphics_end(void); + +#endif /* SUPPORT_GRAPHICS */ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//F:\grub4dos_dev\g4d_dev\home\dev\grub32\include\grub\unicode.h +struct grub_unicode_compact_range +{ + unsigned start:21; + unsigned len:9; + unsigned bidi_type:5; + unsigned comb_type:8; + unsigned bidi_mirror:1; + unsigned join_type:3; +} GRUB_PACKED; + +enum grub_comb_type + { + GRUB_UNICODE_COMB_NONE = 0, + GRUB_UNICODE_COMB_OVERLAY = 1, + GRUB_UNICODE_COMB_HEBREW_SHEVA = 10, + GRUB_UNICODE_COMB_HEBREW_HATAF_SEGOL = 11, + GRUB_UNICODE_COMB_HEBREW_HATAF_PATAH = 12, + GRUB_UNICODE_COMB_HEBREW_HATAF_QAMATS = 13, + GRUB_UNICODE_COMB_HEBREW_HIRIQ = 14, + GRUB_UNICODE_COMB_HEBREW_TSERE = 15, + GRUB_UNICODE_COMB_HEBREW_SEGOL = 16, + GRUB_UNICODE_COMB_HEBREW_PATAH = 17, + GRUB_UNICODE_COMB_HEBREW_QAMATS = 18, + GRUB_UNICODE_COMB_HEBREW_HOLAM = 19, + GRUB_UNICODE_COMB_HEBREW_QUBUTS = 20, + GRUB_UNICODE_COMB_HEBREW_DAGESH = 21, + GRUB_UNICODE_COMB_HEBREW_METEG = 22, + GRUB_UNICODE_COMB_HEBREW_RAFE = 23, + GRUB_UNICODE_COMB_HEBREW_SHIN_DOT = 24, + GRUB_UNICODE_COMB_HEBREW_SIN_DOT = 25, + GRUB_UNICODE_COMB_HEBREW_VARIKA = 26, + GRUB_UNICODE_COMB_ARABIC_FATHATAN = 27, + GRUB_UNICODE_COMB_ARABIC_DAMMATAN = 28, + GRUB_UNICODE_COMB_ARABIC_KASRATAN = 29, + GRUB_UNICODE_COMB_ARABIC_FATHAH = 30, + GRUB_UNICODE_COMB_ARABIC_DAMMAH = 31, + GRUB_UNICODE_COMB_ARABIC_KASRA = 32, + GRUB_UNICODE_COMB_ARABIC_SHADDA = 33, + GRUB_UNICODE_COMB_ARABIC_SUKUN = 34, + GRUB_UNICODE_COMB_ARABIC_SUPERSCRIPT_ALIF = 35, + GRUB_UNICODE_COMB_SYRIAC_SUPERSCRIPT_ALAPH = 36, + GRUB_UNICODE_STACK_ATTACHED_BELOW = 202, + GRUB_UNICODE_STACK_ATTACHED_ABOVE = 214, + GRUB_UNICODE_COMB_ATTACHED_ABOVE_RIGHT = 216, + GRUB_UNICODE_STACK_BELOW = 220, + GRUB_UNICODE_COMB_BELOW_RIGHT = 222, + GRUB_UNICODE_COMB_ABOVE_LEFT = 228, + GRUB_UNICODE_STACK_ABOVE = 230, + GRUB_UNICODE_COMB_ABOVE_RIGHT = 232, + GRUB_UNICODE_COMB_YPOGEGRAMMENI = 240, + /* If combining nature is indicated only by class and + not "combining type". */ + GRUB_UNICODE_COMB_ME = 253, + GRUB_UNICODE_COMB_MC = 254, + GRUB_UNICODE_COMB_MN = 255, + }; + +#define GRUB_UNICODE_MAX_CACHED_CHAR 0x20000 +/* Unicode mandates an arbitrary limit. */ +#define GRUB_BIDI_MAX_EXPLICIT_LEVEL 61 +extern struct grub_unicode_compact_range grub_unicode_compact[1]; +struct grub_unicode_combining +{ + unsigned int code:21; + enum grub_comb_type type:8; +}; + +enum + { + GRUB_UNICODE_DOTLESS_LOWERCASE_I = 0x0131, + GRUB_UNICODE_DOTLESS_LOWERCASE_J = 0x0237, + GRUB_UNICODE_COMBINING_GRAPHEME_JOINER = 0x034f, + GRUB_UNICODE_HEBREW_WAW = 0x05d5, + GRUB_UNICODE_ARABIC_START = 0x0600, + GRUB_UNICODE_ARABIC_END = 0x0700, + GRUB_UNICODE_THAANA_ABAFILI = 0x07a6, + GRUB_UNICODE_THAANA_AABAAFILI = 0x07a7, + GRUB_UNICODE_THAANA_IBIFILI = 0x07a8, + GRUB_UNICODE_THAANA_EEBEEFILI = 0x07a9, + GRUB_UNICODE_THAANA_UBUFILI = 0x07aa, + GRUB_UNICODE_THAANA_OOBOOFILI = 0x07ab, + GRUB_UNICODE_THAANA_EBEFILI = 0x07ac, + GRUB_UNICODE_THAANA_EYBEYFILI = 0x07ad, + GRUB_UNICODE_THAANA_OBOFILI = 0x07ae, + GRUB_UNICODE_THAANA_OABOAFILI = 0x07af, + GRUB_UNICODE_THAANA_SUKUN = 0x07b0, + GRUB_UNICODE_ZWNJ = 0x200c, + GRUB_UNICODE_ZWJ = 0x200d, + GRUB_UNICODE_LRM = 0x200e, + GRUB_UNICODE_RLM = 0x200f, + GRUB_UNICODE_LRE = 0x202a, + GRUB_UNICODE_RLE = 0x202b, + GRUB_UNICODE_PDF = 0x202c, + GRUB_UNICODE_LRO = 0x202d, + GRUB_UNICODE_RLO = 0x202e, + GRUB_UNICODE_LEFTARROW = 0x2190, + GRUB_UNICODE_UPARROW = 0x2191, + GRUB_UNICODE_RIGHTARROW = 0x2192, + GRUB_UNICODE_DOWNARROW = 0x2193, + GRUB_UNICODE_UPDOWNARROW = 0x2195, + GRUB_UNICODE_LIGHT_HLINE = 0x2500, + GRUB_UNICODE_HLINE = 0x2501, + GRUB_UNICODE_LIGHT_VLINE = 0x2502, + GRUB_UNICODE_VLINE = 0x2503, + GRUB_UNICODE_LIGHT_CORNER_UL = 0x250c, + GRUB_UNICODE_CORNER_UL = 0x250f, + GRUB_UNICODE_LIGHT_CORNER_UR = 0x2510, + GRUB_UNICODE_CORNER_UR = 0x2513, + GRUB_UNICODE_LIGHT_CORNER_LL = 0x2514, + GRUB_UNICODE_CORNER_LL = 0x2517, + GRUB_UNICODE_LIGHT_CORNER_LR = 0x2518, + GRUB_UNICODE_CORNER_LR = 0x251b, + GRUB_UNICODE_BLACK_UP_TRIANGLE = 0x25b2, + GRUB_UNICODE_BLACK_RIGHT_TRIANGLE = 0x25ba, + GRUB_UNICODE_BLACK_DOWN_TRIANGLE = 0x25bc, + GRUB_UNICODE_BLACK_LEFT_TRIANGLE = 0x25c4, + GRUB_UNICODE_VARIATION_SELECTOR_1 = 0xfe00, + GRUB_UNICODE_VARIATION_SELECTOR_16 = 0xfe0f, + GRUB_UNICODE_TAG_START = 0xe0000, + GRUB_UNICODE_TAG_END = 0xe007f, + GRUB_UNICODE_VARIATION_SELECTOR_17 = 0xe0100, + GRUB_UNICODE_VARIATION_SELECTOR_256 = 0xe01ef, + GRUB_UNICODE_LAST_VALID = 0x10ffff + }; + +enum grub_bidi_type + { + GRUB_BIDI_TYPE_L = 0, + GRUB_BIDI_TYPE_LRE, + GRUB_BIDI_TYPE_LRO, + GRUB_BIDI_TYPE_R, + GRUB_BIDI_TYPE_AL, + GRUB_BIDI_TYPE_RLE, + GRUB_BIDI_TYPE_RLO, + GRUB_BIDI_TYPE_PDF, + GRUB_BIDI_TYPE_EN, + GRUB_BIDI_TYPE_ES, + GRUB_BIDI_TYPE_ET, + GRUB_BIDI_TYPE_AN, + GRUB_BIDI_TYPE_CS, + GRUB_BIDI_TYPE_NSM, + GRUB_BIDI_TYPE_BN, + GRUB_BIDI_TYPE_B, + GRUB_BIDI_TYPE_S, + GRUB_BIDI_TYPE_WS, + GRUB_BIDI_TYPE_ON + }; + +/* This structure describes a glyph as opposed to character. 这个结构描述了一个字形,而不是字符。*/ +struct grub_unicode_glyph +{ + unsigned int base:23; /* minimum: 21 */ + unsigned short variant:9; /* minimum: 9 */ + + unsigned char attributes:5; /* minimum: 5 */ + unsigned char bidi_level:6; /* minimum: 6 */ + enum grub_bidi_type bidi_type:5; /* minimum: :5 */ + + unsigned ncomb:8; + /* Hint by unicode subsystem how wide this character usually is. + Real width is determined by font. Set only in UTF-8 stream. */ + int estimated_width:8; + + unsigned int orig_pos; + union + { + struct grub_unicode_combining combining_inline[sizeof (void *) + / sizeof (struct grub_unicode_combining)]; + struct grub_unicode_combining *combining_ptr; + }; +}; + + struct term_entry { /* The name of a terminal. */ const char *name; /* The feature flags defined above. */ - unsigned long flags; + unsigned int flags; /* Default for screen width in chars if not specified */ unsigned short chars_per_line; /* Default for maximum number of lines if not specified */ @@ -86,9 +297,9 @@ struct term_entry void (*setcolorstate) (color_state state); /* Set the normal color and the highlight color. The format of each color is VGA's. */ - void (*setcolor) (unsigned long state,unsigned long long color[]); + void (*setcolor) (unsigned int state,unsigned long long color[]); /* Turn on/off the cursor. */ - void (*setcursor) (unsigned long on); + unsigned int (*setcursor) (unsigned int on); /* function to start a terminal */ int (*startup) (void); @@ -103,45 +314,243 @@ extern struct term_entry term_table[]; extern struct term_entry *current_term; /* The console stuff. */ -unsigned int console_putchar (unsigned int c, unsigned int max_width); +extern unsigned int console_putchar (unsigned int c, unsigned int max_width); +extern int console_checkkey (void); +extern int console_getkey (void); +extern int console_getxy (void); +extern void console_gotoxy (int x, int y); +extern void console_cls (void); +extern void console_setcolorstate (color_state state); +extern void console_setcolor(unsigned int state,unsigned long long color[]); +extern unsigned int console_setcursor (unsigned int on); +extern int console_startup (void); +extern void console_shutdown (void); +extern int grub_console_getkey (int flags); -int console_getxy (void); -void console_gotoxy (int x, int y); -void console_cls (void); -void console_setcolorstate (color_state state); -void console_setcolor(unsigned long state,unsigned long long color[]); -void console_setcursor (unsigned long on); -#ifdef SUPPORT_SERIAL -unsigned int serial_putchar (unsigned int c, unsigned int max_width); -int serial_checkkey (void); -int serial_getkey (void); -int serial_getxy (void); -void serial_gotoxy (int x, int y); -void serial_cls (void); -void serial_setcolorstate (color_state state); -#endif +//F:\grub4dos_dev\g4d_dev\home\dev\grub32\include\grub\list.h +struct grub_list +{ + struct grub_list *next; + struct grub_list **prev; +}; +typedef struct grub_list *grub_list_t; -#ifdef SUPPORT_HERCULES -unsigned int hercules_putchar (unsigned int c, unsigned int max_width); -int hercules_getxy (void); -void hercules_gotoxy (int x, int y); -void hercules_cls (void); -void hercules_setcursor (unsigned long on); -#endif +#define FOR_LIST_ELEMENTS(var, list) for ((var) = (list); (var); (var) = (var)->next) +#define FOR_LIST_ELEMENTS_SAFE(var, nxt, list) for ((var) = (list), (nxt) = ((var) ? (var)->next : 0); (var); (var) = (nxt), ((nxt) = (var) ? (var)->next : 0)) -#ifdef SUPPORT_GRAPHICS -extern unsigned long foreground, background, graphics_inited; -void graphics_set_splash(char *splashfile); -int set_videomode (int mode); -unsigned int graphics_putchar (unsigned int c, unsigned int max_width); -int graphics_getxy(void); -void graphics_gotoxy(int x, int y); -void graphics_cls(void); -int graphics_init(void); -void graphics_end(void); -#endif /* SUPPORT_GRAPHICS */ +//F:\grub4dos_dev\g4d_dev\home\dev\grub32\include\grub\sysbol.h +#define EXPORT_VAR(x) x +#define EXPORT_FUNC(x) x + +//F:\grub4dos_dev\g4d_dev\home\dev\grub32\include\grub\types.h +//typedef unsigned char grub_uint8_t; +//typedef unsigned short grub_uint16_t; +//typedef unsigned long grub_uint32_t; //不要修改long +//typedef grub_uint32_t grub_size_t; + + +//F:\grub4dos_dev\g4d_dev\home\dev\grub32\include\grub\term.h +#define GRUB_TERM_NO_KEY 0 + +/* Internal codes used by GRUB to represent terminal input. GRUB用来表示终端输入的内部代码 */ +/* Only for keys otherwise not having shifted modification. 仅用于键,否则没有移位修改 */ +#define GRUB_TERM_SHIFT 0x01000000 +#define GRUB_TERM_CTRL 0x02000000 +#define GRUB_TERM_ALT 0x04000000 + +/* Keys without associated character. 没有关联字符的键 */ +#define GRUB_TERM_EXTENDED 0x00800000 //扩展 +#define GRUB_TERM_KEY_MASK 0x00ffffff //多重移幅键控 + +#define GRUB_TERM_KEY_LEFT (GRUB_TERM_EXTENDED | 0x4b) +#define GRUB_TERM_KEY_RIGHT (GRUB_TERM_EXTENDED | 0x4d) +#define GRUB_TERM_KEY_UP (GRUB_TERM_EXTENDED | 0x48) +#define GRUB_TERM_KEY_DOWN (GRUB_TERM_EXTENDED | 0x50) +#define GRUB_TERM_KEY_HOME (GRUB_TERM_EXTENDED | 0x47) +#define GRUB_TERM_KEY_END (GRUB_TERM_EXTENDED | 0x4f) +#define GRUB_TERM_KEY_DC (GRUB_TERM_EXTENDED | 0x53) +#define GRUB_TERM_KEY_PPAGE (GRUB_TERM_EXTENDED | 0x49) +#define GRUB_TERM_KEY_NPAGE (GRUB_TERM_EXTENDED | 0x51) +#define GRUB_TERM_KEY_F1 (GRUB_TERM_EXTENDED | 0x3b) +#define GRUB_TERM_KEY_F2 (GRUB_TERM_EXTENDED | 0x3c) +#define GRUB_TERM_KEY_F3 (GRUB_TERM_EXTENDED | 0x3d) +#define GRUB_TERM_KEY_F4 (GRUB_TERM_EXTENDED | 0x3e) +#define GRUB_TERM_KEY_F5 (GRUB_TERM_EXTENDED | 0x3f) +#define GRUB_TERM_KEY_F6 (GRUB_TERM_EXTENDED | 0x40) +#define GRUB_TERM_KEY_F7 (GRUB_TERM_EXTENDED | 0x41) +#define GRUB_TERM_KEY_F8 (GRUB_TERM_EXTENDED | 0x42) +#define GRUB_TERM_KEY_F9 (GRUB_TERM_EXTENDED | 0x43) +#define GRUB_TERM_KEY_F10 (GRUB_TERM_EXTENDED | 0x44) +#define GRUB_TERM_KEY_F11 (GRUB_TERM_EXTENDED | 0x57) +#define GRUB_TERM_KEY_F12 (GRUB_TERM_EXTENDED | 0x58) +#define GRUB_TERM_KEY_INSERT (GRUB_TERM_EXTENDED | 0x52) +#define GRUB_TERM_KEY_CENTER (GRUB_TERM_EXTENDED | 0x4c) + +/* Hex value is used for ESC, since '\e' is nonstandard. 十六进制值用于ESC,因为“\e”是非标准的 */ +#define GRUB_TERM_ESC 0x1b +#define GRUB_TERM_TAB '\t' +#define GRUB_TERM_BACKSPACE '\b' + +#define GRUB_PROGRESS_NO_UPDATE -1 //没有进行更新 +#define GRUB_PROGRESS_FAST 0 //进展快速 +#define GRUB_PROGRESS_SLOW 2 //进展缓慢 + +/* These are used to represent the various color states we use. 这些被用来表示我们使用的各种颜色状态 */ +typedef enum + { + /* The color used to display all text that does not use the + user defined colors below. 用于显示不使用用户定义颜色的所有文本的颜色 */ + GRUB_TERM_COLOR_STANDARD, + /* The user defined colors for normal text.用于正常文本的用户定义颜色 */ + GRUB_TERM_COLOR_NORMAL, + /* The user defined colors for highlighted text. 用于突出显示文本的用户定义颜色 */ + GRUB_TERM_COLOR_HIGHLIGHT + } +grub_term_color_state; + +/* Flags for representing the capabilities of a terminal. 表示终端能力的标志 */ +/* Some notes about the flags: 关于标记的几点注释 + - These flags are used by higher-level functions but not terminals + themselves. 这些标志是由高级函数使用的,而不是终端本身使用的 + - If a terminal is dumb, you may assume that only putchar, getkey and + checkkey are called. 如果终端是愚蠢的,你可以假设只打印字符,获得键,检查键被调用 + - Some fancy features (setcolorstate, setcolor and setcursor) can be set + to NULL. 一些奇特的特征(设置颜色状态,设置颜色和设置游标)可以设置为空 */ + +/* Set when input characters shouldn't be echoed back. 设置输入字符不回写 1 */ +#define GRUB_TERM_NO_ECHO (1 << 0) +/* Set when the editing feature should be disabled. 设置禁用编辑 2 */ +#define GRUB_TERM_NO_EDIT (1 << 1) +/* Set when the terminal cannot do fancy things. 设置终端不能花哨的事 4 */ +#define GRUB_TERM_DUMB (1 << 2) +/* Which encoding does terminal expect stream to be. 终端期望哪种编码 */ +#define GRUB_TERM_CODE_TYPE_SHIFT 3 //换挡 3 +#define GRUB_TERM_CODE_TYPE_MASK (7 << GRUB_TERM_CODE_TYPE_SHIFT) //多重移幅键控 0x38 +/* Only ASCII characters accepted. 只有ASCII字符被接受 0 */ +#define GRUB_TERM_CODE_TYPE_ASCII (0 << GRUB_TERM_CODE_TYPE_SHIFT) +/* Expects CP-437 characters (ASCII + pseudographics). 期待CP-437字符(ASCII +假字符) 8 */ +#define GRUB_TERM_CODE_TYPE_CP437 (1 << GRUB_TERM_CODE_TYPE_SHIFT) +/* UTF-8 stream in logical order. Usually used for terminals UTF-8按逻辑顺序进行流. 通常用于仅将流转发到另一台计算机的终端。 0x10 + which just forward the stream to another computer. */ +#define GRUB_TERM_CODE_TYPE_UTF8_LOGICAL (2 << GRUB_TERM_CODE_TYPE_SHIFT) +/* UTF-8 in visual order. Like UTF-8 logical but for buggy endpoints. 视觉顺序为UTF-8.类似UTF-8逻辑,但对于buggy终端 0x18 */ +#define GRUB_TERM_CODE_TYPE_UTF8_VISUAL (3 << GRUB_TERM_CODE_TYPE_SHIFT) +/* Glyph description in visual order. 视觉顺序中的字形描述 0x20 */ +#define GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS (4 << GRUB_TERM_CODE_TYPE_SHIFT) + + +/* Bitmasks for modifier keys returned by grub_getkeystatus. '获得键状态'返回的修改键的位掩码 */ +#define GRUB_TERM_STATUS_RSHIFT (1 << 0) +#define GRUB_TERM_STATUS_LSHIFT (1 << 1) +#define GRUB_TERM_STATUS_RCTRL (1 << 2) +#define GRUB_TERM_STATUS_RALT (1 << 3) +#define GRUB_TERM_STATUS_SCROLL (1 << 4) +#define GRUB_TERM_STATUS_NUM (1 << 5) +#define GRUB_TERM_STATUS_CAPS (1 << 6) +#define GRUB_TERM_STATUS_LCTRL (1 << 8) +#define GRUB_TERM_STATUS_LALT (1 << 9) + +/* Menu-related geometrical constants. 菜单相关的几何常数 */ + +/* The number of columns/lines between messages/borders/etc. 列/消息之间的行/边界/等等的数 */ +#define GRUB_TERM_MARGIN 1 + +/* The number of columns of scroll information. 滚动信息列数 */ +#define GRUB_TERM_SCROLL_WIDTH 1 + +struct grub_term_input //终端输入结构 +{ + /* The next terminal. 下一终端 0 */ + struct grub_term_input *next; + struct grub_term_input **prev; + + /* The terminal name. 终端名称 10 */ + const char *name; + + /* Initialize the terminal. 初始化终端 18 */ + grub_err_t (*init) (struct grub_term_input *term); + + /* Clean up the terminal. 清理终端 20 */ + grub_err_t (*fini) (struct grub_term_input *term); + + /* Get a character if any input character is available. Otherwise return -1. 如果任何输入字符可用,则获取字符。否则返回-1 28 */ + int (*getkey) (struct grub_term_input *term); + + /* Get keyboard modifier status. 获取键盘修改器状态 30 */ + int (*getkeystatus) (struct grub_term_input *term); + + void *data; //38 +}; +typedef struct grub_term_input *grub_term_input_t; //终端输入结构 + +/* Made in a way to fit into uint32_t and so be passed in a register. 一种适合uint32_t的方法并且所以在一个寄存器中通过 */ +struct grub_term_coordinate //终端坐标 +{ + grub_uint16_t x; + grub_uint16_t y; +}; + +/* +表106 支持的Unicode控制字符 +助记符 Unicode 说明 +Null U+0000 接收时忽略空字符 +BS U+0008 退格键。将光标向左移动一列。如果光标位于左边距,则不执行任何操作。 +TAB U+0009 制表键. +LF U+000A 换行。将光标移到下一行。 +CR U+000D 回车。将光标移到当前行的左边距。 +表107 EFI简单文本输入协议的EFI扫描代码 scan_code +EFI扫描代码 描述 +0x00 空扫描代码 +0x01 将光标向上移动1行 +0x02 将光标向下移动1行 +0x03 将光标向右移动1列 +0x04 将光标向左移动1列。 +0x05 Home. 首行 +0x06 End. 尾行 +0x07 Insert. 插入 +0x08 Delete. 删除 +0x09 Page Up. 上一页 +0x0a Page Down. 下一页 +0x0b Function 1. 功能1 +0x0c Function 2. +0x0d Function 3. +0x0e Function 4. +0x0f Function 5. +0x10 Function 6. +0x11 Function 7. +0x12 Function 8. +0x13 Function 9. +0x14 Function 10. +0x17 Escape. 逃离 +表108 EFI简单文本输入扩展协议的EFI扫描代码 +0x15 Function 11 +0x16 Function 12 +0x68 Function 13 +0x69 Function 14 +0x6A Function 15 +0x6B Function 16 +0x6C Function 17 +0x6D Function 18 +0x6E Function 19 +0x6F Function 20 +0x70 Function 21 +0x71 Function 22 +0x72 Function 23 +0x73 Function 24 +0x7F Mute 静音 +0x80 Volume Up 音量增加 +0x81 Volume Down 音量减少 +0x100 Brightness Up 亮度提高 +0x101 Brightness Down 亮度降低 +0x102 Suspend 暂停 +0x103 Hibernate 休眠 +0x104 Toggle Display 切换显示 +0x105 Recovery 恢复 +0x106 Eject 弹出 +0x8000-0xFFFF OEM Reserved OEM保留 +*/ #endif /* ! GRUB_TERM_HEADER */ diff --git a/stage2/terminfo.c b/stage2/terminfo.c deleted file mode 100644 index 3c7b77d2..00000000 --- a/stage2/terminfo.c +++ /dev/null @@ -1,258 +0,0 @@ -/* terminfo.c - read a terminfo entry from the command line */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2004 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * ###################################################################### - * - * This file contains various functions dealing with different - * terminal capabilities. It knows the difference between a vt52 and vt100 - * terminal (and much more) and is mainly used the terminal emulation - * in the serial driver. - */ - -#include -#include "terminfo.h" -#include "tparm.h" -#include "serial.h" - -/* Current terminal capabilities. Default is "vt100". */ -struct terminfo term = - { - .name = "vt100", - .cursor_address = "\e[%i%p1%d;%p2%dH", - .clear_screen = "\e[H\e[J", - .enter_standout_mode = "\e[7m", - .exit_standout_mode = "\e[m" - }; - -/* A number of escape sequences are provided in the string valued - capabilities for easy encoding of characters there. Both \E and \e - map to an ESCAPE character, ^x maps to a control-x for any - appropriate x, and the sequences \n \l \r \t \b \f \s give a - newline, line-feed, return, tab, backspace, form-feed, and space. - Other escapes include \^ for ^, \\ for \, \, for comma, \: for :, - and \0 for null. (\0 will produce \200, which does not terminate a - string but behaves as a null character on most terminals, provid - ing CS7 is specified. See stty(1).) Finally, characters may be - given as three octal digits after a \. */ - -static char * -ti_unescape_memory (const char *in, const char *end) -{ - static char out_buffer[256]; - char c; - char *out; - - out = out_buffer; - do - { - c = *(in++); - switch (c) - { - case '^': - if (*in >= 'A' && *in <= 'Z') - { - *out = (*in) - 'A'; - in++; - } - else - { - *out = '^'; - } - break; - case '\\': - c = *(in++); - if (c >= '0' && c <= '9') - { - // octal number - int n = 0; - do - { - n = (n << 4) | (c - '0'); - c = *(in++); - } - while (c >= '0' && c <= '9'); - - *out++ = (char)(n & 0xff); - - // redo last character - in--; - - break; - } - - switch (c) - { - case 'e': - case 'E': - *out++ = '\e'; - break; - case 'n': - *out++ = '\n'; - break; - case 'r': - *out++ = '\r'; - break; - case 't': - *out++ = '\t'; - break; - case 'b': - *out++ = '\b'; - break; - case 'f': - *out++ = '\f'; - break; - case 's': - *out++ = ' '; - break; - case '\\': - *out++ = '\\'; - break; - case '^': - *out++ = '^'; - break; - case ',': - *out++ = ','; - break; - case ':': - *out++ = ':'; - break; - case '0': - *out++ = '\200'; - break; - } - break; - default: - *out++ = c; - break; - } - } - while (in <= end); - - return out_buffer; -} - -char * -ti_unescape_string (const char *in) -{ - return ti_unescape_memory (in, in + grub_strlen (in)); -} - -/* convert a memory region containing binary character into an external - * ascii representation. The binary characters will be replaced by an - * "ecsape notation". E.g. "033" will become "\e". */ -static char * -ti_escape_memory (const char *in, const char *end) -{ - static char out_buffer[256]; - char c; - char *out; - - out = out_buffer; - do - { - c = *(in++); - switch (c) - { - case '\e': - *out++ = '\\'; *out++ = 'e'; break; - case ' ': - *out++ = '\\'; *out++ = 's'; break; - case '\\': - *out++ = '\\'; *out++ = '\\'; break; - case '0' ... '9': - case 'a' ... 'z': - case 'A' ... 'Z': - case '%': - case '+': - case '-': - case '*': - case '/': - case ';': - case ':': - case '{': - case '}': - case '[': - case ']': - *out++ = c; break; - case 0 ... 25: - *out++ = '^'; *out++ = 'A' + c; break; - default: - *out++ = '\\'; - *out++ = ((c >> 8) & 7) + '0'; - *out++ = ((c >> 4) & 7) + '0'; - *out++ = ((c >> 0) & 7) + '0'; - break; - } - } - while (in < end); - - *out++ = 0; - - return out_buffer; -} - -/* convert a string containing binary character into an external ascii - * representation. */ -char * -ti_escape_string (const char *in) -{ - return ti_escape_memory (in, in + grub_strlen (in)); -} - -/* move the cursor to the given position starting with "0". */ -void -ti_cursor_address (int x, int y) -{ - grub_putstr (grub_tparm (term.cursor_address, y, x)); -} - -/* clear the screen. */ -void -ti_clear_screen (void) -{ - grub_putstr (grub_tparm (term.clear_screen)); -} - -/* enter reverse video */ -void -ti_enter_standout_mode (void) -{ - grub_putstr (grub_tparm (term.enter_standout_mode)); -} - -/* exit reverse video */ -void -ti_exit_standout_mode (void) -{ - grub_putstr (grub_tparm (term.exit_standout_mode)); -} - -/* set the current terminal emulation to use */ -void -ti_set_term (const struct terminfo *new) -{ - grub_memmove (&term, new, sizeof (struct terminfo)); -} - -/* get the current terminal emulation */ -void -ti_get_term(struct terminfo *copy) -{ - grub_memmove (copy, &term, sizeof (struct terminfo)); -} diff --git a/stage2/terminfo.h b/stage2/terminfo.h deleted file mode 100644 index 6852c654..00000000 --- a/stage2/terminfo.h +++ /dev/null @@ -1,51 +0,0 @@ -/* terminfo.h - read a terminfo entry from the command line */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003,2004 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef GRUB_TERMCAP_HEADER -#define GRUB_TERMCAP_HEADER 1 - -#define TERMINFO_LEN 40 - -typedef struct terminfo -{ - char name[TERMINFO_LEN]; - char cursor_address[TERMINFO_LEN]; - char clear_screen[TERMINFO_LEN]; - char enter_standout_mode[TERMINFO_LEN]; - char exit_standout_mode[TERMINFO_LEN]; -} -terminfo; - - -/* Function prototypes. */ -//char *ti_escape_memory (const char *in, const char *end); -char *ti_escape_string (const char *in); -//char *ti_unescape_memory (const char *in, const char *end); -char *ti_unescape_string (const char *in); - -void ti_set_term (const struct terminfo *new); -void ti_get_term (struct terminfo *copy); - -void ti_cursor_address (int x, int y); -void ti_clear_screen (void); -void ti_enter_standout_mode (void); -void ti_exit_standout_mode (void); - -#endif /* ! GRUB_TERMCAP_HEADER */ diff --git a/stage2/tparm.c b/stage2/tparm.c deleted file mode 100644 index 6a008c8c..00000000 --- a/stage2/tparm.c +++ /dev/null @@ -1,726 +0,0 @@ -/**************************************************************************** - * Copyright (c) 1998,2000,2002 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/********************************************************************** - * This code is a modification of lib_tparm.c found in ncurses-5.2. The - * modification are for use in grub by replacing all libc function through - * special grub functions. This also meant to delete all dynamic memory - * allocation and replace it by a number of fixed buffers. - * - * Modifications by Tilmann Bubeck 2002 - **********************************************************************/ - -/**************************************************************************** - * Author: Zeyd M. Ben-Halim 1992,1995 * - * and: Eric S. Raymond * - ****************************************************************************/ - -/* - * tparm.c - * - */ - -#include "shared.h" - -#include "tparm.h" - -/* - * Common/troublesome character definitions - */ -typedef char grub_bool; -#define isdigit(c) ((c) >= '0' && (c) <= '9') -#ifndef FALSE -# define FALSE (0) -#endif -#ifndef TRUE -# define TRUE (!FALSE) -#endif -#define MAX_FORMAT_LEN 256 -#define max(a,b) ((a) > (b) ? (a) : (b)) - -//MODULE_ID("$Id: tparm.c,v 1.1 2002/11/29 20:39:24 okuji Exp $") - -/* - * char * - * tparm(string, ...) - * - * Substitute the given parameters into the given string by the following - * rules (taken from terminfo(5)): - * - * Cursor addressing and other strings requiring parame- - * ters in the terminal are described by a parameterized string - * capability, with like escapes %x in it. For example, to - * address the cursor, the cup capability is given, using two - * parameters: the row and column to address to. (Rows and - * columns are numbered from zero and refer to the physical - * screen visible to the user, not to any unseen memory.) If - * the terminal has memory relative cursor addressing, that can - * be indicated by - * - * The parameter mechanism uses a stack and special % - * codes to manipulate it. Typically a sequence will push one - * of the parameters onto the stack and then print it in some - * format. Often more complex operations are necessary. - * - * The % encodings have the following meanings: - * - * %% outputs `%' - * %c print pop() like %c in printf() - * %s print pop() like %s in printf() - * %[[:]flags][width[.precision]][doxXs] - * as in printf, flags are [-+#] and space - * The ':' is used to avoid making %+ or %- - * patterns (see below). - * - * %p[1-9] push ith parm - * %P[a-z] set dynamic variable [a-z] to pop() - * %g[a-z] get dynamic variable [a-z] and push it - * %P[A-Z] set static variable [A-Z] to pop() - * %g[A-Z] get static variable [A-Z] and push it - * %l push strlen(pop) - * %'c' push char constant c - * %{nn} push integer constant nn - * - * %+ %- %* %/ %m - * arithmetic (%m is mod): push(pop() op pop()) - * %& %| %^ bit operations: push(pop() op pop()) - * %= %> %< logical operations: push(pop() op pop()) - * %A %O logical and & or operations for conditionals - * %! %~ unary operations push(op pop()) - * %i add 1 to first two parms (for ANSI terminals) - * - * %? expr %t thenpart %e elsepart %; - * if-then-else, %e elsepart is optional. - * else-if's are possible ala Algol 68: - * %? c1 %t b1 %e c2 %t b2 %e c3 %t b3 %e c4 %t b4 %e b5 %; - * - * For those of the above operators which are binary and not commutative, - * the stack works in the usual way, with - * %gx %gy %m - * resulting in x mod y, not the reverse. - */ - -#define STACKSIZE 20 - -typedef struct { - union { - unsigned int num; - char *str; - } data; - grub_bool num_type; -} stack_frame; - -static stack_frame stack[STACKSIZE]; -static int stack_ptr; - -static char out_buff[256]; -static int out_size = 256; -static int out_used; - -static inline void -get_space(int need) -{ - need += out_used; - if (need > out_size) { - // FIX ME! buffer full, what now? - ; - } -} - -static inline void -save_text(const char *fmt, const char *s, int len) -{ - int s_len = grub_strlen(s); - if (len > (int) s_len) - s_len = len; - - get_space(s_len + 1); - - (void) grub_sprintf(out_buff + out_used, fmt, s); - out_used += grub_strlen(out_buff + out_used); -} - -static inline void -save_number(const char *fmt, int number, int len) -{ - if (len < 30) - len = 30; /* actually log10(MAX_INT)+1 */ - - get_space(len + 1); - - (void) grub_sprintf(out_buff + out_used, fmt, number); - out_used += grub_strlen(out_buff + out_used); -} - -static inline void -save_char(int c) -{ - if (c == 0) - c = 0200; - get_space(1); - out_buff[out_used++] = c; -} - -static inline void -npush(int x) -{ - if (stack_ptr < STACKSIZE) { - stack[stack_ptr].num_type = TRUE; - stack[stack_ptr].data.num = x; - stack_ptr++; - } -} - -static inline int -npop(void) -{ - int result = 0; - if (stack_ptr > 0) { - stack_ptr--; - if (stack[stack_ptr].num_type) - result = stack[stack_ptr].data.num; - } - return result; -} - -static inline void -spush(char *x) -{ - if (stack_ptr < STACKSIZE) { - stack[stack_ptr].num_type = FALSE; - stack[stack_ptr].data.str = x; - stack_ptr++; - } -} - -static inline char * -spop(void) -{ - static char dummy[] = ""; /* avoid const-cast */ - char *result = dummy; - if (stack_ptr > 0) { - stack_ptr--; - if (!stack[stack_ptr].num_type && stack[stack_ptr].data.str != 0) - result = stack[stack_ptr].data.str; - } - return result; -} - -static inline const char * -parse_format(const char *s, char *format, int *len) -{ - grub_bool done = FALSE; - grub_bool allowminus = FALSE; - grub_bool dot = FALSE; - grub_bool err = FALSE; - char *fmt = format; - int prec = 0; - int width = 0; - int value = 0; - - *len = 0; - *format++ = '%'; - while (*s != '\0' && !done) { - switch (*s) { - case 'c': /* FALLTHRU */ - case 'd': /* FALLTHRU */ - case 'o': /* FALLTHRU */ - case 'x': /* FALLTHRU */ - case 'X': /* FALLTHRU */ - case 's': - *format++ = *s; - done = TRUE; - break; - case '.': - *format++ = *s++; - if (dot) { - err = TRUE; - } else { - dot = TRUE; - prec = value; - } - value = 0; - break; - case '#': - *format++ = *s++; - break; - case ' ': - *format++ = *s++; - break; - case ':': - s++; - allowminus = TRUE; - break; - case '-': - if (allowminus) { - *format++ = *s++; - } else { - done = TRUE; - } - break; - default: - if (isdigit(*s)) { - value = (value * 10) + (*s - '0'); - if (value > 10000) - err = TRUE; - *format++ = *s++; - } else { - done = TRUE; - } - } - } - - /* - * If we found an error, ignore (and remove) the flags. - */ - if (err) { - prec = width = value = 0; - format = fmt; - *format++ = '%'; - *format++ = *s; - } - - if (dot) - width = value; - else - prec = value; - - *format = '\0'; - /* return maximum string length in print */ - *len = (prec > width) ? prec : width; - return s; -} - -#define isUPPER(c) ((c) >= 'A' && (c) <= 'Z') -#define isLOWER(c) ((c) >= 'a' && (c) <= 'z') - -static inline char * -tparam_internal(const char *string, int *dataptr) -{ -#define NUM_VARS 26 - char *p_is_s[9]; - int param[9]; - int lastpop; - int popcount; - int number; - int len; - int level; - int x, y; - int i; - int len2; - register const char *cp; - static int len_fmt = MAX_FORMAT_LEN; - static char dummy[] = ""; - static char format[MAX_FORMAT_LEN]; - static int dynamic_var[NUM_VARS]; - static int static_vars[NUM_VARS]; - - out_used = 0; - if (string == NULL) - return NULL; - - if ((len2 = grub_strlen(string)) > len_fmt) { - return NULL; - } - - /* - * Find the highest parameter-number referred to in the format string. - * Use this value to limit the number of arguments copied from the - * variable-length argument list. - */ - - number = 0; - lastpop = -1; - popcount = 0; - grub_memset(p_is_s, 0, sizeof(p_is_s)); - - /* - * Analyze the string to see how many parameters we need from the varargs - * list, and what their types are. We will only accept string parameters - * if they appear as a %l or %s format following an explicit parameter - * reference (e.g., %p2%s). All other parameters are numbers. - * - * 'number' counts coarsely the number of pop's we see in the string, and - * 'popcount' shows the highest parameter number in the string. We would - * like to simply use the latter count, but if we are reading termcap - * strings, there may be cases that we cannot see the explicit parameter - * numbers. - */ - for (cp = string; (cp - string) < (int) len2;) { - if (*cp == '%') { - cp++; - cp = parse_format(cp, format, &len); - switch (*cp) { - default: - break; - - case 'd': /* FALLTHRU */ - case 'o': /* FALLTHRU */ - case 'x': /* FALLTHRU */ - case 'X': /* FALLTHRU */ - case 'c': /* FALLTHRU */ - number++; - lastpop = -1; - break; - - case 'l': - case 's': - if (lastpop > 0) - p_is_s[lastpop - 1] = dummy; - ++number; - break; - - case 'p': - cp++; - i = (*cp - '0'); - if (i >= 0 && i <= 9) { - lastpop = i; - if (lastpop > popcount) - popcount = lastpop; - } - break; - - case 'P': - case 'g': - cp++; - break; - - case '\'': - cp += 2; - lastpop = -1; - break; - - case '{': - cp++; - while (*cp >= '0' && *cp <= '9') { - cp++; - } - break; - - case '+': - case '-': - case '*': - case '/': - case 'm': - case 'A': - case 'O': - case '&': - case '|': - case '^': - case '=': - case '<': - case '>': - case '!': - case '~': - lastpop = -1; - number += 2; - break; - - case 'i': - lastpop = -1; - if (popcount < 2) - popcount = 2; - break; - } - } - if (*cp != '\0') - cp++; - } - - if (number > 9) - number = 9; - for (i = 0; i < max(popcount, number); i++) { - /* - * A few caps (such as plab_norm) have string-valued parms. - * We'll have to assume that the caller knows the difference, since - * a char* and an int may not be the same size on the stack. - */ - if (p_is_s[i] != 0) { - p_is_s[i] = (char *)(*(dataptr++)); - } else { - param[i] = (int)(*(dataptr++)); - } - } - - /* - * This is a termcap compatibility hack. If there are no explicit pop - * operations in the string, load the stack in such a way that - * successive pops will grab successive parameters. That will make - * the expansion of (for example) \E[%d;%dH work correctly in termcap - * style, which means tparam() will expand termcap strings OK. - */ - stack_ptr = 0; - if (popcount == 0) { - popcount = number; - for (i = number - 1; i >= 0; i--) - npush(param[i]); - } - - while (*string) { - /* skip delay timings */ - if (*string == '$' && *(string + 1) == '<') { - while( *string && *string != '>') - string++; - if ( *string == '>' ) string++; - } else if ( *string == '%') { - string++; - string = parse_format(string, format, &len); - switch (*string) { - default: - break; - case '%': - save_char('%'); - break; - - case 'd': /* FALLTHRU */ - case 'o': /* FALLTHRU */ - case 'x': /* FALLTHRU */ - case 'X': /* FALLTHRU */ - case 'c': /* FALLTHRU */ - save_number(format, npop(), len); - break; - - case 'l': - save_number("%d", strlen(spop()), 0); - break; - - case 's': - save_text(format, spop(), len); - break; - - case 'p': - string++; - i = (*string - '1'); - if (i >= 0 && i < 9) { - if (p_is_s[i]) - spush(p_is_s[i]); - else - npush(param[i]); - } - break; - - case 'P': - string++; - if (isUPPER(*string)) { - i = (*string - 'A'); - static_vars[i] = npop(); - } else if (isLOWER(*string)) { - i = (*string - 'a'); - dynamic_var[i] = npop(); - } - break; - - case 'g': - string++; - if (isUPPER(*string)) { - i = (*string - 'A'); - npush(static_vars[i]); - } else if (isLOWER(*string)) { - i = (*string - 'a'); - npush(dynamic_var[i]); - } - break; - - case '\'': - string++; - npush(*string); - string++; - break; - - case '{': - number = 0; - string++; - while (*string >= '0' && *string <= '9') { - number = number * 10 + *string - '0'; - string++; - } - npush(number); - break; - - case '+': - npush(npop() + npop()); - break; - - case '-': - y = npop(); - x = npop(); - npush(x - y); - break; - - case '*': - npush(npop() * npop()); - break; - - case '/': - y = npop(); - x = npop(); - npush(y ? (x / y) : 0); - break; - - case 'm': - y = npop(); - x = npop(); - npush(y ? (x % y) : 0); - break; - - case 'A': - npush(npop() && npop()); - break; - - case 'O': - npush(npop() || npop()); - break; - - case '&': - npush(npop() & npop()); - break; - - case '|': - npush(npop() | npop()); - break; - - case '^': - npush(npop() ^ npop()); - break; - - case '=': - y = npop(); - x = npop(); - npush(x == y); - break; - - case '<': - y = npop(); - x = npop(); - npush(x < y); - break; - - case '>': - y = npop(); - x = npop(); - npush(x > y); - break; - - case '!': - npush(!npop()); - break; - - case '~': - npush(~npop()); - break; - - case 'i': - if (p_is_s[0] == 0) - param[0]++; - if (p_is_s[1] == 0) - param[1]++; - break; - - case '?': - break; - - case 't': - x = npop(); - if (!x) { - /* scan forward for %e or %; at level zero */ - string++; - level = 0; - while (*string) { - if (*string == '%') { - string++; - if (*string == '?') - level++; - else if (*string == ';') { - if (level > 0) - level--; - else - break; - } else if (*string == 'e' && level == 0) - break; - } - - if (*string) - string++; - } - } - break; - - case 'e': - /* scan forward for a %; at level zero */ - string++; - level = 0; - while (*string) { - if (*string == '%') { - string++; - if (*string == '?') - level++; - else if (*string == ';') { - if (level > 0) - level--; - else - break; - } - } - - if (*string) - string++; - } - break; - - case ';': - break; - - } /* endswitch (*string) */ - } else { /* endelse (*string == '%') */ - save_char(*string); - } - - if (*string == '\0') - break; - - string++; - } /* endwhile (*string) */ - - get_space(1); - out_buff[out_used] = '\0'; - - return (out_buff); -} - -char * -grub_tparm(const char *string,...) -{ - char *result; - int *dataptr = (int *)(void *) &string; - - dataptr++; - - result = tparam_internal(string, dataptr); - - return result; -} diff --git a/stage2/tparm.h b/stage2/tparm.h deleted file mode 100644 index e2c1b68e..00000000 --- a/stage2/tparm.h +++ /dev/null @@ -1,28 +0,0 @@ -/* tparm.h - parameter formatting of terminfo */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef GRUB_TPARM_HEADER -#define GRUB_TPARM_HEADER 1 - - -/* Function prototypes. */ -char *grub_tparm (const char *string, ...); - -#endif /* ! GRUB_TERMCAP_HEADER */ diff --git a/stage2/ufs2.h b/stage2/ufs2.h deleted file mode 100644 index ba2ef30a..00000000 --- a/stage2/ufs2.h +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Copyright (C) 2004 Free Software Foundation, Inc. - * Copyright (c) 2002 Networks Associates Technology, Inc. - * All rights reserved. - * - * This software was developed for the FreeBSD Project by Marshall - * Kirk McKusick and Network Associates Laboratories, the Security - * Research Division of Network Associates, Inc. under DARPA/SPAWAR - * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS - * research program - * - * Copyright (c) 1982, 1989, 1993 - * The Regents of the University of California. All rights reserved. - * (c) UNIX System Laboratories, Inc. - * All or some portions of this file are derived from material licensed - * to the University of California by American Telephone and Telegraph - * Co. or Unix System Laboratories, Inc. and are reproduced herein with - * the permission of UNIX System Laboratories, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the authors may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)dinode.h 8.3 (Berkeley) 1/21/94 - * $FreeBSD: src/sys/ufs/ufs/dinode.h,v 1.11 2002/07/16 22:36:00 mckusick Exp $ - */ - -#ifndef _GRUB_UFS2_H_ -#define _GRUB_UFS2_H_ - -typedef signed char grub_int8_t; -typedef signed short grub_int16_t; -typedef signed int grub_int32_t; -typedef signed long long int grub_int64_t; -typedef unsigned char grub_uint8_t; -typedef unsigned short grub_uint16_t; -typedef unsigned int grub_uint32_t; -typedef unsigned long long int grub_uint64_t; - -typedef grub_uint8_t grub_u_char; -typedef grub_uint32_t grub_u_int; - -typedef grub_uint8_t grub_u_int8_t; -typedef grub_uint16_t grub_u_int16_t; -typedef grub_uint32_t grub_u_int32_t; -typedef grub_uint64_t grub_u_int64_t; - -#define i_size di_size - - -#define DEV_BSIZE 512 - -/* - * The root inode is the root of the filesystem. Inode 0 can't be used for - * normal purposes and historically bad blocks were linked to inode 1, thus - * the root inode is 2. (Inode 1 is no longer used for this purpose, however - * numerous dump tapes make this assumption, so we are stuck with it). - */ -#define ROOTINO ((grub_ino_t)2) - -/* - * The size of physical and logical block numbers and time fields in UFS. - */ -typedef grub_int32_t ufs1_daddr_t; -typedef grub_int64_t ufs2_daddr_t; -typedef grub_int64_t ufs_lbn_t; -typedef grub_int64_t ufs_time_t; - -/* inode number */ -typedef grub_uint32_t grub_ino_t; - -/* File permissions. */ -#define IEXEC 0000100 /* Executable. */ -#define IWRITE 0000200 /* Writeable. */ -#define IREAD 0000400 /* Readable. */ -#define ISVTX 0001000 /* Sticky bit. */ -#define ISGID 0002000 /* Set-gid. */ -#define ISUID 0004000 /* Set-uid. */ - -/* File types. */ -#define IFMT 0170000 /* Mask of file type. */ -#define IFIFO 0010000 /* Named pipe (fifo). */ -#define IFCHR 0020000 /* Character device. */ -#define IFDIR 0040000 /* Directory file. */ -#define IFBLK 0060000 /* Block device. */ -#define IFREG 0100000 /* Regular file. */ -#define IFLNK 0120000 /* Symbolic link. */ -#define IFSOCK 0140000 /* UNIX domain socket. */ -#define IFWHT 0160000 /* Whiteout. */ - -/* - * A dinode contains all the meta-data associated with a UFS2 file. - * This structure defines the on-disk format of a dinode. Since - * this structure describes an on-disk structure, all its fields - * are defined by types with precise widths. - */ - -#define NXADDR 2 /* External addresses in inode. */ -#define NDADDR 12 /* Direct addresses in inode. */ -#define NIADDR 3 /* Indirect addresses in inode. */ - -struct ufs1_dinode { - grub_u_int16_t di_mode; /* 0: IFMT, permissions; see below. */ - grub_int16_t di_nlink; /* 2: File link count. */ - union { - grub_u_int16_t oldids[2]; /* 4: Ffs: old user and group ids. */ - } di_u; - grub_u_int64_t di_size; /* 8: File byte count. */ - grub_int32_t di_atime; /* 16: Last access time. */ - grub_int32_t di_atimensec; /* 20: Last access time. */ - grub_int32_t di_mtime; /* 24: Last modified time. */ - grub_int32_t di_mtimensec; /* 28: Last modified time. */ - grub_int32_t di_ctime; /* 32: Last inode change time. */ - grub_int32_t di_ctimensec; /* 36: Last inode change time. */ - ufs1_daddr_t di_db[NDADDR]; /* 40: Direct disk blocks. */ - ufs1_daddr_t di_ib[NIADDR]; /* 88: Indirect disk blocks. */ - grub_u_int32_t di_flags; /* 100: Status flags (chflags). */ - grub_int32_t di_blocks; /* 104: Blocks actually held. */ - grub_int32_t di_gen; /* 108: Generation number. */ - grub_u_int32_t di_uid; /* 112: File owner. */ - grub_u_int32_t di_gid; /* 116: File group. */ - grub_int32_t di_spare[2]; /* 120: Reserved; currently unused */ -}; - -struct ufs2_dinode { - grub_u_int16_t di_mode; /* 0: IFMT, permissions; see below. */ - grub_int16_t di_nlink; /* 2: File link count. */ - grub_u_int32_t di_uid; /* 4: File owner. */ - grub_u_int32_t di_gid; /* 8: File group. */ - grub_u_int32_t di_blksize; /* 12: Inode blocksize. */ - grub_u_int64_t di_size; /* 16: File byte count. */ - grub_u_int64_t di_blocks; /* 24: Bytes actually held. */ - ufs_time_t di_atime; /* 32: Last access time. */ - ufs_time_t di_mtime; /* 40: Last modified time. */ - ufs_time_t di_ctime; /* 48: Last inode change time. */ - ufs_time_t di_birthtime; /* 56: Inode creation time. */ - grub_int32_t di_mtimensec; /* 64: Last modified time. */ - grub_int32_t di_atimensec; /* 68: Last access time. */ - grub_int32_t di_ctimensec; /* 72: Last inode change time. */ - grub_int32_t di_birthnsec; /* 76: Inode creation time. */ - grub_int32_t di_gen; /* 80: Generation number. */ - grub_u_int32_t di_kernflags; /* 84: Kernel flags. */ - grub_u_int32_t di_flags; /* 88: Status flags (chflags). */ - grub_int32_t di_extsize; /* 92: External attributes block. */ - ufs2_daddr_t di_extb[NXADDR];/* 96: External attributes block. */ - ufs2_daddr_t di_db[NDADDR]; /* 112: Direct disk blocks. */ - ufs2_daddr_t di_ib[NIADDR]; /* 208: Indirect disk blocks. */ - grub_int64_t di_spare[3]; /* 232: Reserved; currently unused */ -}; - -#define MAXNAMLEN 255 - -struct direct { - grub_u_int32_t d_ino; /* inode number of entry */ - grub_u_int16_t d_reclen; /* length of this record */ - grub_u_int8_t d_type; /* file type, see below */ - grub_u_int8_t d_namlen; /* length of string in d_name */ - char d_name[MAXNAMLEN + 1];/* name with length <= MAXNAMLEN */ -}; - -/* - * File types - */ -#define DT_UNKNOWN 0 -#define DT_FIFO 1 -#define DT_CHR 2 -#define DT_DIR 4 -#define DT_BLK 6 -#define DT_REG 8 -#define DT_LNK 10 -#define DT_SOCK 12 -#define DT_WHT 14 - -/* - * Superblock offsets - */ -#define SBLOCK_FLOPPY 0 -#define SBLOCK_UFS1 8192 -#define SBLOCK_UFS2 65536 -#define SBLOCK_PIGGY 262144 -#define SBLOCKSIZE 8192 -#define SBLOCKSEARCH \ - { SBLOCK_UFS2, SBLOCK_UFS1, SBLOCK_FLOPPY, SBLOCK_PIGGY, -1 } - -#define MAXMNTLEN 512 - -#define NOCSPTRS ((128 / sizeof(void *)) - 4) - -/* - * The maximum number of snapshot nodes that can be associated - * with each filesystem. This limit affects only the number of - * snapshot files that can be recorded within the superblock so - * that they can be found when the filesystem is mounted. However, - * maintaining too many will slow the filesystem performance, so - * having this limit is a good idea. - */ -#define FSMAXSNAP 20 - -/* - * Per cylinder group information; summarized in blocks allocated - * from first cylinder group data blocks. These blocks have to be - * read in from fs_csaddr (size fs_cssize) in addition to the - * super block. - */ -struct csum { - grub_int32_t cs_ndir; /* number of directories */ - grub_int32_t cs_nbfree; /* number of free blocks */ - grub_int32_t cs_nifree; /* number of free inodes */ - grub_int32_t cs_nffree; /* number of free frags */ -}; - -struct csum_total { - grub_int64_t cs_ndir; /* number of directories */ - grub_int64_t cs_nbfree; /* number of free blocks */ - grub_int64_t cs_nifree; /* number of free inodes */ - grub_int64_t cs_nffree; /* number of free frags */ - grub_int64_t cs_numclusters; /* number of free clusters */ - grub_int64_t cs_spare[3]; /* future expansion */ -}; - -/* - * Super block for an FFS filesystem. - */ -struct fs { - grub_int32_t fs_firstfield; /* historic filesystem linked list, */ - grub_int32_t fs_unused_1; /* used for incore super blocks */ - grub_int32_t fs_sblkno; /* offset of super-block in filesys */ - grub_int32_t fs_cblkno; /* offset of cyl-block in filesys */ - grub_int32_t fs_iblkno; /* offset of inode-blocks in filesys */ - grub_int32_t fs_dblkno; /* offset of first data after cg */ - grub_int32_t fs_old_cgoffset; /* cylinder group offset in cylinder */ - grub_int32_t fs_old_cgmask; /* used to calc mod fs_ntrak */ - grub_int32_t fs_old_time; /* last time written */ - grub_int32_t fs_old_size; /* number of blocks in fs */ - grub_int32_t fs_old_dsize; /* number of data blocks in fs */ - grub_int32_t fs_ncg; /* number of cylinder groups */ - grub_int32_t fs_bsize; /* size of basic blocks in fs */ - grub_int32_t fs_fsize; /* size of frag blocks in fs */ - grub_int32_t fs_frag; /* number of frags in a block in fs */ -/* these are configuration parameters */ - grub_int32_t fs_minfree; /* minimum percentage of free blocks */ - grub_int32_t fs_old_rotdelay; /* num of ms for optimal next block */ - grub_int32_t fs_old_rps; /* disk revolutions per second */ -/* these fields can be computed from the others */ - grub_int32_t fs_bmask; /* ``blkoff'' calc of blk offsets */ - grub_int32_t fs_fmask; /* ``fragoff'' calc of frag offsets */ - grub_int32_t fs_bshift; /* ``lblkno'' calc of logical blkno */ - grub_int32_t fs_fshift; /* ``numfrags'' calc number of frags */ -/* these are configuration parameters */ - grub_int32_t fs_maxcontig; /* max number of contiguous blks */ - grub_int32_t fs_maxbpg; /* max number of blks per cyl group */ -/* these fields can be computed from the others */ - grub_int32_t fs_fragshift; /* block to frag shift */ - grub_int32_t fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ - grub_int32_t fs_sbsize; /* actual size of super block */ - grub_int32_t fs_spare1[2]; /* old fs_csmask */ - /* old fs_csshift */ - grub_int32_t fs_nindir; /* value of NINDIR */ - grub_int32_t fs_inopb; /* value of INOPB */ - grub_int32_t fs_old_nspf; /* value of NSPF */ -/* yet another configuration parameter */ - grub_int32_t fs_optim; /* optimization preference, see below */ - grub_int32_t fs_old_npsect; /* # sectors/track including spares */ - grub_int32_t fs_old_interleave; /* hardware sector interleave */ - grub_int32_t fs_old_trackskew; /* sector 0 skew, per track */ - grub_int32_t fs_id[2]; /* unique filesystem id */ -/* sizes determined by number of cylinder groups and their sizes */ - grub_int32_t fs_old_csaddr; /* blk addr of cyl grp summary area */ - grub_int32_t fs_cssize; /* size of cyl grp summary area */ - grub_int32_t fs_cgsize; /* cylinder group size */ - grub_int32_t fs_spare2; /* old fs_ntrak */ - grub_int32_t fs_old_nsect; /* sectors per track */ - grub_int32_t fs_old_spc; /* sectors per cylinder */ - grub_int32_t fs_old_ncyl; /* cylinders in filesystem */ - grub_int32_t fs_old_cpg; /* cylinders per group */ - grub_int32_t fs_ipg; /* inodes per group */ - grub_int32_t fs_fpg; /* blocks per group * fs_frag */ -/* this data must be re-computed after crashes */ - struct csum fs_old_cstotal; /* cylinder summary information */ -/* these fields are cleared at mount time */ - grub_int8_t fs_fmod; /* super block modified flag */ - grub_int8_t fs_clean; /* filesystem is clean flag */ - grub_int8_t fs_ronly; /* mounted read-only flag */ - grub_int8_t fs_old_flags; /* old FS_ flags */ - grub_u_char fs_fsmnt[MAXMNTLEN]; /* name mounted on */ -/* these fields retain the current block allocation info */ - grub_int32_t fs_cgrotor; /* last cg searched */ - void *fs_ocsp[NOCSPTRS]; /* padding; was list of fs_cs buffers */ - grub_u_int8_t *fs_contigdirs; /* # of contiguously allocated dirs */ - struct csum *fs_csp; /* cg summary info buffer for fs_cs */ - grub_int32_t *fs_maxcluster; /* max cluster in each cyl group */ - grub_u_int *fs_active; /* used by snapshots to track fs */ - grub_int32_t fs_old_cpc; /* cyl per cycle in postbl */ - grub_int32_t fs_maxbsize; /* maximum blocking factor permitted */ - grub_int64_t fs_sparecon64[17]; /* old rotation block list head */ - grub_int64_t fs_sblockloc; /* byte offset of standard superblock */ - struct csum_total fs_cstotal; /* cylinder summary information */ - ufs_time_t fs_time; /* last time written */ - grub_int64_t fs_size; /* number of blocks in fs */ - grub_int64_t fs_dsize; /* number of data blocks in fs */ - ufs2_daddr_t fs_csaddr; /* blk addr of cyl grp summary area */ - grub_int64_t fs_pendingblocks; /* blocks in process of being freed */ - grub_int32_t fs_pendinginodes; /* inodes in process of being freed */ - grub_int32_t fs_snapinum[FSMAXSNAP];/* list of snapshot inode numbers */ - grub_int32_t fs_avgfilesize; /* expected average file size */ - grub_int32_t fs_avgfpdir; /* expected # of files per directory */ - grub_int32_t fs_save_cgsize; /* save real cg size to use fs_bsize */ - grub_int32_t fs_sparecon32[26]; /* reserved for future constants */ - grub_int32_t fs_flags; /* see FS_ flags below */ - grub_int32_t fs_contigsumsize; /* size of cluster summary array */ - grub_int32_t fs_maxsymlinklen; /* max length of an internal symlink */ - grub_int32_t fs_old_inodefmt; /* format of on-disk inodes */ - grub_u_int64_t fs_maxfilesize; /* maximum representable file size */ - grub_int64_t fs_qbmask; /* ~fs_bmask for use with 64-bit size */ - grub_int64_t fs_qfmask; /* ~fs_fmask for use with 64-bit size */ - grub_int32_t fs_state; /* validate fs_clean field */ - grub_int32_t fs_old_postblformat; /* format of positional layout tables */ - grub_int32_t fs_old_nrpos; /* number of rotational positions */ - grub_int32_t fs_spare5[2]; /* old fs_postbloff */ - /* old fs_rotbloff */ - grub_int32_t fs_magic; /* magic number */ -}; - -/* - * Filesystem identification - */ -#define FS_UFS1_MAGIC 0x011954 /* UFS1 fast filesystem magic number */ -#define FS_UFS2_MAGIC 0x19540119 /* UFS2 fast filesystem magic number */ - -/* - * Turn filesystem block numbers into disk block addresses. - * This maps filesystem blocks to device size blocks. - */ -#define fsbtodb(fs, b) ((b) << (fs)->fs_fsbtodb) -#define dbtofsb(fs, b) ((b) >> (fs)->fs_fsbtodb) - -/* - * Cylinder group macros to locate things in cylinder groups. - * They calc filesystem addresses of cylinder group data structures. - */ -#define cgbase(fs, c) ((ufs2_daddr_t)((fs)->fs_fpg * (c))) -#define cgimin(fs, c) (cgstart(fs, c) + (fs)->fs_iblkno) /* inode blk */ -#define cgstart(fs, c) \ - ((fs)->fs_magic == FS_UFS2_MAGIC ? cgbase(fs, c) : \ - (cgbase(fs, c) + (fs)->fs_old_cgoffset * ((c) & ~((fs)->fs_old_cgmask)))) - -/* - * Macros for handling inode numbers: - * inode number to filesystem block offset. - * inode number to cylinder group number. - * inode number to filesystem block address. - */ -#define ino_to_cg(fs, x) ((x) / (fs)->fs_ipg) -#define ino_to_fsba(fs, x) \ - ((ufs2_daddr_t)(cgimin(fs, ino_to_cg(fs, x)) + \ - (blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs)))))) -#define ino_to_fsbo(fs, x) ((x) % INOPB(fs)) - -/* - * The following macros optimize certain frequently calculated - * quantities by using shifts and masks in place of divisions - * modulos and multiplications. - */ -#define blkoff(fs, loc) /* calculates (loc % fs->fs_bsize) */ \ - ((loc) & (fs)->fs_qbmask) - -/* Use this only when `blk' is known to be small, e.g., < NDADDR. */ -#define smalllblktosize(fs, blk) /* calculates (blk * fs->fs_bsize) */ \ - ((blk) << (fs)->fs_bshift) - - -#define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \ - ((loc) >> (fs)->fs_bshift) - -#define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \ - (((size) + (fs)->fs_qfmask) & (fs)->fs_fmask) - -#define fragstoblks(fs, frags) /* calculates (frags / fs->fs_frag) */ \ - ((frags) >> (fs)->fs_fragshift) -#define blkstofrags(fs, blks) /* calculates (blks * fs->fs_frag) */ \ - ((blks) << (fs)->fs_fragshift) -#define fragnum(fs, fsb) /* calculates (fsb % fs->fs_frag) */ \ - ((fsb) & ((fs)->fs_frag - 1)) -#define blknum(fs, fsb) /* calculates rounddown(fsb, fs->fs_frag) */ \ - ((fsb) &~ ((fs)->fs_frag - 1)) - -/* - * Determining the size of a file block in the filesystem. - */ -#define blksize(fs, ip, lbn) \ - (((lbn) >= NDADDR || (ip)->i_size >= smalllblktosize(fs, (lbn) + 1)) \ - ? (fs)->fs_bsize \ - : (fragroundup(fs, blkoff(fs, (ip)->i_size)))) -#define sblksize(fs, size, lbn) \ - (((lbn) >= NDADDR || (size) >= ((lbn) + 1) << (fs)->fs_bshift) \ - ? (fs)->fs_bsize \ - : (fragroundup(fs, blkoff(fs, (size))))) - - -/* - * Number of inodes in a secondary storage block/fragment. - */ -#define INOPB(fs) ((fs)->fs_inopb) -#define INOPF(fs) ((fs)->fs_inopb >> (fs)->fs_fragshift) - -/* - * Number of indirects in a filesystem block. - */ -#define NINDIR(fs) ((fs)->fs_nindir) - -#define FS_UNCLEAN 0x01 /* filesystem not clean at mount */ -#define FS_DOSOFTDEP 0x02 /* filesystem using soft dependencies */ -#define FS_NEEDSFSCK 0x04 /* filesystem needs sync fsck before mount */ -#define FS_INDEXDIRS 0x08 /* kernel supports indexed directories */ -#define FS_ACLS 0x10 /* file system has ACLs enabled */ -#define FS_MULTILABEL 0x20 /* file system is MAC multi-label */ -#define FS_FLAGS_UPDATED 0x80 /* flags have been moved to new location */ - -#endif /* _GRUB_UFS2_H_ */ diff --git a/stage2/vstafs.h b/stage2/vstafs.h deleted file mode 100644 index cc7820cb..00000000 --- a/stage2/vstafs.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2001 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#ifndef VSTAFS_H -#define VSTAFS_H 1 - - -#define LINE 16 -#define BLOCK_SIZE 512 -#define VSTAFS_START_DATA 320 - -struct bootrecord -{ - unsigned char flag; - unsigned char s_sector; - unsigned char s_head; - unsigned char s_cylinder; - unsigned char p_type; - unsigned char e_sector; - unsigned char e_head; - unsigned char e_cylinder; - unsigned long start_lba; - unsigned long nr_sector_lba; -}; - -struct alloc -{ - unsigned long a_start; - unsigned long a_len; -}; - -struct first_sector -{ - unsigned long fs_magic; - unsigned long fs_size; - unsigned long fs_extsize; - unsigned long fs_free; - struct alloc fs_freesecs[0]; -}; - -struct prot -{ - unsigned char len; - unsigned char pdefault; - unsigned char id[7]; - unsigned char bits[7]; -}; - -struct fs_file -{ - unsigned long prev; - unsigned long rev; - unsigned long len; - unsigned short type; - unsigned short nlink; - struct prot pprot; - unsigned int owner; - unsigned int extents; - struct alloc blocks[32]; - long fs_ctime, fs_mtime; /* it is not lon but time_t */ - char pad[16]; - char data[0]; -}; - -struct dir_entry -{ - char name[28]; - unsigned long start; -}; - -#endif /* ! VSTAFS_H */ diff --git a/stage2/xfs.h b/stage2/xfs.h deleted file mode 100644 index 02f8dcd1..00000000 --- a/stage2/xfs.h +++ /dev/null @@ -1,544 +0,0 @@ -/* xfs.h - an extraction from xfsprogs-1.3.5/include/xfs* into one file */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved. - * Copyright (C) 2001,2004 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ - -typedef signed char xfs_int8_t; -typedef unsigned char xfs_uint8_t; -typedef short xfs_int16_t; -typedef unsigned short xfs_uint16_t; -typedef int xfs_int32_t; -typedef unsigned int xfs_uint32_t; -typedef long long xfs_int64_t; -typedef unsigned long long xfs_uint64_t; - -typedef xfs_uint64_t xfs_ino_t; -typedef xfs_uint32_t xfs_agino_t; -typedef xfs_int64_t xfs_daddr_t; -typedef xfs_int64_t xfs_off_t; -typedef xfs_uint8_t uuid_t[16]; - - -/* those are from xfs_types.h */ - -typedef xfs_uint32_t xfs_agblock_t; /* blockno in alloc. group */ -typedef xfs_uint32_t xfs_extlen_t; /* extent length in blocks */ -typedef xfs_uint32_t xfs_agnumber_t; /* allocation group number */ -typedef xfs_int32_t xfs_extnum_t; /* # of extents in a file */ -typedef xfs_int16_t xfs_aextnum_t; /* # extents in an attribute fork */ -typedef xfs_int64_t xfs_fsize_t; /* bytes in a file */ - -typedef xfs_uint32_t xfs_dablk_t; /* dir/attr block number (in file) */ -typedef xfs_uint32_t xfs_dahash_t; /* dir/attr hash value */ - -/* - * Disk based types: - */ -typedef xfs_uint64_t xfs_dfsbno_t; /* blockno in filesystem (agno|agbno) */ -typedef xfs_uint64_t xfs_drfsbno_t; /* blockno in filesystem (raw) */ -typedef xfs_uint64_t xfs_drtbno_t; /* extent (block) in realtime area */ -typedef xfs_uint64_t xfs_dfiloff_t; /* block number in a file */ - -typedef xfs_uint64_t xfs_fsblock_t; /* blockno in filesystem (agno|agbno) */ -typedef xfs_uint64_t xfs_fileoff_t; /* block number in a file */ -typedef xfs_uint64_t xfs_filblks_t; /* number of blocks in a file */ - - -/* those are from xfs_sb.h */ - -#define XFS_SB_MAGIC 0x58465342 /* 'XFSB'*/ -#define XFS_SB_VERSION_4 4 /* 6.2+ - bitmask version */ -#define XFS_SB_VERSION_NUMBITS 0x000f - -typedef struct xfs_sb -{ - xfs_uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */ - xfs_uint32_t sb_blocksize; /* logical block size, bytes */ - xfs_drfsbno_t sb_dblocks; /* number of data blocks */ - xfs_drfsbno_t sb_rblocks; /* number of realtime blocks */ - xfs_drtbno_t sb_rextents; /* number of realtime extents */ - uuid_t sb_uuid; /* file system unique id */ - xfs_dfsbno_t sb_logstart; /* starting block of log if internal */ - xfs_ino_t sb_rootino; /* root inode number */ - xfs_ino_t sb_rbmino; /* bitmap inode for realtime extents */ - xfs_ino_t sb_rsumino; /* summary inode for rt bitmap */ - xfs_agblock_t sb_rextsize; /* realtime extent size, blocks */ - xfs_agblock_t sb_agblocks; /* size of an allocation group */ - xfs_agnumber_t sb_agcount; /* number of allocation groups */ - xfs_extlen_t sb_rbmblocks; /* number of rt bitmap blocks */ - xfs_extlen_t sb_logblocks; /* number of log blocks */ - xfs_uint16_t sb_versionnum; /* header version == XFS_SB_VERSION */ - xfs_uint16_t sb_sectsize; /* volume sector size, bytes */ - xfs_uint16_t sb_inodesize; /* inode size, bytes */ - xfs_uint16_t sb_inopblock; /* inodes per block */ - char sb_fname[12]; /* file system name */ - xfs_uint8_t sb_blocklog; /* log2 of sb_blocksize */ - xfs_uint8_t sb_sectlog; /* log2 of sb_sectsize */ - xfs_uint8_t sb_inodelog; /* log2 of sb_inodesize */ - xfs_uint8_t sb_inopblog; /* log2 of sb_inopblock */ - xfs_uint8_t sb_agblklog; /* log2 of sb_agblocks (rounded up) */ - xfs_uint8_t sb_rextslog; /* log2 of sb_rextents */ - xfs_uint8_t sb_inprogress; /* mkfs is in progress, don't mount */ - xfs_uint8_t sb_imax_pct; /* max % of fs for inode space */ - /* statistics */ - /* - * These fields must remain contiguous. If you really - * want to change their layout, make sure you fix the - * code in xfs_trans_apply_sb_deltas(). - */ - xfs_uint64_t sb_icount; /* allocated inodes */ - xfs_uint64_t sb_ifree; /* free inodes */ - xfs_uint64_t sb_fdblocks; /* free data blocks */ - xfs_uint64_t sb_frextents; /* free realtime extents */ - /* - * End contiguous fields. - */ - xfs_ino_t sb_uquotino; /* user quota inode */ - xfs_ino_t sb_gquotino; /* group quota inode */ - xfs_uint16_t sb_qflags; /* quota flags */ - xfs_uint8_t sb_flags; /* misc. flags */ - xfs_uint8_t sb_shared_vn; /* shared version number */ - xfs_extlen_t sb_inoalignmt; /* inode chunk alignment, fsblocks */ - xfs_uint32_t sb_unit; /* stripe or raid unit */ - xfs_uint32_t sb_width; /* stripe or raid width */ - xfs_uint8_t sb_dirblklog; /* log2 of dir block size (fsbs) */ - xfs_uint8_t sb_dummy[7]; /* padding */ -} xfs_sb_t; - - -/* those are from xfs_btree.h */ - -/* - * Long form header: bmap btrees. - */ -typedef struct xfs_btree_lblock -{ - xfs_uint32_t bb_magic; /* magic number for block type */ - xfs_uint16_t bb_level; /* 0 is a leaf */ - xfs_uint16_t bb_numrecs; /* current # of data records */ - xfs_dfsbno_t bb_leftsib; /* left sibling block or NULLDFSBNO */ - xfs_dfsbno_t bb_rightsib; /* right sibling block or NULLDFSBNO */ -} xfs_btree_lblock_t; - -/* - * Combined header and structure, used by common code. - */ -typedef struct xfs_btree_hdr -{ - xfs_uint32_t bb_magic; /* magic number for block type */ - xfs_uint16_t bb_level; /* 0 is a leaf */ - xfs_uint16_t bb_numrecs; /* current # of data records */ -} xfs_btree_hdr_t; - -typedef struct xfs_btree_block -{ - xfs_btree_hdr_t bb_h; /* header */ - union { - struct { - xfs_agblock_t bb_leftsib; - xfs_agblock_t bb_rightsib; - } s; /* short form pointers */ - struct { - xfs_dfsbno_t bb_leftsib; - xfs_dfsbno_t bb_rightsib; - } l; /* long form pointers */ - } bb_u; /* rest */ -} xfs_btree_block_t; - -/* those are from xfs_bmap_btree.h */ - -/* - * Bmap root header, on-disk form only. - */ -typedef struct xfs_bmdr_block -{ - xfs_uint16_t bb_level; /* 0 is a leaf */ - xfs_uint16_t bb_numrecs; /* current # of data records */ -} xfs_bmdr_block_t; - -/* - * Bmap btree record and extent descriptor. - * For 32-bit kernels, - * l0:31 is an extent flag (value 1 indicates non-normal). - * l0:0-30 and l1:9-31 are startoff. - * l1:0-8, l2:0-31, and l3:21-31 are startblock. - * l3:0-20 are blockcount. - * For 64-bit kernels, - * l0:63 is an extent flag (value 1 indicates non-normal). - * l0:9-62 are startoff. - * l0:0-8 and l1:21-63 are startblock. - * l1:0-20 are blockcount. - */ - -#define BMBT_USE_64 1 - -typedef struct xfs_bmbt_rec_32 -{ - xfs_uint32_t l0, l1, l2, l3; -} xfs_bmbt_rec_32_t; -typedef struct xfs_bmbt_rec_64 -{ - xfs_uint64_t l0, l1; -} xfs_bmbt_rec_64_t; - -#if BMBT_USE_64 -typedef xfs_uint64_t xfs_bmbt_rec_base_t; /* use this for casts */ -typedef xfs_bmbt_rec_64_t xfs_bmbt_rec_t, xfs_bmdr_rec_t; -#else /* !BMBT_USE_64 */ -typedef xfs_uint32_t xfs_bmbt_rec_base_t; /* use this for casts */ -typedef xfs_bmbt_rec_32_t xfs_bmbt_rec_t, xfs_bmdr_rec_t; -#endif /* BMBT_USE_64 */ - -/* - * Key structure for non-leaf levels of the tree. - */ -typedef struct xfs_bmbt_key -{ - xfs_dfiloff_t br_startoff; /* starting file offset */ -} xfs_bmbt_key_t, xfs_bmdr_key_t; - -typedef xfs_dfsbno_t xfs_bmbt_ptr_t, xfs_bmdr_ptr_t; /* btree pointer type */ - /* btree block header type */ -typedef struct xfs_btree_lblock xfs_bmbt_block_t; - - -/* those are from xfs_dir2.h */ -/* - * Directory version 2. - * There are 4 possible formats: - * shortform - * single block - data with embedded leaf at the end - * multiple data blocks, single leaf+freeindex block - * data blocks, node&leaf blocks (btree), freeindex blocks - * - * The shortform format is in xfs_dir2_sf.h. - * The single block format is in xfs_dir2_block.h. - * The data block format is in xfs_dir2_data.h. - * The leaf and freeindex block formats are in xfs_dir2_leaf.h. - * Node blocks are the same as the other version, in xfs_da_btree.h. - */ - -/* - * Byte offset in data block and shortform entry. - */ -typedef xfs_uint16_t xfs_dir2_data_off_t; - -/* - * Byte offset in a directory. - */ -typedef xfs_off_t xfs_dir2_off_t; - -/* those are from xfs_da_btree.h */ -/*======================================================================== - * Directory Structure when greater than XFS_LBSIZE(mp) bytes. - *========================================================================*/ - -/* - * This structure is common to both leaf nodes and non-leaf nodes in the Btree. - * - * Is is used to manage a doubly linked list of all blocks at the same - * level in the Btree, and to identify which type of block this is. - */ -#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */ -#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */ - -typedef struct xfs_da_blkinfo { - xfs_dablk_t forw; /* previous block in list */ - xfs_dablk_t back; /* following block in list */ - xfs_uint16_t magic; /* validity check on block */ - xfs_uint16_t pad; /* unused */ -} xfs_da_blkinfo_t; - -/* - * This is the structure of the root and intermediate nodes in the Btree. - * The leaf nodes are defined above. - * - * Entries are not packed. - * - * Since we have duplicate keys, use a binary search but always follow - * all match in the block, not just the first match found. - */ - -typedef struct xfs_da_intnode { - struct xfs_da_node_hdr { /* constant-structure header block */ - xfs_da_blkinfo_t info; /* block type, links, etc. */ - xfs_uint16_t count; /* count of active entries */ - xfs_uint16_t level; /* level above leaves (leaf == 0) */ - } hdr; - struct xfs_da_node_entry { - xfs_dahash_t hashval; /* hash value for this descendant */ - xfs_dablk_t before; /* Btree block before this key */ - } btree[1]; /* variable sized array of keys */ -} xfs_da_intnode_t; - - -/* those are from xfs_dir2_data.h */ -/* - * Directory format 2, data block structures. - */ - -/* - * Constants. - */ -#define XFS_DIR2_DATA_FREE_TAG 0xffff -#define XFS_DIR2_DATA_FD_COUNT 3 - -/* - * Structures. - */ - -/* - * Describe a free area in the data block. - * The freespace will be formatted as a xfs_dir2_data_unused_t. - */ -typedef struct xfs_dir2_data_free { - xfs_dir2_data_off_t offset; /* start of freespace */ - xfs_dir2_data_off_t length; /* length of freespace */ -} xfs_dir2_data_free_t; - -/* - * Header for the data blocks. - * Always at the beginning of a directory-sized block. - * The code knows that XFS_DIR2_DATA_FD_COUNT is 3. - */ -typedef struct xfs_dir2_data_hdr { - xfs_uint32_t magic; /* XFS_DIR2_DATA_MAGIC */ - /* or XFS_DIR2_BLOCK_MAGIC */ - xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT]; -} xfs_dir2_data_hdr_t; - -/* - * Active entry in a data block. Aligned to 8 bytes. - * Tag appears as the last 2 bytes. - */ -typedef struct xfs_dir2_data_entry { - xfs_ino_t inumber; /* inode number */ - xfs_uint8_t namelen; /* name length */ - xfs_uint8_t name[1]; /* name bytes, no null */ - /* variable offset */ - xfs_dir2_data_off_t tag; /* starting offset of us */ -} xfs_dir2_data_entry_t; - -/* - * Unused entry in a data block. Aligned to 8 bytes. - * Tag appears as the last 2 bytes. - */ -typedef struct xfs_dir2_data_unused { - xfs_uint16_t freetag; /* XFS_DIR2_DATA_FREE_TAG */ - xfs_dir2_data_off_t length; /* total free length */ - /* variable offset */ - xfs_dir2_data_off_t tag; /* starting offset of us */ -} xfs_dir2_data_unused_t; - -typedef union { - xfs_dir2_data_entry_t entry; - xfs_dir2_data_unused_t unused; -} xfs_dir2_data_union_t; - - -/* those are from xfs_dir2_leaf.h */ -/* - * Directory version 2, leaf block structures. - */ - -/* - * Leaf block header. - */ -typedef struct xfs_dir2_leaf_hdr { - xfs_da_blkinfo_t info; /* header for da routines */ - xfs_uint16_t count; /* count of entries */ - xfs_uint16_t stale; /* count of stale entries */ -} xfs_dir2_leaf_hdr_t; - - -/* those are from xfs_dir2_block.h */ -/* - * xfs_dir2_block.h - * Directory version 2, single block format structures - */ - -/* - * The single block format is as follows: - * xfs_dir2_data_hdr_t structure - * xfs_dir2_data_entry_t and xfs_dir2_data_unused_t structures - * xfs_dir2_leaf_entry_t structures - * xfs_dir2_block_tail_t structure - */ - -#define XFS_DIR2_BLOCK_MAGIC 0x58443242 /* XD2B: for one block dirs */ - -typedef struct xfs_dir2_block_tail { - xfs_uint32_t count; /* count of leaf entries */ - xfs_uint32_t stale; /* count of stale lf entries */ -} xfs_dir2_block_tail_t; - - -/* those are from xfs_dir2_sf.h */ - -/* - * Directory layout when stored internal to an inode. - * - * Small directories are packed as tightly as possible so as to - * fit into the literal area of the inode. - */ - -/* - * Inode number stored as 8 8-bit values. - */ -typedef struct { xfs_uint8_t i[8]; } xfs_dir2_ino8_t; - -/* - * Inode number stored as 4 8-bit values. - * Works a lot of the time, when all the inode numbers in a directory - * fit in 32 bits. - */ -typedef struct { xfs_uint8_t i[4]; } xfs_dir2_ino4_t; - -typedef union { - xfs_dir2_ino8_t i8; - xfs_dir2_ino4_t i4; -} xfs_dir2_inou_t; - -/* - * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t. - * Only need 16 bits, this is the byte offset into the single block form. - */ -typedef struct { xfs_uint8_t i[2]; } xfs_dir2_sf_off_t; - -/* - * The parent directory has a dedicated field, and the self-pointer must - * be calculated on the fly. - * - * Entries are packed toward the top as tightly as possible. The header - * and the elements must be bcopy()'d out into a work area to get correct - * alignment for the inode number fields. - */ -typedef struct xfs_dir2_sf_hdr { - xfs_uint8_t count; /* count of entries */ - xfs_uint8_t i8count; /* count of 8-byte inode #s */ - xfs_dir2_inou_t parent; /* parent dir inode number */ -} xfs_dir2_sf_hdr_t; - -typedef struct xfs_dir2_sf_entry { - xfs_uint8_t namelen; /* actual name length */ - xfs_dir2_sf_off_t offset; /* saved offset */ - xfs_uint8_t name[1]; /* name, variable size */ - xfs_dir2_inou_t inumber; /* inode number, var. offset */ -} xfs_dir2_sf_entry_t; - -typedef struct xfs_dir2_sf { - xfs_dir2_sf_hdr_t hdr; /* shortform header */ - xfs_dir2_sf_entry_t list[1]; /* shortform entries */ -} xfs_dir2_sf_t; - -/* those are from xfs_dinode.h */ - -#define XFS_DINODE_VERSION_1 1 -#define XFS_DINODE_VERSION_2 2 -#define XFS_DINODE_MAGIC 0x494e /* 'IN' */ - -/* - * Disk inode structure. - * This is just the header; the inode is expanded to fill a variable size - * with the last field expanding. It is split into the core and "other" - * because we only need the core part in the in-core inode. - */ -typedef struct xfs_timestamp { - xfs_int32_t t_sec; /* timestamp seconds */ - xfs_int32_t t_nsec; /* timestamp nanoseconds */ -} xfs_timestamp_t; - -/* - * Note: Coordinate changes to this structure with the XFS_DI_* #defines - * below and the offsets table in xfs_ialloc_log_di(). - */ -typedef struct xfs_dinode_core -{ - xfs_uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */ - xfs_uint16_t di_mode; /* mode and type of file */ - xfs_int8_t di_version; /* inode version */ - xfs_int8_t di_format; /* format of di_c data */ - xfs_uint16_t di_onlink; /* old number of links to file */ - xfs_uint32_t di_uid; /* owner's user id */ - xfs_uint32_t di_gid; /* owner's group id */ - xfs_uint32_t di_nlink; /* number of links to file */ - xfs_uint16_t di_projid; /* owner's project id */ - xfs_uint8_t di_pad[10]; /* unused, zeroed space */ - xfs_timestamp_t di_atime; /* time last accessed */ - xfs_timestamp_t di_mtime; /* time last modified */ - xfs_timestamp_t di_ctime; /* time created/inode modified */ - xfs_fsize_t di_size; /* number of bytes in file */ - xfs_drfsbno_t di_nblocks; /* # of direct & btree blocks used */ - xfs_extlen_t di_extsize; /* basic/minimum extent size for file */ - xfs_extnum_t di_nextents; /* number of extents in data fork */ - xfs_aextnum_t di_anextents; /* number of extents in attribute fork*/ - xfs_uint8_t di_forkoff; /* attr fork offs, <<3 for 64b align */ - xfs_int8_t di_aformat; /* format of attr fork's data */ - xfs_uint32_t di_dmevmask; /* DMIG event mask */ - xfs_uint16_t di_dmstate; /* DMIG state info */ - xfs_uint16_t di_flags; /* random flags, XFS_DIFLAG_... */ - xfs_uint32_t di_gen; /* generation number */ -} xfs_dinode_core_t; - -typedef struct xfs_dinode -{ - xfs_dinode_core_t di_core; - xfs_agino_t di_next_unlinked;/* agi unlinked list ptr */ - union { - xfs_bmdr_block_t di_bmbt; /* btree root block */ - xfs_bmbt_rec_32_t di_bmx[1]; /* extent list */ - xfs_dir2_sf_t di_dir2sf; /* shortform directory v2 */ - char di_c[1]; /* local contents */ - } di_u; -} xfs_dinode_t; - -/* - * Values for di_format - */ -typedef enum xfs_dinode_fmt -{ - XFS_DINODE_FMT_DEV, /* CHR, BLK: di_dev */ - XFS_DINODE_FMT_LOCAL, /* DIR, REG: di_c */ - /* LNK: di_symlink */ - XFS_DINODE_FMT_EXTENTS, /* DIR, REG, LNK: di_bmx */ - XFS_DINODE_FMT_BTREE, /* DIR, REG, LNK: di_bmbt */ - XFS_DINODE_FMT_UUID /* MNT: di_uuid */ -} xfs_dinode_fmt_t; - -/* - * File types (mode field) - */ -#define IFMT 0170000 /* type of file */ -#define IFDIR 0040000 /* directory */ -#define IFREG 0100000 /* regular */ -#define IFLNK 0120000 /* symbolic link */