Create EFI System Partition on USB image during build.

The EFI System Partition is a special disk partition where EFI BIOS expects
to find the platform-specific bootloader. We need this in order to work on
the BIOS/kernel handoff. It's not needed for the final ChromeOS image and it
isn't useful for legacy BIOS systems, so right now it only makes any difference on x86
devices with development BIOSes.

This change creates the partition for ARM builds as well; it has no effect
there, either.

Review URL: http://codereview.chromium.org/1513019
This commit is contained in:
Bill Richardson 2010-04-06 15:00:10 -07:00
parent e450333e3f
commit 8b3bd10b91
3 changed files with 63 additions and 17 deletions

View File

@ -26,12 +26,12 @@ DEFINE_string board_root "" \
# Usage. # Usage.
FLAGS_HELP=$(cat <<EOF FLAGS_HELP=$(cat <<EOF
Usage: $(basename $0) [flags] IMAGEDIR OUTDEV Usage: $(basename $0) [flags] IMAGEDIR OUTDEV
This takes the image components in IMAGEDIR and creates a bootable, This takes the image components in IMAGEDIR and creates a bootable,
GPT-formatted image in OUTDEV. OUTDEV can be a file or block device. GPT-formatted image in OUTDEV. OUTDEV can be a file or block device.
EOF EOF
) )
@ -99,6 +99,12 @@ if [[ ! -s ${STATEFUL_IMG} ]]; then
exit 1 exit 1
fi fi
ESP_IMG="${IMAGEDIR}/esp.image"
if [[ ! -s ${ESP_IMG} ]]; then
error "Can't find ${ESP_IMG}"
exit 1
fi
# We'll need some code to put in the PMBR, for booting on legacy BIOS. Some ARM # We'll need some code to put in the PMBR, for booting on legacy BIOS. Some ARM
# systems will use a U-Boot script temporarily, but it goes in the same place. # systems will use a U-Boot script temporarily, but it goes in the same place.
if [[ "$ARCH" = "arm" ]]; then if [[ "$ARCH" = "arm" ]]; then
@ -107,7 +113,7 @@ if [[ "$ARCH" = "arm" ]]; then
# set the appropriate environment variables. Then we can create the correct # set the appropriate environment variables. Then we can create the correct
# script and install it for real. A bit awkward, but this is only temporary. # script and install it for real. A bit awkward, but this is only temporary.
echo "Installing fake GPT first, to calculate locations..." echo "Installing fake GPT first, to calculate locations..."
install_gpt $OUTDEV $ROOTFS_IMG $KERNEL_IMG $STATEFUL_IMG /dev/zero install_gpt $OUTDEV $ROOTFS_IMG $KERNEL_IMG $STATEFUL_IMG /dev/zero $ESP_IMG
# Create the U-Boot script to copy the kernel into memory and boot it. # Create the U-Boot script to copy the kernel into memory and boot it.
KERNEL_OFFSET=$(printf "0x%08x" ${START_KERN_A}) KERNEL_OFFSET=$(printf "0x%08x" ${START_KERN_A})
@ -147,7 +153,7 @@ fi
# Create the GPT. This has the side-effect of setting some global vars # Create the GPT. This has the side-effect of setting some global vars
# describing the partition table entries (see the comments in the source). # describing the partition table entries (see the comments in the source).
install_gpt $OUTDEV $ROOTFS_IMG $KERNEL_IMG $STATEFUL_IMG $PMBRCODE install_gpt $OUTDEV $ROOTFS_IMG $KERNEL_IMG $STATEFUL_IMG $PMBRCODE $ESP_IMG
# Emit helpful scripts for testers, etc. # Emit helpful scripts for testers, etc.
${SCRIPTS_DIR}/emit_gpt_scripts.sh "${OUTDEV}" "${IMAGEDIR}" ${SCRIPTS_DIR}/emit_gpt_scripts.sh "${OUTDEV}" "${IMAGEDIR}"
@ -169,6 +175,9 @@ $sudo dd if=${KERNEL_IMG} of=${OUTDEV} conv=notrunc bs=512 seek=${START_KERN_A}
echo "Copying rootfs..." echo "Copying rootfs..."
$sudo dd if=${ROOTFS_IMG} of=${OUTDEV} conv=notrunc bs=512 seek=${START_ROOTFS_A} $sudo dd if=${ROOTFS_IMG} of=${OUTDEV} conv=notrunc bs=512 seek=${START_ROOTFS_A}
echo "Copying EFI system partition..."
dd if=${ESP_IMG} of=${OUTDEV} conv=notrunc bs=512 seek=${START_ESP}
# Clean up temporary files. # Clean up temporary files.
if [[ -n "${MBR_IMG:-}" ]]; then if [[ -n "${MBR_IMG:-}" ]]; then
rm "${MBR_IMG}" rm "${MBR_IMG}"

View File

@ -56,7 +56,7 @@ if [ -z "$FLAGS_board" ] ; then
fi fi
# Sanity check: statefuldev cannot be true if withdev is false. # Sanity check: statefuldev cannot be true if withdev is false.
if [ $FLAGS_statefuldev -eq $FLAGS_TRUE ] && if [ $FLAGS_statefuldev -eq $FLAGS_TRUE ] &&
[ $FLAGS_withdev -eq $FLAGS_FALSE ] ; then [ $FLAGS_withdev -eq $FLAGS_FALSE ] ; then
echo "ERROR: statefuldev flag cannot be set to true without withdev" echo "ERROR: statefuldev flag cannot be set to true without withdev"
exit 1 exit 1
@ -129,6 +129,10 @@ cleanup_stateful_fs_loop() {
sudo losetup -d "$STATEFUL_LOOP_DEV" sudo losetup -d "$STATEFUL_LOOP_DEV"
} }
cleanup_esp_loop() {
sudo umount "$ESP_DIR"
}
cleanup() { cleanup() {
# Disable die on error. # Disable die on error.
set +e set +e
@ -146,6 +150,10 @@ cleanup() {
cleanup_rootfs_loop cleanup_rootfs_loop
fi fi
if [[ -n "$ESP_DIR" ]]; then
cleanup_esp_loop
fi
# Turn die on error back on. # Turn die on error back on.
set -e set -e
} }
@ -250,13 +258,13 @@ if [ $FLAGS_statefuldev -eq $FLAGS_TRUE ] ; then
echo "Setting up symlinks for stateful partition install" echo "Setting up symlinks for stateful partition install"
DEV_IMAGE_ROOT="$STATEFUL_DIR/dev_image" DEV_IMAGE_ROOT="$STATEFUL_DIR/dev_image"
sudo mkdir -p "$DEV_IMAGE_ROOT/usr" sudo mkdir -p "$DEV_IMAGE_ROOT/usr"
# Setup symlinks in stateful partition. # Setup symlinks in stateful partition.
for path in bin include lib libexec sbin share; do for path in bin include lib libexec sbin share; do
sudo mkdir "$DEV_IMAGE_ROOT/$path" sudo mkdir "$DEV_IMAGE_ROOT/$path"
sudo ln -s "$DEV_IMAGE_ROOT/$path" "$DEV_IMAGE_ROOT/usr/$path" sudo ln -s "$DEV_IMAGE_ROOT/$path" "$DEV_IMAGE_ROOT/usr/$path"
done done
# Setup symlinks that don't conform to above model. # Setup symlinks that don't conform to above model.
sudo ln -s "$DEV_IMAGE_ROOT/lib" "$DEV_IMAGE_ROOT/usr/lib64" sudo ln -s "$DEV_IMAGE_ROOT/lib" "$DEV_IMAGE_ROOT/usr/lib64"
sudo ln -s "$DEV_IMAGE_ROOT" "$DEV_IMAGE_ROOT/usr/local" sudo ln -s "$DEV_IMAGE_ROOT" "$DEV_IMAGE_ROOT/usr/local"
@ -296,7 +304,7 @@ if [[ $FLAGS_withtest -eq $FLAGS_TRUE ]] ; then
--usepkgonly chromeos-test $EMERGE_JOBS --usepkgonly chromeos-test $EMERGE_JOBS
fi fi
# Clean up links setup for stateful install of extra packages. # Clean up links setup for stateful install of extra packages.
if [ $FLAGS_statefuldev -eq $FLAGS_TRUE ] ; then if [ $FLAGS_statefuldev -eq $FLAGS_TRUE ] ; then
# Fix symlinks so they work on live system. # Fix symlinks so they work on live system.
for path in bin include lib libexec sbin share; do for path in bin include lib libexec sbin share; do
@ -312,7 +320,7 @@ if [ $FLAGS_statefuldev -eq $FLAGS_TRUE ] ; then
sudo ln -s "/usr/local" "$DEV_IMAGE_ROOT/usr/local" sudo ln -s "/usr/local" "$DEV_IMAGE_ROOT/usr/local"
#TODO(sosa@chromium.org) - /usr/bin/xterm symlink not created in stateful. #TODO(sosa@chromium.org) - /usr/bin/xterm symlink not created in stateful.
sudo ln -sf "/usr/local/bin/aterm" "/usr/bin/xterm" sudo ln -sf "/usr/local/bin/aterm" "/usr/bin/xterm"
fi fi
# Perform any customizations on the root file system that are needed. # Perform any customizations on the root file system that are needed.
@ -322,10 +330,34 @@ if [[ $FLAGS_withdev -eq $FLAGS_TRUE ]]; then
fi fi
# Extract the kernel from the root filesystem for use by the GPT image. Legacy # Extract the kernel from the root filesystem for use by the GPT image. Legacy
# BIOS will use the kernel in the rootfs (via syslinux), ChromeOS BIOS will use # BIOS will use the kernel in the rootfs (via syslinux), Chrome OS BIOS will
# the kernel partition. # use the kernel partition.
sudo cp -f "${ROOT_FS_DIR}/boot/vmlinuz" "${OUTPUT_DIR}/vmlinuz.image" sudo cp -f "${ROOT_FS_DIR}/boot/vmlinuz" "${OUTPUT_DIR}/vmlinuz.image"
# Create EFI System Partition to boot stock EFI BIOS (but not ChromeOS EFI
# BIOS). We only need this for x86, but it's simpler and safer to keep the disk
# images the same for both x86 and ARM.
ESP_IMG=${OUTPUT_DIR}/esp.image
# NOTE: The size argument for mkfs.vfat is in 1024-byte blocks. We'll hard-code
# it to 16M for now.
ESP_BLOCKS=16384
/usr/sbin/mkfs.vfat -C ${OUTPUT_DIR}/esp.image ${ESP_BLOCKS}
ESP_DIR=${OUTPUT_DIR}/esp
mkdir -p ${ESP_DIR}
sudo mount -o loop ${ESP_IMG} ${ESP_DIR}
sudo mkdir -p ${ESP_DIR}/efi/boot
sudo grub-mkimage -p /efi/boot -o ${ESP_DIR}/efi/boot/bootx64.efi \
part_gpt fat ext2 normal boot sh chain configfile linux
sudo cp ${ROOT_FS_DIR}/boot/vmlinuz ${ESP_DIR}/efi/boot/vmlinuz
cat <<EOF | sudo dd of=${ESP_DIR}/efi/boot/grub.cfg
set timeout=2
set default=0
menuentry "32-bit serial" {
linux /efi/boot/vmlinuz earlyprintk=serial,ttyS0,115200 i915.modeset=0 console=ttyS0,115200 acpi=off init=/sbin/init boot=local rootwait root=/dev/sda3 ro noresume noswap loglevel=7
}
EOF
#TODO(sosa@chromium.org) - Does it make sense to leave /usr/local bound here? #TODO(sosa@chromium.org) - Does it make sense to leave /usr/local bound here?
"${SCRIPTS_DIR}/customize_rootfs" \ "${SCRIPTS_DIR}/customize_rootfs" \
--root="$ROOT_FS_DIR" \ --root="$ROOT_FS_DIR" \
@ -350,6 +382,7 @@ if [ $FLAGS_statefuldev -eq $FLAGS_TRUE ] ; then
fi fi
# Cleanup loop devices. # Cleanup loop devices.
cleanup_esp_loop
cleanup_stateful_fs_loop cleanup_stateful_fs_loop
cleanup_rootfs_loop cleanup_rootfs_loop
@ -359,8 +392,9 @@ ${SCRIPTS_DIR}/build_gpt.sh \
"${OUTPUT_DIR}" "${OUTPUT_IMG}" "${OUTPUT_DIR}" "${OUTPUT_IMG}"
# Clean up temporary files. # Clean up temporary files.
rm -f "${ROOT_FS_IMG}" "${STATEFUL_IMG}" "${OUTPUT_DIR}/vmlinuz.image" rm -f "${ROOT_FS_IMG}" "${STATEFUL_IMG}" "${OUTPUT_DIR}/vmlinuz.image" \
rmdir "${ROOT_FS_DIR}" "${STATEFUL_DIR}" "${ESP_IMG}"
rmdir "${ROOT_FS_DIR}" "${STATEFUL_DIR}" "${ESP_DIR}"
OUTSIDE_OUTPUT_DIR="../build/images/${FLAGS_board}/${IMAGE_SUBDIR}" OUTSIDE_OUTPUT_DIR="../build/images/${FLAGS_board}/${IMAGE_SUBDIR}"
echo "Done. Image created in ${OUTPUT_DIR}" echo "Done. Image created in ${OUTPUT_DIR}"

View File

@ -33,7 +33,7 @@ DEFINE_string state_image "" \
"Stateful partition image (defaults to creating new statful partition)" "Stateful partition image (defaults to creating new statful partition)"
DEFINE_string format "vmware" \ DEFINE_string format "vmware" \
"Output format, either vmware or virtualbox" "Output format, either vmware or virtualbox"
DEFINE_boolean make_vmx ${FLAGS_TRUE} \ DEFINE_boolean make_vmx ${FLAGS_TRUE} \
"Create a vmx file for use with vmplayer (vmware only)." "Create a vmx file for use with vmplayer (vmware only)."
DEFINE_string vmdk "$DEFAULT_VMDK" \ DEFINE_string vmdk "$DEFAULT_VMDK" \
@ -57,7 +57,7 @@ if [ "$FLAGS_format" != "vmware" ]; then
FLAGS_make_vmx=${FLAGS_FALSE} FLAGS_make_vmx=${FLAGS_FALSE}
fi fi
# Convert args to paths. Need eval to un-quote the string so that shell # Convert args to paths. Need eval to un-quote the string so that shell
# chars like ~ are processed; just doing FOO=`readlink -f $FOO` won't work. # chars like ~ are processed; just doing FOO=`readlink -f $FOO` won't work.
FLAGS_from=`eval readlink -f $FLAGS_from` FLAGS_from=`eval readlink -f $FLAGS_from`
FLAGS_to=`eval readlink -f $FLAGS_to` FLAGS_to=`eval readlink -f $FLAGS_to`
@ -68,6 +68,8 @@ TEMP_DIR=$(mktemp -d)
"${FLAGS_from}/unpack_partitions.sh" "${FLAGS_from}/chromiumos_image.bin") "${FLAGS_from}/unpack_partitions.sh" "${FLAGS_from}/chromiumos_image.bin")
# Fix the kernel command line # Fix the kernel command line
# FIXME: TEMP_ESP is only partition 4 at the moment. It may change!
TEMP_ESP="$TEMP_DIR"/part_4
TEMP_ROOTFS="$TEMP_DIR"/part_3 TEMP_ROOTFS="$TEMP_DIR"/part_3
TEMP_STATE="$TEMP_DIR"/part_1 TEMP_STATE="$TEMP_DIR"/part_1
if [ -n "${FLAGS_state_image}" ]; then if [ -n "${FLAGS_state_image}" ]; then
@ -97,11 +99,12 @@ sudo dd if=/dev/zero of="${TEMP_IMG}" bs=1 count=1 \
# Set up the partition table # Set up the partition table
install_gpt "$TEMP_IMG" "$TEMP_ROOTFS" "$TEMP_KERN" "$TEMP_STATE" \ install_gpt "$TEMP_IMG" "$TEMP_ROOTFS" "$TEMP_KERN" "$TEMP_STATE" \
"$TEMP_PMBR" true "$TEMP_PMBR" "$TEMP_ESP" true
# Copy into the partition parts of the file # Copy into the partition parts of the file
dd if="$TEMP_ROOTFS" of="$TEMP_IMG" conv=notrunc bs=512 seek="$START_ROOTFS_A" dd if="$TEMP_ROOTFS" of="$TEMP_IMG" conv=notrunc bs=512 seek="$START_ROOTFS_A"
dd if="$TEMP_STATE" of="$TEMP_IMG" conv=notrunc bs=512 seek="$START_STATEFUL" dd if="$TEMP_STATE" of="$TEMP_IMG" conv=notrunc bs=512 seek="$START_STATEFUL"
dd if="$TEMP_KERN" of="$TEMP_IMG" conv=notrunc bs=512 seek="$START_KERN_A" dd if="$TEMP_KERN" of="$TEMP_IMG" conv=notrunc bs=512 seek="$START_KERN_A"
dd if="$TEMP_ESP" of="$TEMP_IMG" conv=notrunc bs=512 seek="$START_ESP"
echo Creating final image echo Creating final image
# Convert image to output format # Convert image to output format
@ -117,7 +120,7 @@ else
exit 1 exit 1
fi fi
rm -rf "$TEMP_DIR" "${VBOX_TEMP_IMAGE}" "$TEMP_IMG" rm -rf "$TEMP_DIR" "${VBOX_TEMP_IMAGE}" "$TEMP_IMG"
if [ -z "$FLAGS_state_image" ]; then if [ -z "$FLAGS_state_image" ]; then
rm -f "$STATE_IMAGE" rm -f "$STATE_IMAGE"
fi fi