分区结构
在img写入后, 会产生两个分区
EMUELEC: 用于启动的文件, 例如dtb文件等, 以及system.img & system.img.md5, EmuELEC的系统文件都在这个img里面
STORAGE: 空
运行中目录结构
- /dev/mmcblk1p1 511.7M 373.6M 138.2M 73% /flash
- /dev/loop0 357.5M 357.5M 0 100% /
- /dev/mmcblk1p2 28.6G 3.5G 25.1G 12% /storage
启动后, EMUELEC分区被挂载为 /flash, STORAGE分区被挂载为 /storage, system.img 通过 /dev/loop0 被挂载为系统根目录 /
所以, 用户能修改的仅仅是 /flash 和 /storage 目录下的内容
root用户的home目录被定位到 /storage, 如果需要添加登录后自动执行的命令(例如添加alias), 可以直接在 /storage 目录下新建 .profile 文件来实现
开机启动顺序
这个是在uboot中进行管理的, 可以通过fw_printenv命令进行查看
- EmuELEC:/usr/sbin # fw_printenv
- ...
- baudrate=115200
- boot_count=0
- bootcmd=if test ${bootfromnand} = 1; then setenv bootfromnand 0; saveenv; else run bootfromsd; run bootfromusb; fi; run storeboot
- bootcount_check=echo bootcounts=${boot_count}; if itest ${boot_count} == 0; then setenv boot_count 1;saveenv;else if itest ${boot_count} == 1; then setenv boot_count 2;saveenv;else if itest ${boot_count} == 2; then setenv boot_count 3;saveenv;else if itest ${boot_count} == 3; then setenv boot_count 4;saveenv;else if itest ${boot_count} == 4; then run recovery_from_flash;fi;fi;fi;fi;fi
- bootdelay=0
- bootfromnand=0
- bootfromsd=mmcinfo; if fatload mmc 0 ${loadaddr} kernel.img; then run sddtb; setenv bootargs ${bootargs} bootfromsd; bootm; fi
- bootfromusb=usb start 0; if fatload usb 0 ${loadaddr} kernel.img; then run usbdtb; setenv bootargs ${bootargs} bootfromusb; bootm; fi
- bootmode_check=get_rebootmode; echo reboot_mode=${reboot_mode};if test ${reboot_mode} = factory_reset; then defenv_reserv;setenv upgrade_step 2; save;fi;
- cmdline_keys=if keyman init 0x1234; then if sec_keyunify read mac ${loadaddr} str; then setenv bootargs ${bootargs} mac=${mac} androidboot.mac=${mac};fi;fi;
- ...
可以看到其中的 bootfromnand 变量是用于控制设备的启动顺序, 如果值为1, 那么从nand(设备内部存储, eMMC等), 如果值为0, 那么依次从sd, 从usb启动, 在这个过程中如果某个介质可以启动了, 就把这个方式加到bootargs变量的值当中去, 例如
- setenv bootargs ${bootargs} bootfromsd;
.然后调用系统函数bootm启动内核. bootm会调用 ./lib_arm/armlinux.c的do_bootm() 方法, 里面会调用./common/cmd_bootm.c的do_bootm_linux()
如果这些都不成功, 那就调用storeboot
- storeboot=if imgread kernel boot ${loadaddr}; then bootm ${loadaddr}; fi;run update;
而update会依次尝试从各个媒介升级
- update=run usb_burning; run sdc_burning; if mmcinfo; then run recovery_from_sdcard;fi;if usb start 0; then run recovery_from_udisk;fi;run recovery_from_flash;
中间还会记录启动次数, 如果启动次数达到4, 就会执行 recovery_from_flash
- recovery_from_flash=setenv bootargs ${bootargs} aml_dt=${aml_dt} recovery_part={recovery_part} recovery_offset={recovery_offset};if imgread kernel ${recovery_part} ${loadaddr} ${recovery_offset}; then wipeisb; bootm ${loadaddr}; fi
ES的Quit菜单中的Reboot From NAND, 实际执行的就是 /usr/sbin/rebootfromnand 这个命令, 里面将 bootfromnand 值设为了1
- EmuELEC:/usr/sbin # more rebootfromnand
- #!/bin/sh
- # SPDX-License-Identifier: GPL-2.0-or-later
- # Copyright (C) 2016-2018 kszaq (kszaquitto@gmail.com)
- # Copyright (C) 2018-present Team CoreELEC (https://coreelec.org)
- if /usr/sbin/fw_printenv whereToBootFrom > /dev/null 2>&1; then /usr/sbin/fw_setenv whereToBootFrom internal; fi
- /usr/sbin/fw_setenv bootfromnand 1
服务启动顺序
系统启动的服务是通过systemd管理的, 启动脚本位于 /usr/lib/systemd/system/ 下, 因为是过loop设备挂载的, 所以这里面的文件都不可修改. 默认的启动target为
- EmuELEC:/usr/lib/systemd/system # systemctl get-default
- emuelec.target
- EmuELEC:/usr/lib/systemd/system # ll def*.*
- lrwxrwxrwx 1 root root 14 Nov 19 00:42 default.target -> emuelec.target
服务依赖关系为
- EmuELEC:/usr/lib/systemd/system # systemctl list-dependencies emuelec.target
- emuelec.target
- ● ├─emuelec-autostart.service
- ● ├─emustation.service
- ● ├─retroarch.service
- ● ├─tmp-assets.mount
- ● ├─tmp-cores.mount
- ● ├─tmp-database.mount
- ● ├─tmp-joypads.mount
- ● ├─tmp-overlays.mount
- ● ├─tmp-shaders.mount
- ● ├─graphical.target
- ● │ ├─unbind-console.service
- ● │ └─multi-user.target
- ● │ ├─avahi-daemon.service
- ● │ ├─connman.service
- ● │ ├─dbus.service
- ● │ ├─entware.service
- ● │ ├─iptables.service
- ● │ ├─nmbd.service
- ● │ ├─pulseaudio.service
- ● │ ├─rpcbind.service
- ● │ ├─sixaxis@multi-user.service
- ● │ ├─smbd.service
- ● │ ├─sshd.service
- ● │ ├─systemd-ask-password-wall.path
- ● │ ├─systemd-logind.service
- ● │ └─basic.target
- ● │ ├─add-entropy.service
- ● │ ├─amlogic-dvb.service
- ● │ ├─fstrim.service
- ● │ ├─hwdb.service
- ● │ ├─kvimfan.service
- ● │ ├─openvfd.service
- ● │ ├─show-version.service
- ● │ ├─swap.service
- ● │ ├─tmp.mount
- ● │ ├─var.mount
- ● │ ├─wetekdvb.service
- ● │ ├─paths.target
- ● │ ├─slices.target
- ● │ │ ├─-.slice
- ● │ │ └─system.slice
- ● │ ├─sockets.target
- ● │ │ ├─dbus.socket
- ● │ │ ├─systemd-initctl.socket
- ● │ │ ├─systemd-journald-audit.socket
- ● │ │ ├─systemd-journald-dev-log.socket
- ● │ │ ├─systemd-journald.socket
- ● │ │ ├─systemd-udevd-control.socket
- ● │ │ └─systemd-udevd-kernel.socket
- ● │ ├─sysinit.target
- ● │ │ ├─debug-shell.service
- ● │ │ ├─debugconfig.service
- ● │ │ ├─dev-hugepages.mount
- ● │ │ ├─dev-mqueue.mount
- ● │ │ ├─kmod-static-nodes.service
- ● │ │ ├─machine-id.service
- ● │ │ ├─openssl-config.service
- ● │ │ ├─sys-fs-fuse-connections.mount
- ● │ │ ├─sys-kernel-config.mount
- ● │ │ ├─sys-kernel-debug.mount
- ● │ │ ├─systemd-ask-password-console.path
- ● │ │ ├─systemd-hwdb-update.service
- ● │ │ ├─systemd-journal-catalog-update.service
- ● │ │ ├─systemd-journal-flush.service
- ● │ │ ├─systemd-journald.service
- ● │ │ ├─systemd-modules-load.service
- ● │ │ ├─systemd-sysctl.service
- ● │ │ ├─systemd-tmpfiles-setup-dev.service
- ● │ │ ├─systemd-tmpfiles-setup.service
- ● │ │ ├─systemd-udev-trigger.service
- ● │ │ ├─systemd-udevd.service
- ● │ │ ├─tz-data.service
- ● │ │ ├─usercache.service
- ● │ │ ├─userconfig.service
- ● │ │ ├─local-fs.target
- ● │ │ │ ├─kernel-overlays.service
- ● │ │ │ ├─libmali.service
- ● │ │ │ ├─tmp.mount
- ● │ │ │ └─var.mount
- ● │ │ └─swap.target
- ● │ └─timers.target
- ● │ └─systemd-tmpfiles-clean.timer
- ● └─multi-user.target
- ● ├─avahi-daemon.service
- ● ├─connman.service
- ● ├─dbus.service
- ● ├─entware.service
- ● ├─iptables.service
- ● ├─nmbd.service
- ● ├─pulseaudio.service
- ● ├─rpcbind.service
- ● ├─sixaxis@multi-user.service
- ● ├─smbd.service
- ● ├─sshd.service
- ● ├─systemd-ask-password-wall.path
- ● ├─systemd-logind.service
- ● └─basic.target
在 emuelec-autostart.service 里, 执行了/storage/.config/autostart.sh
在autostart.sh的结尾, 又执行了 /storage/.config/custom_start.sh