Early boot

From OLPC
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
  This page is monitored by the OLPC team.


Pencil.png NOTE: The contents of this page are not set in stone, and are subject to change!

This page is a draft in active flux ...
Please leave suggestions on the talk page.

Pencil.png

Draft of early boot upgrade/init procedures designed by Michael Stone and C. Scott Ananian.

Early userland startup steps

Stage 1: Initramfs

See the source code for more details. Instructions are available for building initramfsen.

  1. Control is passed to the initramfs' /init program.
    • This program runs python2.5 as PID 1.
  2. /init executes the Theft deterrence protocol, checking its 'am I stolen?' flag and looking for a validFirmware Key and Signature Formats#Antitheft/Activation Lease activation lease.
  3. If successful, /init will fork and hand over control to user-land.

...(sometime later, or immediately if already activated)

Stage 2: NAND

  1. callback (as pid NNN)
  2. mount /sysroot, unmount usb/sd
  3. copy /security/lease to /sysroot/security/lease if first boot (activation)
  4. parse chosen/bootpath, swing /versions/current
  5. make minimal userland context (mount --move /sysroot /)
  6. ideally protect PID 1, RTC <- vserver delta time

Stage 3: Userland

Perhaps, we're booting a custom userland. In that case, /sbin/olpc_init.py will contain something like:

|def run():  
|    os.exec('/sbin/init')

and will be imported and run by PID 1.

Perhaps we're booting from a backup OS. Assuming that we've only got one partition to deal with:

  1. make new config w/ swapped current and alt
    • (ie. create a /versions/configs/XXX w/ new current, alt)
  2. then swing /versions/boot symlink

If multiple partitions are present:

  1. Make boot:/boot/alt/alt point to ../`basename(readlink boot:/boot)`
  2. Make boot:/boot point to boot-versions/`basename(readlinke boot:/boot/alt)`

In either case:

  1. Make the /versions/running symlink point to pristine/<hash>
  2. Set $current equal to the basename of readlink of /versions/running (which should be a hash)
  3. mount /home /versions/run/$current/home (or /home from home partition)
  4. mount /security /versions/run/$current/security (or /security from boot partition)
  5. mount /versions /versions/run/$current/versions
  6. chroot /versions/run/$current (mount --move ?)

Finally, as suggested above:

if exists '/sbin/olpc_init.py':
  sys.path = ['/sbin'] + sys.path
  from olpc_init import run
  run(<parameters?>)
else:
  exec '/sbin/init --init'

Notes on P_SF_RUN

P_SF_RUN:
 off = allow mod = run from /versions/run/X
 on  = pristine  = run from /versions/run/X

switch on->off: set the unlink flags on /versions/run
      off->on:  create immutably-tagged /versions/run/a,b from /versions/a,b

List of directories in boot partition

 /boot -> boot-versions/<hash>
 /boot-alt -> boot/alt
 /boot-versions/<version>/{runos.zip,runrd.zip,etc}
 /boot-versions/<version>/alt -> ../<alternate version>
 /security

List of directories in root partition

 /sys, /proc, /ofw   vfs
 /versions/pristine/{hashes}
 /versions/contents/{hashes}  (contents files for the corresponding pristine tree)
 /versions/configs/`mkdtemp`/current -> ../../pristine/<hash> (backwards compatibility; don't use)
 /versions/configs/`mkdtemp`/alt     -> ../../pristine/<hash> (backwards compatibility; don't use)
 /versions/boot -> configs/<something> (backwards compatibility; don't use)
 /versions/running -> pristine/<hash>  (version we booted from; hash matches /boot symlink from boot partition)
 /versions/updates/<hash>   (temporary space for updates, preserved in case update
                             net connection drops & updater is restarted)
 /versions/run/{hashes}
 /security
 /boot -> versions/boot/current/boot (backwards compatibility; don't use)
 /boot-alt -> versions/boot/alt/boot (backwards compatibility; don't use)

List of directories in home partition

 /home

Upgrade procedure

Upgrade procedure, creating new b from a (w.l.o.g)
 Rainbow: (ATC gives <version> <hash> <priority>)
 -1: Check that /versions/pristine/<hash> doesn't already exist.
  If unpartitioned:
   0. Create new /versions/configs/$c <- where $c = mkdtemp
   1. Create /versions/configs/$c/current -> ../../pristine/`basename(readlink /versions/running)`
   2. Swap /versions/boot to point to configs/$c, save old contents in $old
  If partitioned:
   0-2. Make /boot/alt point to ../`basename(readlink /versions/running)`
  3a. Delete the tree(s) pointed to from /versions/configs/$old which are not pointed to by
     /versions/running (revisit when multiple trees)
  3b. Delete corresponding members of /boot-versions if using a boot partition
  4. Delete /versions/configs/$old.
  4b. Delete corresponding member of /boot-versions if using a boot partition.
  5. Invoke 'olpc-updater <version>'
     in new container:
[MICHAEL WILL REWRITE STARTING FROM HERE]
  NOTE THAT /upgrade must live in same bind-mount as /current if we're to be able to clone it.
  MORE LIKELY THAT RAINBOW WILL CREATE /upgrade FOR US AS CLONE OF /current
           /current (ro-bind mount from /versions/a)
           /upgrade (initially empty)
 OLPC updater:
  6. clone /current to /upgrade
  7. upgrade /upgrade by hook or crook
[END MICHAEL REWRITES]
  8. exit
 Rainbow:
  9. Verify /versions/updates/<hash> matches <hash>
 10. Move /versions/updates/<hash> to /versions/pristine/<hash>
 10b. Create /versions/run/<hash> from /versions/pristine/<hash> according to P_SF_RUN setting
 If unpartitioned:
  11. Make a new config /versions/configs/$d (d = mkdtemp)
  12. Create 'current' symlink to /versions/pristine/<hash>
  13. Create 'alt' symlink to *realpath of* /versions/running
  14. Swing /versions/boot to /versions/configs/$d
       (atomic!  iff we do file move of new symlink)
  15. Delete /versions/configs/$c
 If partitioned:
  11. Copy /versions/pristine/<hash>/boot to boot:/boot-versions/<hash>
  12. Make boot:/boot-versions/<hash>/alt point to what boot:/boot currently points to
  13. Atomically swing boot:/boot to point to /boot-versions/<hash>
 16. If <priority> reboot. (Ask Eben & sugar folks)

Open Questions

  1. Are thawed trees persistent?
    1. when I use a frozen tree?
    2. when I upgrade
  2. Is "thawness" global? Or per-OS-version?
  3. Can thawed trees be frozen for temporary read-only use?
  4. Space limits for upgrader?
  5. UI for:
    1. P_SF_RUN
    2. which image you boot (esp if more than two)
    3. Rest of security UI
  6. Configuration versioning / globalness
    1. do security settings persist across updates
    2. do we inherit a security configuration from the 'old' version when upgrading?
  7. Loadable kernel modules
    1. Bind-mount /lib/modules read-only? (Doesn't fix the problem, really)

Related pages