Adding OpenWrt support for ws-ap3825i

I'm not sure of these dumps: the board calls itself P1020RDB, not P1020SKU. I would be interested to see:

  • The copy of Linux in this GPL dump actually booting on the AP3825i
  • A vbindiff of the compiled U-boot with one from the boards themselves.

... but after some thought, I don't think that any of that is the reason for this board not booting. I don't think AP3825i can boot using initramfs for AP3710i; there is probably plenty of setup required for the AP3825i specifically, like having a platform file specific to AP3825i (for AP3710i, it is target/linux/mpc85xx/files/arch/powerpc/platforms/85xx/ws-ap3710i.c).

We should closely copy 16b01fb1b9c99513c318109bef96a1a3545c57a0 in this respect.

Edit: Now that I am essentially finished with the AP370 port, I will turn to the ws-ap3825i. I have only one of these boards, but I will soon order more for testing once I get Linux booting on the first ...

2021-11-27: Addendum: I still have not been able to get the serial console to come up to find what is crashing the board on early boot. However, I looked closely into the standard boot script and have found a possible way to view the content of the kernel ring buffer after a soft reset triggered by the watchdog timer (WDT). The stock U-boot uses the WDT to detect whether the watchdog caused the last reboot; it can do this because neither u-boot nor the BootROM reset the content of RAM upon reboot, and the WDT sets the value of a small patch of memory (through some special-purpose registers) upon reboot.

All I'd need to do is use the System.map (https://support.xilinx.com/s/question/0D52E00006hpihR/linux-kernel-hangs-after-allocatting-dma-contiguous-pool-on-zynq-7000?language=en_US) to find the memory location from which to read the kernel message log.

Here are the details of how the existing boot script works:

:
bootcmd=run boot_flash
boot_flash=source boot_kernel
:

boot_kernel is a script stored in u-boot which sets up the watchdog timer (WDT) and then boots an image from JFFS2; it also describes the mechanism for how it sets up the WDT and checks, upon each boot, whether the last reboot was caused by the WDT.

Some other necessary variables to understand the script:

BOOT_KERNEL=primary
DEFAULT_SETTING=0
LOGHDRRREASON=0xfffec24
MOSTRECENTKERNEL=0
REBOOT_PATTERN_WDG=0x5A5A5A5A
WATCHDOG_COUNT=0x00000001
WATCHDOG_LIMIT=3

And the script itself:

boot_kernel
# U-boot script start
bSaveEnvironment=0
saved_ver=$ver
# The watchdog registers are actually SPR's.
# These are hardcoded in the chenv command as 0xffffffff for TSR and 0xfffffffe for TCR.
# NOTE 1: test command is non-intuitive, for environment variables try to do the -eq check for 0, not 1
#         if the variable is not present, -eq 1 will return true
reg_tsr=0xffffffff
reg_tcr=0xfffffffe
if test $DEFAULT_SETTING -eq 1; then
    bSaveEnvironment=1
    setenv DEFAULT_SETTING 0
    setenv CURR_VER $ver
    echo first time using environment, will save at the end...
# The application has informed us which kernel is more recent in MOSTRECENTKERNEL.
if test $MOSTRECENTKERNEL -eq 0; then
    newer="primary"
    older="secondary"
else
    newer="secondary"
    older="primary"
# This is the default order of images to boot.
if test $USE_ALT_DTB -eq 0; then
    smp_amp="-"
    dtbnum=1
    order="${newer} ${older}"
else
    smp_amp="+"
    dtbnum=2
    order="${newer} ${older} ${older}"
if test $WATCHDOG_LIMIT -ne 0; then
    echo check for watchdog, limit=$WATCHDOG_LIMIT...
    if test $WATCHDOG_COUNT -ge $WATCHDOG_LIMIT; then
        echo watchdog count hit previously, running older image...
        order="${older}"
    else        
        echo check for reset by watchdog...
        rebootReason=$LOGHDRRREASON
        if itest.l *${rebootReason} -eq $REBOOT_PATTERN_WDG; then
            if test ${intWd} -ne 1; then
                echo last reset caused by watchdog...
                chenv WATCHDOG_COUNT + 1
                bSaveEnvironment=1
            fi
            if test $WATCHDOG_COUNT -ge $WATCHDOG_LIMIT; then
                echo watchdog limit reached, cnt=$WATCHDOG_COUNT...
                echo switching to older image...
                order="${older}"
            else
                echo updating watchdog count, cnt=$WATCHDOG_COUNT...
            fi
       else
            echo no watchdog...
       fi
    fi
else
    echo skipping all watchdog checks...
echo bSaveEnviron=${bSaveEnvironment} image_order=${order}
if test ${bSaveEnvironment} -eq 1; then
    saveenv
    saveenv
chenv REBOOT_PATTERN_WDG save.l $LOGHDRRREASON
# Set watchdog to about 1 minute.
# If WATCHDOG_DISABLE is not set, then the test command returns 0.
if test $WATCHDOG_DISABLE -eq 0; then
    setenv TCR 0xA4100000
    chenv TCR save.l ${reg_tcr}
    setenv TSR 0xE0000000
for image in ${order}
    # Kick the watchdog.
    if test $WATCHDOG_DISABLE -eq 0; then
        chenv TSR save.l ${reg_tsr}
    fi
    
    if fsload 0x0A000000 "${image}.gz.uImage"; then
        setenv bootargs "$mtdparts BOOT_BOOTROM=\""${saved_ver}"\"" BOOT_KERNEL=${image} $static_bootargs
        echo ready to boot kernel... [DTB ${dtbnum}]
        # Reset system when watchdog occurs (starts the final countdown).
        if test $WATCHDOG_DISABLE -eq 0; then
            chenv TSR save.l ${reg_tsr}
        fi
        # If this command fails, then the image is corrupt. If it succeeds, then we are running the kernel.
        bootm 0x0A000000 - ${smp_amp}
        echo boot failed...
        # For SMP/AMP images, we trying running with the 2nd DTB, for both the newer then the
        # older image. However, if that doesn't work, then try running the older image again with the
        # 1st DTB.
        if test ${image} = ${older}; then
            smp_amp="-"
            dtbnum=1
        fi
    fi
done
# If we are here, there is a problem with the image(s) we were trying to run.
setenv ZERO 0
chenv ZERO save.l $LOGHDRRREASON
setenv ZERO
echo ERROR: Cannot boot either kernel image, dropping to interactive shell (watchdog might trigger)

So a script to set the WDT and boot might be:

setenv ipaddr 10.0.7.2
setenv serverip 10.0.7.1
tftpboot 0xa000000 openwrt-mpc85xx-p1020-extreme-networks_ws-ap3825i-initramfs-kernel.bin
tftpboot 0x6000000 openwrt-mpc85xx-p1020-extreme-networks_ws-ap3825i-squashfs-fdt.bin;

reg_tsr=0xffffffff
reg_tcr=0xfffffffe

chenv REBOOT_PATTERN_WDG save.l $LOGHDRRREASON
setenv TCR 0xA4100000

chenv TCR save.l ${reg_tcr}
setenv TSR 0xE0000000

chenv TSR save.l ${reg_tsr}
bootm 0xa000000 - 0x6000000

My System.map compiles out __log_buf to 0xc0a88e84. An md to that address crashes u-boot, I realize now because that's virtual memory. Apparently CONFIG_KERNEL_START is usually 0xC0000000 on PowerPC. So I just need to do a md a88e84.

This should all work, but unfortunately md shows there is nothing in any of the buffers, so I'm forced to assume the kernel just never launches ...

Edit: I have managed to capture a couple of lines of an oops. Not sure why these lines are so incomplete, though: https://paste.c-net.org/DaisyDearest

Edit: I disabled SMP and got are more robust output: there's probably something going on where output gets destroyed by SMP being active: https://paste.c-net.org/BauerFlippers

2 Likes