最近在使用mkzedboot做平铺的时候出现问题,所以分析了一下这个脚本
问题如下
dd 的时候出现问题,那我们来具体分析下
首先使用
bash -x fx mkzedboot /dev/sdd
找到zedboot的执行流程,发现mkzendboot的命令如下
直接分析命令
tools/devshell/mkzedboot /dev/sdd
该脚本首先解析参数,接受的参数包括
-f 代表强制写入
-i / --install 表示把系统写写入磁盘(正常情况只写入引导,通过网络下载系统)
剩下的参数为 u盘的路径, 如果用户没有指定,使用fx-command-run list-usb-disk, 也就是执行list-usb-disk脚本列出当前的usb退出, 代码如下
39 USB_DEVICE="$1"
40 if [[ -z "${USB_DEVICE}" ]]; then
41 echo >&2 "device argument required"
42 echo "USB disks:"
43 fx-command-run list-usb-disks
44 exit 1
45 fi
接下来使用is_usb函数判断设备是否为usb设备,如果不是同样使用
fx-command-run list-usb-disks 列出usb退出
is_usb 函数如下
33 is_usb() {
34 if ! ${force}; then
35 fx-command-run list-usb-disks | grep "$1"
36 fi
37 }
**
这里也体现出来了 -f 参数的含义,如果不是usb设备的话,-f 可以强制写入u盘镜像
53 echo >&2 "Changing ownership of ${USB_DEVICE} to ${USER}"
54 sudo chown "${USER}" "${USB_DEVICE}"
53 行和54行把设备的属主改为当前用户,接下来就可以读写该设备了
62 open_device() {
63 case "$(uname)" in
64 Darwin)
65 if ! diskutil quiet unmountDisk "${USB_DEVICE}"; then
66 echo >&2 "Failed to unmount ${USB_DEVICE}, cannot continue"
67 exit 1
68 fi
69 ;;
70 esac
71 exec 3>>"${USB_DEVICE}"
72 }
73 close_device() {
74 echo >&2 "Closing device."
75 exec 3>&-
76 }
77 open_device
77行执行open_device操作, 该操作主要执行的命令为 exec 3>>"${USB_DEVICE}" 也就是将3号文件描述符作为 打开 /dev/sdd的文件描述符
79 # Destroy any existing GPT/MBR on the device and re-create
80 echo "Create new GPT partition table… "
81 “
F
U
C
H
S
I
A
B
U
I
L
D
D
I
R
/
t
o
o
l
s
/
c
g
p
t
"
c
r
e
a
t
e
"
{FUCHSIA_BUILD_DIR}/tools/cgpt" create "
FUCHSIABUILDDIR/tools/cgpt"create"{USB_DEVICE}”
82 “
F
U
C
H
S
I
A
B
U
I
L
D
D
I
R
/
t
o
o
l
s
/
c
g
p
t
"
b
o
o
t
−
p
"
{FUCHSIA_BUILD_DIR}/tools/cgpt" boot -p "
FUCHSIABUILDDIR/tools/cgpt"boot−p"{USB_DEVICE}”
83 echo “done”
79-83行重新创建 usb设备分区, cgpt的用法可以使用man cgpt查看,tool下的cgpt就是linux下的cgpt, 下面列出一下关于cgpt的帮助文档
cgpt - Utility to manipulate GPT partitions with Chromium OS extensions
SYNOPSIS
cgpt COMMAND [OPTIONS] DRIVE
DESCRIPTION
Cgpt is a tool to manipulate a GUID Partition Table from the command
line. Although several other utilities exist for the same basic purpose
- some with more features and a captive user interface - cgpt is unique
in that it also supports Chromium OS extensions. These extensions are
not generally useful; they are specific to the u-boot firmware found on
some Chromebooks. They may be used to change priority for kernel parti‐
tions and give other hints to u-boot Chromebook firmware. Use this
utility only to manipulate a partition table for compatible Chrome‐
COMMANDS
Each action performed by this program - with the notable exception of
the -h OPTION - is initiated by a command which tells cgpt the type of
operation to perform. All available commands are described below.
create Create or reset GPT headers and tables.
boot Edit the PMBR sector for legacy BIOSes.
-D NUM Size (in bytes) of the disk where partitions reside
default 0, meaning partitions and GPT structs are
both on DRIVE
-i NUM Set bootable partition
-b FILE Install bootloader code in the PMBR
-p Create legacy PMBR partition table
create命令会创建gpt的 头和分区表
boot命令则会编辑PMBR分区为了兼容mbr分析格式), -p选项是创建pmbr
85 echo "Create new partitions... "
86 # ESP needs to be a FAT compatible size
87 esp_size=$(((63*1024*1024)/512))
88 vboot_size=$(((64*1024*1024)/512))
89 esp_offset=2048
90 vboot_offset=$(($esp_size + $esp_offset))
91 "${FUCHSIA_BUILD_DIR}/tools/cgpt" add -s "${esp_size}" -t efi -b "${esp_offs et}" -l esp "${USB_DEVICE}"
92 "${FUCHSIA_BUILD_DIR}/tools/cgpt" add -s "${vboot_size}" -t kernel -b "${vbo ot_offset}" -l zedboot "${USB_DEVICE}"
91行创建了一个esp分区,分区的大小为(((6310241024)/512)), 也就是53m所站的扇区, 分区的类型为efi, 也就是uefi启动分区,起始扇区为2048扇区,也就是1m开始的地方,label为 esp 。 这样就创建了一个uefi的引导分区
(cgpt add -s 129024 -t efi -b 2048 -l esp /dev/sdd)
92 行创建了一个分区 类型为kernel, 大小为64m, 开始地址紧挨着efi分区, label为zedboot
(cgpt add -s 131072 -t kernel -b 131072 -l zedboot /dev/sdd)
创建好分区之后,就应该把相应的文件内容写入设备。
下面一段是对-i |–install 选项的执行,作者说dd太慢,太自己使用osync写入, 我们先不分析这里,最后再分析
129 "${FUCHSIA_BUILD_DIR}/tools/cgpt" add -i 2 -T 1 -S 1 -P 2 "${USB_DEVICE}"
130 echo "done"
131
132 echo "Writing zedboot for EFI"
133 dd if="${FUCHSIA_BUILD_DIR}/${IMAGE_ZEDBOOT_ESP}" of="${USB_DEVICE}" seek=${ esp_offset}
134 echo "Writing zedboot for Cros"
135 dd if="${FUCHSIA_BUILD_DIR}/${IMAGE_ZEDBOOT_VBOOT}" of="${USB_DEVICE}" seek= ${vboot_offset}
136 if $include_install; then
137 echo "Writing install partition"
138 dd if="${FUCHSIA_BUILD_DIR}/${IMAGE_INSTALLER_RAW}" of="${USB_DEVICE}" see k=${install_offset} bs=4194304
139 fi
140 echo "done"
141
129行 给第二个分区(zedboot)分区设置一些flag,包括 -T 1 tries flag为1 , successful flag 为1 , priority flag为2 ,
TODO解释flags
133 使用dd命令将 “
F
U
C
H
S
I
A
B
U
I
L
D
D
I
R
/
{FUCHSIA_BUILD_DIR}/
FUCHSIABUILDDIR/{IMAGE_ZEDBOOT_ESP}” 写入到第efi分区 (dd if=out/default/zedboot.esp.blk of=/dev/sdd seek=2048)
这里seek 2048 应该为2048个扇区, 应该给block设置为512
135 将
F
U
C
H
S
I
A
B
U
I
L
D
D
I
R
/
{FUCHSIA_BUILD_DIR}/
FUCHSIABUILDDIR/{IMAGE_ZEDBOOT_VBOOT}" 写入zboot分区(dd if=out/default/zedboot.vboot of=/dev/sdd seek=131072)
这里seek 131072 应该为131072个扇区, 应该给block设置为512
到这里我们在看看intsall 的处理 这里懒得看了 无非就是创建一个分区,用dd命令写入数据
最后我们总结下mkzedboot的作用
1 创建gpt分区
cgpt create /dev/sdd
2 创建pmbr
cgpt boot -p /dev/sdd
3 创建efi分区
cgpt add -s 129024 -t efi -b 2048 -l esp /dev/sdfd
4 创建zedboot分区
cgpt add -s 131072 -t kernel -b 131072 -l zedboot /dev/sdd
5 给 zedboot分区添加标志
cgpt add -i 2 -T 1 -S 1 -P 2 /dev/sdd
6 dd写入efi引导
dd if=out/default/zedboot.esp.blk of=/dev/sdd seek=2048
7 写入zedboot分区
dd if=out/default/zedboot.vboot of=/dev/sdd seek=131072