Advertisement
Guest User

sailfish init tenderloin

a guest
Jan 21st, 2019
170
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.91 KB | None | 0 0
  1. #!/bin/sh
  2. #
  3. # Hybris adaptation bootstrapping initramfs init script.
  4. #
  5. # Copyright (c) 2014 Jolla Oy
  6. #
  7. # This program is free software; you can redistribute it and/or modify it under
  8. # the terms of the GNU General Public License version 2 as published by the
  9. # Free Software Foundation.
  10. #
  11. # Authors:
  12. # - Tom Swindell <t.swindell@rubyx.co.uk>
  13. # - David Greaves <david@dgreaves.com>
  14. #
  15.  
  16. # This init script runs in early boot in initrd and does a switch_root
  17. # to the real rootfs. It can also be copied into rootfs and provide
  18. # monitoring of the boot process there too.
  19.  
  20. # Be careful - you can't run any external commands until busybox has installed.
  21.  
  22. # General logging
  23. set -x
  24. exec > /init.log 2>&1
  25. echo "Running Mer Boat Loader"
  26.  
  27. BOOTLOGO=
  28. ALWAYSDEBUG=
  29. DATA_PARTITION=/dev/store/cm-data
  30. DEFAULT_OS=sailfishos
  31.  
  32. set_welcome_msg(){
  33. cat <<EOF > /etc/issue.net
  34. Welcome to the Mer/SailfishOS Boat loader debug init system.
  35.  
  36. Log so far is in /init.log
  37.  
  38. To make post-switch_root halt before starting systemd, perform:
  39. EOF
  40. if [ "$DONE_SWITCH" = "no" ]; then
  41. cat <<EOF >> /etc/issue.net
  42. touch /target/init_enter_debug2
  43. EOF
  44. else
  45. cat <<EOF >> /etc/issue.net
  46. touch /init_enter_debug2
  47. EOF
  48. fi
  49. cat <<EOF >> /etc/issue.net
  50. (When run post-switch_root, telnet is on port 2323, not 23)
  51.  
  52. EOF
  53.  
  54. HALT_BOOT="${1:-y}"
  55. if [ "$HALT_BOOT" = "y" ]; then
  56. cat <<EOF >> /etc/issue.net
  57. You may inject commands into init shell process (PID 1):
  58.  
  59. To see output of commands as they're injected:
  60. tail -f /init.log &
  61. To run a command:
  62. echo "ls -l /" >/init-ctl/stdin
  63.  
  64. (Be careful if you experiment with exec as you need to terminate
  65. daemons and disable busybox hotplug handling)
  66.  
  67. To allow init to continue:
  68. echo "continue" >/init-ctl/stdin
  69.  
  70. EOF
  71. fi
  72.  
  73. if [ "$DONE_SWITCH" = "no" ]; then
  74. cat <<EOF >> /etc/issue.net
  75. In order to work safely with the device's mmc you should
  76. echo "umount_stowaways" >/init-ctl/stdin
  77.  
  78. Then you can mount and modify exported mass storage on host. When done
  79. echo "mount_stowaways" >/init-ctl/stdin
  80.  
  81.  
  82. EOF
  83. fi
  84. }
  85.  
  86. export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
  87.  
  88. # Default setting is rndis - add mass_storage for a debug boot
  89. # enable using usb_setup
  90. USB_FUNCTIONS=rndis
  91.  
  92. ANDROID_USB=/sys/class/android_usb/android0
  93. GADGET_DIR=/config/usb_gadget
  94. LOCAL_IP=192.168.2.15
  95.  
  96. DONE_SWITCH=no
  97. # Are we running in real rootfs
  98. if [ "$0" = "/init-debug" ]; then
  99. DONE_SWITCH=yes
  100. fi
  101.  
  102. # Get options from kernel command line
  103. get_opt() {
  104. for param in $(cat /proc/cmdline); do
  105. echo "$param" | grep "^$1=*" | cut -d'=' -f2
  106. done
  107. }
  108.  
  109. # Minimal mounts for initrd or pre-init debug session
  110. do_mount_devprocsys()
  111. {
  112. echo "########################## mounting devprocsys"
  113. mkdir /dev
  114. mount -t devtmpfs devtmpfs /dev
  115. # telnetd needs /dev/pts/ entries
  116. mkdir /dev/pts
  117. mount -t devpts devpts /dev/pts
  118.  
  119. mkdir /proc
  120. mkdir /sys
  121. mount -t sysfs sysfs /sys
  122. mount -t proc proc /proc
  123.  
  124. mkdir /config
  125. mount -t configfs none /config
  126. }
  127.  
  128. do_hotplug_scan()
  129. {
  130. echo /sbin/mdev > /proc/sys/kernel/hotplug
  131. mdev -s
  132. # There is no way to know when all hotplug events have been processed :(
  133. sleep 2
  134. }
  135.  
  136. bootsplash() {
  137. if [ x$BOOTLOGO = x1 ]; then
  138. zcat /bootsplash.gz > /dev/fb0
  139. fi
  140. }
  141.  
  142.  
  143. mount_stowaways() {
  144. echo "########################## mounting stowaways"
  145. if [ ! -z $DATA_PARTITION ]; then
  146. echo "[initramfs] Activating LVM..."
  147. mkdir /boot
  148. mount -o ro -t ext3 /dev/mmcblk0p13 /boot
  149. LVM_SYSTEM_DIR=/boot/etc/lvm /boot/usr/sbin/lvm.static vgscan
  150. sleep 2
  151. LVM_SYSTEM_DIR=/boot/etc/lvm /boot/usr/sbin/lvm.static vgmknodes
  152. sleep 2
  153. LVM_SYSTEM_DIR=/boot/etc/lvm /boot/usr/sbin/lvm.static vgchange -a y
  154. umount /boot
  155.  
  156. data_subdir="$(get_opt data_subdir)"
  157.  
  158. mkdir /data
  159. mkdir /target
  160.  
  161. mount $DATA_PARTITION /data
  162. ln -s /data/media/0/.stowaways /data
  163. mount --bind /data/${data_subdir}/.stowaways/${DEFAULT_OS} /target
  164. mkdir /target/data # in new fs
  165. mount --bind /data/${data_subdir} /target/data
  166. else
  167. echo "Failed to mount /target, device node '$DATA_PARTITION' not found!" >> /diagnosis.log
  168. fi
  169. mount
  170. }
  171.  
  172. umount_stowaways() {
  173. if [ ! -z $DATA_PARTITION ]; then
  174. umount /target/data
  175. umount /target
  176. umount /data
  177. fi
  178. }
  179.  
  180. # Sugar for accessing usb config
  181. write() {
  182. echo -n "$2" > "$1"
  183. }
  184.  
  185. inject_loop() {
  186. INJ_DIR=/init-ctl
  187. INJ_STDIN=$INJ_DIR/stdin
  188.  
  189. mkdir $INJ_DIR
  190. mkfifo $INJ_STDIN
  191. echo "This entire directory is for debugging init - it can safely be removed" > $INJ_DIR/README
  192.  
  193. echo "########################## Beginning inject loop"
  194. while : ; do
  195. while read IN; do
  196. if [ "$IN" = "continue" ]; then break 2;fi
  197. $IN
  198. done <$INJ_STDIN
  199. done
  200. rm -rf $INJ_DIR # Clean up if we exited nicely
  201. echo "########################## inject loop done"
  202. }
  203.  
  204. # This sets up the USB with whatever USB_FUNCTIONS are set to via configfs
  205. usb_setup_configfs() {
  206. G_USB_ISERIAL=$GADGET_DIR/g1/strings/0x409/serialnumber
  207.  
  208. mkdir $GADGET_DIR/g1
  209. write $GADGET_DIR/g1/idVendor "0x18D1"
  210. write $GADGET_DIR/g1/idProduct "0xD001"
  211. mkdir $GADGET_DIR/g1/strings/0x409
  212. write $GADGET_DIR/g1/strings/0x409/serialnumber "$1"
  213. write $GADGET_DIR/g1/strings/0x409/manufacturer "Mer Boat Loader"
  214. write $GADGET_DIR/g1/strings/0x409/product "$CUSTOMPRODUCT"
  215.  
  216. if echo $USB_FUNCTIONS | grep -q "rndis"; then
  217. mkdir $GADGET_DIR/g1/functions/rndis.usb0
  218. mkdir $GADGET_DIR/g1/functions/rndis_bam.rndis
  219. fi
  220. echo $USB_FUNCTIONS | grep -q "mass_storage" && mkdir $GADGET_DIR/g1/functions/storage.0
  221.  
  222. mkdir $GADGET_DIR/g1/configs/c.1
  223. mkdir $GADGET_DIR/g1/configs/c.1/strings/0x409
  224. write $GADGET_DIR/g1/configs/c.1/strings/0x409/configuration "$USB_FUNCTIONS"
  225.  
  226. if echo $USB_FUNCTIONS | grep -q "rndis"; then
  227. ln -s $GADGET_DIR/g1/functions/rndis.usb0 $GADGET_DIR/g1/configs/c.1
  228. ln -s $GADGET_DIR/g1/functions/rndis_bam.rndis $GADGET_DIR/g1/configs/c.1
  229. fi
  230. echo $USB_FUNCTIONS | grep -q "mass_storage" && ln -s $GADGET_DIR/g1/functions/storage.0 $GADGET_DIR/g1/configs/c.1
  231.  
  232. echo "$(ls /sys/class/udc)" > $GADGET_DIR/g1/UDC
  233. }
  234.  
  235. # This sets up the USB with whatever USB_FUNCTIONS are set to via android_usb
  236. usb_setup_android_usb() {
  237. G_USB_ISERIAL=$ANDROID_USB/iSerial
  238. write $ANDROID_USB/enable 0
  239. write $ANDROID_USB/functions ""
  240. write $ANDROID_USB/enable 1
  241. usleep 500000 # 0.5 delay to attempt to remove rndis function
  242. write $ANDROID_USB/enable 0
  243. write $ANDROID_USB/idVendor 18D1
  244. write $ANDROID_USB/idProduct D001
  245. write $ANDROID_USB/iManufacturer "Mer Boat Loader"
  246. write $ANDROID_USB/iProduct "$CUSTOMPRODUCT"
  247. write $ANDROID_USB/iSerial "$1"
  248. write $ANDROID_USB/functions $USB_FUNCTIONS
  249. write $ANDROID_USB/enable 1
  250. }
  251.  
  252. # This determines which USB setup method is going to be used
  253. usb_setup() {
  254. if [ -d $ANDROID_USB ]; then
  255. usb_setup_android_usb $1
  256. elif [ -d $GADGET_DIR ]; then
  257. usb_setup_configfs $1
  258. fi
  259. }
  260.  
  261. # This lets us communicate errors to host (if it needs disable/enable then that's a problem)
  262. usb_info() {
  263. # make sure USB is settled
  264. echo "########################## usb_info: $1"
  265. sleep 1
  266. write $G_USB_ISERIAL "$1"
  267. }
  268.  
  269.  
  270. run_debug_session() {
  271. CUSTOMPRODUCT=$1
  272. echo "########################## Debug session : $1"
  273. usb_setup "Mer Debug setting up (DONE_SWITCH=$DONE_SWITCH)"
  274.  
  275. USB_IFACE=notfound
  276. /sbin/ifconfig rndis0 $LOCAL_IP && USB_IFACE=rndis0
  277. if [ x$USB_IFACE = xnotfound ]; then
  278. /sbin/ifconfig usb0 $LOCAL_IP && USB_IFACE=usb0
  279. fi
  280. # Report for the logs
  281. /sbin/ifconfig -a
  282.  
  283. # Unable to set up USB interface? Reboot.
  284. if [ x$USB_IFACE = xnotfound ]; then
  285. usb_info "Mer Debug: ERROR: could not setup USB as usb0 or rndis0"
  286. dmesg
  287. sleep 60 # plenty long enough to check usb on host
  288. reboot -f
  289. fi
  290.  
  291. # Create /etc/udhcpd.conf file.
  292. echo "start 192.168.2.20" > /etc/udhcpd.conf
  293. echo "end 192.168.2.90" >> /etc/udhcpd.conf
  294. echo "lease_file /var/udhcpd.leases" >> /etc/udhcpd.conf
  295. echo "interface $USB_IFACE" >> /etc/udhcpd.conf
  296. echo "option subnet 255.255.255.0" >> /etc/udhcpd.conf
  297.  
  298. # Be explicit about busybox so this works in a rootfs too
  299. echo "########################## starting dhcpd"
  300. $EXPLICIT_BUSYBOX udhcpd
  301.  
  302. HALT_BOOT="${2:-y}"
  303. set_welcome_msg $HALT_BOOT
  304.  
  305. if [ -z $DISABLE_TELNET ]; then
  306. # Non-blocking telnetd
  307. echo "########################## starting telnetd"
  308. # We run telnetd on different ports pre/post-switch_root This
  309. # avoids problems with an unterminated pre-switch_root telnetd
  310. # hogging the port
  311. $EXPLICIT_BUSYBOX telnetd -b ${LOCAL_IP}:${TELNET_DEBUG_PORT} -l /bin/sh
  312.  
  313. # For some reason this does not work in rootfs
  314. usb_info "Mer Debug telnet on port $TELNET_DEBUG_PORT on $USB_IFACE $LOCAL_IP - also running udhcpd"
  315. fi
  316.  
  317. if [ "$HALT_BOOT" = "y" ]; then
  318. # Some logging output
  319. ps -wlT
  320. ps -ef
  321. netstat -lnp
  322. cat /proc/mounts
  323. sync
  324.  
  325. # Run command injection loop = can be exited via 'continue'
  326. inject_loop
  327. fi
  328. }
  329.  
  330. # writes to /diagnosis.log if there's a problem
  331. check_kernel_config() {
  332. echo "Checking kernel config"
  333. if [ ! -e /proc/config.gz ]; then
  334. echo "No /proc/config.gz. Enable CONFIG_IKCONFIG and CONFIG_IKCONFIG_PROC" >> /diagnosis.log
  335. else
  336. # Must be =y
  337. for x in CONFIG_CGROUPS CONFIG_AUTOFS4_FS CONFIG_DEVTMPFS_MOUNT CONFIG_DEVTMPFS CONFIG_UNIX CONFIG_INOTIFY_USER CONFIG_SYSVIPC CONFIG_NET CONFIG_PROC_FS CONFIG_SIGNALFD CONFIG_SYSFS CONFIG_TMPFS_POSIX_ACL CONFIG_VT; do
  338. zcat /proc/config.gz | grep -E "^$x=y\$" || echo "$x=y not found in /proc/config.gz" >> /diagnosis.log
  339. done
  340. # Must not be =y
  341. for x in CONFIG_DUMMY CONFIG_SYSFS_DEPRECATED; do
  342. zcat /proc/config.gz | grep -E "^$x=y\$" && echo "$x=y found in /proc/config.gz, must be disabled" >> /diagnosis.log
  343. done
  344. fi
  345. }
  346.  
  347. # Now either initrd or rootfs sequence
  348.  
  349. if [ "$DONE_SWITCH" = "no" ]; then
  350. EXPLICIT_BUSYBOX=""
  351. TELNET_DEBUG_PORT=23
  352. /bin/busybox --install -s
  353. date
  354.  
  355. do_mount_devprocsys
  356.  
  357. do_hotplug_scan
  358.  
  359. # Support /dev/mmcXXX only in initrd phase
  360. ln -s . /dev/block
  361. ln -s /proc/mounts /etc/mtab
  362.  
  363. check_kernel_config
  364.  
  365. bootsplash
  366.  
  367. mount_stowaways
  368.  
  369. # No target debug unless we debug here too (for now)
  370.  
  371. DBG_REASON=""
  372. [ -e /diagnosis.log ] && DBG_REASON="Refusing to boot. See /diagnosis.log (in initrd only)"
  373. [ "$(get_opt bootmode)" = "debug" ] && DBG_REASON="bootmode=debug on kernel command line"
  374. [ x$ALWAYSDEBUG = x1 ] && DBG_REASON="Always debug: rndis + mass_storage"
  375. [ -f /target/init_enter_debug ] && DBG_REASON="/init_enter_debug exists"
  376. [ -f /target/init_disable_telnet ] && DISABLE_TELNET="y"
  377.  
  378. if ! [ "$DBG_REASON" = "" ] ; then
  379. # During debug we export mmc too (some variations in location here)
  380. lun=/sys/class/android_usb/f_mass_storage/lun/file
  381. if [ -f $lun ]; then echo /dev/mmcblk0 > $lun; fi
  382. lun=/sys/class/android_usb/f_mass_storage/lun0/file
  383. if [ -f $lun ]; then echo /dev/mmcblk0 > $lun; fi
  384. USB_FUNCTIONS=rndis,mass_storage
  385.  
  386. run_debug_session $DBG_REASON
  387.  
  388. # Tidy up before we switch_root (rootfs init-debug leaves these running during bootup)
  389. killall telnetd
  390. killall udhcpd
  391.  
  392. USB_FUNCTIONS=rndis
  393. usb_setup "Mer Debug: done debug, disabling storage"
  394. fi
  395.  
  396. # Disable mdev hotplug now - let udev handle it in main boot
  397. echo "" > /proc/sys/kernel/hotplug
  398.  
  399. if [ -f "/target/init-debug" ]; then
  400. exec switch_root /target /init-debug &> /target/init-debug-stderrout
  401. else
  402. # Prefer /sbin/preinit over /sbin/init
  403. [ -x /target/sbin/preinit ] && INIT=/sbin/preinit || INIT=/sbin/init
  404. if [ -x "/target$INIT" ]; then
  405. exec switch_root /target $INIT --log-level=debug --log-target=kmsg &> /target/init-stderrout
  406. fi
  407. fi
  408. run_debug_session "Failed to boot init in real rootfs"
  409.  
  410. else
  411. # We're in the real rootfs running as init-debug
  412. EXPLICIT_BUSYBOX="/bin/busybox-static"
  413. TELNET_DEBUG_PORT=2323
  414.  
  415. do_mount_devprocsys
  416.  
  417. HALT_BOOT="n"
  418. [ -f /init_enter_debug2 ] && HALT_BOOT="y"
  419. [ -f /init_disable_telnet ] && DISABLE_TELNET="y"
  420. run_debug_session "init-debug in real rootfs" $HALT_BOOT
  421.  
  422. # If we don't do this then udev will not be able to create /dev/*
  423. rm /dev/block
  424.  
  425. # Now try to boot the real init
  426. # Prefer /sbin/preinit over /sbin/init
  427. [ -x /sbin/preinit ] && INIT=/sbin/preinit || INIT=/sbin/init
  428. exec $INIT --log-level=debug --log-target=kmsg &> /boot/systemd_stdouterr
  429. run_debug_session "init in real rootfs failed"
  430. fi
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement