mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-27 22:24:11 +08:00
067595d728
Some versions of mtools (fixed somewhere between 4.0.31 and 4.0.35) generate bad output for mformat when used with the partition= option. Use the offset= option instead. An mtools.conf entry is *also* needed with partition= to support mpartition; combining them in one entry does not work either. Don't specify the -t option to mpartition; it is unnecessary and seems to confuse mpartition under some circumstances. Also do a few minor optimizations: Use a larger cluster size; there is no reason for the typical 4K clusters when we are dealing mainly with comparatively huge files. Start the partition at 32K. There is no reason to align it more than that, since the internal FAT filesystem structures will at best be cluster-aligned, and 32K is the maximum FAT cluster size. [ bp: Remove "we". ] Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com> Signed-off-by: Borislav Petkov <bp@suse.de> Link: https://lkml.kernel.org/r/20210911003906.2700218-1-hpa@zytor.com
273 lines
6.5 KiB
Bash
273 lines
6.5 KiB
Bash
#!/bin/bash
|
|
#
|
|
# This file is subject to the terms and conditions of the GNU General Public
|
|
# License. See the file "COPYING" in the main directory of this archive
|
|
# for more details.
|
|
#
|
|
# Copyright (C) 2017 by Changbin Du <changbin.du@intel.com>
|
|
#
|
|
# Adapted from code in arch/x86/boot/Makefile by H. Peter Anvin and others
|
|
#
|
|
# "make fdimage/fdimage144/fdimage288/hdimage/isoimage"
|
|
# script for x86 architecture
|
|
#
|
|
# Arguments:
|
|
# $1 - fdimage format
|
|
# $2 - target image file
|
|
# $3 - kernel bzImage file
|
|
# $4 - mtools configuration file
|
|
# $5 - kernel cmdline
|
|
# $6+ - initrd image file(s)
|
|
#
|
|
# This script requires:
|
|
# bash
|
|
# syslinux
|
|
# mtools (for fdimage* and hdimage)
|
|
# edk2/OVMF (for hdimage)
|
|
#
|
|
# Otherwise try to stick to POSIX shell commands...
|
|
#
|
|
|
|
# Use "make V=1" to debug this script
|
|
case "${KBUILD_VERBOSE}" in
|
|
*1*)
|
|
set -x
|
|
;;
|
|
esac
|
|
|
|
# Exit the top-level shell with an error
|
|
topshell=$$
|
|
trap 'exit 1' USR1
|
|
die() {
|
|
echo "" 1>&2
|
|
echo " *** $*" 1>&2
|
|
echo "" 1>&2
|
|
kill -USR1 $topshell
|
|
}
|
|
|
|
# Verify the existence and readability of a file
|
|
verify() {
|
|
if [ ! -f "$1" -o ! -r "$1" ]; then
|
|
die "Missing file: $1"
|
|
fi
|
|
}
|
|
|
|
diskfmt="$1"
|
|
FIMAGE="$2"
|
|
FBZIMAGE="$3"
|
|
MTOOLSRC="$4"
|
|
KCMDLINE="$5"
|
|
shift 5 # Remaining arguments = initrd files
|
|
|
|
export MTOOLSRC
|
|
|
|
# common options for dd
|
|
dd='dd iflag=fullblock'
|
|
|
|
# Make sure the files actually exist
|
|
verify "$FBZIMAGE"
|
|
|
|
declare -a FDINITRDS
|
|
irdpfx=' initrd='
|
|
initrdopts_syslinux=''
|
|
initrdopts_efi=''
|
|
for f in "$@"; do
|
|
if [ -f "$f" -a -r "$f" ]; then
|
|
FDINITRDS=("${FDINITRDS[@]}" "$f")
|
|
fname="$(basename "$f")"
|
|
initrdopts_syslinux="${initrdopts_syslinux}${irdpfx}${fname}"
|
|
irdpfx=,
|
|
initrdopts_efi="${initrdopts_efi} initrd=${fname}"
|
|
fi
|
|
done
|
|
|
|
# Read a $3-byte littleendian unsigned value at offset $2 from file $1
|
|
le() {
|
|
local n=0
|
|
local m=1
|
|
for b in $(od -A n -v -j $2 -N $3 -t u1 "$1"); do
|
|
n=$((n + b*m))
|
|
m=$((m * 256))
|
|
done
|
|
echo $n
|
|
}
|
|
|
|
# Get the EFI architecture name such that boot{name}.efi is the default
|
|
# boot file name. Returns false with no output if the file is not an
|
|
# EFI image or otherwise unknown.
|
|
efiarch() {
|
|
[ -f "$1" ] || return
|
|
[ $(le "$1" 0 2) -eq 23117 ] || return # MZ magic
|
|
peoffs=$(le "$1" 60 4) # PE header offset
|
|
[ $peoffs -ge 64 ] || return
|
|
[ $(le "$1" $peoffs 4) -eq 17744 ] || return # PE magic
|
|
case $(le "$1" $((peoffs+4+20)) 2) in # PE type
|
|
267) ;; # PE32
|
|
523) ;; # PE32+
|
|
*) return 1 ;; # Invalid
|
|
esac
|
|
[ $(le "$1" $((peoffs+4+20+68)) 2) -eq 10 ] || return # EFI app
|
|
case $(le "$1" $((peoffs+4)) 2) in # Machine type
|
|
332) echo i386 ;;
|
|
450) echo arm ;;
|
|
512) echo ia64 ;;
|
|
20530) echo riscv32 ;;
|
|
20580) echo riscv64 ;;
|
|
20776) echo riscv128 ;;
|
|
34404) echo x64 ;;
|
|
43620) echo aa64 ;;
|
|
esac
|
|
}
|
|
|
|
# Get the combined sizes in bytes of the files given, counting sparse
|
|
# files as full length, and padding each file to cluster size
|
|
cluster=16384
|
|
filesizes() {
|
|
local t=0
|
|
local s
|
|
for s in $(ls -lnL "$@" 2>/dev/null | awk '/^-/{ print $5; }'); do
|
|
t=$((t + ((s+cluster-1)/cluster)*cluster))
|
|
done
|
|
echo $t
|
|
}
|
|
|
|
# Expand directory names which should be in /usr/share into a list
|
|
# of possible alternatives
|
|
sharedirs() {
|
|
local dir file
|
|
for dir in /usr/share /usr/lib64 /usr/lib; do
|
|
for file; do
|
|
echo "$dir/$file"
|
|
echo "$dir/${file^^}"
|
|
done
|
|
done
|
|
}
|
|
efidirs() {
|
|
local dir file
|
|
for dir in /usr/share /boot /usr/lib64 /usr/lib; do
|
|
for file; do
|
|
echo "$dir/$file"
|
|
echo "$dir/${file^^}"
|
|
done
|
|
done
|
|
}
|
|
|
|
findsyslinux() {
|
|
local f="$(find -L $(sharedirs syslinux isolinux) \
|
|
-name "$1" -readable -type f -print -quit 2>/dev/null)"
|
|
if [ ! -f "$f" ]; then
|
|
die "Need a $1 file, please install syslinux/isolinux."
|
|
fi
|
|
echo "$f"
|
|
return 0
|
|
}
|
|
|
|
findovmf() {
|
|
local arch="$1"
|
|
shift
|
|
local -a names=(-false)
|
|
local name f
|
|
for name; do
|
|
names=("${names[@]}" -or -iname "$name")
|
|
done
|
|
for f in $(find -L $(efidirs edk2 ovmf) \
|
|
\( "${names[@]}" \) -readable -type f \
|
|
-print 2>/dev/null); do
|
|
if [ "$(efiarch "$f")" = "$arch" ]; then
|
|
echo "$f"
|
|
return 0
|
|
fi
|
|
done
|
|
die "Need a $1 file for $arch, please install EDK2/OVMF."
|
|
}
|
|
|
|
do_mcopy() {
|
|
if [ ${#FDINITRDS[@]} -gt 0 ]; then
|
|
mcopy "${FDINITRDS[@]}" "$1"
|
|
fi
|
|
if [ -n "$efishell" ]; then
|
|
mmd "$1"EFI "$1"EFI/Boot
|
|
mcopy "$efishell" "$1"EFI/Boot/boot${kefiarch}.efi
|
|
fi
|
|
if [ -n "$kefiarch" ]; then
|
|
echo linux "$KCMDLINE$initrdopts_efi" | \
|
|
mcopy - "$1"startup.nsh
|
|
fi
|
|
echo default linux "$KCMDLINE$initrdopts_syslinux" | \
|
|
mcopy - "$1"syslinux.cfg
|
|
mcopy "$FBZIMAGE" "$1"linux
|
|
}
|
|
|
|
genbzdisk() {
|
|
verify "$MTOOLSRC"
|
|
mformat -v 'LINUX_BOOT' a:
|
|
syslinux "$FIMAGE"
|
|
do_mcopy a:
|
|
}
|
|
|
|
genfdimage144() {
|
|
verify "$MTOOLSRC"
|
|
$dd if=/dev/zero of="$FIMAGE" bs=1024 count=1440 2>/dev/null
|
|
mformat -v 'LINUX_BOOT' v:
|
|
syslinux "$FIMAGE"
|
|
do_mcopy v:
|
|
}
|
|
|
|
genfdimage288() {
|
|
verify "$MTOOLSRC"
|
|
$dd if=/dev/zero of="$FIMAGE" bs=1024 count=2880 2>/dev/null
|
|
mformat -v 'LINUX_BOOT' w:
|
|
syslinux "$FIMAGE"
|
|
do_mcopy w:
|
|
}
|
|
|
|
genhdimage() {
|
|
verify "$MTOOLSRC"
|
|
mbr="$(findsyslinux mbr.bin)"
|
|
kefiarch="$(efiarch "$FBZIMAGE")"
|
|
if [ -n "$kefiarch" ]; then
|
|
# The efishell provides command line handling
|
|
efishell="$(findovmf $kefiarch shell.efi shell${kefiarch}.efi)"
|
|
ptype='-T 0xef' # EFI system partition, no GPT
|
|
fi
|
|
sizes=$(filesizes "$FBZIMAGE" "${FDINITRDS[@]}" "$efishell")
|
|
# Allow 1% + 2 MiB for filesystem and partition table overhead,
|
|
# syslinux, and config files; this is probably excessive...
|
|
megs=$(((sizes + sizes/100 + 2*1024*1024 - 1)/(1024*1024)))
|
|
$dd if=/dev/zero of="$FIMAGE" bs=$((1024*1024)) count=$megs 2>/dev/null
|
|
mpartition -I -c -s 32 -h 64 $ptype -b 64 -a p:
|
|
$dd if="$mbr" of="$FIMAGE" bs=440 count=1 conv=notrunc 2>/dev/null
|
|
mformat -v 'LINUX_BOOT' -s 32 -h 64 -c $((cluster/512)) -t $megs h:
|
|
syslinux --offset $((64*512)) "$FIMAGE"
|
|
do_mcopy h:
|
|
}
|
|
|
|
geniso() {
|
|
tmp_dir="$(dirname "$FIMAGE")/isoimage"
|
|
rm -rf "$tmp_dir"
|
|
mkdir "$tmp_dir"
|
|
isolinux=$(findsyslinux isolinux.bin)
|
|
ldlinux=$(findsyslinux ldlinux.c32)
|
|
cp "$isolinux" "$ldlinux" "$tmp_dir"
|
|
cp "$FBZIMAGE" "$tmp_dir"/linux
|
|
echo default linux "$KCMDLINE" > "$tmp_dir"/isolinux.cfg
|
|
cp "${FDINITRDS[@]}" "$tmp_dir"/
|
|
genisoimage -J -r -appid 'LINUX_BOOT' -input-charset=utf-8 \
|
|
-quiet -o "$FIMAGE" -b isolinux.bin \
|
|
-c boot.cat -no-emul-boot -boot-load-size 4 \
|
|
-boot-info-table "$tmp_dir"
|
|
isohybrid "$FIMAGE" 2>/dev/null || true
|
|
rm -rf "$tmp_dir"
|
|
}
|
|
|
|
rm -f "$FIMAGE"
|
|
|
|
case "$diskfmt" in
|
|
bzdisk) genbzdisk;;
|
|
fdimage144) genfdimage144;;
|
|
fdimage288) genfdimage288;;
|
|
hdimage) genhdimage;;
|
|
isoimage) geniso;;
|
|
*) die "Unknown image format: $diskfmt";;
|
|
esac
|