| #!/bin/sh |
| |
| # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| |
| # The kernel mounts /proc, /sys and /dev during initialization, prior |
| # to starting init. |
| |
| # Mount /tmp first, so that bootstat can record output right away. |
| mount -n -t tmpfs -o nodev,noexec,nosuid tmp /tmp |
| bootstat pre-startup |
| # Mount debugfs as crossystem requires chromeos_arm driver interface. |
| mount -n -t debugfs debugfs /sys/kernel/debug |
| |
| IS_FACTORY_MODE= |
| if [ -f /root/.factory_test -o -f /root/.factory_installer ]; then |
| IS_FACTORY_MODE=1 |
| fi |
| |
| # Splash screen! Unless we are in noninteractive mode. |
| # TODO(sosa@chromium.org) - Use kernel flag |
| BOOT_SPLASH_PID= |
| if [ -z "$IS_FACTORY_MODE" ]; then |
| # Moblin trick: Disable blinking cursor. Without this a splash screen |
| # will show a distinct cursor shape even when the cursor is set to none. |
| echo 0 > /sys/devices/virtual/graphics/fbcon/cursor_blink |
| ply-image --gamma /usr/share/color/bin/internal_display.bin \ |
| /usr/share/chromeos-assets/images/boot_splash.png \ |
| /usr/share/chromeos-assets/images/boot_splash_frame*.png & |
| BOOT_SPLASH_PID="$!" |
| fi |
| |
| mkdir -p /dev/shm /dev/pts |
| mount -n -t tmpfs -o nodev,noexec,nosuid shmfs /dev/shm |
| mount -n -t devpts -o noexec,nosuid,gid=5,mode=0620 devpts /dev/pts |
| |
| # Prepare to mount stateful partition |
| ROOT_DEV=$(rootdev -s) |
| ROOTDEV_RET_CODE=$? |
| ROOTDEV_TYPE=${ROOT_DEV%[0-9]*} |
| # Check if we are booted on physical media. rootdev will fail if we are in |
| # an initramfs or tmpfs rootfs (used for x86 factory images). When using |
| # initrd+tftpboot (used for ARM factory images), ROOTDEV_TYPE will be |
| # /dev/ram. |
| if [ "$ROOTDEV_RET_CODE" = "0" -a "$ROOTDEV_TYPE" != "/dev/ram" ]; then |
| # Find our stateful partition. It's always partition 1. |
| STATE_DEV=${ROOTDEV_TYPE}1 |
| |
| # For factory install shim, we never want to write to the SDCard. |
| # In some cases, we boot the factory install shim directly from removable |
| # media like an SDCard. In those cases we don't want to write to that |
| # removable media. |
| if [ -f /root/.factory_installer ]; then |
| mount -n -t tmpfs -o nodev,noexec,nosuid,mode=0755 tmp \ |
| /mnt/stateful_partition |
| # Fetch our writeable lsb-release from the stateful |
| # partition if available. |
| TMP_STATEFUL="$(mktemp -d)" |
| FACTORY_LSB_REL="dev_image/etc/lsb-factory" |
| mkdir -p /mnt/stateful_partition/dev_image/etc |
| mount -n -t ext3 -o nodev,noexec,nosuid,commit=600 \ |
| "$STATE_DEV" "$TMP_STATEFUL" |
| if [ -f "${TMP_STATEFUL}/${FACTORY_LSB_REL}" ]; then |
| cp -a "${TMP_STATEFUL}/${FACTORY_LSB_REL}" \ |
| /mnt/stateful_partition/${FACTORY_LSB_REL} |
| fi |
| umount "$TMP_STATEFUL" |
| rmdir "$TMP_STATEFUL" |
| |
| # For all other cases, mount stateful partition from STATE_DEV. |
| elif ! mount -n -t ext3 -o nodev,noexec,nosuid,commit=600 \ |
| "$STATE_DEV" /mnt/stateful_partition; then |
| # Try to rebuild the stateful partition by clobber-state |
| # (for security concern, we don't use fast mode) |
| [ -z "$BOOT_SPLASH_PID" ] || wait $BOOT_SPLASH_PID |
| chromeos-boot-alert self_repair /dev/tty1 |
| clobber-log --repair "$STATE_DEV" "Self-repair corrupted stateful partition" |
| exec clobber-state "keepimg" |
| fi |
| fi |
| |
| # DEV_MODE is used to determine if we're booted in developer mode, |
| # by checking only the developer and recovery switch states. |
| # Values: 0=recovery/non-dev mode, 1=dev (SSD) mode, 2=bypass devcheck |
| crossystem devsw_boot?1 recoverysw_boot?0 |
| DEV_MODE=$((! $?)) |
| |
| # CROS_DEBUG equals one if we've booted in developer mode or we've booted a |
| # developer image. |
| crossystem cros_debug?1 |
| CROS_DEBUG=$((! $?)) |
| |
| # Check if we need to perform firmware update. |
| FIRMWARE_UPDATE_SCRIPT=/usr/sbin/chromeos-firmwareupdate |
| if [ -x "$FIRMWARE_UPDATE_SCRIPT" ]; then |
| FIRMWARE_UPDATE_LOGS=/mnt/stateful_partition/var/log/update_firmware.log |
| |
| if [ "$(crossystem mainfw_type)" = developer ]; then |
| chromeos-boot-alert dev_fwcheck /dev/tty1 |
| else |
| # fwupdate_tries is not supported in legacy system like CR48, so a cookie |
| # file in stateful partition is used when fwupdate_tries is not available) |
| tries="$(crossystem fwupdate_tries || echo 0)" |
| if [ $tries -gt 0 ]; then |
| tries=$((tries - 1)) |
| crossystem fwupdate_tries=$tries |
| |
| # TODO(arkaitzr): remove references to /root/.dev_mode in this file if |
| # CROS_DEBUG is also being check since CROS_DEBUG==1 for dev images. |
| if [ "$CROS_DEBUG" = "1" -o -f /root/.dev_mode ]; then |
| # More message on console for developer mode and dev builds |
| FIRMWARE_UPDATE_LOGS="/dev/tty1 $FIRMWARE_UPDATE_LOGS" |
| fi |
| # TODO(hungte) don't duplicate the creation of var/log code |
| mkdir -p -m 0755 /mnt/stateful_partition/var/log |
| [ -z "$BOOT_SPLASH_PID" ] || wait $BOOT_SPLASH_PID |
| chromeos-boot-alert update_firmware /dev/tty1 |
| |
| "$FIRMWARE_UPDATE_SCRIPT" --mode=startup 2>&1 | |
| tee $FIRMWARE_UPDATE_LOGS |
| fi |
| fi |
| fi |
| |
| # If we've switched from verified mode to developer mode, clobber the state. |
| # The reverse is not possible to detect reliably, but we try. |
| # In addition, normal and unsupported are treated are equivalent otherwise |
| # booting the first time on a legacy device would clobber state for no reason. |
| # (NOTE, this will not be triggered in recovery mode.) |
| |
| # File used to trigger a stateful reset |
| RESET_FILE="/mnt/stateful_partition/factory_install_reset" |
| |
| # File defined by clobber-state |
| DEV_MODE_FILE="/mnt/stateful_partition/.developer_mode" |
| |
| # If in factory mode or a wipe process is already scheduled, don't change it. |
| if [ -n "$IS_FACTORY_MODE" -o -O "$RESET_FILE" ]; then |
| DEV_MODE=2 |
| fi |
| |
| if [ ${DEV_MODE} -eq 1 ]; then |
| PLATFORM=$(mosys platform name) |
| FW_TYPE=$(crossystem mainfw_type) |
| # Mario always displays the developer mode warning in firmware while |
| # other platforms only display it if the firmware volume is "developer". |
| if [ "${PLATFORM}" != "Mario" -a "${FW_TYPE}" != "developer" ]; then |
| [ -z "$BOOT_SPLASH_PID" ] || wait $BOOT_SPLASH_PID |
| chromeos-boot-alert warn_dev /dev/tty1 |
| fi |
| fi |
| |
| # Transition to devmode |
| if [ ${DEV_MODE} -eq 1 -a ! -O ${DEV_MODE_FILE} ]; then |
| # Delay the first developer mode boot by 5 minutes unless the images is a |
| # developer image. We check the dev image here to avoid a stat(2) on normal |
| # boots |
| # TODO(wad) just have the dev_mode build stamp the stateful. |
| if [ ! -f /root/.dev_mode ]; then |
| # TODO(wad) Throw up a splash. |
| [ -z "$BOOT_SPLASH_PID" ] || wait $BOOT_SPLASH_PID |
| chromeos-boot-alert enter_dev /dev/tty1 |
| # TODO(wad,wfrichar) Have user input sudo/vt2 password here. |
| echo "keepimg" > ${RESET_FILE} |
| clobber-log -- "Enter developer mode" |
| fi |
| |
| # Transition from devmode |
| elif [ ${DEV_MODE} -eq 0 -a -O ${DEV_MODE_FILE} ]; then |
| # When coming back from developer mode, we don't need to clobber |
| # as aggressively. Fast will do the trick. |
| if [ ! -f /root/.dev_mode ]; then |
| [ -z "$BOOT_SPLASH_PID" ] || wait $BOOT_SPLASH_PID |
| chromeos-boot-alert leave_dev /dev/tty1 |
| echo "fast keepimg" > ${RESET_FILE} |
| clobber-log -- "Leave developer mode" |
| fi |
| fi |
| |
| # Check if we have an update to stateful pending. |
| # Note: THIS MUST BE DONE BEFORE CLOBBER STATE. |
| VAR_NEW="/mnt/stateful_partition/var_new" |
| DEVELOPER_NEW="/mnt/stateful_partition/dev_image_new" |
| STATEFUL_UPDATE="/mnt/stateful_partition/.update_available" |
| if [ -f "$STATEFUL_UPDATE" ] ; then |
| STATEFUL_UPDATE_ARGS=$(cat "$STATEFUL_UPDATE") |
| # Remove old state in case this process got interrupted by a reset, this is |
| # usually a no-op. |
| rm -rf /mnt/stateful_partition/dev_image_old \ |
| /mnt/stateful_partition/var_old |
| # The moves can fail if they were previously interrupted mid-op. |
| mv /mnt/stateful_partition/dev_image \ |
| /mnt/stateful_partition/dev_image_old || true |
| mv /mnt/stateful_partition/var /mnt/stateful_partition/var_old || true |
| mv "$DEVELOPER_NEW" /mnt/stateful_partition/dev_image || true |
| mv "$VAR_NEW" /mnt/stateful_partition/var || true |
| # Check for clobber. |
| if [ "$STATEFUL_UPDATE_ARGS" = "clobber" ]; then |
| # Removes all dirs except the new dev_image and var. |
| find /mnt/stateful_partition -mindepth 1 -maxdepth 1 | |
| grep -v -e dev_image\$ -e var\$ | |
| xargs -d "\n" rm -rf |
| # Let's really be done before coming back. |
| sync |
| else |
| # Backgrounded to take off boot path. |
| rm -rf "$STATEFUL_UPDATE" \ |
| /mnt/stateful_partition/dev_image_old \ |
| /mnt/stateful_partition/var_old & |
| fi |
| fi |
| |
| # Check if the stateful partition has requested self-destruction |
| # This is used for the factory install process |
| if [ -O "$RESET_FILE" ]; then |
| [ -z "$BOOT_SPLASH_PID" ] || wait $BOOT_SPLASH_PID |
| chromeos-boot-alert wipe /dev/tty1 \ |
| /mnt/stateful_partition/wipe_splash.png |
| ARGS="$(cat ${RESET_FILE})" |
| exec clobber-state "$ARGS" |
| fi |
| |
| # Make sure stateful partition has some basic directories |
| mkdir -p -m 0755 /mnt/stateful_partition/etc |
| mkdir -p -m 0755 /mnt/stateful_partition/home |
| mkdir -p -m 0755 /mnt/stateful_partition/home/chronos |
| mkdir -p -m 0755 /mnt/stateful_partition/var |
| mkdir -p -m 0755 /mnt/stateful_partition/var/cache |
| mkdir -p -m 0755 /mnt/stateful_partition/var/db |
| mkdir -p -m 0755 /mnt/stateful_partition/var/empty |
| mkdir -p -m 0755 /mnt/stateful_partition/var/lib |
| mkdir -p -m 0755 /mnt/stateful_partition/var/lib/ureadahead |
| mkdir -p -m 0755 /mnt/stateful_partition/var/lock |
| mkdir -p -m 0755 /mnt/stateful_partition/var/log |
| mkdir -p -m 0755 /mnt/stateful_partition/var/log/metrics |
| mkdir -p -m 0755 /mnt/stateful_partition/var/log/window_manager |
| mkdir -p -m 0755 /mnt/stateful_partition/var/run |
| mkdir -p -m 1777 /mnt/stateful_partition/var/tmp |
| |
| # Selected directories must belong to the chronos user. |
| chown chronos:chronos /mnt/stateful_partition/home/chronos |
| chown chronos:chronos /mnt/stateful_partition/var/log/metrics |
| chown chronos:chronos /mnt/stateful_partition/var/log/window_manager |
| |
| # Mount some /var directories and /home. These mounts inherit |
| # nodev,noexec,nosuid from /mnt/stateful_partition above. |
| mount -n --bind /mnt/stateful_partition/var /var |
| mount -n --bind /mnt/stateful_partition/home /home |
| # If we're mod_for_test, both /home and /tmp need to be mounted without noexec |
| #mod_for_test#mount -n -o remount,exec,suid /home |
| #mod_for_test#mount -n -o remount,exec,suid /tmp |
| |
| # Mount stateful partition for dev packages |
| # TODO(arkaitzr@chromium.org) - Only use CROS_DEBUG when cros_debug is |
| # correctly set in a test VM after updating itself to itself (that is, it does |
| # not fail cros_au_test_harness). |
| if [ "$CROS_DEBUG" = "1" -o -f /root/.dev_mode ]; then |
| # Create dev_image directory in base images in developer mode. |
| if [ ! -d /mnt/stateful_partition/dev_image ]; then |
| mkdir -p -m 0755 /mnt/stateful_partition/dev_image |
| fi |
| # Mount and then remount to enable exec/suid |
| mount -n --bind /mnt/stateful_partition/dev_image /usr/local |
| mount -n -o remount,exec,suid /usr/local |
| fi |
| |
| mount -n -t tmpfs -o mode=0755,nodev,noexec,nosuid varrun /var/run |
| touch /var/run/.ramfs # TODO: Is this needed? |
| mount -n -t tmpfs -o mode=1777,nodev,noexec,nosuid varlock /var/lock |
| touch /var/lock/.ramfs # TODO: Is this needed? |
| mount -n -t tmpfs -o nodev,noexec,nosuid media /media |
| |
| # Enable crash reporting for all future exec'd processes, even those that have |
| # gone through setuid. |
| echo 2 > /proc/sys/fs/suid_dumpable |
| |
| # NOTE: ensure that a rootdev has been found. |
| if [ "$ROOTDEV_RET_CODE" = "0" ] ; then |
| if [ ! -e /home/chronos/.oobe_completed ]; then |
| # This script dumps VPD RO/RW data into /var/log/vpd_2.0.txt. |
| # So that OOBE process can read the default locale setting from VPD. |
| if [ -x /usr/sbin/dump_vpd_log ]; then |
| /usr/sbin/dump_vpd_log |
| fi |
| # End of OOBE block |
| |
| # TODO(yjlou): We are developing a more generic hook mechanism (i.e. |
| # pre-OOBE-oem.sh), and will move this block to new hook point. |
| # |
| # The activate_date script is installed in partner's board- |
| # specific private overlay. Hence the vpd utility dependency |
| # is described in private overlay, instead of chromeos-init. |
| # |
| # If the activate date script is executable (installed from the private |
| # overlay), run it. |
| if [ -x /usr/sbin/activate_date ]; then |
| # Since this script will invoke flash read/write (around 20 secs), |
| # run it in background. |
| (/usr/sbin/activate_date ; /usr/sbin/dump_vpd_log --force) & |
| fi |
| # End of activate_date block |
| |
| # Dump machine info from mosys |
| mosys -k smbios info system > /tmp/machine-info |
| fi |
| fi |
| |
| # Check if we need to run post install tasks. The tasks should be safe |
| # to be run more than once, as we'll rerun the tasks in case the device |
| # shuts down before completing the tasks, though it's unlikely to happen. |
| INSTALL_COMPLETED=/mnt/stateful_partition/.install_completed |
| if [ -f "${INSTALL_COMPLETED}" ]; then |
| # Remove XKB cache files, as the files may be incompatible after upgrade. |
| # TODO(wad,satorux) move this to ui.conf. |
| rm -f /var/lib/xkb/*.xkm |
| |
| # This has to be done at the end of the block. |
| rm -f "${INSTALL_COMPLETED}" |
| fi |
| |
| # |
| # Note that ureadahead depends on some of the operations above. |
| # Notably, the command requires /var to be mounted, because the pack |
| # file is located in /var/lib/ureadahead, and ureadahead tracing |
| # requires /sys/kernel/debug be mounted. |
| # |
| ureadahead & |
| |
| # Some things freak out if no hostname is set. |
| hostname localhost |
| |
| bootstat post-startup |
| |
| # Always return success to avoid killing init |
| exit 0 |