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.
[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:
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
.
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.
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:
[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:
[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.
[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:
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
.
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.
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:
[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:
[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.