install.sh 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. #!/usr/bin/env bash
  2. #-
  3. # Copyright © 2010-2014
  4. # Waldemar Brodkorb <wbx@openadk.org>
  5. # Thorsten Glaser <tg@mirbsd.org>
  6. #
  7. # Provided that these terms and disclaimer and all copyright notices
  8. # are retained or reproduced in an accompanying document, permission
  9. # is granted to deal in this work without restriction, including un‐
  10. # limited rights to use, publicly perform, distribute, sell, modify,
  11. # merge, give away, or sublicence.
  12. #
  13. # This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
  14. # the utmost extent permitted by applicable law, neither express nor
  15. # implied; without malicious intent or gross negligence. In no event
  16. # may a licensor, author or contributor be held liable for indirect,
  17. # direct, other damage, loss, or other issues arising in any way out
  18. # of dealing in the work, even if advised of the possibility of such
  19. # damage or existence of a defect, except proven that it results out
  20. # of said person’s immediate fault when using the work as intended.
  21. #
  22. # Alternatively, this work may be distributed under the terms of the
  23. # General Public License, any version, as published by the Free Soft-
  24. # ware Foundation.
  25. #-
  26. # Prepare a USB stick or CF/SD/MMC card or hard disc for installation
  27. # of OpenADK
  28. ADK_TOPDIR=$(pwd)
  29. HOST=$(gcc -dumpmachine)
  30. me=$0
  31. case :$PATH: in
  32. (*:$ADK_TOPDIR/host_$HOST/usr/bin:*) ;;
  33. (*) export PATH=$PATH:$ADK_TOPDIR/host_$HOST/usr/bin ;;
  34. esac
  35. test -n "$KSH_VERSION" || exec mksh "$me" "$@"
  36. if test -z "$KSH_VERSION"; then
  37. echo >&2 Fatal error: could not run myself with mksh!
  38. exit 255
  39. fi
  40. ### run with mksh from here onwards ###
  41. me=${me##*/}
  42. if (( USER_ID )); then
  43. print -u2 Installation is only possible as root!
  44. exit 1
  45. fi
  46. ADK_TOPDIR=$(realpath .)
  47. ostype=$(uname -s)
  48. fs=ext4
  49. cfgfs=1
  50. datafssz=0
  51. noformat=0
  52. quiet=0
  53. serial=0
  54. speed=115200
  55. panicreboot=10
  56. function usage {
  57. cat >&2 <<EOF
  58. Syntax: $me [-f filesystem] [-c cfgfssize] [-d datafssize] [-n]
  59. [-p panictime] [±q] [-s serialspeed] [±t] <target> <device> <archive>
  60. Partition sizes are in MiB. Filesystem type is currently ignored (ext4).
  61. Defaults: -c 1 -p 10 -s 115200; -t = enable serial console
  62. EOF
  63. exit $1
  64. }
  65. while getopts "c:d:f:hnp:qs:t" ch; do
  66. case $ch {
  67. (c) if (( (cfgfs = OPTARG) < 0 || cfgfs > 16 )); then
  68. print -u2 "$me: -c $OPTARG out of bounds"
  69. exit 1
  70. fi ;;
  71. (d) if (( (datafssz = OPTARG) < 0 )); then
  72. print -u2 "$me: -d $OPTARG out of bounds"
  73. exit 1
  74. fi ;;
  75. (f) if [[ $OPTARG != @(ext2|ext3|ext4|xfs) ]]; then
  76. print -u2 "$me: filesystem $OPTARG invalid"
  77. exit 1
  78. fi
  79. fs=$OPTARG ;;
  80. (h) usage 0 ;;
  81. (p) if (( (panicreboot = OPTARG) < 0 || panicreboot > 300 )); then
  82. print -u2 "$me: -p $OPTARG out of bounds"
  83. exit 1
  84. fi ;;
  85. (q) quiet=1 ;;
  86. (+q) quiet=0 ;;
  87. (s) if [[ $OPTARG != @(96|192|384|576|1152)00 ]]; then
  88. print -u2 "$me: serial speed $OPTARG invalid"
  89. exit 1
  90. fi
  91. speed=$OPTARG ;;
  92. (n) noformat=1 ;;
  93. (t) serial=1 ;;
  94. (+t) serial=0 ;;
  95. (*) usage 1 ;;
  96. }
  97. done
  98. shift $((OPTIND - 1))
  99. (( $# == 3 )) || usage 1
  100. f=0
  101. case $ostype {
  102. (Linux)
  103. tools="bc mkfs.$fs tune2fs"
  104. ;;
  105. (Darwin)
  106. tools="bc diskutil"
  107. ;;
  108. (*)
  109. print -u2 Sorry, not ported to the OS "'$ostype'" yet.
  110. exit 1
  111. ;;
  112. }
  113. for tool in $tools; do
  114. print -n Checking if $tool is installed...
  115. if whence -p $tool >/dev/null; then
  116. print " okay"
  117. else
  118. print " failed"
  119. f=1
  120. fi
  121. done
  122. (( f )) && exit 1
  123. target=$1
  124. tgt=$2
  125. src=$3
  126. case $target {
  127. (raspberry-pi|solidrun-imx6|default) ;;
  128. (*)
  129. print -u2 "Unknown target '$target', exiting"
  130. exit 1 ;;
  131. }
  132. if [[ ! -b $tgt ]]; then
  133. print -u2 "'$tgt' is not a block device, exiting"
  134. exit 1
  135. fi
  136. if [[ ! -f $src ]]; then
  137. print -u2 "'$src' is not a file, exiting"
  138. exit 1
  139. fi
  140. (( quiet )) || print "Installing $src on $tgt."
  141. case $ostype {
  142. (Darwin)
  143. R=/Volumes/ADKROOT
  144. B=/Volumes/ADKBOOT
  145. D=/Volumes/ADKDATA
  146. basedev=$tgt
  147. rootpart=${basedev}s1
  148. datapart=${basedev}s2
  149. if [[ $target = raspberry-pi ]]; then
  150. bootpart=${basedev}s1
  151. rootpart=${basedev}s2
  152. datapart=${basedev}s3
  153. fi
  154. match=\'${basedev}\''?(s+([0-9]))'
  155. function mount_fs {
  156. }
  157. function create_fs {
  158. if [[ $3 = ext4 ]]; then
  159. fstype=UFSD_EXTFS4
  160. fi
  161. if [[ $3 = vfat ]]; then
  162. fstype=fat32
  163. fi
  164. diskutil eraseVolume $fstype "$2" "$1"
  165. }
  166. ;;
  167. (Linux)
  168. basedev=$tgt
  169. rootpart=${basedev}1
  170. datapart=${basedev}2
  171. if [[ $target = raspberry-pi ]]; then
  172. bootpart=${basedev}1
  173. rootpart=${basedev}2
  174. datapart=${basedev}3
  175. fi
  176. match=\'${basedev}\''+([0-9])'
  177. function mount_fs {
  178. mount -t "$3" "$1" "$2"
  179. }
  180. function create_fs {
  181. mkfs.$3 "$1"
  182. tune2fs -c 0 -i 0 "$1"
  183. }
  184. ;;
  185. }
  186. mount |&
  187. while read -p dev rest; do
  188. eval [[ \$dev = $match ]] || continue
  189. print -u2 "Block device $tgt is in use, please umount first."
  190. exit 1
  191. done
  192. if (( !quiet )); then
  193. print "WARNING: This will overwrite $basedev - type Yes to continue!"
  194. read x
  195. [[ $x = Yes ]] || exit 0
  196. fi
  197. if ! T=$(mktemp -d /tmp/openadk.XXXXXXXXXX); then
  198. print -u2 Error creating temporary directory.
  199. exit 1
  200. fi
  201. if [[ $ostype != Darwin ]]; then
  202. R=$T/rootmnt
  203. B=$T/bootmnt
  204. D=$T/datamnt
  205. mkdir -p "$R" "$B" "$D"
  206. fi
  207. # get disk size
  208. dksz=$(dkgetsz "$tgt")
  209. # partition layouts:
  210. # n̲a̲m̲e̲ p̲a̲r̲t̲#̲0̲ p̲̲a̲r̲t̲#̲1̲ p̲̲a̲r̲t̲#̲2̲ p̲̲a̲r̲t̲#̲3̲
  211. # default: 0x83(system) 0x83(?data) -(unused) 0x88(cfgfs)
  212. # raspberry: 0x0B(boot) 0x83(system) 0x83(?data) 0x88(cfgfs)
  213. # sizes:
  214. # boot(raspberry) - fixed (100 MiB)
  215. # cfgfs - fixed (parameter, max. 16 MiB)
  216. # data - flexible (parameter)
  217. # system - everything else
  218. if [[ $target = raspberry-pi ]]; then
  219. bootfssz=100
  220. if (( grub )); then
  221. print -u2 "Cannot combine GRUB with $target"
  222. rm -rf "$T"
  223. exit 1
  224. fi
  225. else
  226. bootfssz=0
  227. fi
  228. heads=64
  229. secs=32
  230. (( cyls = dksz / heads / secs ))
  231. if (( cyls < (bootfssz + cfgfs + datafssz + 2) )); then
  232. print -u2 "Size of $tgt is $dksz, this looks fishy?"
  233. rm -rf "$T"
  234. exit 1
  235. fi
  236. if stat -qs .>/dev/null 2>&1; then
  237. statcmd='stat -f %z' # BSD stat (or so we assume)
  238. else
  239. statcmd='stat -c %s' # GNU stat
  240. fi
  241. if (( grub )); then
  242. tar -xOzf "$src" boot/grub/core.img >"$T/core.img"
  243. integer coreimgsz=$($statcmd "$T/core.img")
  244. else
  245. coreimgsz=65024
  246. fi
  247. if (( coreimgsz < 1024 )); then
  248. print -u2 core.img is probably too small: $coreimgsz
  249. rm -rf "$T"
  250. exit 1
  251. fi
  252. if (( coreimgsz > 65024 )); then
  253. print -u2 core.img is larger than 64K-512: $coreimgsz
  254. rm -rf "$T"
  255. exit 1
  256. fi
  257. (( coreendsec = (coreimgsz + 511) / 512 ))
  258. if [[ $basedev = /dev/svnd+([0-9]) ]]; then
  259. # BSD svnd0 mode: protect sector #1
  260. corestartsec=2
  261. (( ++coreendsec ))
  262. corepatchofs=$((0x614))
  263. else
  264. corestartsec=1
  265. corepatchofs=$((0x414))
  266. fi
  267. # partition offset: at least coreendsec+1 but aligned on a multiple of secs
  268. #(( partofs = ((coreendsec / secs) + 1) * secs ))
  269. # we just use 2048 all the time, since some loaders are longer
  270. partofs=2048
  271. if [[ $target = raspberry-pi ]]; then
  272. (( spartofs = partofs + (100 * 2048) ))
  273. else
  274. spartofs=$partofs
  275. fi
  276. (( quiet )) || if (( grub )); then
  277. print Preparing MBR and GRUB2...
  278. else
  279. print Preparing MBR...
  280. fi
  281. dd if=/dev/zero of="$T/firsttrack" count=$partofs 2>/dev/null
  282. # add another MiB to clear the first partition
  283. dd if=/dev/zero bs=1048576 count=1 >>"$T/firsttrack" 2>/dev/null
  284. echo $corestartsec $coreendsec | mksh "$ADK_TOPDIR/scripts/bootgrub.mksh" \
  285. -A -g $((cyls - bootfssz - cfgfs - datafssz)):$heads:$secs -M 1:0x83 \
  286. -O $spartofs | dd of="$T/firsttrack" conv=notrunc 2>/dev/null
  287. (( grub )) && dd if="$T/core.img" of="$T/firsttrack" conv=notrunc \
  288. seek=$corestartsec 2>/dev/null
  289. # set partition where it can find /boot/grub
  290. (( grub )) && print -n '\0\0\0\0' | \
  291. dd of="$T/firsttrack" conv=notrunc bs=1 seek=$corepatchofs 2>/dev/null
  292. # create cfgfs partition (mostly taken from bootgrub.mksh)
  293. set -A thecode
  294. typeset -Uui8 thecode
  295. mbrpno=0
  296. set -A g_code $cyls $heads $secs
  297. (( psz = g_code[0] * g_code[1] * g_code[2] ))
  298. (( pofs = (cyls - cfgfs) * g_code[1] * g_code[2] ))
  299. set -A o_code # g_code equivalent for partition offset
  300. (( o_code[2] = pofs % g_code[2] + 1 ))
  301. (( o_code[1] = pofs / g_code[2] ))
  302. (( o_code[0] = o_code[1] / g_code[1] + 1 ))
  303. (( o_code[1] = o_code[1] % g_code[1] + 1 ))
  304. # boot flag; C/H/S offset
  305. thecode[mbrpno++]=0x00
  306. (( thecode[mbrpno++] = o_code[1] - 1 ))
  307. (( cylno = o_code[0] > 1024 ? 1023 : o_code[0] - 1 ))
  308. (( thecode[mbrpno++] = o_code[2] | ((cylno & 0x0300) >> 2) ))
  309. (( thecode[mbrpno++] = cylno & 0x00FF ))
  310. # partition type; C/H/S end
  311. (( thecode[mbrpno++] = 0x88 ))
  312. (( thecode[mbrpno++] = g_code[1] - 1 ))
  313. (( cylno = g_code[0] > 1024 ? 1023 : g_code[0] - 1 ))
  314. (( thecode[mbrpno++] = g_code[2] | ((cylno & 0x0300) >> 2) ))
  315. (( thecode[mbrpno++] = cylno & 0x00FF ))
  316. # partition offset, size (LBA)
  317. (( thecode[mbrpno++] = pofs & 0xFF ))
  318. (( thecode[mbrpno++] = (pofs >> 8) & 0xFF ))
  319. (( thecode[mbrpno++] = (pofs >> 16) & 0xFF ))
  320. (( thecode[mbrpno++] = (pofs >> 24) & 0xFF ))
  321. (( pssz = psz - pofs ))
  322. (( thecode[mbrpno++] = pssz & 0xFF ))
  323. (( thecode[mbrpno++] = (pssz >> 8) & 0xFF ))
  324. (( thecode[mbrpno++] = (pssz >> 16) & 0xFF ))
  325. (( thecode[mbrpno++] = (pssz >> 24) & 0xFF ))
  326. # write partition table entry
  327. ostr=
  328. curptr=0
  329. while (( curptr < 16 )); do
  330. ostr=$ostr\\0${thecode[curptr++]#8#}
  331. done
  332. print -n "$ostr" | \
  333. dd of="$T/firsttrack" conv=notrunc bs=1 seek=$((0x1EE)) 2>/dev/null
  334. if (( datafssz )); then
  335. # create data partition (copy of the above :)
  336. set -A thecode
  337. typeset -Uui8 thecode
  338. mbrpno=0
  339. set -A g_code $cyls $heads $secs
  340. (( psz = (cyls - cfgfs) * g_code[1] * g_code[2] ))
  341. (( pofs = (cyls - cfgfs - datafssz) * g_code[1] * g_code[2] ))
  342. set -A o_code # g_code equivalent for partition offset
  343. (( o_code[2] = pofs % g_code[2] + 1 ))
  344. (( o_code[1] = pofs / g_code[2] ))
  345. (( o_code[0] = o_code[1] / g_code[1] + 1 ))
  346. (( o_code[1] = o_code[1] % g_code[1] + 1 ))
  347. # boot flag; C/H/S offset
  348. thecode[mbrpno++]=0x00
  349. (( thecode[mbrpno++] = o_code[1] - 1 ))
  350. (( cylno = o_code[0] > 1024 ? 1023 : o_code[0] - 1 ))
  351. (( thecode[mbrpno++] = o_code[2] | ((cylno & 0x0300) >> 2) ))
  352. (( thecode[mbrpno++] = cylno & 0x00FF ))
  353. # partition type; C/H/S end
  354. (( thecode[mbrpno++] = 0x83 ))
  355. (( thecode[mbrpno++] = g_code[1] - 1 ))
  356. (( cylno = (g_code[0] - cfgfs) > 1024 ? 1023 : g_code[0] - cfgfs - 1 ))
  357. (( thecode[mbrpno++] = g_code[2] | ((cylno & 0x0300) >> 2) ))
  358. (( thecode[mbrpno++] = cylno & 0x00FF ))
  359. # partition offset, size (LBA)
  360. (( thecode[mbrpno++] = pofs & 0xFF ))
  361. (( thecode[mbrpno++] = (pofs >> 8) & 0xFF ))
  362. (( thecode[mbrpno++] = (pofs >> 16) & 0xFF ))
  363. (( thecode[mbrpno++] = (pofs >> 24) & 0xFF ))
  364. (( pssz = psz - pofs ))
  365. (( thecode[mbrpno++] = pssz & 0xFF ))
  366. (( thecode[mbrpno++] = (pssz >> 8) & 0xFF ))
  367. (( thecode[mbrpno++] = (pssz >> 16) & 0xFF ))
  368. (( thecode[mbrpno++] = (pssz >> 24) & 0xFF ))
  369. # write partition table entry
  370. ostr=
  371. curptr=0
  372. while (( curptr < 16 )); do
  373. ostr=$ostr\\0${thecode[curptr++]#8#}
  374. done
  375. print -n "$ostr" | \
  376. dd of="$T/firsttrack" conv=notrunc bs=1 seek=$((0x1CE)) 2>/dev/null
  377. fi
  378. if [[ $target = raspberry-pi ]]; then
  379. # move system and data partition from #0/#1 to #1/#2
  380. dd if="$T/firsttrack" bs=1 skip=$((0x1BE)) count=32 of="$T/x" 2>/dev/null
  381. dd of="$T/firsttrack" conv=notrunc bs=1 seek=$((0x1CE)) if="$T/x" 2>/dev/null
  382. # create boot partition (copy of the above :)
  383. set -A thecode
  384. typeset -Uui8 thecode
  385. mbrpno=0
  386. set -A g_code $cyls $heads $secs
  387. psz=$spartofs
  388. pofs=$partofs
  389. set -A o_code # g_code equivalent for partition offset
  390. (( o_code[2] = pofs % g_code[2] + 1 ))
  391. (( o_code[1] = pofs / g_code[2] ))
  392. (( o_code[0] = o_code[1] / g_code[1] + 1 ))
  393. (( o_code[1] = o_code[1] % g_code[1] + 1 ))
  394. # boot flag; C/H/S offset
  395. thecode[mbrpno++]=0x00
  396. (( thecode[mbrpno++] = o_code[1] - 1 ))
  397. (( cylno = o_code[0] > 1024 ? 1023 : o_code[0] - 1 ))
  398. (( thecode[mbrpno++] = o_code[2] | ((cylno & 0x0300) >> 2) ))
  399. (( thecode[mbrpno++] = cylno & 0x00FF ))
  400. # partition type; C/H/S end
  401. (( thecode[mbrpno++] = 0x0B ))
  402. (( thecode[mbrpno++] = g_code[1] - 1 ))
  403. (( cylno = (spartofs / 2048) > 1024 ? 1023 : (spartofs / 2048) - 1 ))
  404. (( thecode[mbrpno++] = g_code[2] | ((cylno & 0x0300) >> 2) ))
  405. (( thecode[mbrpno++] = cylno & 0x00FF ))
  406. # partition offset, size (LBA)
  407. (( thecode[mbrpno++] = pofs & 0xFF ))
  408. (( thecode[mbrpno++] = (pofs >> 8) & 0xFF ))
  409. (( thecode[mbrpno++] = (pofs >> 16) & 0xFF ))
  410. (( thecode[mbrpno++] = (pofs >> 24) & 0xFF ))
  411. (( pssz = psz - pofs ))
  412. (( thecode[mbrpno++] = pssz & 0xFF ))
  413. (( thecode[mbrpno++] = (pssz >> 8) & 0xFF ))
  414. (( thecode[mbrpno++] = (pssz >> 16) & 0xFF ))
  415. (( thecode[mbrpno++] = (pssz >> 24) & 0xFF ))
  416. # write partition table entry
  417. ostr=
  418. curptr=0
  419. while (( curptr < 16 )); do
  420. ostr=$ostr\\0${thecode[curptr++]#8#}
  421. done
  422. print -n "$ostr" | \
  423. dd of="$T/firsttrack" conv=notrunc bs=1 seek=$((0x1BE)) 2>/dev/null
  424. fi
  425. (( quiet )) || print Cleaning out partitions...
  426. (( datafssz )) && dd if=/dev/zero bs=1048576 count=1 \
  427. seek=$((cyls - cfgfs - datafssz)) 2>/dev/null
  428. dd if=/dev/zero bs=1048576 count=1 seek=$((spartofs / 2048)) 2>/dev/null
  429. (( quiet )) || if (( grub )); then
  430. print Writing MBR and GRUB2 to target device...
  431. else
  432. print Writing MBR to target device...
  433. fi
  434. dd if="$T/firsttrack" of="$tgt"
  435. case $target {
  436. (solidrun-imx6)
  437. fwdir=$(dirname "$src")
  438. dd if="$fwdir/SPL" of="$tgt" bs=1024 seek=1
  439. dd if="$fwdir/u-boot.img" of="$tgt" bs=1024 seek=42
  440. ;;
  441. (raspberry-pi)
  442. (( quiet )) || print "Creating filesystem on ${bootpart}..."
  443. (( noformat )) || create_fs "$bootpart" ADKBOOT vfat
  444. ;;
  445. }
  446. (( quiet )) || print "Creating filesystem on ${rootpart}..."
  447. (( noformat )) || create_fs "$rootpart" ADKROOT ext4
  448. #partuuid=$(/sbin/fdisk -l /dev/$tgt | awk '/Disk identifier/ { print $3 "-01" }'|sed -e "s#^0x##")
  449. (( quiet )) || print Extracting installation archive...
  450. mount_fs "$rootpart" "$R" ext4
  451. gzip -dc "$src" | (cd "$R"; tar -xpf -)
  452. case $target {
  453. (raspberry-pi)
  454. mount_fs "$bootpart" "$B" vfat
  455. for x in "$R"/boot/.*; do
  456. [[ -e "$x" ]] && mv -f "$R"/boot/.* "$B/"
  457. break
  458. done
  459. for x in "$R"/boot/*; do
  460. [[ -e "$x" ]] && mv -f "$R"/boot/* "$B/"
  461. break
  462. done
  463. umount "$B"
  464. ;;
  465. (solidrun-imx6)
  466. for x in "$fwdir"/*.dtb; do
  467. [[ -e "$x" ]] && cp "$fwdir"/*.dtb "$R/boot/"
  468. break
  469. done
  470. ;;
  471. }
  472. cd "$R"
  473. rnddev=/dev/urandom
  474. [[ -c /dev/arandom ]] && rnddev=/dev/arandom
  475. dd if=$rnddev bs=16 count=1 >>etc/.rnd 2>/dev/null
  476. (( quiet )) || print Fixing up permissions...
  477. chown 0:0 tmp
  478. chmod 1777 tmp
  479. [[ -f usr/bin/sudo ]] && chmod 4755 usr/bin/sudo
  480. if (( grub )); then
  481. (( quiet )) || print Configuring GRUB2 bootloader...
  482. mkdir -p boot/grub
  483. (
  484. print set default=0
  485. print set timeout=1
  486. if (( serial )); then
  487. print serial --unit=0 --speed=$speed
  488. print terminal_output serial
  489. print terminal_input serial
  490. consargs="console=ttyS0,$speed console=tty0"
  491. else
  492. print terminal_output console
  493. print terminal_input console
  494. consargs="console=tty0"
  495. fi
  496. print
  497. print 'menuentry "GNU/Linux (OpenADK)" {'
  498. linuxargs="root=PARTUUID=$partuuid $consargs"
  499. (( panicreboot )) && linuxargs="$linuxargs panic=$panicreboot"
  500. print "\tlinux /boot/kernel $linuxargs"
  501. print '}'
  502. ) >boot/grub/grub.cfg
  503. fi
  504. (( quiet )) || print Finishing up...
  505. cd "$ADK_TOPDIR"
  506. sync
  507. umount "$R"
  508. sync
  509. rm -rf "$T"
  510. exit 0