# HG changeset patch # User Pascal Bellard # Date 1335612347 -7200 # Node ID 4caf2c7f24c8b90a39b5a33eacb63de45111f9d8 # Parent 66e38bd6a1320b7f35f2607fddd8c775fe476949 linux: update bootloader.sh diff -r 66e38bd6a132 -r 4caf2c7f24c8 linux/stuff/bootloader.sh --- a/linux/stuff/bootloader.sh Sat Apr 28 13:23:21 2012 +0200 +++ b/linux/stuff/bootloader.sh Sat Apr 28 13:25:47 2012 +0200 @@ -9,218 +9,260 @@ usage() { cat < /dev/null; } + +patch() { - dd $@ 2> /dev/null + echo -en $(echo ":$2" | sed 's/:/\\x/g') | \ + ddq bs=1 conv=notrunc of=$3 seek=$((0x$1)) + [ -n "$DEBUG" ] && echo "patch $1 $2 $4" 1>&2 } -dbg() +# usage: store bits offset data file +store() { - [ -n "$DEBUG" ] && echo "$@" 1>&2 + n=$3; for i in $(seq 8 8 $1); do + printf '\\\\x%02X' $(($n & 255)) + n=$(($n >> 8)) + done | xargs echo -en | ddq bs=1 conv=notrunc of=$4 seek=$(($2)) + [ -n "$DEBUG" ] && printf "store%d(%03X) = %0$(($1/4))X %s\n" $1 $2 $3 "$5" 1>&2 } -# write a 32 bits data -# usage: put offset data32 file [bytes] -put() +# usage: getlong offset file +getlong() { - n=$2; for i in $(seq 1 ${4:-4}); do - printf '\\\\x%02X' $(($n & 255)) - n=$(($n >> 8)) - done | xargs echo -en | ddq bs=1 conv=notrunc of=$3 seek=$1 - [ -n "$DEBUG" ] && printf "put$4(%04X) = %X\n" $1 $2 1>&2 + ddq if=$2 bs=1 skip=$(($1)) count=4 | hexdump -e '"" 1/4 "%d" "\n"' } -# read a 32 bits data -# usage: get offset file [bytes] -get() +error() { - ddq if=$2 bs=1 skip=$(($1)) count=${3:-4} | hexdump -e '"" 1/4 "%d"' + echo $@ 1>&2 + rm -f $bs + exit 1 } -SetupSzOfs=0x1F1 -SyssizeOfs=0x1F4 -RamfsLenOfs=0x21C -ArgPtrOfs=0x228 - floppyset() { # bzImage offsets - CylinderCount=0x1F0 - FlagsOfs=0x1F2 - VideoModeOfs=0x1FA - RootDevOfs=0x1FC - CodeAdrOfs=0x214 + SetupSzOfs=497 + FlagsOfs=498 + VideoModeOfs=506 + RootDevOfs=508 + Magic=0x202 RamfsAdrOfs=0x218 + RamfsLenOfs=0x21C # boot+setup address SetupBase=0x90000 - stacktop=0x9E00 - bs=/tmp/bs$$ # Get and patch boot sector - # See http://hg.slitaz.org/wok/raw-file/711d076b277c/linux/stuff/linux-header-2.6.34.u + # See http://hg.slitaz.org/wok/file/66e38bd6a132/linux/stuff/linux-header.u + [ -n "$DEBUG" ] && echo "Read bootsector..." 1>&2 ddq if=$KERNEL bs=512 count=1 of=$bs + + [ $(( $(getlong 0x1FE $bs) & 0xFFFF )) -eq 43605 ] || + error "Not bootable" + uudecode <&2 ddq if=$KERNEL bs=512 skip=1 count=$setupsz >> $bs - if [ -n "$TRACKS" ]; then - dbg -n "--tracks " - put $CylinderCount $TRACKS $bs 1 + Version=$(( $(getlong 0x206 $bs) & 0xFFFF )) + [ $(getlong $Magic $bs) -ne 1400005704 ] && Version=0 + feature="" + while read prot kern info ; do + [ $Version -lt $((0x$prot)) ] && continue + feature="features $prot starting from kernel $kern " + done <&2 + + # Old kernels need bootsector patches to disable rescent features + while read minversion maxversion offset bytes rem; do + [ $Version -gt $(( 0x$maxversion )) ] && continue + [ $Version -lt $(( 0x$minversion )) ] && continue + patch $offset $bytes $bs "$rem" + done < /dev/null) - [ -n "$n" ] || n=$RDEV - put $RootDevOfs $n $bs 2 + [ -n "$CMDLINE" ] || patch 04D EB $bs "No cmdline" + [ -n "$NOEDIT" ] && patch 059 0D:46:EB:14 $bs 'mov CR,%al ; inc %si; jmp putal' + [ 1$TRACKS -ne 180 ] && store 8 0x171 $TRACKS $bs TRACKS + + [ -n "$FLAGS" ] && store 16 $FlagsOfs $FLAGS $bs FLAGS + [ -n "$VIDEO" ] && store 16 $VideoModeOfs $VIDEO $bs VIDEO + [ -n "$RDEV" ] || case "$FORMAT" in + 1200) RDEV=0x0208 ;; + 1440) RDEV=0x021C ;; + 2880) RDEV=0x0220 ;; + *) RDEV=0x0200 ;; + esac + while [ -L "$RDEV" ]; do RDEV="$(readlink "$RDEV")"; done + [ -b "$RDEV" ] && RDEV=$(stat -c '0x%02t%02T' $RDEV 2> /dev/null) + store 16 $RootDevOfs $RDEV $bs RDEV + + # Store cmdline after setup + if [ -n "$CMDLINE" ]; then + echo -n "$CMDLINE" | ddq bs=512 count=1 conv=sync >> $bs + CmdlineOfs=0x9E00 # Should be in 0x8000 .. 0xA000 + ArgPtrOfs=0x228 + ArgPtrVal=$(( $SetupBase + $CmdlineOfs )) + if [ $Version -lt 514 ]; then + ArgPtrOfs=0x0020 + ArgPtrVal=$(( 0xA33F + ($CmdlineOfs << 16) )) + fi + store 32 $ArgPtrOfs $ArgPtrVal $bs "Cmdline '$CMDLINE'" fi - # Store cmdline after setup - if [ -n "$CMDLINE" ]; then - dbg -n "--cmdline '$CMDLINE' " - echo -n "$CMDLINE" | ddq bs=512 count=1 conv=sync >> $bs - put $ArgPtrOfs $(( $SetupBase + $stacktop )) $bs - fi - - # Compute initramfs size + # Compute initramfs size (protocol >= 2.00) + [ $Version -lt 512 ] && INITRD="" initrdlen=0 - padding=0 +INITRDPAD=4 +INITRDALIGN=0x1000 for i in $( echo $INITRD | sed 's/,/ /' ); do [ -s "$i" ] || continue - dbg "--initrd $i " - initrdlen=$(( $initrdlen + $padding )) - padding=$(stat -c %s $i) - initrdlen=$(( $initrdlen + $padding )) - padding=$(( 4096 - ($padding & 4095) )) - [ $padding -eq 4096 ] && padding=0 + while [ -L "$i" ]; do i="$(readlink $i)"; done + size=$(( ($(stat -c %s "$i") + $INITRDPAD - 1) & -$INITRDPAD )) + [ -n "$DEBUG" ] && echo "initrd $i $size " 1>&2 + initrdlen=$(( $initrdlen + $size )) + [ -n "$ADRSRD" ] || ADRSRD=$(( (($MEM * 0x100000) - $initrdlen) & -$INITRDALIGN )) + store 32 $RamfsAdrOfs $(( $ADRSRD )) $bs initrd adrs + store 32 $RamfsLenOfs $initrdlen $bs initrdlen done - Ksize=$(( $(get $SyssizeOfs $bs)*16 )) - Kpad=$(( (($Ksize+4095)/4096)*4096 - Ksize )) - if [ $initrdlen -ne 0 ]; then - dbg "initrdlen = $initrdlen " - Kbase=$(get $CodeAdrOfs $bs) - put $RamfsAdrOfs \ - $(( (0x1000000 - $initrdlen) & 0xFFFF0000 )) $bs - put $RamfsLenOfs $(( ($initrdlen + 3) & -4 )) $bs - fi + + [ -n "$NOSYSSIZEFIX" ] || store 32 0x1F4 \ + $(( ($(stat -c %s $KERNEL)+15)/16 - ($setupsz+1)*32)) $bs fix system size # Output boot sector + setup + cmdline ddq if=$bs # Output kernel code - ddq if=$KERNEL bs=512 skip=$(( $setupsz + 1 )) - - # Pad to next sector - Kpad=$(( 512 - ($(stat -c %s $KERNEL) & 511) )) - [ $Kpad -eq 512 ] || ddq if=/dev/zero bs=1 count=$Kpad + syssz=$(( ($(getlong 0x1F4 $bs)+31)/32 )) + cat $KERNEL /dev/zero | ddq bs=512 skip=$(( $setupsz+1 )) count=$syssz # Output initramfs - padding=0 for i in $( echo $INITRD | sed 's/,/ /' ); do [ -s "$i" ] || continue - [ $padding -ne 0 ] && ddq if=/dev/zero bs=1 count=$padding ddq if=$i - padding=$(( 4 - ($(stat -c %s $i) & 3) )) - [ $padding -eq 4 ] && padding=0 + padding=$(( $INITRDPAD - ($(stat -c %s $i) % $INITRDPAD) )) + [ $padding -eq $INITRDPAD ] || ddq if=/dev/zero bs=1 count=$padding done # Cleanup rm -f $bs } -KERNEL="" -INITRD="" -CMDLINE="" -PREFIX="floppy." -FORMAT="1440" -RDEV="" -VIDEO="" -FLAGS="" -TRACKS="" -DEBUG="" -while [ -n "$1" ]; do - case "${1/--/-}" in - -c*) CMDLINE="$2"; shift;; - -i*) INITRD="$INITRD $2"; shift;; - -p*) PREFIX="$2"; shift;; - -fl*) FLAGS="$2"; shift;; # 1 read-only, 0 read-write - -f*) FORMAT="$2"; shift;; - -r*) RDEV="$2"; shift;; # /dev/??? - -v*) VIDEO="$2"; shift;; # -3 .. n - -t*) TRACKS="$2"; shift;; # likely 81 .. 84 - -d*) DEBUG="1";; - -e*) ddq bs=512 count=2 > kernel - setupsz=$(get $SetupSzOfs kernel 1) - ddq bs=512 count=$(($setupsz - 1)) >> kernel - [ $(get $ArgPtrOfs kernel) -ne 0 ] && - ddq bs=512 count=1 | strings > cmdline - syssz=$(get $SyssizeOfs kernel) - ddq bs=512 count=$(( ($syssz + 31) / 32 )) >> kernel - ddq bs=16 seek=$(($syssz + 32 + $setupsz*32)) count=0 of=kernel - ramsz=$(get $RamfsLenOfs kernel) - ddq bs=512 count=$((($ramsz + 511) / 512)) of=rootfs - ddq bs=1 seek=$ramsz count=0 of=rootfs - exit ;; - *) KERNEL="$1";; - esac - shift -done -[ -n "$KERNEL" -a -f "$KERNEL" ] || usage -[ -n "$TRACKS" ] && [ $(( $FORMAT % $TRACKS )) -ne 0 ] && - echo "Invalid track count for format $FORMAT." && usage - if [ "$FORMAT" == "0" ]; then # unsplitted floppyset > $PREFIX + PAD=$(( 512 - ($(stat -c %s $PREFIX) % 512) )) + [ $PAD -ne 512 ] && ddq if=/dev/zero bs=1 count=$PAD >> $PREFIX exit fi floppyset | split -b ${FORMAT}k /dev/stdin floppy$$ i=1 -ls floppy$$* | while read file ; do +ls floppy$$* 2> /dev/null | while read file ; do output=$PREFIX$(printf "%03d" $i) cat $file /dev/zero | ddq bs=1k count=$FORMAT conv=sync of=$output echo $output