Boot Phicomm N1 without emmc_autoscript / s905_autoscriptIt’s recommended to backup your firmware environment variables before changing them.
If fw_printenv
/ fw_setenv
does not work on your device, you might want to checkout this post to fix them.
emmc_autoscript
/ s905_autoscript
is just a script run by start_emmc_autoscript
:
In your case start_emmc_autoscript
is likely using fatload
instead ext4load
as here. I changed the variable to use ext4 /boot
partition before.
12 [root@n1-box ~]# fw_printenv start_emmc_autoscriptstart_emmc_autoscript=if ext4load mmc 1 1020000 emmc_autoscript; then autoscr 1020000; fi;
If you got an error from executing this command, such as ## Error: "start_emmc_autoscript" not defined
, it means that your device is not booting though the variable. You could fix this by:
1 fw_setenv start_autoscript 'if usb start; then run start_usb_autoscript; fi; run start_emmc_autoscript;'
Do not reboot your system now. start_emmc_autoscript
has not been defined yet (see below).
Let’s get back to emmc_autoscript
. The file in my case is:
This chould be different from your case, as I changed it so that kernel image name could by specified in /boot/uEnv.ini
.
123456 setenv env_addr "0x10400000"setenv kernel_addr "0x11000000"setenv initrd_addr "0x13000000"setenv dtb_mem_addr "0x1000000"setenv boot_start booti ${kernel_addr} ${initrd_addr} ${dtb_mem_addr}if ext4load mmc 1 ${env_addr} uEnv.ini; then env import -t ${env_addr} ${filesize}; if ext4load mmc 1 ${kernel_addr} ${kernel_name}; then if ext4load mmc 1 ${initrd_addr} uInitrd; then if ext4load mmc 1 ${dtb_mem_addr} ${dtb_name}; then run boot_start;fi;fi;fi;fi;
It’s possible to bake the entire script into firmware variables, by executing the following commands:
The following commands also 1) change filename of /boot/uEnv.ini
to /boot/boot.ini
, 2) read dtb’s filename from /boot/boot.ini
instead of hardcoding it, 3) and change the variable names of kernel_name
, dtb_name
in /boot/boot.ini
to image
, dtb
, respectively. Feel free to revert these changes back if you want.
Actually I believe that with the help of rewritting start_emmc_autoscript
(to import /boot/boot.ini
using env import
), emmc_autoscript
could be written in /boot/boot.ini
(in a slightly different format, though) in its entirety. However, I don’t see much sense in doing this, they do not change much anyway.
123456 fw_setenv env_addr 0x10400000fw_setenv kernel_addr 0x11000000fw_setenv initrd_addr 0x13000000fw_setenv dtb_mem_addr 0x1000000fw_setenv boot_start 'booti ${kernel_addr} ${initrd_addr} ${dtb_mem_addr}'fw_setenv start_emmc_autoscript 'if ext4load mmc 1 ${env_addr} boot.ini; then env import -t ${env_addr} ${filesize}; if ext4load mmc 1 ${kernel_addr} ${image}; then if ext4load mmc 1 ${initrd_addr} ${initrd}; then if ext4load mmc 1 ${dtb_mem_addr} ${dtb}; then run boot_start;fi;fi;fi;fi;'
… and use /boot/boot.ini
to specify the kernel, initrd, and dtb’s filename:
12345 [root@n1-box ~]# cat /boot/boot.iniimage=vmlinuz-5.0.2initrd=uInitrddtb=meson-gxl-s905d-phicomm-n1.dtbbootargs=root=LABEL=ROOT_EMMC rootflags=data=writeback rw console=ttyAML0,115200n8 console=tty0 no_console_suspend consoleblank=0 fsck.fix=yes fsck.repair=yes net.ifnames=0
/boot/uEnv.ini
, /boot/*_autoscript
could all be removed now.
Now /boot/
should look like this way:
123456 [root@n1-box ~]# find /boot//boot//boot/boot.ini/boot/vmlinuz-5.0.2/boot/meson-gxl-s905d-phicomm-n1.dtb/boot/uInitrd
It’s recommended to backup your firmware environment variables before changing them.
If fw_printenv
/ fw_setenv
does not work on your device, you might want to checkout this post to fix them.
emmc_autoscript
/ s905_autoscript
is just a script run by start_emmc_autoscript
:
In your case start_emmc_autoscript
is likely using fatload
instead ext4load
as here. I changed the variable to use ext4 /boot
partition before.
1 2 | [root@n1-box ~]# fw_printenv start_emmc_autoscript start_emmc_autoscript=if ext4load mmc 1 1020000 emmc_autoscript; then autoscr 1020000; fi; |
If you got an error from executing this command, such as ## Error: "start_emmc_autoscript" not defined
, it means that your device is not booting though the variable. You could fix this by:
1 | fw_setenv start_autoscript 'if usb start; then run start_usb_autoscript; fi; run start_emmc_autoscript;' |
Do not reboot your system now. start_emmc_autoscript
has not been defined yet (see below).
Let’s get back to emmc_autoscript
. The file in my case is:
This chould be different from your case, as I changed it so that kernel image name could by specified in /boot/uEnv.ini
.
1 2 3 4 5 6 | setenv env_addr "0x10400000" setenv kernel_addr "0x11000000" setenv initrd_addr "0x13000000" setenv dtb_mem_addr "0x1000000" setenv boot_start booti ${kernel_addr} ${initrd_addr} ${dtb_mem_addr} if ext4load mmc 1 ${env_addr} uEnv.ini; then env import -t ${env_addr} ${filesize}; if ext4load mmc 1 ${kernel_addr} ${kernel_name}; then if ext4load mmc 1 ${initrd_addr} uInitrd; then if ext4load mmc 1 ${dtb_mem_addr} ${dtb_name}; then run boot_start;fi;fi;fi;fi; |
It’s possible to bake the entire script into firmware variables, by executing the following commands:
The following commands also 1) change filename of /boot/uEnv.ini
to /boot/boot.ini
, 2) read dtb’s filename from /boot/boot.ini
instead of hardcoding it, 3) and change the variable names of kernel_name
, dtb_name
in /boot/boot.ini
to image
, dtb
, respectively. Feel free to revert these changes back if you want.
Actually I believe that with the help of rewritting start_emmc_autoscript
(to import /boot/boot.ini
using env import
), emmc_autoscript
could be written in /boot/boot.ini
(in a slightly different format, though) in its entirety. However, I don’t see much sense in doing this, they do not change much anyway.
1 2 3 4 5 6 | fw_setenv env_addr 0x10400000 fw_setenv kernel_addr 0x11000000 fw_setenv initrd_addr 0x13000000 fw_setenv dtb_mem_addr 0x1000000 fw_setenv boot_start 'booti ${kernel_addr} ${initrd_addr} ${dtb_mem_addr}' fw_setenv start_emmc_autoscript 'if ext4load mmc 1 ${env_addr} boot.ini; then env import -t ${env_addr} ${filesize}; if ext4load mmc 1 ${kernel_addr} ${image}; then if ext4load mmc 1 ${initrd_addr} ${initrd}; then if ext4load mmc 1 ${dtb_mem_addr} ${dtb}; then run boot_start;fi;fi;fi;fi;' |
… and use /boot/boot.ini
to specify the kernel, initrd, and dtb’s filename:
1 2 3 4 5 | [root@n1-box ~]# cat /boot/boot.ini image=vmlinuz-5.0.2 initrd=uInitrd dtb=meson-gxl-s905d-phicomm-n1.dtb bootargs=root=LABEL=ROOT_EMMC rootflags=data=writeback rw console=ttyAML0,115200n8 console=tty0 no_console_suspend consoleblank=0 fsck.fix=yes fsck.repair=yes net.ifnames=0 |
/boot/uEnv.ini
, /boot/*_autoscript
could all be removed now.
Now /boot/
should look like this way:
1 2 3 4 5 6 | [root@n1-box ~]# find /boot/ /boot/ /boot/boot.ini /boot/vmlinuz-5.0.2 /boot/meson-gxl-s905d-phicomm-n1.dtb /boot/uInitrd |
thanks for the idea, i tried to load uboot directly with ext4load from start_emmc_autoscript, but it won’t boot, turns out there is bug in ext4load, but good news is that phicomm uboot has another 2 commands to avoid the bug: icache on ; dcache on
so this is the final, now we can get rid of the scripts on /boot, and i can have single extlinux directory on boot.
start_emmc_autoscript=icache on ; dcache on ; if ext4load mmc 1 0x1000000 uboot; then go 0x1000000; fi;
do the same for start_usb_autoscript
source:
https://github.com/u-boot/u-boot/blob/master/cmd/cache.c
https://github.com/archdemac/Phicomm-N1-info/blob/master/logs/uboot-help.log
after successfully load mainline uboot from ext4 root partition, without the EMMC_AUTOSCRIPT / S905_AUTOSCRIPT. i try to move it further to put uboot in /boot/extlinux/uboot, and instruct start_emmc_autoscript to load uboot from “extlinux/uboot”, here is the result
ext4load extlinux/uboot : failed to boot
fatload extlinux/uboot : ok to boot.
looks like there is another bug for ext4load.
so, give up, now my /boot looks like this:
config-linux-phicomm-n1
dtbs
extlinux
initramfs-linux-phicomm-n1.img
uboot
vmlinuz-linux-phicomm-n1
As far as I can understand it, I see no reason how enabling icache/dcache can address correctness issues.
Sure its beneficial from performance perspective but that is unlikely to cause any difference in functionality.
One thing that crossed my mind it that Cortex-A53 (among others ARM uarchs) does not keep icache coherent with dcache, so one needs to flush icache explicitly for self-modifying-code to run correctly.
Difference between fatload and extload might be caused by different icache footprint, and fatload inadvertently (and “correctly”) evicted cache lines that should be flushed.
Doing an
icache flush
before jumping to newly-loaded code might make a difference.But I no longer have an N1 at hand so all of the above are my speculation and probably wrong, do take them with a grain of salt.
i don’t know which part did not work, but since “….fatload whatever/dir/uboot ; go 0xHEX” ALWAYS work, but ext4load + go always fail. i gave icache, dcache a try, and it happened to be working.
let me try “icache flush” alone. and i’ll come back to you.
icache flush or dcache flush or both does not make a difference.
still can’t load uboot from another dir in ext4 root : ext4load uboot fine, ext4load [/]extlinux/uboot fail.
i don’t have serial connection so i don’t know what actually happened.
That’s unfortunate, but thanks for the feedback!
maybe it is related to how ext4 was formatted? here is the print
sudo tune2fs -l /dev/mmcblk1p1
tune2fs 1.46.5 (30-Dec-2021)
Filesystem volume name:
Last mounted on: /boot
Filesystem UUID: 8632715c-4a22-4427-b9bf-e9c79682f1c2
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal ext_attr resize_inode dir_index filetype needs_recovery extent 64bit flex_bg sparse_super large_file huge_file dir_nlink extra_isize metadata_csum
Filesystem flags: unsigned_directory_hash
Default mount options: user_xattr acl
Filesystem state: clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 32768
Block count: 131072
Reserved block count: 6553
Overhead clusters: 6347
Free blocks: 119674
Free inodes: 32665
First block: 0
Block size: 4096
Fragment size: 4096
Group descriptor size: 64
Reserved GDT blocks: 63
Blocks per group: 32768
Fragments per group: 32768
Inodes per group: 8192
Inode blocks per group: 512
Flex block group size: 16
Filesystem created: Sat Dec 24 08:55:29 2022
Last mount time: Mon Dec 26 14:50:54 2022
Last write time: Mon Dec 26 14:50:54 2022
Mount count: 34
Maximum mount count: -1
Last checked: Sat Dec 24 08:55:29 2022
Check interval: 0 ()
Lifetime writes: 52 MB
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 256
Required extra isize: 32
Desired extra isize: 32
Journal inode: 8
Default directory hash: half_md4
Directory Hash Seed: 3083faf5-67a0-40cf-b488-7b1e3ac868ec
Journal backup: inode blocks
Checksum type: crc32c
Checksum: 0x5f1c9f74
i see your another post, say 64bit has to be turned off? in my case, i did not turn it off. what i did is just mkfs.ext4 /dev/mmcblk1p1/p2
funny enough:
# with emmc_autoscript
start_emmc_autoscript=if ext4load mmc 1 1020000 emmc_autoscript; then autoscr 1020000; fi;
in emmc_autoscript : if ext4load mmc 1 0x1000000 uboot; then go 0x1000000; fi; // work
# without emmc_autoscript
start_emmc_autoscript=if ext4load mmc 1 0x1000000 uboot; then go 0x1000000; fi; // fail, but fatload works.
# without emmc_autoscript, add icache dcache
start_emmc_autoscript=icache on; dcache on ; if ext4load mmc 1 0x1000000 uboot; then go 0x1000000; fi; // work, fatload works too.
# without emmc_autoscript, add icache dcache, use one more level directory
start_emmc_autoscript=icache on; dcache on ; if ext4load mmc 1 0x1000000 extlinux/uboot; then go 0x1000000; fi; // fail, but fatload works.
# without emmc_autoscript, add icache dcache, use one more level directory, add a flush
start_emmc_autoscript=icache on; dcache on ; icache flush ; dcache flush ; if ext4load mmc 1 0x1000000 extlinux/uboot; then go 0x1000000; fi; // fail
I’m not sure if 64bit is still relevant here. I assume it was just a bug of certain versions of UBoot and should have been fixed.