firstboot 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #!/bin/sh
  2. . /etc/functions.sh
  3. partname="rootfs_data"
  4. mtdpart="$(find_mtd_part $partname)"
  5. rom=$(awk '/squashfs/ {print $2}' /proc/mounts)
  6. jffs=$(awk '/jffs2/ {print $2}' /proc/mounts)
  7. dupe() { # <new_root> <old_root>
  8. cd $1
  9. echo -n "creating directories... "
  10. {
  11. cd $2
  12. find . -xdev -type d
  13. echo "./dev ./jffs ./mnt ./proc ./tmp"
  14. # xdev skips mounted directories
  15. cd $1
  16. } | xargs mkdir -p
  17. echo "done"
  18. echo -n "setting up symlinks... "
  19. for file in $(cd $2; find . -xdev -type f;); do
  20. case "$file" in
  21. ./rom/note) ;; #nothing
  22. ./etc/config*|\
  23. ./usr/lib/opkg/info/*) cp -af $2/$file $file;;
  24. *) ln -sf /rom/${file#./*} $file;;
  25. esac
  26. done
  27. for file in $(cd $2; find . -xdev -type l;); do
  28. cp -af $2/${file#./*} $file
  29. done
  30. echo "done"
  31. }
  32. pivot() { # <new_root> <old_root>
  33. mount -o move /proc $1/proc && \
  34. pivot_root $1 $1$2 && {
  35. mount -o move $2/dev /dev
  36. mount -o move $2/tmp /tmp
  37. mount -o move $2/sys /sys 2>&-
  38. mount -o move $2/jffs /jffs 2>&-
  39. return 0
  40. }
  41. }
  42. fopivot() { # <rw_root> <ro_root> <dupe?>
  43. root=$1
  44. {
  45. if grep -q mini_fo /proc/filesystems; then
  46. mount -t mini_fo -o base=/,sto=$1 "mini_fo:$1" /mnt 2>&- && root=/mnt
  47. else
  48. mount --bind / /mnt
  49. mount --bind -o union "$1" /mnt && root=/mnt
  50. fi
  51. } || {
  52. [ "$3" = "1" ] && {
  53. mount | grep "on $1 type" 2>&- 1>&- || mount -o bind $1 $1
  54. dupe $1 $rom
  55. }
  56. }
  57. pivot $root $2
  58. }
  59. ramoverlay() {
  60. mkdir -p /tmp/root
  61. mount -t tmpfs root /tmp/root
  62. fopivot /tmp/root /rom 1
  63. }
  64. # invoked as an executable
  65. [ "${0##*/}" = "firstboot" ] && {
  66. [ -z "$mtdpart" ] && {
  67. echo "MTD partition not found."
  68. exit 1
  69. }
  70. [ -z "$rom" ] && {
  71. echo "You do not have a squashfs partition; aborting"
  72. echo "(firstboot cannot be run on jffs2 based firmwares)"
  73. exit 1
  74. }
  75. [ "$1" = "switch2jffs" ] && {
  76. if grep -q mini_fo /proc/filesystems; then
  77. mount "$mtdpart" /rom/jffs -t jffs2 || exit
  78. # try to avoid fs changing while copying
  79. mount -o remount,ro none / 2>&-
  80. # copy ramoverlay to jffs2
  81. echo -n "copying files ... "
  82. cp -a /tmp/root/* /rom/jffs 2>&-
  83. echo "done"
  84. # switch back to squashfs (temporarily)
  85. # and park the ramdisk ontop of /tmp/root
  86. pivot /rom /mnt
  87. mount -o move /mnt /tmp/root
  88. # /jffs is the overlay
  89. # /rom is the readonly
  90. fopivot /jffs /rom
  91. # try to get rid of /tmp/root
  92. # this will almost always fail
  93. umount /tmp/root 2>&-
  94. else
  95. # switch back to squashfs temporarily
  96. pivot /rom /mnt
  97. # get rid of the old overlay
  98. umount -l /mnt
  99. # another umount to get rid of the bind from /tmp/root
  100. umount -l /mnt
  101. # initialize jffs2
  102. mount "$mtdpart" /jffs -t jffs2 || exit
  103. # workaround to ensure that union can attach properly
  104. sync
  105. ls /jffs >/dev/null
  106. # switch to the new (empty) jffs2
  107. fopivot /jffs /rom 1
  108. # copy ramoverlay to jffs2, must be done after switching
  109. # to the new rootfs to avoid creating opaque directories
  110. echo -n "copying files ... "
  111. cp -a /tmp/root/* / >/dev/null 2>&1
  112. sync
  113. echo "done"
  114. umount -l /jffs
  115. umount -l /tmp/root
  116. fi
  117. exit 0
  118. }
  119. # script run manually
  120. [ \! -z "$jffs" ] && {
  121. echo "firstboot has already been run"
  122. echo "jffs2 partition is mounted, only resetting files"
  123. grep mini_fo /proc/filesystems >&-
  124. [ $? != 0 ] && {
  125. dupe $jffs $rom
  126. exit 0
  127. } || {
  128. rm -rf $jffs/* 2>&-
  129. mount -o remount $jffs / 2>&-
  130. exit 0
  131. }
  132. }
  133. mtd erase "$partname"
  134. mount "$mtdpart" /jffs -t jffs2
  135. fopivot /jffs /rom 1
  136. }