tazpanel diff bootloader @ rev 516
Makefile add install_extra
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Sun Aug 02 20:24:23 2015 +0200 (2015-08-02) |
parents | |
children | 506184fa1105 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/bootloader Sun Aug 02 20:24:23 2015 +0200 1.3 @@ -0,0 +1,396 @@ 1.4 +#!/bin/sh 1.5 +# 1.6 +# This script creates a floppy image set from a linux bzImage and can merge 1.7 +# a cmdline and/or one or more initramfs. 1.8 +# 1.9 +# (C) 2009-2015 Pascal Bellard - GNU General Public License v3. 1.10 + 1.11 +usage() 1.12 +{ 1.13 +cat <<EOT 1.14 +Usage: $0 bzImage [--prefix image_prefix] [--info file] [--quiet] 1.15 + [--format 1200|1440|1680|1920|2880|...] [--mem mb] [--tracks cnt] 1.16 + [--rdev device] [--video mode] [--flags rootflags] [--no-syssize-fix] 1.17 + [--dont-edit-cmdline] [--cmdline 'args'] [--hide-version-string] 1.18 + [--address-initrd address] [--initrd initrdfile]... 1.19 + 1.20 +Default values: --format 1440 --tracks 80 --rdev /dev/fd0 --prefix floppy. --mem 16 1.21 + 1.22 +Example: 1.23 +$0 /boot/bzImage --rdev /dev/ram0 --video -3 --cmdline 'rw lang=fr_FR kmap=fr-latin1 laptop autologin' --initrd /boot/rootfs.gz --initrd ./myconfig.gz 1.24 + 1.25 +or: $0 --extract floppy* 1.26 + 1.27 +Create kernel and maybe cmdline, initrd and info files from a floppy images set 1.28 +EOT 1.29 +exit 1 1.30 +} 1.31 + 1.32 +# bzImage offsets 1.33 +SetupSzOfs=497 1.34 +FlagsOfs=498 1.35 +OldRamfsLenOfs=504 1.36 +VideoModeOfs=506 1.37 +RootDevOfs=508 1.38 +Magic=0x202 1.39 +RamfsAdrOfs=0x218 1.40 +RamfsLenOfs=0x21C 1.41 + 1.42 +ddq() { dd $@ 2> /dev/null; } 1.43 + 1.44 +get() 1.45 +{ 1.46 +echo $( od -v -j $(($1)) -N ${4:-${3:-2}} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null || 1.47 + hexdump -v -s $(($1)) -n ${4:-${3:-2}} -e "\"\" 1/${3:-2} \" %d\n\"" $2 ) 1.48 +} 1.49 + 1.50 +trace() 1.51 +{ 1.52 + [ -n "$DEBUG" ] && printf "$@" 1>&2 && echo 1>&2 1.53 +} 1.54 + 1.55 +# usage: store bits offset data file 1.56 +store() 1.57 +{ 1.58 + n=$3; for i in $(seq 8 8 $1); do 1.59 + printf '\\\\x%02X' $(($n & 255)) 1.60 + n=$(($n >> 8)) 1.61 + done | xargs echo -en | ddq bs=1 conv=notrunc of=$4 seek=$(($2)) 1.62 + s=$1; a=$2; d=$3; shift 4; c="$@" 1.63 + trace "store$s(%03X) = %0$(($s/4))X $c" $a $d 1.64 +} 1.65 + 1.66 +die() 1.67 +{ 1.68 + echo $@ 1>&2 1.69 + exit 1 1.70 +} 1.71 +extract() 1.72 +{ 1.73 + shift 1.74 + [ ! -s "$1" ] && die "No floppy ?" 1.75 + [ $(get 0x1FE "$1") -ne 43605 ] && die "Not bootable" 1.76 + [ $(get $Magic "$1" 4) != 1400005704 ] && 1.77 + [ $(get 0x1F4 "$1") -gt 32768 -o $(get 0x1F6 "$1") -ne 0 ] && 1.78 + die "Not linux." 1.79 + FORMAT="$(($(stat -c "%s" $1)/1024))" 1.80 + cat <<EOT 1.81 +--format $FORMAT 1.82 +--rdev $(printf "0x%04X" $(get $RootDevOfs $1)) 1.83 +--video $(get $VideoModeOfs $1) 1.84 +--flags $(get $FlagsOfs $1) 1.85 +EOT 1.86 + MYBB="$(ddq if=$1 bs=512 count=1 | strings | grep "Insert disk 00")" 1.87 + cmdline=0 1.88 + info=0 1.89 + if [ "$MYBB" ]; then 1.90 + cmdline=$(get 0x22 $1) 1.91 + info=$(get 0x1EF $1) 1.92 + [ $(get 0x75 $1) -eq $((0xDB0)) ] && echo "--dont-edit-cmdline" 1.93 + [ $(get 0x58 $1) -eq $((0x9090)) ] && echo "--hide-version-string" 1.94 + fi 1.95 + n=$(($(get $SetupSzOfs $1 1)+1)) 1.96 + [ $n -eq 1 ] && n=5 1.97 + [ $info -ne 0 ] && infolen=$(($n-$info/512)) && n=$(($info/512)) 1.98 + [ $cmdline -ne 0 ] && n=$(($cmdline/512)) 1.99 + cat "$@" | { 1.100 + ddq bs=512 count=$n >kernel 1.101 + files="kernel" 1.102 + if [ "$MYBB" ]; then 1.103 + store 8 $SetupSzOfs $(($n-1)) kernel "setup size $n" 1.104 + store 16 0x22 0 kernel "clear cmdline" 1.105 + store 16 0x1EF 0 kernel "clear info" 1.106 + fi 1.107 + [ $cmdline -ne 0 ] && files="$files cmdline" && 1.108 + ddq bs=512 count=1 | strings | sed q > cmdline 1.109 + [ $info -ne 0 ] && files="$files info" && 1.110 + ddq bs=512 count=$infolen | sed \ 1.111 + 's/'$(echo -en "\xff\xff$//;s/\xff/\f")'/g;s/\r/\n/g;q' > info 1.112 + syssz=$(get 0x1F4 kernel 4) 1.113 + ddq bs=16 count=$syssz >>kernel 1.114 + [ $(($syssz % 32)) -ne 0 ] && 1.115 + ddq bs=16 of=/dev/null count=$((32 - ($syssz % 32))) 1.116 + if [ $(get $Magic kernel 4) == 1400005704 ]; then 1.117 + ddq bs=1 count=200 skip=$((512+$(get 0x20E kernel 2))) \ 1.118 + if=kernel | strings | sed q 1.119 + len=$(get $RamfsLenOfs kernel 4) 1.120 + if [ $len -ne 0 ]; then 1.121 + adrs=$(get $RamfsAdrOfs kernel 4) 1.122 + printf "--address-initrd 0x%X \n" $adrs 1.123 + echo "--mem $(((($adrs+$len)/1024+512)/1024))" 1.124 + ddq bs=512 count=$((($len+511)/512)) > initrd 1.125 + ddq count=0 bs=1 seek=$len of=initrd 1.126 + files="$files initrd" 1.127 + store 64 $RamfsAdrOfs 0 kernel "reset initrd" 1.128 + fi 1.129 + if [ $(get 0x206 kernel) -ge 514 ]; then 1.130 + store 32 0x228 0 kernel "clean cmdline32" 1.131 + fi 1.132 + else 1.133 + len=$(get $OldRamfsLenOfs kernel) 1.134 + [ $len -ne 0 ] && files="$files initrd" && 1.135 + if [ -s "$2" ]; then 1.136 + ddq if=$2 bs=1024 count=$len of=initrd 1.137 + else 1.138 + ddq if=$1 bs=1024 skip=256 count=$len of=initrd 1.139 + fi 1.140 + fi 1.141 + ls -l $files 1.142 + } 1.143 + exit 1.144 +} 1.145 + 1.146 +KERNEL="" 1.147 +INITRD="" 1.148 +ADRSRD="" 1.149 +CMDLINE="" 1.150 +PREFIX="floppy." 1.151 +FORMAT="1440" 1.152 +RDEV="" 1.153 +VIDEO="" 1.154 +FLAGS="" 1.155 +TRACKS="80" 1.156 +MEM="16" 1.157 +HIDE="" 1.158 +NOEDIT="" 1.159 +QUIET="" 1.160 +NOSYSSIZEFIX="" 1.161 +INFOFILE="" 1.162 +DEBUG="" 1.163 +while [ -n "$1" ]; do 1.164 + case "${1/--/-}" in 1.165 + -c*) CMDLINE="$2"; shift;; 1.166 + -inf*) INFOFILE="$2"; shift;; 1.167 + -i*) INITRD="$INITRD $2"; shift;; 1.168 + -a*) ADRSRD="$2"; shift;; 1.169 + -h*) HIDE="1";; 1.170 + -p*) PREFIX="$2"; shift;; 1.171 + -fl*)FLAGS="$2"; shift;; # 1 read-only, 0 read-write 1.172 + -f*) FORMAT="$2"; shift;; 1.173 + -m*) MEM="$(echo $2 | sed 's/[^0-9]//g')"; shift;; 1.174 + -r*) RDEV="$2"; shift;; 1.175 + -v*) VIDEO="$2"; shift;; # -3 .. n 1.176 + -t*) TRACKS="$2"; shift;; # likely 81 .. 84 1.177 + -n*) NOSYSSIZEFIX="1";; 1.178 + -debug) DEBUG="1";; 1.179 + -d*) NOEDIT="1";; 1.180 + -q*) QUIET="1";; 1.181 + -e*) extract "$@";; 1.182 + *) KERNEL="$1";; 1.183 + esac 1.184 + shift 1.185 +done 1.186 +[ -n "$KERNEL" -a -f "$KERNEL" ] || usage 1.187 +while [ -L "$KERNEL" ]; do KERNEL="$(readlink "$KERNEL")"; done 1.188 +if [ $(( $FORMAT % $TRACKS )) -ne 0 ]; then 1.189 + echo "Invalid track count for format $FORMAT." 1.190 + usage 1.191 +fi 1.192 +[ 0$MEM -lt 2 ] && MEM=2 1.193 + 1.194 +patch() 1.195 +{ 1.196 + echo -en $(echo ":$2" | sed 's/:/\\x/g') | \ 1.197 + ddq bs=1 conv=notrunc of=$3 seek=$((0x$1)) 1.198 + trace "patch $1 $2 $4" 1.199 +} 1.200 + 1.201 +error() 1.202 +{ 1.203 + rm -f $bs 1.204 + die $@ 1.205 +} 1.206 + 1.207 +floppyset() 1.208 +{ 1.209 + # boot+setup address 1.210 + SetupBase=0x90000 1.211 + 1.212 + bs=/tmp/bs$$ 1.213 + 1.214 + # Get and patch boot sector 1.215 + # See http://hg.slitaz.org/wok/raw-file/13835bce7189/syslinux/stuff/iso2exe/bootloader.S 1.216 + trace "Read bootsector..." 1.217 + ddq if=$KERNEL bs=512 count=1 of=$bs 1.218 + 1.219 + [ $(get 0x1FE $bs) -eq 43605 ] || error "Not bootable" 1.220 + 1.221 + uudecode <<EOT | ddq of=$bs conv=notrunc 1.222 +begin-base64 644 - 1.223 +v8adaACQF4n8FgcxwLk7APOqWx+g8X1AD6H6xXd4XwZXvQAAsQbzpRYfZGaP 1.224 +R3jGRfg/l1hB6CQBMfYLNu8BdAzoggF0B+hgATwbdfS+AAKBTBAggMZEJZvo 1.225 +ZwEx9gt3G3Q6x0cZP6PoWwGwIOgtASwYc/lO6DEBmDwIdAOIBK05dxt08OgV 1.226 +ATwKdd+IfP4WB78AgIn+h3cbtQLzpFuJ5v9IEMdAFAiTgPMIdfO79AGxBaEV 1.227 +AmaLH2ZLZtPrZkOJRBtmv4AAAABmKfuccwIB31BTVjHbaACAB+hwAF5bjMG0 1.228 +hxYHzRVYBQABEEwfnXfPuQkCuxwCOE/+che0iM0VPQCwcgaIbB+Ib/+hGQLT 1.229 +b+J1o5fNE+oAACCQWjjBdzRgzRP56HMAYVJQKMh3ArABOfhyAon4ULQCzRNa 1.230 +WHLclQHRjukA1wDXKddadE2M6ZU4wXXUiMixATDOdcz+xYD9UHXFtQBgvtEB 1.231 +U7sPAIAg8Ev+AIA4OXf16EwAW4n16CkAdRVSmM0TuAECzRNa0NQ6Zv516kVI 1.232 +debrjbAxHAO0DrsHAM0QPA1088O/bARkxgWmuA0BZDoldArNFnT0mM0WjudH 1.233 +wwN0DrAN6NL/rDwAf/jDSW5zZXJ0IGRpc2sgMDAxIGFuZCBFbnRlci4HDQAA 1.234 +AAA= 1.235 +==== 1.236 +EOT 1.237 + # Get setup 1.238 + setupsz=$(get $SetupSzOfs $bs 1) 1.239 + if [ $setupsz -eq 0 ]; then 1.240 + setupsz=4 1.241 + store 8 $SetupSzOfs $setupsz $bs "setup size $setupsz" 1.242 + fi 1.243 + trace "Read setup ($setupsz sectors) ..." 1.244 + ddq if=$KERNEL bs=512 skip=1 count=$setupsz >> $bs 1.245 + 1.246 + Version=$(get 0x206 $bs) 1.247 + [ $(get $Magic $bs 4) != 1400005704 ] && Version=0 1.248 + feature="" 1.249 + while read prot kern info ; do 1.250 + [ $Version -lt $((0x$prot)) ] && continue 1.251 + feature="features $prot starting from kernel $kern " 1.252 + done <<EOT 1.253 +200 1.3.73 kernel_version, bzImage, initrd, loadflags/type_of_loader 1.254 +201 1.3.76 heap_end_ptr 1.255 +202 2.4.0 new cmdline + relocatable setup 1.256 +204 2.6.14 long syssize 1.257 +206 2.6.22 cmdline maxsize $(get 0x238 $bs 4) 1.258 +EOT 1.259 + trace "Protocol %X $feature" $Version 1.260 + 1.261 + # Old kernels need bootsector patches to disable rescent features 1.262 + while read minversion maxversion offset bytes rem; do 1.263 + [ $Version -gt $(( 0x$maxversion )) ] && continue 1.264 + [ $Version -lt $(( 0x$minversion )) ] && continue 1.265 + patch $offset $bytes $bs "$rem" 1.266 + done <<EOT 1.267 +000 1FF 0B2 B8:00:01 force zImage (movw \$0x100, %ax) 1.268 +000 1FF 0F9 EB skip initrd code 1.269 +000 1FF 059 90:90:90 no kernel version 1.270 +000 1FF 050 90:90:90:90:90 type_of_loader 1.271 +000 200 055 90:90:90:90 heap_end_ptr 1.272 +000 203 1F6 00:00 syssize32 1.273 +EOT 1.274 + [ -n "$CMDLINE" ] || patch 061 EB $bs "No cmdline" 1.275 + [ -n "$HIDE" ] && patch 058 90 90 90 $bs "Hide version" 1.276 + [ -n "$NOEDIT" ] && patch 075 B0:0D:90 $bs 'mov CR,%al ; nop' 1.277 + [ 1$TRACKS -ne 180 ] && store 8 0x15F $TRACKS $bs TRACKS 1.278 + 1.279 + [ -n "$FLAGS" ] && store 16 $FlagsOfs $FLAGS $bs FLAGS 1.280 + [ -n "$VIDEO" ] && store 16 $VideoModeOfs $VIDEO $bs VIDEO 1.281 + [ -n "$RDEV" ] || case "$FORMAT" in 1.282 + 1200) RDEV=0x0208 ;; 1.283 + 1440) RDEV=0x021C ;; 1.284 + 2880) RDEV=0x0220 ;; 1.285 + *) RDEV=0x0200 ;; 1.286 + esac 1.287 + while [ -L "$RDEV" ]; do RDEV="$(readlink "$RDEV")"; done 1.288 + [ -b "$RDEV" ] && RDEV=$(stat -c '0x%02t%02T' $RDEV 2> /dev/null) 1.289 + [ "$(echo $RDEV | tr '[0-9A-FXa-fx]' 0 | sed 's/0//g')" ] || 1.290 + store 16 $RootDevOfs $RDEV $bs RDEV 1.291 + 1.292 + [ $FORMAT -lt 720 ] && store 8 0x15F 40 $bs 360K 1.293 + [ $FORMAT -lt 320 ] && store 8 0x158 237 $bs 160K 1.294 + 1.295 + extra=0 1.296 + # Store cmdline after setup for kernels >= 0.99 1.297 + if [ -n "$CMDLINE" ]; then 1.298 + CmdlineOfs=$(stat -c '%s' $bs) 1.299 + store 16 0x22 $CmdlineOfs $bs "Cmdline @$CmdlineOfs '$CMDLINE'" 1.300 + [ $Version -ge 514 ] && 1.301 + store 32 0x228 $(( $SetupBase + 0x8000 )) $bs "Cmdline32" 1.302 + echo -n "$CMDLINE" | ddq bs=512 count=1 conv=sync >> $bs 1.303 + extra=$(($extra+1)) 1.304 + store 8 0x1F1 $(($setupsz+$extra)) $bs setup size 1.305 + [ $Version -ge 512 ] && [ -n "$QUIET" ] && 1.306 + store 8 0x211 $(($(get 0x211 $bs 1) | 32)) $bs suppress early messages 1.307 + fi 1.308 + 1.309 + # Info text after setup 1.310 + if [ -s "$INFOFILE" ]; then 1.311 + InfoOfs=$(stat -c '%s' $bs) 1.312 + sed -e ':a;N;$!ba;s/\r\n/\r/g;s/\n/\r/g' \ 1.313 + -e 's/'$(echo -e "\f/\xff/g;s/$/\xff\xff")'/' \ 1.314 + < "$INFOFILE" > $bs.infotext 1.315 + ddq if=/dev/zero bs=512 count=1 >>$bs.infotext 1.316 + infolen=$(($(stat -c %s $bs.infotext)/512)) 1.317 + ddq if=$bs.infotext count=$infolen bs=512 >> $bs 1.318 + extra=$(($extra+$infolen)) 1.319 + rm -f $bs.infotext 1.320 + store 8 0x1F1 $(($setupsz+$extra)) $bs setup size 1.321 + store 16 0x1EF $InfoOfs $bs update infoptr 1.322 + fi 1.323 + 1.324 + syssz=$((($(stat -c %s $KERNEL)+15)/16-32*(1+$setupsz))) 1.325 + #syssz=$(get 0x1F4 $bs 4) 1.326 + sysszsect=$((($syssz+31)/32)) 1.327 + store 16 $OldRamfsLenOfs 0 $bs clear oldramfs 1.328 + INITRD="${INITRD# }" 1.329 + INITRDPAD=4 1.330 + [ -n "$INITRD" ] && 1.331 + if [ $Version -lt 512 ]; then 1.332 + # Compute initramfs location (protocol < 2.00) 1.333 + [ $syssz -gt 32768 ] && syssz=$(get 0x1F4 $bs 2) 1.334 + [ $syssz -eq 0 ] && syssz=$((0x7F00)) 1.335 + sysszsect=$((($syssz+31)/32)) 1.336 + INITRD="${INITRD%%,*}" 1.337 + initrdlen=$(stat -c %s "$INITRD") 1.338 + store 16 $OldRamfsLenOfs $(($initrdlen/1024)) $bs set oldramfs 1.339 + INITRDDISKALIGN=$((0x40000)) 1.340 + [ $(($initrdlen+$INITRDDISKALIGN)) -gt $(($FORMAT*1024)) -o \ 1.341 + $(((512*$sysszsect) + $(stat -c %s $bs))) -gt $INITRDDISKALIGN -o \ 1.342 + -n "$ADRSRD" ] && INITRDDISKALIGN=$(($FORMAT*1024)) 1.343 + else 1.344 +INITRDRAMALIGN=0x1000 1.345 + # Compute initramfs size (protocol >= 2.00) 1.346 + initrdlen=0 1.347 + INITRDDISKALIGN=0 1.348 + for i in ${INITRD//,/ }; do 1.349 + [ -s "$i" ] || continue 1.350 + while [ -L "$i" ]; do i="$(readlink $i)"; done 1.351 + size=$(stat -c %s "$i") 1.352 + trace "initrd $i $size " 1.353 + initrdlen=$(((($initrdlen + $INITRDPAD - 1) & -$INITRDPAD) + $size)) 1.354 + ADRSRD2=$(( (($MEM * 0x100000) - $initrdlen) & -$INITRDRAMALIGN )) 1.355 + store 32 $RamfsAdrOfs $(( ${ADRSRD:-$ADRSRD2} )) $bs initrd adrs 1.356 + store 32 $RamfsLenOfs $initrdlen $bs initrdlen 1.357 + done 1.358 + fi 1.359 + 1.360 + [ -n "$NOSYSSIZEFIX" ] || store 32 0x1F4 $syssz $bs fix system size 1.361 + 1.362 + # Output boot sector + setup + cmdline + info 1.363 + ddq if=$bs 1.364 + 1.365 + # Output kernel code 1.366 + [ $INITRDDISKALIGN -ne 0 ] && 1.367 + INITRDDISKALIGN=$(($INITRDDISKALIGN/512-$sysszsect-$extra-$setupsz-1)) 1.368 + cat $KERNEL /dev/zero | ddq bs=512 skip=$(( $setupsz+1 )) \ 1.369 + count=$(($sysszsect+$INITRDDISKALIGN)) conv=sync 1.370 + 1.371 + # Output initramfs 1.372 + padding=$INITRDPAD 1.373 + for i in ${INITRD//,/ }; do 1.374 + [ -s "$i" ] || continue 1.375 + [ $padding -eq $INITRDPAD ] || ddq if=/dev/zero bs=1 count=$padding 1.376 + ddq if=$i 1.377 + trace "initrd $i ($(stat -c %s $i) bytes) padding $INITRDPAD" 1.378 + padding=$(( $INITRDPAD - ($(stat -c %s $i) % $INITRDPAD) )) 1.379 + done 1.380 + 1.381 + # Cleanup 1.382 + rm -f $bs 1.383 +} 1.384 + 1.385 +if [ "$FORMAT" == "0" ]; then # unsplitted 1.386 + floppyset > $PREFIX 1.387 + PAD=$(( 512 - ($(stat -c %s $PREFIX) % 512) )) 1.388 + [ $PAD -ne 512 ] && ddq if=/dev/zero bs=1 count=$PAD >> $PREFIX 1.389 + exit 1.390 +fi 1.391 +floppyset | split -b ${FORMAT}k /dev/stdin floppy$$ 1.392 +i=1 1.393 +ls floppy$$* 2> /dev/null | while read file ; do 1.394 + output=$PREFIX$(printf "%03d" $i) 1.395 + cat $file /dev/zero | ddq bs=1k count=$FORMAT conv=sync of=$output 1.396 + echo $output 1.397 + rm -f $file 1.398 + i=$(( $i + 1 )) 1.399 +done