tianocore ovmf
https://github.com/tianocore/edk2
什么是OVMF
The Open Virtual Machine Firmware (OVMF) project aims to support firmware for Virtual Machines using the edk2 code base. More information can be found at:
http://www.tianocore.org/ovmf/
OVMF可以在如下的网站下载:
https://github.com/tianocore/edk2
下载到的是一个edk2的完全版本,其中的OvmfPkg可以用来生成OVMF二进制。
OVMF编译
Ubuntu下的编译:
为了能够顺利编译,需要有以下的几个操作:
1. 进入BaseTools,生成编译工具,使用命令:make;
2. 下载nasm和iasl,使用命令:apt install nasm iasl;
之后返回主目录,使用下面的命令进行编译:
- source edksetup.sh
- build -p OvmfPkg/OvmfPkgX64.dsc -a X64
编译后的文件可以在Build目录下找到。
Windows下的编译:
首先需要安装VS,可以使用Visual Studio Community 2015,它有免费的版本就可以编译UEFI。
安装Community的时候需要注意安装的过程中需要添加如下的配置,否则编译UEFI时会报错:
其它还需要安装ASL和nasm编译器,这就是两个exe,不过需要放置到正确的位置(位置由Conf下的tools_def.txt决定)。
另外,在GitHub上下载的代码没有提供Windows下的UEFI需要使用的工具(就是Linux里用make编译出来的),需要自己下载。
https://code.csdn.net/jiangwei0512/edk2-udk2017.git中有以上的Windows工具和ASL、nasm等,可以直接拿来用。
需要将ASL放到C目录下。(也可以不换,不过需要修改Conf下的tools_def.txt文件,比较麻烦)
编译的时候打开Windows Shell,然后进入UEFI目录,运行Edk2Setup.bat,然后执行Build就可以编译OVMF了。
OVMF运行
这里使用QEMU来运行OVMF。
所以首先需要下载QEMU:apt install qemu
之后就可以运行了:
- qemu-system-x86_64 -bios OVMF.fd
下面是运行的结果:
这里有个问题,就是没有UEFI的打印,为了能够有打印,首先需要添加编译选项并重新生成二进制:
- build -p OvmfPkg/OvmfPkgX64.dsc -a X64 -D DEBUG_ON_SERIAL_PORT
然后在使用qemu运行时,需要加入新的参数:
- qemu-system-x86_64 -bios OVMF.fd -serial stdio
之前说过 Alpine Linux 是一个超轻量级的发行版,这个轻量不仅体现在系统体积上,这系统的安装过程也是没有图形界面的,和常见的各种发行版都不同。虽然一般来说接触到的这个系统都是现成安装好的,比如 docker 容器或者 vps 里直接灌进去的现成系统,但还是开个文章记录一下安装过程,也当备忘。
测试是在虚拟机里,Alpine 的安装是先把系统载入内存中,然后需要手动输入命令才开始安装过程。
加载镜像后,首先会看到此提示,输入用户名 root
直接回车登录:
然后按照提示输入 setup-alpine
开始安装:
键盘布局输入两次 cn
:
接着就是选择网络配置,绑定域名和设置 DNS 之类,一般情况下一律直接回车即可,然后设定 root 用户密码:
时区先按?
调出选项,国内当然就是输入 PRC
了,注意时区要区分大小写,然后代理和 NTP 都默认设置即可:
然后需要稍等一会,会自动检测软件源,按照提示设置,r 是代表随机指定一个源,f 是自动检测速度最快的源,e 是编辑系统对应文件,可以添加指定的源,这里输入 38,选个上海交大的源:
然后选择硬盘,我这里就一块硬盘,所以直接输入名称 sda
,当做系统盘,后面输入 sys
,按照提示确定格式化即可:
最后看到如下界面就是安装完毕了,输入 reboot 重启即可进入系统:
注意默认装好的 Alpine 不允许 SSH 远程连接,十分不方便,开启远程 SSH 连接的话使用以下指令:
vi /etc/ssh/sshd_config
编辑器的用法和其他 linux 一样,按 i 进入编辑模式,esc 退出,:wq 保存退出等。
把配置文件里 #PermitRootLogin prohibit-password
这一行修改为:PermitRootLogin yes
,并注意取消注释,然后重启系统即可。
qemu-kvm -enable-kvm -cpu EPYC -machine q35 -smp 2,maxcpus=64 -m 512M,slots=5,maxmem=30G -nographic -drive if=pflash,format=raw,unit=0,file=/tmp/OVMF_CODE.fd,readonly -object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=5 -machine memory-encryption=sev0 -monitor pty -cdrom ubuntu-20.10-live-server-amd64.iso
qemu-system-x86_64 -drive if=pflash,format=raw,unit=0,file=./OVMF_CODE.fd,readonly -hda a.img -m 1024 -smp 4 -cdrom
qemu-img create -f qcow2 a.img 10G
-net nic -net tap,ifname=tap3,script=no,downscript=no
run_cmd () {
$*
if [ $? -ne 0 ]; then
echo "command $* failed"
fi
}
run_cmd "ip tuntap add $GUEST_TAP_NAME mode tap user `whoami`"
run_cmd "ip link set $GUEST_TAP_NAME up"
run_cmd "ip link set $GUEST_TAP_NAME master virbr0"
echo "-device e1000,mac=${GUEST_MAC_ADDR},netdev=net0 -netdev tap,id=net0,ifname=${GUEST_TAP_NAME},script=no,downscript=no"
qemu-kvm -enable-kvm -cpu host -smp 2,maxcpus=64 -m 2048M,slots=5,maxmem=30G -drive if=pflash,format=raw,unit=0,file=./OVMF_CODE.fd,readonly -hda d.img -nographic -net nic -net tap,ifname=tap3,script=no,downscript=no -device e1000,netdev=network0
qemu-kvm -enable-kvm -cpu host -smp 2,maxcpus=64 -m 2048M,slots=5,maxmem=30G -drive if=pflash,format=raw,unit=0,file=./OVMF_CODE.fd,readonly -hda m2.img -object sev-guest,id=sev0,policy=1073741825,cbitpos=47,reduced-phys-bits=5 -machine memory-encryption=sev0 -name guest=csv-vm -nographic -net nic -net tap,ifname=tap3,script=no,downscript=no
#!/bin/bash
# parameters
GUEST_NAME_BASE=$1
GUEST_MEMORY_SIZE=(4096*1024*1024)
#GUEST_NAME="guest=${GUEST_NAME_BASE}"
GUEST_NAME="${GUEST_NAME_BASE}"
if [ `id -u` -ne 0 ]; then
echo "Must be run as root!"
exit 1
fi
if [ $# -ne 1 ];
then
echo "Usage:"
echo "sudo ./dump-guest-memory.sh GUEST_NAME"
exit 1
fi
echo_cmd() {
cmd="$*"
echo -e "\n\033[1;4;31m$cmd\033[0m"
sleep 1.5
}
clear
# List all VM
tput rmam
#cmd="ps axo user,pid,vsz,command | grep qemu-system-x86_64"
cmd="ps axo user,pid,vsz,command | grep -w $GUEST_NAME"
echo_cmd $cmd
#ps axo user,pid,vsz,command | grep qemu-system-x86_64
ps axo user,pid,vsz,command | grep -w $GUEST_NAME
#sleep 1
# Get all VM pids
#vm_pid_array=($(ps axo user,pid,vsz,command | grep "qemu-system-x86_64" | awk -F " " '{print $2}'))
vm_pid_array=($(ps axo user,pid,vsz,command | grep -w "$GUEST_NAME" | awk -F " " '{print $2}'))
#echo ${vm_pid_array[@]}
# Iterate vm_pid_array to dump memory
#for(( i=0;i<${#vm_pid_array[@]};i++)) do
proc_map_path=/proc/${vm_pid_array[i]}/maps
# Get the start HVA of a VM memory
if [ -f $proc_map_path ];then
sev_guest_str=($(ps axo user,pid,vsz,command | grep "${vm_pid_array[i]}" | grep "qemu-system-x86_64" | grep -w "$GUEST_NAME"))
if [ ! -z ${sev_guest_str} ]; then
echo -e "\n$GUEST_NAME PID: \e[1;4;34m${vm_pid_array[i]}\e[0m";
sleep 3
#echo -e "\nSEV VM PID: ${vm_pid_array[i]}";
#else
#echo -e "\nStandard VM PID: ${vm_pid_array[i]}";
fi
#clear
cmd="cat $proc_map_path"
#echo_cmd $cmd
echo -e "\n\033[1;4;31m$cmd\033[0m"
#cat $proc_map_path | head -28
cat $proc_map_path > maps
cat maps | while read line
do
echo $line | awk -F " " '{printf("%s %s",$1,$2)}' >> sort_maps
start_hva=($(echo $line | \
awk -F " " '{print $1}' | \
awk -F "-" '{print "0x"$2"-""0x"$1}'| \
awk -F "-" '{printf("%s",$2)}' | \
awk -F "x" '{print $2}' \
))
#echo $start_hva
((start_hva=0x$start_hva))
end_hva=($(echo $line | \
awk -F " " '{print $1}' | \
awk -F "-" '{print "0x"$2"-""0x"$1}'| \
awk -F "-" '{printf("%s",$1)}' | \
awk -F "x" '{print $2}' \
))
#echo $end_hva
((end_hva=0x$end_hva))
((mem_size=$end_hva-$start_hva))
#echo $mem_size
printf " %.8x " $mem_size >> sort_maps
echo $line | awk -F " " '{print $4,$5,$6}' >> sort_maps
done
echo -e "address\t\t\t perms\toffset\tdev inode\tpathname"
sort -rk3,3 sort_maps > sorted_maps
head -15 sorted_maps
# get vm_start_hva from sorted_maps
vm_start_hva=($(head -1 sorted_maps | \
awk -F " " '{print $1}' | \
awk -F "-" '{print $1}'))
#echo "vm_start_hva" $vm_start_hva
rm -rf maps sort_maps sorted_maps
echo -e "\nVM memory start: \e[1;4;34m0x$vm_start_hva\e[0m"
vm_start_hva_hex=`echo $vm_start_hva`
((vm_start_hva=0x$vm_start_hva))
((vm_start_hva=($vm_start_hva/4096)))
#echo $vm_start_hva
sleep 4
#clear
#set -x
# Dump the VM memory of the first page
cmd="dd if=/proc/${vm_pid_array[i]}/mem bs=4096 count=1 skip=(0x$vm_start_hva_hex/4096) | hexdump"
echo_cmd $cmd
dd if=/proc/${vm_pid_array[i]}/mem bs=4096 count=1 skip=$vm_start_hva | hexdump -C -v | head -12
#dd if=/proc/${vm_pid_array[i]}/mem bs=4096 count=1 skip=$vm_start_hva > vm_first_page
#set +x
fi
#done;