2014年10月12日 星期日

{Banana Pi][U-Boot][Sunxi] Error: Can't overwrite "ethaddr" in Every Boot


===murmur begin===

If Banana Pi wants to compete with Raspberry Pi, it definetely needs more harder work to improve quality of DVK.
===murmur end===

You may found that there is an annoyed problem after you "save env" to store environment variables to u-boot, instead of using defaults. Everytime you boot Banana pi, you will find error message of error of overwrittng ethaddr.

U-Boot 2014.04-10694-g2ae8b32-dirty (Oct 01 2014 - 16:23:27) Allwinner Technology

CPU:   Allwinner A20 (SUN7I)
Board: Bananapi
I2C:   ready
DRAM:  1 GiB
MMC:   SUNXI SD/MMC: 0
In:    serial
Out:   serial
Err:   serial
## Error: Can't overwrite "ethaddr"
## Error inserting "ethaddr" variable, errno=1
Net:   dwmac.1c50000
Hit any key to stop autoboot:  0
This is caused by the last commit of board/sunxi/board.c to "Fix the problem that the mac address under u-boot can not change on d…", enclosed by "CONFIG_BANANAPI". With this patch, ethaddr will be set during every system boot up, regardless ethaddr exist or not.

To fix it, you may either comment out the block of this change, or simply adding a if-statement to ensure the ethaddr setting is only performed if it cannot be found in nvram. (though I think it would be always true since it is checked in the beginning of this function)

else {
    unsigned char *p;
    p = getenv("ethaddr");
    uint32_t reg_val = readl(SUNXI_SID_BASE);

    if ((p == NULL) && reg_val) {
        uint8_t mac_addr[6];
        int i;

        mac_addr[0] = 0x02; /* Non OUI / registered MAC address */
        mac_addr[1] = (reg_val >> 0) & 0xff;
        reg_val = readl(SUNXI_SID_BASE + 0x0c);
        mac_addr[2] = (reg_val >> 24) & 0xff;
        mac_addr[3] = (reg_val >> 16) & 0xff;
        mac_addr[4] = (reg_val >> 8) & 0xff;
        mac_addr[5] = (reg_val >> 0) & 0xff;

        for(i = 0; i < 6; i ++)
        {
                if(mac_addr[i] != *(p + i)){
                eth_setenv_enetaddr("ethaddr", mac_addr);
                break;
        }
    }

}










2014年10月3日 星期五

{Banana Pi][Sunxi] U-boot Environment Variables and Something more...

===murmur begin===
not now ===murmur end===

Increase console I/O buffer size

(U-Boot 2014.04-10694)
In order to modify default environment variable, specifically 'loadkernel', I found that it's impossible to change the variable by 'env set' since the console cannot accept command line more than 256(?) characters.

console I/O buffer size is defined by CONFIG_SYS_CBSIZE at include/configs/sunxi-common.h

the changes are like:
#if 0 /* RR, increase console buffer size */
#define CONFIG_SYS_CBSIZE    256    /* Console I/O Buffer Size */
#define CONFIG_SYS_PBSIZE    384    /* Print Buffer Size */
#else

#define CONFIG_SYS_CBSIZE    512    /* Console I/O Buffer Size */
#define CONFIG_SYS_PBSIZE    (CONFIG_SYS_CBSIZE + 128)    /* Print Buffer Size */
#endif
Note: CONFIG_SYS_PBSIZE has better to be calculated by CONFIG_SYS_CBSIZE plus CONFIG_SYS_PROMPT and some bonus value, like 16 in this case.

Reset to default environment variables


to reset environment variables to default:
env default -f -a

 to modify default environment variables/parameters:


starts at ${uboot_dir}/include/env_default.h and
${uboot_dir}/include/configs/sunxi-common.h

look for CONFIG_EXTRA_ENV_SETTINGS.


Concise environment variables


default environment parameters are something like:
autoboot=run loadkernel && run setargs && true && bootm 0x48000000
baudrate=115200
boot_ram=saved_stdout=$stdout;setenv stdout nc;if iminfo 0x41000000; then true; setenv stdout $saved_stdout; source 0x41000000;else setenv stdout $saved_stdout;fi
bootcmd=if run loadbootenv; then echo Loaded environment from ${bootenv};env import -t ${scriptaddr} ${filesize};fi;if test -n "${uenvcmd}"; then echo Running uenvcmd ...;run uenvcmd;fi;if run loadbootscr; then echo Jumping to ${bootscr};source ${scriptaddr};fi;run autoboot;
bootdelay=2
bootenv=uEnv.txt
bootm_size=0x10000000
bootscr=boot.scr
console=ttyS0,115200
device=mmc
ethact=dwmac.1c50000
kernel=uImage
loadbootenv=fatload $device $partition $scriptaddr ${bootenv} || ext2load $device $partition $scriptaddr boot/${bootenv} || ext2load $device $partition $scriptaddr ${bootenv}
loadbootscr=fatload $device $partition $scriptaddr ${bootscr} || ext2load $device $partition $scriptaddr boot/${bootscr} ||ext2load $device $partition $scriptaddr ${bootscr}
loadkernel=if bootpath=/boot/ && ext2load $device $partition 0x43000000 ${bootpath}${script} && ext2load $device $partition 0x48000000 ${bootpath}${kernel};then true; elif bootpath=/ && fatload $device $partition 0x43000000 ${script} && fatload $device $partition 0x48000000 ${kernel};then true; elif bootpath=/ && ext2load $device $partition 0x43000000 ${bootpath}${script} && ext2load $device $partition 0x48000000 ${bootpath}${kernel};then true; else false;fi
loglevel=8
panicarg=panic=10
partition=0:1
script=script.bin
scriptaddr=0x44000000
setargs=if test -z \\"$root\\"; then if test \\"$bootpath\\" = "/boot/"; then root="/dev/mmcblk0p1 rootwait"; else root="/dev/mmcblk0p2 rootwait"; fi; fi; setenv bootargs console=${console} root=${root} loglevel=${loglevel} ${panicarg} ${extraargs}
stderr=serial
stdin=serial
stdout=serial
abviously, those are too much for studying. If using the image placed from lemark (pretty strange since I cannot find the link in www.bananapi.org), i.e. with files of script.bin, uEnv.txt, and uImage at 1st partition of SD card, you can use the simple version of environment settings as below:

baudrate=115200
bootcmd=if run loadbootenv; then echo Loaded environment from ${bootenv};env import -t ${scriptaddr} ${filesize};fi;if test -n "${uenvcmd}"; then echo Running uenvcmd ...;run uenvcmd;fi
bootdelay=2
bootenv=uEnv.txt
bootscr=boot.scr
console=ttys0,115200
device=mmc
ethact=dwmac.1c50000
ethaddr=02:8b:03:01:93:3e
filesize=158
kernel=uimage
loadbootenv=fatload $device $partition $scriptaddr ${bootenv} || ext2load $device $partition $scriptaddr boot/${bootenv} || ext2load $device $partition $scriptaddr ${bootenv}
loglevel=8
panicarg=panic=10
partition=0:1
script=script.bin
scriptaddr=0x44000000
stderr=serial
stdin=serial
stdout=serial
while the content of uEnv.txt is
aload_script=fatload $device $partition 0x43000000 /script.bin;
aload_kernel=fatload $device $partition 0x48000000 /uImage;bootm 0x48000000
uenvcmd=run aload_script aload_kernel
bootargs=console=ttyS0,115200 console=tty0 disp.screen0_output_mode=EDID:1280x720p60 hdmi.audio=EDID:0 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
Note that uEnv.txt is loaded to 0x44000000, script is loaded to 0x43000000, uImage is loaded to 0x48000000, as u-boot itself is running at 0x4a000000 base (see include/configs/sunxi-common.h)

TBD: need to trace FEL to u-boot procedure? seems FEL using cache as TEXT.



2014年9月17日 星期三

[Banana Pi] [A20] Boot Process

===murmur begin===
    As a firmware engineer, I am interested in checking boot process in the beginning of development. The time spent will usually get times of reward soon, mostly during board bring up.

    However, Allwinner provides few documentation (in public), all I can find are

- A20 User Manual 2013-03-22
- A20 Product Brief
- A20 Datasheet

    All of them don't describe boot procedure clearly. poor Allwinner!

====murmur end===

    A20 User's manual says "After power on, the system will try to boot from SDC0, NAND, SDC2, SPI0, and USB, respectively. In Banana Pi, there is no NAND and the default boot device is SD0.
    According to BROM, linux-sunxi-org, the boot sequence of A20 (probably A10, A13, A31 as well) is as follows:

    BROM(FEL, 0xffff0000) -> BROM(0xffff4000, magic eGON.BRM at 0xffff4004) -> boot0 -> boot1 -> uboot


Note that according to here,

linux-sunxi u-boot is fully SPL enabled which means it supports booting directly on the bare metal with no help from the Allwinner bootloaders. U-Boot SPL fully replaces Allwinner boot0 & boot1.

[BROM]

    BROM in A20 is at the address 0xFFFF0000, After power up, arm core will fetch the first instruction at 0xFFFF0000 and execute it. The BROM is actually split up into two parts. FEL mode and eGON.BRM. FEL mode is at the start, at 0xffff0000 followed by eGON.BRM at 0xffff4000.

    At 0xffff0000 is the reset vector which jumps to 0xffff0028. There it loads 0xffff4000 into the program counter to be executed next.

    The extraction of BROM and diassemble can be found at github.

 [SD]

      Load 4k data from sdcard slot 0 beginning at offset 8k to the internal sram, check if the data has a magic string(eGON.BT0), if so, it's a boot0 head. Get boot0 size from the boot0 head, and load the whole boot0. If the checksum of boot0 is ok, will jump to boot0. Any of above is wrong, will jump to FEL.




SD Card Layout


start size usage
0 8KB Unused, available for partition table etc.
8 24KB Initial SPL loader
32 512KB u-boot
544 128KB environment
672 352KB reserved
1024 - Free for partitions

[TBD]
1. screenshot of memdump of boot codes 
2. details of files output for boot0 and u-boot

[Reference]
- BROM, linux-sunxi-org
- Bootable SD card, linux-sunxi-org
- Allwinner Bootloader
- 全志A1X启动步骤