MCU-PLUS-SDK-AM243X: Flash Protocol Changes

Part Number: MCU-PLUS-SDK-AM243X
Other Parts Discussed in Thread: SYSCONFIG

Tool/software:

Hello,

This is a follow-up question to the final comment in another thread: 1S-1S-4S Protocol Not Working

In it, Daniel mentioned: "We have actually observed similar behavior in the past and we are currently investigating to resolve this problem."  While the original post was about 4S mode, the solution suggested by Daniel was initially created for 8D mode. 

1. I'm interested to know if TI has since observed issues with protocol switching after ROM boot for QSPI devices as well.

2. Is TI's solution to the 8D problem flashFixUpOspiBoot() and should that function be modified for QSPI protocol?

3. Is there another resolution?

Thank you,

Joe

  • Hello Joe,

    Thank you for your question.

    Meanwhile I figure out if 

    flashFixUpOspiBoot()

    is the fix to the problem raised in the linked thread, can you please let me know the flash part you are using.

    Can you also send the SysConfig file for the flash configuration?

    I would also request you to go through: https://www.ti.com/lit/po/sprt764a/sprt764a.pdf?ts=1719384725116&ref_url=https%253A%252F%252Fe2e.ti.com%252F

    Looking forward to your response.

    Regards,

    Vaibhav

  • Hi Vaibhav,

    To give you a little more background, we are booting successfully with Infineon S25HS01GTDPBHI030
    in 4S-4D-4D mode.  Because we are using Tap mode we have restrictions on clock rate, divider, and tap delay that allow us to meet setup and hold.  It turns out that we can get higher throughput in 4S-4S-4S mode.  We've observed that the bootloader fails authentication when we change SysConfig for the 4S-4S-4S protocol.  The changes were limited to Protocol, clock divider, ReadCMD, Mode Clocks (Read).

    Thanks,

    Joe

  • Hello Joe,

    flashFixUpOspiBoot() is the fix for only octal spi.

    For QSPI the fix has not yet been integrated into the SDK.

    Regards,

    Vaibhav

  • Hi Vaibhav,

    Are you able to elaborate on the problem observed with QSPI or the proposed fix?

    Thank you,

    Joe

  • Greetings Joe,

    So, currently we do not have a fix coming for QSPI in the upcoming SDK release.

    But I will convey this information to the dev team in order to incorporate not only for OSPI but for QSPI as well.

    Regards,

    Vaibhav

  • Greetings Joe,

    The fix for QSPI has been accepted for MCU PLUS SDK release 10.01.00.

    Closing this thread. Please respond for further queries or create a new one.

    Regards,

    Vaibhav

  • Thank you, Vaibhav

  • Greetings Joe,

    Some open questions as received over mail are as follows. 

    1. What is the root of the problem we are observing in protocol switching?  Does TI have a problem description?
    2. Does the software workaround exist that we can implement ahead of October?

    I am going to respond to these here and on the mail as well.

    For the first question,

    ROM doesn't reset the OSPI flash. This can make the flash initialization troublesome because sequences are very different in Octal DDR mode. So for a moment switch OSPI controller to 8D mode and do a flash reset.

    In short when the ROM passes control to SBL, SBL needs to do a fresh initialization of the flash. So the main goal is to reset the flash.

    For the second question,

    Currently no SW workaround exists.

    A recent update from development team, they have started to test the code changes, I will update you with the progress on or before 16/7/2024.

    A follow up question from my end:

    Is there a reset line in the flash part?

    Looking forward to your response.

    Regards,

    Vaibhav

  • Hello Vaibhav,

    Thank you.  Yes, we have attempted to duplicate the QSPI setup in the AM243 LP EVM, using a spare CS line as a reset:

  • Hello Joe,

    If you happen to have a reset line from the flash part, you can do a toggle on that line to reset it. But none the less, I think we are trying to have the code up and running from our end as soon as possible.

    I will keep you updated with the progress on the same.

    Regards,

    Vaibhav

  • Thank you,Vaibhav.

  • Hello Joe,

    I was tracking the JIRA and figured out that the fix(commit) has been merged.

    I am going to send you the files once I have tested the same from my end on AM243x-LP.

    Regards,

    Vaibhav

  • Hi Vaibhav, thanks for the update!  That's great news.

  • Hello Joe,

    Thanks for your patience.

    I am attaching the file here for your reference.

    am243x-lp.zip

    Please go ahead and replace the folder at the following directory: mcu_plus_sdk_install_path\examples\drivers\boot\sbl_ospi

    Please try it at your end and update me with the results.

    Regards,

    Vaibhav

  • Hi Vaibhav, really appreciate your support here.  We'll give it a try and let you know how it goes.

  • Hello Joe,

    Thanks for acknowledging.

    I am glad to support you on this query. Looking forward to your logs.

    Regards,

    Vaibhav

  • Hi Vaibhav,

    We implemented the reset line and code changes.  Unfortunately, we still fail at Bootloader_parseMultiCoreAppImage when running in 4S-4S-4S mode.  We tried operating at 50MHz and 25MHz without success.  Reverting SysConfig back to 4S-4D-4D mode at 20MHz worked without issue.

    Thank you,

    Joe

  • Hello Joe,

    So the default configuration of 4S-4D-4D works right?

    Allow me sometime to recreate this issue and check if its failing on the TI EVM AM243-LP as well with 4S-4S-4S.

    Regards,

    Vaibhav

  • Thanks very much, Vaibhav.

    As a reference, we made a few changes to the Flash from the default AM243-LP Bootloader SysConfig for the protocol change

    • Protocol = 4S-4S-4S
    • Read Command = EB (Infineon Datasheet 4-4-4 transaction table)
    • Mode Clocks (READ) = 2 (Latency code (cycles) versus frequency table)
    • Multiple variations of clock were tried:
      • Clock = 200MHz with Div4 then Div8
      • Clock = 100MHz with Div4

    This was a critical - in order to get 4S-4D-4D to boot properly we also found that we had to add an API call to OSPI_enableDacMode immediately after Board_driversOpen(). 

    Additionally our hardware config requires the use of Tap Mode so PHY Mode is disabled in Sysconfig.

    Thank you,

    Joe

  • Hi Joe,

    As a reference, we made a few changes to the Flash from the default AM243-LP Bootloader SysConfig for the protocol change

    • Protocol = 4S-4S-4S
    • Read Command = EB (Infineon Datasheet 4-4-4 transaction table)
    • Mode Clocks (READ) = 2 (Latency code (cycles) versus frequency table)
    • Multiple variations of clock were tried:
      • Clock = 200MHz with Div4 then Div8
      • Clock = 100MHz with Div4

    With the above changes did it work for you?

    Regards,

    Vaibhav

  • Hi Vaibhav,

    No.  I posted the above to let you know what changes we made to SysConfig expecting 4S-4S-4S to be operational.  It didn't appear that anything else needed to be changed to support Infineon QSPI.

    4S-4D-4D was failing until we added the API call I mentioned.

    Thanks

    Joe

  • Hello Joe,

    There must be some SysConfig values changes to the flash parameter required for this. Some values must be missing.

    Can you send me the error logs you get by running in 4s-4s-4s mode?

    Regards,

    Vaibhav

  • Hi Vaibhav,

    Unfortunately, the error logs don't provide any details.  The console says "Some Tests Failed".  We've determined through some debugging that we fail at Bootloader_parseMultiCoreAppImage().

    Thank you,

    Joe

  • Hi Joe,

    I understand your flow failed at the following function.

    Bootloader_parseMultiCoreAppImage().

    I would need you to go inside this function and let me know where exactly it is failing.

    It could be failing in Bootloader_verifyMulticoreImage and maybe after that.

    We need to know the exact point before moving forward.

    Regards,

    Vaibhav

  • Hi Vaibhav,

    We have stepped through the code to the point where there was a handoff to the DMSC controller and we were not able to debug it after that.  At this time, we have too many other parts of the firmware to get operational so we cannot dedicate any more time on this for awhile.  If you'd like to close out this ticket you can.  Perhaps we can revisit it later.

    Thank you for your help,

    Joe

  • Hello Joe,

    We can do an easier alternative to debugging via a JTAG. 

    I have gone through the flow for parsing multicore image and verifying the image in the bootloader.c file.

    Since you already mentioned that your flow returns status as -1 at  Bootloader_parseMultiCoreAppImage(), so I have added debug statements in the bootloader.c file which will tell us where exactly things went wrong.

    Please find the attached file.

    Make sure to replace the bootloader.c file with the contents below.

    /*
     *  Copyright (C) 2021-23 Texas Instruments Incorporated
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /**
     *  \file bootloader.c
     *
     *  \brief Bootloader Driver API source file.
     */
    
    /* ========================================================================== */
    /*                             Include Files                                  */
    /* ========================================================================== */
    
    #include <kernel/dpl/SystemP.h>
    #include <kernel/dpl/CacheP.h>
    
    #include <drivers/bootloader.h>
    #ifdef DRV_VERSION_MMCSD_V0
    #include <drivers/bootloader/bootloader_mmcsd_raw.h>
    #endif
    #include <drivers/bootloader/soc/bootloader_soc.h>
    #include <drivers/bootloader/bootloader_priv.h>
    #include <string.h>
    
    /* ========================================================================== */
    /*                           Macros & Typedefs                                */
    /* ========================================================================== */
    
    /*RPRC image ID for linux load only images */
    #define RPRC_LINUX_LOAD_ONLY_IMAGE_ID (21U)
    
    
    /* ========================================================================== */
    /*                             Global Variables                               */
    /* ========================================================================== */
    
    extern Bootloader_Config gBootloaderConfig[];
    extern uint32_t gBootloaderConfigNum;
    
    /* ========================================================================== */
    /*                             Function Definitions                           */
    /* ========================================================================== */
    
    Bootloader_Handle Bootloader_open(uint32_t instanceNum, Bootloader_Params *openParams)
    {
        Bootloader_Config *config = NULL;
    
        if(instanceNum < gBootloaderConfigNum)
        {
            config = &gBootloaderConfig[instanceNum];
            if(config->fxns && config->fxns->imgOpenFxn && config->args)
            {
                int32_t status;
    
                status = config->fxns->imgOpenFxn(config->args, openParams);
                if(status != SystemP_SUCCESS)
                {
                    config = NULL;
                }
            }
        }
    
        return (Bootloader_Handle)config;
    }
    
    void Bootloader_close(Bootloader_Handle handle)
    {
        Bootloader_Config *config = (Bootloader_Config *)handle;
    
        if(config && config->fxns && config->fxns->imgCloseFxn)
        {
            config->fxns->imgCloseFxn(handle, config->args);
        }
    }
    
    int32_t Bootloader_loadCpu(Bootloader_Handle handle, Bootloader_CpuInfo *cpuInfo)
    {
        int32_t status = SystemP_SUCCESS;
    
        status = Bootloader_socCpuRequest(cpuInfo->cpuId);
    
        status = Bootloader_socCpuSetClock(cpuInfo->cpuId, cpuInfo->clkHz);
    
        if(SystemP_SUCCESS == status)
        {
            Bootloader_Config *config = (Bootloader_Config *)handle;
            status = Bootloader_socCpuPowerOnReset(cpuInfo->cpuId,config->socCoreOpMode);
        }
    
        if(SystemP_SUCCESS == status)
        {
            if( cpuInfo->rprcOffset != BOOTLOADER_INVALID_ID)
            {
                status = Bootloader_rprcImageLoad(handle, cpuInfo);
            }
        }
    
        return status;
    }
    
    int32_t Bootloader_runCpu(Bootloader_Handle handle, Bootloader_CpuInfo *cpuInfo)
    {
        int32_t status = SystemP_SUCCESS;
        uintptr_t entryPoint = cpuInfo->entryPoint;
    
        if( cpuInfo->rprcOffset == BOOTLOADER_INVALID_ID)
        {
            /* boot a dummy while(1) loop */
            entryPoint = 0;
        }
        status = Bootloader_socCpuResetRelease(cpuInfo->cpuId, entryPoint);
    
        if(SystemP_SUCCESS == status)
        {
            status = Bootloader_socCpuRelease(cpuInfo->cpuId);
        }
    
        if(status == SystemP_SUCCESS)
        {
            uint64_t cpuHz;
    
            cpuHz = Bootloader_socCpuGetClock(cpuInfo->cpuId);
            if(cpuHz > 0)
            {
                DebugP_logInfo("CPU %s is initialized to %d Hz !!!\r\n",
                    Bootloader_socGetCoreName(cpuInfo->cpuId), (uint32_t)cpuHz);
            }
        }
    
        return status;
    }
    
    int32_t Bootloader_loadSelfCpu(Bootloader_Handle handle, Bootloader_CpuInfo *cpuInfo, uint32_t skipLoad)
    {
        int32_t status = SystemP_SUCCESS;
        uint32_t cpuId = cpuInfo->cpuId;
    
        status = Bootloader_socCpuRequest(cpuId);
        if(SystemP_SUCCESS == status)
        {
            status = Bootloader_socCpuSetClock(cpuId, cpuInfo->clkHz);
        }
        if(SystemP_SUCCESS == status)
        {
            if( cpuInfo->rprcOffset != BOOTLOADER_INVALID_ID)
            {
                status = Bootloader_rprcImageParseEntryPoint(handle, cpuInfo);
            }
        }
        if(SystemP_SUCCESS == status)
        {
            uintptr_t entryPoint = cpuInfo->entryPoint;
    
            if( cpuInfo->rprcOffset == BOOTLOADER_INVALID_ID)
            {
                entryPoint = 0;
            }
            status = Bootloader_socCpuSetEntryPoint(cpuId, entryPoint);
        }
        if(SystemP_SUCCESS == status)
        {
            status = Bootloader_socMemInitCpu(cpuId);
        }
        if((SystemP_SUCCESS == status) && (skipLoad == FALSE))
        {
            if( cpuInfo->rprcOffset != BOOTLOADER_INVALID_ID)
            {
                status = Bootloader_rprcImageLoad(handle, cpuInfo);
            }
        }
        if(status == SystemP_SUCCESS)
        {
            uint64_t cpuHz;
    
            cpuHz = Bootloader_socCpuGetClock(cpuId);
            if(cpuHz > 0)
            {
                DebugP_logInfo("CPU %s is initialized to %d Hz !!!\r\n", Bootloader_socGetCoreName(cpuId), (uint32_t)cpuHz);
            }
        }
        return status;
    }
    
    int32_t Bootloader_runSelfCpu(Bootloader_Handle handle, Bootloader_BootImageInfo *bootImageInfo)
    {
        int32_t status = SystemP_SUCCESS;
    
        DebugP_logInfo("All done, reseting self ...\r\n\n");
        status = Bootloader_socCpuResetReleaseSelf();
        /* control will not reach here */
    
        return status;
    }
    
    int32_t Bootloader_bootCpu(Bootloader_Handle handle, Bootloader_CpuInfo *cpuInfo)
    {
        int32_t status = SystemP_SUCCESS;
    
        status = Bootloader_loadCpu(handle, cpuInfo);
    
        if(status == SystemP_SUCCESS)
        {
            status = Bootloader_runCpu(handle, cpuInfo);
        }
    
        return status;
    }
    
    int32_t Bootloader_rprcImageParseEntryPoint(Bootloader_Handle handle, Bootloader_CpuInfo *cpuInfo)
    {
        int32_t status = SystemP_SUCCESS;
    
        Bootloader_RprcFileHeader header;
    
        Bootloader_Config *config = (Bootloader_Config *)handle;
    
        config->fxns->imgSeekFxn(cpuInfo->rprcOffset, config->args);
        status = config->fxns->imgReadFxn(&header, sizeof(Bootloader_RprcFileHeader), config->args);
    
        cpuInfo->entryPoint = (uintptr_t)header.entry;
    
        return status;
    }
    
    int32_t Bootloader_bootSelfCpu(Bootloader_Handle handle, Bootloader_BootImageInfo *bootImageInfo)
    {
        int32_t status = SystemP_SUCCESS;
        uint32_t i = 0;
        uint32_t *selfCpuList  = Bootloader_socGetSelfCpuList();
    
        while( selfCpuList[i] != BOOTLOADER_INVALID_ID)
        {
            status = Bootloader_loadSelfCpu(handle, &bootImageInfo->cpuInfo[ selfCpuList[i] ], FALSE);
            if(status!=SystemP_SUCCESS)
            {
                break;
            }
            i++;
        }
    
        if(status == SystemP_SUCCESS)
        {
            status = Bootloader_runSelfCpu(handle, bootImageInfo);
        }
    
        return status;
    }
    
    int32_t Bootloader_rprcImageLoad(Bootloader_Handle handle, Bootloader_CpuInfo *cpuInfo)
    {
        Bootloader_RprcFileHeader     header;
        Bootloader_RprcSectionHeader section;
    
        int32_t status = SystemP_SUCCESS;
    
        Bootloader_Config *config = (Bootloader_Config *)handle;
    
        config->fxns->imgSeekFxn(cpuInfo->rprcOffset, config->args);
        status = config->fxns->imgReadFxn(&header, sizeof(Bootloader_RprcFileHeader), config->args);
    
        if(header.magic != BOOTLOADER_RPRC_MAGIC_NUMBER)
        {
            status = SystemP_FAILURE;
        }
        else
        {
            cpuInfo->entryPoint = (uintptr_t)header.entry;
    
            uint32_t i;
    
            for(i=0; i<header.sectionCount; i++)
            {
                status = config->fxns->imgReadFxn(&section, sizeof(Bootloader_RprcSectionHeader), config->args);
    
                section.addr = Bootloader_socTranslateSectionAddr(cpuInfo->cpuId, section.addr);
    
                /* Add check for SBL reserved memory */
                Bootloader_resMemSections *resMem;
                uint32_t resSectionCnt, start, end;
                resMem = Bootloader_socGetSBLMem();
                for (resSectionCnt = 0; resSectionCnt < resMem->numSections; resSectionCnt++)
                {
                    start = resMem->memSection[resSectionCnt].memStart;
                    end = resMem->memSection[resSectionCnt].memEnd;
                    if((section.addr > start) && (section.addr < end))
                    {
                        status = SystemP_FAILURE;
                        DebugP_logError("Application image has a load address (0x%08X) in the SBL reserved memory range!!\r\n", section.addr);
                        break;
                    }
                }
                if (status == SystemP_SUCCESS)
                {
                    status = config->fxns->imgReadFxn((void *)(uintptr_t)(section.addr), section.size, config->args);
                    config->bootImageSize += section.size;
                }
            }
        }
    
        return status;
    }
    
    uint32_t Bootloader_getX509CertLen(uint8_t *x509_cert_ptr)
    {
        uint32_t certLen = 0;
        uint8_t *pCertLen = (uint8_t *)&certLen;
    
        if ( *x509_cert_ptr != 0x30)
        {
            return 0;
        }
    
        certLen = *(x509_cert_ptr + 1);
    
        /* If you need more than 2 bytes to store the cert length  */
        /* it means that the cert length is greater than 64 Kbytes */
        /* and we do not support it                                */
        if ((certLen > 0x80) &&
            (certLen != 0x82))
        {
            return 0;
        }
    
        if ( certLen == 0x82)
        {
            *pCertLen = *(x509_cert_ptr + 3);
            *(pCertLen + 1) = *(x509_cert_ptr + 2);
    
            /* add current offset from start of x509 cert */
            certLen += 3;
        }
        else
        {
            /* add current offset from start of x509 cert  */
            /* if cert len was obtained from 2nd byte i.e. */
            /* cert size is 127 bytes or less              */
            certLen += 1;
        }
    
        /* certLen now contains the offset of the last byte */
        /* of the cert from the ccert_start. To get the size */
        /* of certificate, add 1                             */
    
        return certLen + 1;
    }
    
    uint8_t *Bootloader_findSeq(uint8_t *x509_cert_ptr, uint32_t x509_cert_size, uint8_t *seq_oid, uint8_t seq_len)
    {
        uint8_t *x509_cert_end = x509_cert_ptr + x509_cert_size - seq_len;
    
        /* searching for the following byte seq in the cert */
        /* seq_id(0x30) seq_len(< 0x80) 0x06 0x09 0x2B...   */
        while (x509_cert_ptr < x509_cert_end)
        {
            if ((*x509_cert_ptr == seq_oid[0]) &&
                (*(x509_cert_ptr + 2) == seq_oid[2]) &&
                (*(x509_cert_ptr - 2) == 0x30))
            {
                if ((memcmp((const void *)x509_cert_ptr, (const void *)seq_oid, seq_len)) == 0)
                {
                    /* return start boot_seq */
                    return (x509_cert_ptr - 2);
                }
            }
            x509_cert_ptr++;
        }
    
        return NULL;
    }
    
    uint32_t Bootloader_getMsgLen(uint8_t *x509_cert_ptr, uint32_t x509_cert_size)
    {
        uint8_t *boot_seq_ptr;
        uint32_t msg_len = 0, boot_seq_len;
        uint8_t *msg_len_ptr = (uint8_t *)&msg_len;
        uint8_t boot_seq_oid[11];
        Bootloader_socGetBootSeqOid(boot_seq_oid);
        boot_seq_ptr = Bootloader_findSeq(x509_cert_ptr, x509_cert_size, boot_seq_oid, sizeof(boot_seq_oid));
    
        /* length of seq is stored in the byte after the 0x30 seq_id */
        /* length of seq is stored as offset of the last byte of seq */
        /* from current offset. Jump to the end of the boot seq as   */
        /* the length of the message  is the last field of this seq  */
        boot_seq_len = *(++boot_seq_ptr);
        boot_seq_ptr = boot_seq_ptr + boot_seq_len;
    
        /* The last integer in this sequence is the msg length    */
        /* integers are tagged 0x20, so search backwards for 0x20 */
        /* The msg size can be encoded in 1, 2, 3 or 4 bytes      */
        /* 0x02 0x01 0x##                                         */
        /* 0x02 0x02 0x## 0x##                                    */
        /* 0x02 0x03 0x## 0x## 0x##                               */
        /* 0x02 0x04 0x## 0x## 0x## 0x##                          */
        if ( (*(boot_seq_ptr - 5) == 0x02) &&
             (*(boot_seq_ptr - 4) == 0x04) )
        {
            /* msg length encoded in 4 bytes */
            *msg_len_ptr = *boot_seq_ptr;
            *(msg_len_ptr + 1) = *(boot_seq_ptr - 1);
            *(msg_len_ptr + 2) = *(boot_seq_ptr - 2);
            *(msg_len_ptr + 3) = *(boot_seq_ptr - 3);
        }
        else if ( (*(boot_seq_ptr - 4) == 0x02) &&
             (*(boot_seq_ptr - 3) == 0x03) )
        {
            /* msg length encoded in 3 bytes */
            *msg_len_ptr = *boot_seq_ptr;
            *(msg_len_ptr + 1) = *(boot_seq_ptr - 1);
            *(msg_len_ptr + 2) = *(boot_seq_ptr - 2);
        }
        else if ( (*(boot_seq_ptr - 3) == 0x02) &&
             (*(boot_seq_ptr - 2) == 0x02) )
        {
            /* msg length encoded in 2 bytes */
            *msg_len_ptr = *boot_seq_ptr;
            *(msg_len_ptr + 1) = *(boot_seq_ptr - 1);
        }
        else if ( (*(boot_seq_ptr - 2) == 0x02) &&
             (*(boot_seq_ptr - 1) == 0x01) )
        {
            /* msg length encoded in 1 byte */
            *msg_len_ptr = *boot_seq_ptr;
        }
    
        return msg_len;
    }
    
    /* This API should only be called after all the rprc loading is complete */
    uint32_t Bootloader_getMulticoreImageSize(Bootloader_Handle handle)
    {
        uint32_t size = 0;
    
        if(handle != NULL)
        {
            Bootloader_Config *config = (Bootloader_Config *)handle;
            size = config->bootImageSize;
        }
        return size;
    }
    
    /* This API should only be called after the bootimage is parsed */
    uint32_t Bootloader_isCorePresent(Bootloader_Handle handle, uint32_t cslCoreId)
    {
        uint32_t retVal = FALSE;
    
        if(handle != NULL)
        {
            Bootloader_Config *config = (Bootloader_Config *)handle;
            if((config->coresPresentMap & (1 << cslCoreId)) != 0)
            {
                retVal = TRUE;
            }
        }
    
        return retVal;
    }
    
    uint32_t Bootloader_getBootMedia(Bootloader_Handle handle)
    {
        uint32_t media = BOOTLOADER_INVALID_ID;
    
        if(NULL != handle)
        {
            Bootloader_Config *config = (Bootloader_Config *)handle;
            media = config->bootMedia;
        }
    
        return media;
    }
    
    int32_t Bootloader_verifyMulticoreImage(Bootloader_Handle handle)
    {
        int32_t status = SystemP_FAILURE, authStatus = SystemP_FAILURE;
        uint32_t certLen = 0U, imageLen = 0U;
        uint32_t certLoadAddr = 0xFFFFFFFFU;
    
        Bootloader_Config *config = (Bootloader_Config *)handle;
    
        if(config->fxns->imgReadFxn == NULL || config->fxns->imgSeekFxn == NULL)
        {
            status = SystemP_FAILURE;
        }
        else
        {
            uint8_t x509Header[4];
            if((config->bootMedia == BOOTLOADER_MEDIA_MEM) ||
                    (config->bootMedia == BOOTLOADER_MEDIA_PCIE))
            {
                DebugP_log("Bootmedia is PCIE or MEM !! \n\r");
    
                Bootloader_MemArgs *memArgs = (Bootloader_MemArgs *)(config->args);
                certLoadAddr = memArgs->appImageBaseAddr;
            }
            else if(config->bootMedia == BOOTLOADER_MEDIA_FLASH)
            {
                DebugP_log("Bootmedia is Flash !! \n\r");
    
                Bootloader_FlashArgs *flashArgs = (Bootloader_FlashArgs *)(config->args);
                certLoadAddr = flashArgs->appImageOffset + SOC_getFlashDataBaseAddr();
            }
    #ifdef DRV_VERSION_MMCSD_V0
            else if(config->bootMedia == BOOTLOADER_MEDIA_EMMC)
            {
                DebugP_log("Bootmedia is eMMC !! \n\r");
    
                Bootloader_MmcsdArgs *mmcsdArgs = (Bootloader_MmcsdArgs *)(config->args);
                certLoadAddr = mmcsdArgs->appImageOffset;
    
                config->fxns->imgReadFxn(x509Header, 4, config->args);
                config->fxns->imgSeekFxn(0, config->args);
    
                if(config->scratchMemPtr != NULL)
                {
                    certLen = Bootloader_getX509CertLen(x509Header);
                    config->fxns->imgReadFxn((void *)config->scratchMemPtr, 0x800, config->args);
    
                    imageLen = Bootloader_getMsgLen((uint8_t *)config->scratchMemPtr, certLen);
    
                    uint32_t totalLen = (certLen + imageLen + 128) & ~(127);
    
                    DebugP_log("Bootmedia is eMMC, total length = %d !! \n\r", totalLen);
                    
    
                    config->fxns->imgSeekFxn(0, config->args);
                    config->fxns->imgReadFxn((void *)config->scratchMemPtr, totalLen, config->args);
    
                    certLoadAddr = (uint32_t)(&(config->scratchMemPtr[0]));
    
                    config->fxns->imgSeekFxn(0, config->args);
                }
            }
    #endif
            if (config->bootMedia != BOOTLOADER_MEDIA_EMMC)
            {
                /* Read first 4 bytes of the appimage to determine if it is signed with x509 certificate */
                config->fxns->imgReadFxn(x509Header, 4, config->args);
                config->fxns->imgSeekFxn(0, config->args);
    
                DebugP_log("Bootmedia is not eMMC hence compute certificate and image length !! \n\r");
    
                certLen = Bootloader_getX509CertLen(x509Header);
                imageLen = Bootloader_getMsgLen((uint8_t *)certLoadAddr, certLen);
            }
            /* Get the 128B cache-line aligned image length */
            uint32_t cacheAlignedLen = (certLen + imageLen + 128) & ~(127);
    
            DebugP_log("Cache Aligned length: %d !! \n\r", cacheAlignedLen);
    
    
            /* Write back and invalidate the cache before passing to HSM */
            CacheP_wbInv((void *)certLoadAddr, cacheAlignedLen, CacheP_TYPE_ALL);
    
            /* Check if the certificate length is within valid range */
            if((certLen > 0x100) && (certLen < 0x800))
            {
                if(config->disableAppImageAuth == TRUE)
                {
                    /* NOTE: This is an option to skip image authentication in a signed
                    image to aid initial development on HS devices. If the user has
                    opted to disable image authentication, do not authenticate/decrypt.
                    Skip the certificate length and start loading as in GP */
                    authStatus = SystemP_SUCCESS;
                }
                else
                {
                    authStatus = Bootloader_socAuthImage(certLoadAddr);
                }
    
                /* Invalidate the cache before reading in case HSM decrypted image */
                CacheP_inv((void *)certLoadAddr, cacheAlignedLen, CacheP_TYPE_ALL);
    
                if(config->bootMedia == BOOTLOADER_MEDIA_BUFIO)
                {
                    /* Authentication will fail in Buf Io because we don't have full data yet,
                    so make it pass here for testing. Default behaviour is to assert. */
    
                    /* authStatus = SystemP_SUCCESS; */
                    DebugP_assertNoLog(authStatus == SystemP_SUCCESS);
                }
    
                if(authStatus == SystemP_FAILURE)
                {
                    status = SystemP_FAILURE;
                }
                else
                {
                    /* Authentication passed, all good. Now re-init bootloader params to point to image start instead of start of x509 certificate */
                    if((config->bootMedia == BOOTLOADER_MEDIA_MEM) ||
                        (config->bootMedia == BOOTLOADER_MEDIA_PCIE))
                    {
                        Bootloader_MemArgs *memArgs = (Bootloader_MemArgs *)(config->args);
                        memArgs->appImageBaseAddr += certLen;
                    }
                    else if(config->bootMedia == BOOTLOADER_MEDIA_FLASH)
                    {
                        Bootloader_FlashArgs *flashArgs = (Bootloader_FlashArgs *)(config->args);
                        flashArgs->appImageOffset += certLen;
                        flashArgs->curOffset = flashArgs->appImageOffset;
                    }
                    else if(config->bootMedia == BOOTLOADER_MEDIA_BUFIO)
                    {
                        Bootloader_BufIoArgs *bufIoArgs = (Bootloader_BufIoArgs *)(config->args);
                        bufIoArgs->appImageOffset += certLen;
                        bufIoArgs->curOffset = bufIoArgs->appImageOffset;
                    }
    #ifdef DRV_VERSION_MMCSD_V0
                    else if(config->bootMedia == BOOTLOADER_MEDIA_EMMC)
                    {
                        Bootloader_MmcsdArgs *mmcsdArgs = (Bootloader_MmcsdArgs *)(config->args);
                        mmcsdArgs->appImageOffset += certLen;
                        mmcsdArgs->curOffset = mmcsdArgs->appImageOffset;
                    }
    #endif
                    status = SystemP_SUCCESS;
                }
            }
            else
            {
                status = SystemP_FAILURE;
            }
    
        }
        DebugP_log("Status value: %d !! \n\r", status);
    
    
        return status;
    }
    
    int32_t Bootloader_parseMultiCoreAppImage(Bootloader_Handle handle, Bootloader_BootImageInfo *bootImageInfo)
    {
        int32_t status = SystemP_SUCCESS;
    
        Bootloader_Config *config = (Bootloader_Config *)handle;
    
        if(config->fxns->imgReadFxn == NULL || config->fxns->imgSeekFxn == NULL)
        {
            status = SystemP_FAILURE;
        }
        else
        {
            Bootloader_MetaHeaderStart mHdrStr;
            Bootloader_MetaHeaderCore  mHdrCore[BOOTLOADER_MAX_INPUT_FILES];
    
            /* Verify the multicore image if authentication is required */
            if((Bootloader_socIsAuthRequired() == TRUE) && (config->isAppimageSigned == TRUE))
            {
                /* Device is HS, verify image. */
                DebugP_log("Starting to verify the image by calling Bootloader_verifyMulticoreImage() !! \n\r");
                status = Bootloader_verifyMulticoreImage(handle);
                DebugP_log("Image verified, status is: %d !! \n\r", status);
    
            }
            else
            {
                /* Device is GP, no authentication required OR appimage is not signed, boot like GP */
                status = SystemP_SUCCESS;
            }
    
            if(SystemP_SUCCESS == status)
            {
                memset(&mHdrCore[0], 0xFF, BOOTLOADER_MAX_INPUT_FILES*sizeof(Bootloader_MetaHeaderCore));
    
                status = config->fxns->imgReadFxn(&mHdrStr, sizeof(Bootloader_MetaHeaderStart), config->args);
    
                DebugP_log("Image parsed successfully !! \n\r");
    
    
                if(mHdrStr.magicStr != BOOTLOADER_META_HDR_MAGIC_STR)
                {
                    status = SystemP_FAILURE;
                }
                else
                {
                    /* TODO */
                    /* Check for device Id later if needed, just a warning */
    
                    /* Read all the core offset addresses */
                    uint32_t i;
    
                    DebugP_log("Starting to read all the core offset addresses !! \n\r");
    
    
                    for(i=0U; i<mHdrStr.numFiles; i++)
                    {
                        status = config->fxns->imgReadFxn(&mHdrCore[i], sizeof(Bootloader_MetaHeaderCore), config->args);
                        /* TODO: Figure out how to add boot media specific offset */
                    }
    
                    DebugP_log("Starting to parse individual rprc files !! \n\r");
    
    
                    /* Parse individual rprc files */
                    for(i=0U; i<mHdrStr.numFiles; i++)
                    {
                        if(mHdrCore[i].coreId != (0xFFFFFFFFU))
                        {
                            uint32_t cslCoreId = Bootloader_socRprcToCslCoreId(mHdrCore[i].coreId);
                            Bootloader_CpuInfo *cpuInfo = &bootImageInfo->cpuInfo[cslCoreId];
                            cpuInfo->rprcOffset = mHdrCore[i].imageOffset;
                            cpuInfo->entryPoint = 0;
                            cpuInfo->cpuId      = cslCoreId;
                            config->coresPresentMap |= (1 << cslCoreId);
                        }
                    }
                }
            }
            else
            {
                status = SystemP_FAILURE;
            }
        }
    
        return status;
    }
    
    void Bootloader_Params_init(Bootloader_Params *params)
    {
        params->memArgsAppImageBaseAddr = BOOTLOADER_INVALID_ID;
    }
    
    void Bootloader_CpuInfo_init(Bootloader_CpuInfo *cpuInfo)
    {
        cpuInfo->cpuId = CSL_CORE_ID_MAX;
        cpuInfo->clkHz = 0U;
        cpuInfo->rprcOffset = BOOTLOADER_INVALID_ID;
        cpuInfo->entryPoint = BOOTLOADER_INVALID_ID;
    }
    
    void Bootloader_BootImageInfo_init(Bootloader_BootImageInfo *bootImageInfo)
    {
        uint16_t i;
    
        for(i=0; i<CSL_CORE_ID_MAX; i++)
        {
            Bootloader_CpuInfo_init(&bootImageInfo->cpuInfo[i]);
            bootImageInfo->cpuInfo[i].cpuId = i;
            bootImageInfo->cpuInfo[i].clkHz = Bootloader_socCpuGetClkDefault(i);
        }
    }
    
    #if defined (SOC_AM64X)
    /* Linux image load is applicable only for am64x. */
    int32_t Bootloader_parseAndLoadLinuxAppImage(Bootloader_Handle handle, Bootloader_BootImageInfo *bootImageInfo)
    {
        int32_t status = SystemP_SUCCESS;
    
        Bootloader_Config *config = (Bootloader_Config *)handle;
    
        if(config->fxns->imgReadFxn == NULL || config->fxns->imgSeekFxn == NULL)
        {
            status = SystemP_FAILURE;
        }
        else
        {
            Bootloader_MetaHeaderStart mHdrStr;
            Bootloader_MetaHeaderCore  mHdrCore[BOOTLOADER_MAX_INPUT_FILES];
    
            /* Verify the multicore image if authentication is required */
            if(Bootloader_socIsAuthRequired() == TRUE)
            {
                /* Device is HS, verify image. */
                status = Bootloader_verifyMulticoreImage(handle);
            }
            else
            {
                /* Device is GP, no authentication required */
                status = SystemP_SUCCESS;
            }
    
            if(SystemP_SUCCESS == status)
            {
    
                memset(&mHdrCore[0], 0xFF, BOOTLOADER_MAX_INPUT_FILES*sizeof(Bootloader_MetaHeaderCore));
    
                status = config->fxns->imgReadFxn(&mHdrStr, sizeof(Bootloader_MetaHeaderStart), config->args);
    
                if(mHdrStr.magicStr != BOOTLOADER_META_HDR_MAGIC_STR)
                {
                    status = SystemP_FAILURE;
                }
                else
                {
                    /* TODO */
                    /* Check for device Id later if needed, just a warning */
    
                    /* Read all the core offset addresses */
                    uint32_t i;
    
                    for(i=0U; i<mHdrStr.numFiles; i++)
                    {
                        status = config->fxns->imgReadFxn(&mHdrCore[i], sizeof(Bootloader_MetaHeaderCore), config->args);
                        /* TODO: Figure out how to add boot media specific offset */
                    }
    
                    /* Parse individual rprc files */
                    for(i=0U; i<mHdrStr.numFiles; i++)
                    {
                        /* Load the load only linux images */
                        if(mHdrCore[i].coreId == RPRC_LINUX_LOAD_ONLY_IMAGE_ID)
                        {
                            Bootloader_CpuInfo load_only_image;
                            load_only_image.rprcOffset = mHdrCore[i].imageOffset;
                            load_only_image.entryPoint = 0;
    
                            /* Set CPU ID as A53 as linux runs on A53 */
                            load_only_image.cpuId = CSL_CORE_ID_A53SS0_0;
    
                            /**************/
                            if (status == SystemP_SUCCESS)
                            {
                                status = Bootloader_rprcImageLoad(handle, &load_only_image);
                            }
    
                            continue;
                        }
    
                        if(mHdrCore[i].coreId != (0xFFFFFFFFU))
                        {
                            uint32_t cslCoreId = Bootloader_socRprcToCslCoreId(mHdrCore[i].coreId);
                            Bootloader_CpuInfo *cpuInfo = &bootImageInfo->cpuInfo[cslCoreId];
                            cpuInfo->rprcOffset = mHdrCore[i].imageOffset;
                            cpuInfo->entryPoint = 0;
                            cpuInfo->cpuId      = cslCoreId;
                            config->coresPresentMap |= (1 << cslCoreId);
                        }
                    }
                }
            }
            else
            {
                status = SystemP_FAILURE;
            }
        }
    
        return status;
    }
    
    int32_t Bootloader_runSelfCpuWithLinux(void)
    {
        int32_t status = SystemP_SUCCESS;
    
        DebugP_logInfo("All done, reseting self ...\r\n\n");
        status = Bootloader_socCpuResetReleaseSelf();
        /* control will not reach here */
    
        return status;
    }
    
    #endif
    

    I am hoping you have UART logs enabled by the help of which we can see the logs onto the console/the COM Port.

    After replacing the file contents, please run the following commands at MCU_PLUS_SDK/source/drivers

    gmake -s -f makefile.am243x.r5f.ti-arm-clang PROFILE=release

    gmake -s -f makefile.am243x.r5f.ti-arm-clang PROFILE=debug

    Now go ahead into your example directory/tiarmclang and rebuild the application using

    gmake all PROFILE=release

    gmake all PROFILE=debug

    Give it a free run and share with me the logs.

    Looking forward to your response.

    Regards,

    Vaibhav

  • Vaibhav,

    Thank you very much for providing this.  Once firmware resources are freed up we will respond with results.

    Joe

  • Hello Joe,

    Thank you very much for providing this.

    You are welcome.

    Once firmware resources are freed up we will respond with results.

    I will be looking forward to the logs.

    Regards,

    Vaibhav

  • Hi Vaibhav,

    Sorry it has taken so long to get back to you.  I have done the following changes:

    • Added QSPI reset pin and function
    • Added new bootloader.c with logs
    • Captured the SFDP table from the Infineon flash and converted to JSON file format

    Now in SysConfig after selecting the flash protocol, I load the SFDP data from the JSON.

    There is no change in behavior.  I cannot boot my application with 4S-4S-4S at 50MHz or anything less.

    Here is the output from your new bootloader.c after it fails within Bootloader_parseMultiCoreAppImage:

    Interestingly, Infineon appears to have incorrect data in their SFDP table at least for 4s-4d-4d:

    For Read Command they have 0xEB instead of 0xED.  EB is the read command for 4s-4s-4s mode.

    For Mode Clocks (READ) they have 2 instead of 1.

    Whoever in TI that set up the default Sysconfig for the AM243x EVM discovered that same problem and fixed it.

    All that being said, either the SDK, Processor, or Infineon NOR only loads my application in 4S-4D-4D.  

    Thanks,

    Joe

    Here's the SFDP capture:

    ================================================
    SFDP
    ================================================
    SFDP Major Revision : 0x1
    SFDP Minor Revision : 0x8
    Number of Parameter Headers in this Table : 4

    Types of Additional Parameter Tables in this flash
    ---------------------------------------------------
    4 BYTE ADDRESSING MODE INSTRUCTIONS TABLE
    SECTOR MAP TABLE
    STATUS CONTROL AND CONFIGURATION REGISTER MAP TABLE
    JSON Data for the flash :

    {

    "flashSize": 134217728,
    "flashPageSize": 256,
    "flashManfId": "0x34",
    "flashDeviceId": "0x2B1B",
    "flashBlockSize": 262144,
    "flashSectorSize": 4096,
    "cmdBlockErase3B": "0xD8",
    "cmdBlockErase4B": "0xDC",
    "cmdSectorErase3B": "0x20",
    "cmdSectorErase4B": "0x21",
    "protos": {
    "p111": {
    "isDtr": false,
    "cmdRd": "0x03",
    "cmdWr": "0x02",
    "modeClksCmd": 0,
    "modeClksRd": 0,
    "dummyClksCmd": 0,
    "dummyClksRd": 0,
    "enableType": "0",
    "enableSeq": "0x00",
    "dummyCfg": null,
    "protoCfg": null,
    "strDtrCfg": null
    },
    "p112": {
    "isDtr": false,
    "cmdRd": "0xFF",
    "cmdWr": "0x02",
    "modeClksCmd": 0,
    "modeClksRd": 0,
    "dummyClksCmd": 0,
    "dummyClksRd": 0,
    "enableType": "0",
    "enableSeq": "0x00",
    "dummyCfg": null,
    "protoCfg": null,
    "strDtrCfg": null
    },
    "p114": {
    "isDtr": false,
    "cmdRd": "0x6C",
    "cmdWr": "0x02",
    "modeClksCmd": 0,
    "modeClksRd": 0,
    "dummyClksCmd": 0,
    "dummyClksRd": 8,
    "enableType": "5",
    "enableSeq": "0x00",
    "dummyCfg": null,
    "protoCfg": null,
    "strDtrCfg": null
    },
    "p118": null,
    "p444s": {
    "isDtr": false,
    "cmdRd": "0xEB",
    "cmdWr": "0x02",
    "modeClksCmd": 0,
    "modeClksRd": 2,
    "dummyClksCmd": 0,
    "dummyClksRd": 8,
    "enableType": "5",
    "enableSeq": "0x08",
    "dummyCfg": {
    "isAddrReg": true,
    "cmdRegRd":"0x65",
    "cmdRegWr":"0x71",
    "cfgReg":"0x00800003",
    "shift":0,
    "mask":"0x03",
    "bitP":8
    },
    "protoCfg": {
    "isAddrReg": true,
    "cmdRegRd": "0x65",
    "cmdRegWr": "0x71",
    "cfgReg": "0x00800003",
    "shift": 6,
    "mask": "0x00",
    "bitP": 6
    },
    "strDtrCfg": {
    "isAddrReg": false,
    "cmdRegRd": "0x00",
    "cmdRegWr": "0x00",
    "cfgReg": "0x00000000",
    "shift": 0,
    "mask": "0x00",
    "bitP": 0
    }
    },
    "p444d": {
    "isDtr": true,
    "cmdRd": "0xEB",
    "cmdWr": "0x02",
    "modeClksCmd": 0,
    "modeClksRd": 2,
    "dummyClksCmd": 0,
    "dummyClksRd": 8,
    "enableType": "5",
    "enableSeq": "0x08",
    "dummyCfg": {
    "isAddrReg": true,
    "cmdRegRd":"0x65",
    "cmdRegWr":"0x71",
    "cfgReg":"0x00800003",
    "shift":0,
    "mask":"0x03",
    "bitP":8
    },
    "protoCfg": {
    "isAddrReg": true,
    "cmdRegRd": "0x65",
    "cmdRegWr": "0x71",
    "cfgReg": "0x00800003",
    "shift": 6,
    "mask": "0x00",
    "bitP": 6
    },
    "strDtrCfg": {
    "isAddrReg": false,
    "cmdRegRd": "0x00",
    "cmdRegWr": "0x00",
    "cfgReg": "0x00000000",
    "shift": 0,
    "mask": "0x00",
    "bitP": 0
    }
    },
    "p888s": null,
    "p888d": null,
    "pCustom": {
    "fxn": null
    }
    },
    "addrByteSupport": "1",
    "fourByteAddrEnSeq": "0xA1",
    "cmdExtType": "REPEAT",
    "resetType": "0x38",
    "deviceBusyType": "1",
    "cmdWren": "0x06",
    "cmdRdsr": "0x05",
    "srWip": 0,
    "srWel": 1,
    "cmdChipErase": "0xC7",
    "rdIdSettings": {
    "cmd": "0x9F",
    "numBytes": 5,
    "dummy4": 0,
    "dummy8": 0
    },
    "xspiWipRdCmd": "0x65",
    "xspiWipReg": "0x00800000",
    "xspiWipBit": 0,
    "flashDeviceBusyTimeout": 448000000,
    "flashPageProgTimeout": 512
    }

  • Hi Joe,

    The expert is currently out of office for a week. Responses to this thread will be delayed.

    Thanks for your patience.

    Regards,

    Tushar

  • Hello Joe,

    The SFDP capture is a nice add on here.

    Would appreciate if you attached a json file for it instead of writing it as a text on E2E as its difficult to read.

    Apart from this, I would suggest you to run the code again but with the new bootloader.c file. The new file has added logs on top of the existing logs.

    So will help me narrow down where the problem exists.

    /*
     *  Copyright (C) 2021-23 Texas Instruments Incorporated
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /**
     *  \file bootloader.c
     *
     *  \brief Bootloader Driver API source file.
     */
    
    /* ========================================================================== */
    /*                             Include Files                                  */
    /* ========================================================================== */
    
    #include <kernel/dpl/SystemP.h>
    #include <kernel/dpl/CacheP.h>
    
    #include <drivers/bootloader.h>
    #ifdef DRV_VERSION_MMCSD_V0
    #include <drivers/bootloader/bootloader_mmcsd_raw.h>
    #endif
    #include <drivers/bootloader/soc/bootloader_soc.h>
    #include <drivers/bootloader/bootloader_priv.h>
    #include <string.h>
    
    /* ========================================================================== */
    /*                           Macros & Typedefs                                */
    /* ========================================================================== */
    
    /*RPRC image ID for linux load only images */
    #define RPRC_LINUX_LOAD_ONLY_IMAGE_ID (21U)
    
    
    /* ========================================================================== */
    /*                             Global Variables                               */
    /* ========================================================================== */
    
    extern Bootloader_Config gBootloaderConfig[];
    extern uint32_t gBootloaderConfigNum;
    
    /* ========================================================================== */
    /*                             Function Definitions                           */
    /* ========================================================================== */
    
    Bootloader_Handle Bootloader_open(uint32_t instanceNum, Bootloader_Params *openParams)
    {
        Bootloader_Config *config = NULL;
    
        if(instanceNum < gBootloaderConfigNum)
        {
            config = &gBootloaderConfig[instanceNum];
            if(config->fxns && config->fxns->imgOpenFxn && config->args)
            {
                int32_t status;
    
                status = config->fxns->imgOpenFxn(config->args, openParams);
                if(status != SystemP_SUCCESS)
                {
                    config = NULL;
                }
            }
        }
    
        return (Bootloader_Handle)config;
    }
    
    void Bootloader_close(Bootloader_Handle handle)
    {
        Bootloader_Config *config = (Bootloader_Config *)handle;
    
        if(config && config->fxns && config->fxns->imgCloseFxn)
        {
            config->fxns->imgCloseFxn(handle, config->args);
        }
    }
    
    int32_t Bootloader_loadCpu(Bootloader_Handle handle, Bootloader_CpuInfo *cpuInfo)
    {
        int32_t status = SystemP_SUCCESS;
    
        status = Bootloader_socCpuRequest(cpuInfo->cpuId);
    
        status = Bootloader_socCpuSetClock(cpuInfo->cpuId, cpuInfo->clkHz);
    
        if(SystemP_SUCCESS == status)
        {
            Bootloader_Config *config = (Bootloader_Config *)handle;
            status = Bootloader_socCpuPowerOnReset(cpuInfo->cpuId,config->socCoreOpMode);
        }
    
        if(SystemP_SUCCESS == status)
        {
            if( cpuInfo->rprcOffset != BOOTLOADER_INVALID_ID)
            {
                status = Bootloader_rprcImageLoad(handle, cpuInfo);
            }
        }
    
        return status;
    }
    
    int32_t Bootloader_runCpu(Bootloader_Handle handle, Bootloader_CpuInfo *cpuInfo)
    {
        int32_t status = SystemP_SUCCESS;
        uintptr_t entryPoint = cpuInfo->entryPoint;
    
        if( cpuInfo->rprcOffset == BOOTLOADER_INVALID_ID)
        {
            /* boot a dummy while(1) loop */
            entryPoint = 0;
        }
        status = Bootloader_socCpuResetRelease(cpuInfo->cpuId, entryPoint);
    
        if(SystemP_SUCCESS == status)
        {
            status = Bootloader_socCpuRelease(cpuInfo->cpuId);
        }
    
        if(status == SystemP_SUCCESS)
        {
            uint64_t cpuHz;
    
            cpuHz = Bootloader_socCpuGetClock(cpuInfo->cpuId);
            if(cpuHz > 0)
            {
                DebugP_logInfo("CPU %s is initialized to %d Hz !!!\r\n",
                    Bootloader_socGetCoreName(cpuInfo->cpuId), (uint32_t)cpuHz);
            }
        }
    
        return status;
    }
    
    int32_t Bootloader_loadSelfCpu(Bootloader_Handle handle, Bootloader_CpuInfo *cpuInfo, uint32_t skipLoad)
    {
        int32_t status = SystemP_SUCCESS;
        uint32_t cpuId = cpuInfo->cpuId;
    
        status = Bootloader_socCpuRequest(cpuId);
        if(SystemP_SUCCESS == status)
        {
            status = Bootloader_socCpuSetClock(cpuId, cpuInfo->clkHz);
        }
        if(SystemP_SUCCESS == status)
        {
            if( cpuInfo->rprcOffset != BOOTLOADER_INVALID_ID)
            {
                status = Bootloader_rprcImageParseEntryPoint(handle, cpuInfo);
            }
        }
        if(SystemP_SUCCESS == status)
        {
            uintptr_t entryPoint = cpuInfo->entryPoint;
    
            if( cpuInfo->rprcOffset == BOOTLOADER_INVALID_ID)
            {
                entryPoint = 0;
            }
            status = Bootloader_socCpuSetEntryPoint(cpuId, entryPoint);
        }
        if(SystemP_SUCCESS == status)
        {
            status = Bootloader_socMemInitCpu(cpuId);
        }
        if((SystemP_SUCCESS == status) && (skipLoad == FALSE))
        {
            if( cpuInfo->rprcOffset != BOOTLOADER_INVALID_ID)
            {
                status = Bootloader_rprcImageLoad(handle, cpuInfo);
            }
        }
        if(status == SystemP_SUCCESS)
        {
            uint64_t cpuHz;
    
            cpuHz = Bootloader_socCpuGetClock(cpuId);
            if(cpuHz > 0)
            {
                DebugP_logInfo("CPU %s is initialized to %d Hz !!!\r\n", Bootloader_socGetCoreName(cpuId), (uint32_t)cpuHz);
            }
        }
        return status;
    }
    
    int32_t Bootloader_runSelfCpu(Bootloader_Handle handle, Bootloader_BootImageInfo *bootImageInfo)
    {
        int32_t status = SystemP_SUCCESS;
    
        DebugP_logInfo("All done, reseting self ...\r\n\n");
        status = Bootloader_socCpuResetReleaseSelf();
        /* control will not reach here */
    
        return status;
    }
    
    int32_t Bootloader_bootCpu(Bootloader_Handle handle, Bootloader_CpuInfo *cpuInfo)
    {
        int32_t status = SystemP_SUCCESS;
    
        status = Bootloader_loadCpu(handle, cpuInfo);
    
        if(status == SystemP_SUCCESS)
        {
            status = Bootloader_runCpu(handle, cpuInfo);
        }
    
        return status;
    }
    
    int32_t Bootloader_rprcImageParseEntryPoint(Bootloader_Handle handle, Bootloader_CpuInfo *cpuInfo)
    {
        int32_t status = SystemP_SUCCESS;
    
        Bootloader_RprcFileHeader header;
    
        Bootloader_Config *config = (Bootloader_Config *)handle;
    
        config->fxns->imgSeekFxn(cpuInfo->rprcOffset, config->args);
        status = config->fxns->imgReadFxn(&header, sizeof(Bootloader_RprcFileHeader), config->args);
    
        cpuInfo->entryPoint = (uintptr_t)header.entry;
    
        return status;
    }
    
    int32_t Bootloader_bootSelfCpu(Bootloader_Handle handle, Bootloader_BootImageInfo *bootImageInfo)
    {
        int32_t status = SystemP_SUCCESS;
        uint32_t i = 0;
        uint32_t *selfCpuList  = Bootloader_socGetSelfCpuList();
    
        while( selfCpuList[i] != BOOTLOADER_INVALID_ID)
        {
            status = Bootloader_loadSelfCpu(handle, &bootImageInfo->cpuInfo[ selfCpuList[i] ], FALSE);
            if(status!=SystemP_SUCCESS)
            {
                break;
            }
            i++;
        }
    
        if(status == SystemP_SUCCESS)
        {
            status = Bootloader_runSelfCpu(handle, bootImageInfo);
        }
    
        return status;
    }
    
    int32_t Bootloader_rprcImageLoad(Bootloader_Handle handle, Bootloader_CpuInfo *cpuInfo)
    {
        Bootloader_RprcFileHeader     header;
        Bootloader_RprcSectionHeader section;
    
        int32_t status = SystemP_SUCCESS;
    
        Bootloader_Config *config = (Bootloader_Config *)handle;
    
        config->fxns->imgSeekFxn(cpuInfo->rprcOffset, config->args);
        status = config->fxns->imgReadFxn(&header, sizeof(Bootloader_RprcFileHeader), config->args);
    
        if(header.magic != BOOTLOADER_RPRC_MAGIC_NUMBER)
        {
            status = SystemP_FAILURE;
        }
        else
        {
            cpuInfo->entryPoint = (uintptr_t)header.entry;
    
            uint32_t i;
    
            for(i=0; i<header.sectionCount; i++)
            {
                status = config->fxns->imgReadFxn(&section, sizeof(Bootloader_RprcSectionHeader), config->args);
    
                section.addr = Bootloader_socTranslateSectionAddr(cpuInfo->cpuId, section.addr);
    
                /* Add check for SBL reserved memory */
                Bootloader_resMemSections *resMem;
                uint32_t resSectionCnt, start, end;
                resMem = Bootloader_socGetSBLMem();
                for (resSectionCnt = 0; resSectionCnt < resMem->numSections; resSectionCnt++)
                {
                    start = resMem->memSection[resSectionCnt].memStart;
                    end = resMem->memSection[resSectionCnt].memEnd;
                    if((section.addr > start) && (section.addr < end))
                    {
                        status = SystemP_FAILURE;
                        DebugP_logError("Application image has a load address (0x%08X) in the SBL reserved memory range!!\r\n", section.addr);
                        break;
                    }
                }
                if (status == SystemP_SUCCESS)
                {
                    status = config->fxns->imgReadFxn((void *)(uintptr_t)(section.addr), section.size, config->args);
                    config->bootImageSize += section.size;
                }
            }
        }
    
        return status;
    }
    
    uint32_t Bootloader_getX509CertLen(uint8_t *x509_cert_ptr)
    {
        uint32_t certLen = 0;
        uint8_t *pCertLen = (uint8_t *)&certLen;
    
        if ( *x509_cert_ptr != 0x30)
        {
            return 0;
        }
    
        certLen = *(x509_cert_ptr + 1);
    
        /* If you need more than 2 bytes to store the cert length  */
        /* it means that the cert length is greater than 64 Kbytes */
        /* and we do not support it                                */
        if ((certLen > 0x80) &&
            (certLen != 0x82))
        {
            return 0;
        }
    
        if ( certLen == 0x82)
        {
            *pCertLen = *(x509_cert_ptr + 3);
            *(pCertLen + 1) = *(x509_cert_ptr + 2);
    
            /* add current offset from start of x509 cert */
            certLen += 3;
        }
        else
        {
            /* add current offset from start of x509 cert  */
            /* if cert len was obtained from 2nd byte i.e. */
            /* cert size is 127 bytes or less              */
            certLen += 1;
        }
    
        /* certLen now contains the offset of the last byte */
        /* of the cert from the ccert_start. To get the size */
        /* of certificate, add 1                             */
    
        return certLen + 1;
    }
    
    uint8_t *Bootloader_findSeq(uint8_t *x509_cert_ptr, uint32_t x509_cert_size, uint8_t *seq_oid, uint8_t seq_len)
    {
        uint8_t *x509_cert_end = x509_cert_ptr + x509_cert_size - seq_len;
    
        /* searching for the following byte seq in the cert */
        /* seq_id(0x30) seq_len(< 0x80) 0x06 0x09 0x2B...   */
        while (x509_cert_ptr < x509_cert_end)
        {
            if ((*x509_cert_ptr == seq_oid[0]) &&
                (*(x509_cert_ptr + 2) == seq_oid[2]) &&
                (*(x509_cert_ptr - 2) == 0x30))
            {
                if ((memcmp((const void *)x509_cert_ptr, (const void *)seq_oid, seq_len)) == 0)
                {
                    /* return start boot_seq */
                    return (x509_cert_ptr - 2);
                }
            }
            x509_cert_ptr++;
        }
    
        return NULL;
    }
    
    uint32_t Bootloader_getMsgLen(uint8_t *x509_cert_ptr, uint32_t x509_cert_size)
    {
        uint8_t *boot_seq_ptr;
        uint32_t msg_len = 0, boot_seq_len;
        uint8_t *msg_len_ptr = (uint8_t *)&msg_len;
        uint8_t boot_seq_oid[11];
        Bootloader_socGetBootSeqOid(boot_seq_oid);
        boot_seq_ptr = Bootloader_findSeq(x509_cert_ptr, x509_cert_size, boot_seq_oid, sizeof(boot_seq_oid));
    
        /* length of seq is stored in the byte after the 0x30 seq_id */
        /* length of seq is stored as offset of the last byte of seq */
        /* from current offset. Jump to the end of the boot seq as   */
        /* the length of the message  is the last field of this seq  */
        boot_seq_len = *(++boot_seq_ptr);
        boot_seq_ptr = boot_seq_ptr + boot_seq_len;
    
        /* The last integer in this sequence is the msg length    */
        /* integers are tagged 0x20, so search backwards for 0x20 */
        /* The msg size can be encoded in 1, 2, 3 or 4 bytes      */
        /* 0x02 0x01 0x##                                         */
        /* 0x02 0x02 0x## 0x##                                    */
        /* 0x02 0x03 0x## 0x## 0x##                               */
        /* 0x02 0x04 0x## 0x## 0x## 0x##                          */
        if ( (*(boot_seq_ptr - 5) == 0x02) &&
             (*(boot_seq_ptr - 4) == 0x04) )
        {
            /* msg length encoded in 4 bytes */
            *msg_len_ptr = *boot_seq_ptr;
            *(msg_len_ptr + 1) = *(boot_seq_ptr - 1);
            *(msg_len_ptr + 2) = *(boot_seq_ptr - 2);
            *(msg_len_ptr + 3) = *(boot_seq_ptr - 3);
        }
        else if ( (*(boot_seq_ptr - 4) == 0x02) &&
             (*(boot_seq_ptr - 3) == 0x03) )
        {
            /* msg length encoded in 3 bytes */
            *msg_len_ptr = *boot_seq_ptr;
            *(msg_len_ptr + 1) = *(boot_seq_ptr - 1);
            *(msg_len_ptr + 2) = *(boot_seq_ptr - 2);
        }
        else if ( (*(boot_seq_ptr - 3) == 0x02) &&
             (*(boot_seq_ptr - 2) == 0x02) )
        {
            /* msg length encoded in 2 bytes */
            *msg_len_ptr = *boot_seq_ptr;
            *(msg_len_ptr + 1) = *(boot_seq_ptr - 1);
        }
        else if ( (*(boot_seq_ptr - 2) == 0x02) &&
             (*(boot_seq_ptr - 1) == 0x01) )
        {
            /* msg length encoded in 1 byte */
            *msg_len_ptr = *boot_seq_ptr;
        }
    
        return msg_len;
    }
    
    /* This API should only be called after all the rprc loading is complete */
    uint32_t Bootloader_getMulticoreImageSize(Bootloader_Handle handle)
    {
        uint32_t size = 0;
    
        if(handle != NULL)
        {
            Bootloader_Config *config = (Bootloader_Config *)handle;
            size = config->bootImageSize;
        }
        return size;
    }
    
    /* This API should only be called after the bootimage is parsed */
    uint32_t Bootloader_isCorePresent(Bootloader_Handle handle, uint32_t cslCoreId)
    {
        uint32_t retVal = FALSE;
    
        if(handle != NULL)
        {
            Bootloader_Config *config = (Bootloader_Config *)handle;
            if((config->coresPresentMap & (1 << cslCoreId)) != 0)
            {
                retVal = TRUE;
            }
        }
    
        return retVal;
    }
    
    uint32_t Bootloader_getBootMedia(Bootloader_Handle handle)
    {
        uint32_t media = BOOTLOADER_INVALID_ID;
    
        if(NULL != handle)
        {
            Bootloader_Config *config = (Bootloader_Config *)handle;
            media = config->bootMedia;
        }
    
        return media;
    }
    
    int32_t Bootloader_verifyMulticoreImage(Bootloader_Handle handle)
    {
        int32_t status = SystemP_FAILURE, authStatus = SystemP_FAILURE;
        uint32_t certLen = 0U, imageLen = 0U;
        uint32_t certLoadAddr = 0xFFFFFFFFU;
    
        Bootloader_Config *config = (Bootloader_Config *)handle;
    
        if(config->fxns->imgReadFxn == NULL || config->fxns->imgSeekFxn == NULL)
        {
            status = SystemP_FAILURE;
        }
        else
        {
            uint8_t x509Header[4];
            if((config->bootMedia == BOOTLOADER_MEDIA_MEM) ||
                    (config->bootMedia == BOOTLOADER_MEDIA_PCIE))
            {
                DebugP_log("Bootmedia is PCIE or MEM !! \n\r");
    
                Bootloader_MemArgs *memArgs = (Bootloader_MemArgs *)(config->args);
                certLoadAddr = memArgs->appImageBaseAddr;
            }
            else if(config->bootMedia == BOOTLOADER_MEDIA_FLASH)
            {
                DebugP_log("Bootmedia is Flash !! \n\r");
    
                Bootloader_FlashArgs *flashArgs = (Bootloader_FlashArgs *)(config->args);
                certLoadAddr = flashArgs->appImageOffset + SOC_getFlashDataBaseAddr();
            }
    #ifdef DRV_VERSION_MMCSD_V0
            else if(config->bootMedia == BOOTLOADER_MEDIA_EMMC)
            {
                DebugP_log("Bootmedia is eMMC !! \n\r");
    
                Bootloader_MmcsdArgs *mmcsdArgs = (Bootloader_MmcsdArgs *)(config->args);
                certLoadAddr = mmcsdArgs->appImageOffset;
    
                config->fxns->imgReadFxn(x509Header, 4, config->args);
                config->fxns->imgSeekFxn(0, config->args);
    
                if(config->scratchMemPtr != NULL)
                {
                    certLen = Bootloader_getX509CertLen(x509Header);
                    config->fxns->imgReadFxn((void *)config->scratchMemPtr, 0x800, config->args);
    
                    imageLen = Bootloader_getMsgLen((uint8_t *)config->scratchMemPtr, certLen);
    
                    uint32_t totalLen = (certLen + imageLen + 128) & ~(127);
    
                    DebugP_log("Bootmedia is eMMC, total length = %d !! \n\r", totalLen);
                    
    
                    config->fxns->imgSeekFxn(0, config->args);
                    config->fxns->imgReadFxn((void *)config->scratchMemPtr, totalLen, config->args);
    
                    certLoadAddr = (uint32_t)(&(config->scratchMemPtr[0]));
    
                    config->fxns->imgSeekFxn(0, config->args);
                }
            }
    #endif
            if (config->bootMedia != BOOTLOADER_MEDIA_EMMC)
            {
                /* Read first 4 bytes of the appimage to determine if it is signed with x509 certificate */
                config->fxns->imgReadFxn(x509Header, 4, config->args);
                config->fxns->imgSeekFxn(0, config->args);
    
                DebugP_log("Bootmedia is not eMMC hence compute certificate and image length !! \n\r");
    
                certLen = Bootloader_getX509CertLen(x509Header);
                imageLen = Bootloader_getMsgLen((uint8_t *)certLoadAddr, certLen);
            }
            /* Get the 128B cache-line aligned image length */
            uint32_t cacheAlignedLen = (certLen + imageLen + 128) & ~(127);
    
    	DebugP_log("Certificate Length: %d and Image Length: %d !! \n\r", certLen, imageLen);
    
            DebugP_log("Cache Aligned length: %d !! \n\r", cacheAlignedLen);
    
    
            /* Write back and invalidate the cache before passing to HSM */
            CacheP_wbInv((void *)certLoadAddr, cacheAlignedLen, CacheP_TYPE_ALL);
    
            /* Check if the certificate length is within valid range */
            if((certLen > 0x100) && (certLen < 0x800))
            {
    	    DebugP_log("Certificate length is valid \n\r");
                if(config->disableAppImageAuth == TRUE)
                {
                    /* NOTE: This is an option to skip image authentication in a signed
                    image to aid initial development on HS devices. If the user has
                    opted to disable image authentication, do not authenticate/decrypt.
                    Skip the certificate length and start loading as in GP */
                    authStatus = SystemP_SUCCESS;
                    DebugP_log("Image authentication skipped \n\r");
                }
                else
                {
                    authStatus = Bootloader_socAuthImage(certLoadAddr);
                    DebugP_log("Image authentication done, results authStatus: %d \n\r", authStatus);
                }
    
                /* Invalidate the cache before reading in case HSM decrypted image */
                CacheP_inv((void *)certLoadAddr, cacheAlignedLen, CacheP_TYPE_ALL);
    
                if(config->bootMedia == BOOTLOADER_MEDIA_BUFIO)
                {
                    /* Authentication will fail in Buf Io because we don't have full data yet,
                    so make it pass here for testing. Default behaviour is to assert. */
    
                    /* authStatus = SystemP_SUCCESS; */
                    DebugP_assertNoLog(authStatus == SystemP_SUCCESS);
                }
    
                if(authStatus == SystemP_FAILURE)
                {
                    status = SystemP_FAILURE;
                    DebugP_log("Image Authentication Failed !! \n\r");
                }
                else
                {
                    DebugP_log("Image Authentication passed !! \n\r");
                    /* Authentication passed, all good. Now re-init bootloader params to point to image start instead of start of x509 certificate */
                    if((config->bootMedia == BOOTLOADER_MEDIA_MEM) ||
                        (config->bootMedia == BOOTLOADER_MEDIA_PCIE))
                    {
                        Bootloader_MemArgs *memArgs = (Bootloader_MemArgs *)(config->args);
                        memArgs->appImageBaseAddr += certLen;
                    }
                    else if(config->bootMedia == BOOTLOADER_MEDIA_FLASH)
                    {
                        Bootloader_FlashArgs *flashArgs = (Bootloader_FlashArgs *)(config->args);
                        flashArgs->appImageOffset += certLen;
                        flashArgs->curOffset = flashArgs->appImageOffset;
                    }
                    else if(config->bootMedia == BOOTLOADER_MEDIA_BUFIO)
                    {
                        Bootloader_BufIoArgs *bufIoArgs = (Bootloader_BufIoArgs *)(config->args);
                        bufIoArgs->appImageOffset += certLen;
                        bufIoArgs->curOffset = bufIoArgs->appImageOffset;
                    }
    #ifdef DRV_VERSION_MMCSD_V0
                    else if(config->bootMedia == BOOTLOADER_MEDIA_EMMC)
                    {
                        Bootloader_MmcsdArgs *mmcsdArgs = (Bootloader_MmcsdArgs *)(config->args);
                        mmcsdArgs->appImageOffset += certLen;
                        mmcsdArgs->curOffset = mmcsdArgs->appImageOffset;
                    }
    #endif
                    status = SystemP_SUCCESS;
                }
            }
            else
            {
                status = SystemP_FAILURE;
            }
    
        }
        DebugP_log("Status value: %d !! \n\r", status);
    
    
        return status;
    }
    
    int32_t Bootloader_parseMultiCoreAppImage(Bootloader_Handle handle, Bootloader_BootImageInfo *bootImageInfo)
    {
        int32_t status = SystemP_SUCCESS;
    
        Bootloader_Config *config = (Bootloader_Config *)handle;
    
        if(config->fxns->imgReadFxn == NULL || config->fxns->imgSeekFxn == NULL)
        {
            status = SystemP_FAILURE;
        }
        else
        {
            Bootloader_MetaHeaderStart mHdrStr;
            Bootloader_MetaHeaderCore  mHdrCore[BOOTLOADER_MAX_INPUT_FILES];
    
            /* Verify the multicore image if authentication is required */
            if((Bootloader_socIsAuthRequired() == TRUE) && (config->isAppimageSigned == TRUE))
            {
                /* Device is HS, verify image. */
                DebugP_log("Starting to verify the image by calling Bootloader_verifyMulticoreImage() !! \n\r");
                status = Bootloader_verifyMulticoreImage(handle);
                DebugP_log("Image verified, status is: %d !! \n\r", status);
    
            }
            else
            {
                /* Device is GP, no authentication required OR appimage is not signed, boot like GP */
                status = SystemP_SUCCESS;
            }
    
            if(SystemP_SUCCESS == status)
            {
                memset(&mHdrCore[0], 0xFF, BOOTLOADER_MAX_INPUT_FILES*sizeof(Bootloader_MetaHeaderCore));
    
                status = config->fxns->imgReadFxn(&mHdrStr, sizeof(Bootloader_MetaHeaderStart), config->args);
    
                DebugP_log("Image parsed successfully !! \n\r");
    
    
                if(mHdrStr.magicStr != BOOTLOADER_META_HDR_MAGIC_STR)
                {
                    status = SystemP_FAILURE;
                }
                else
                {
                    /* TODO */
                    /* Check for device Id later if needed, just a warning */
    
                    /* Read all the core offset addresses */
                    uint32_t i;
    
                    DebugP_log("Starting to read all the core offset addresses !! \n\r");
    
    
                    for(i=0U; i<mHdrStr.numFiles; i++)
                    {
                        status = config->fxns->imgReadFxn(&mHdrCore[i], sizeof(Bootloader_MetaHeaderCore), config->args);
                        /* TODO: Figure out how to add boot media specific offset */
                    }
    
                    DebugP_log("Starting to parse individual rprc files !! \n\r");
    
    
                    /* Parse individual rprc files */
                    for(i=0U; i<mHdrStr.numFiles; i++)
                    {
                        if(mHdrCore[i].coreId != (0xFFFFFFFFU))
                        {
                            uint32_t cslCoreId = Bootloader_socRprcToCslCoreId(mHdrCore[i].coreId);
                            Bootloader_CpuInfo *cpuInfo = &bootImageInfo->cpuInfo[cslCoreId];
                            cpuInfo->rprcOffset = mHdrCore[i].imageOffset;
                            cpuInfo->entryPoint = 0;
                            cpuInfo->cpuId      = cslCoreId;
                            config->coresPresentMap |= (1 << cslCoreId);
                        }
                    }
                }
            }
            else
            {
                status = SystemP_FAILURE;
            }
        }
    
        return status;
    }
    
    void Bootloader_Params_init(Bootloader_Params *params)
    {
        params->memArgsAppImageBaseAddr = BOOTLOADER_INVALID_ID;
    }
    
    void Bootloader_CpuInfo_init(Bootloader_CpuInfo *cpuInfo)
    {
        cpuInfo->cpuId = CSL_CORE_ID_MAX;
        cpuInfo->clkHz = 0U;
        cpuInfo->rprcOffset = BOOTLOADER_INVALID_ID;
        cpuInfo->entryPoint = BOOTLOADER_INVALID_ID;
    }
    
    void Bootloader_BootImageInfo_init(Bootloader_BootImageInfo *bootImageInfo)
    {
        uint16_t i;
    
        for(i=0; i<CSL_CORE_ID_MAX; i++)
        {
            Bootloader_CpuInfo_init(&bootImageInfo->cpuInfo[i]);
            bootImageInfo->cpuInfo[i].cpuId = i;
            bootImageInfo->cpuInfo[i].clkHz = Bootloader_socCpuGetClkDefault(i);
        }
    }
    
    #if defined (SOC_AM64X)
    /* Linux image load is applicable only for am64x. */
    int32_t Bootloader_parseAndLoadLinuxAppImage(Bootloader_Handle handle, Bootloader_BootImageInfo *bootImageInfo)
    {
        int32_t status = SystemP_SUCCESS;
    
        Bootloader_Config *config = (Bootloader_Config *)handle;
    
        if(config->fxns->imgReadFxn == NULL || config->fxns->imgSeekFxn == NULL)
        {
            status = SystemP_FAILURE;
        }
        else
        {
            Bootloader_MetaHeaderStart mHdrStr;
            Bootloader_MetaHeaderCore  mHdrCore[BOOTLOADER_MAX_INPUT_FILES];
    
            /* Verify the multicore image if authentication is required */
            if(Bootloader_socIsAuthRequired() == TRUE)
            {
                /* Device is HS, verify image. */
                status = Bootloader_verifyMulticoreImage(handle);
            }
            else
            {
                /* Device is GP, no authentication required */
                status = SystemP_SUCCESS;
            }
    
            if(SystemP_SUCCESS == status)
            {
    
                memset(&mHdrCore[0], 0xFF, BOOTLOADER_MAX_INPUT_FILES*sizeof(Bootloader_MetaHeaderCore));
    
                status = config->fxns->imgReadFxn(&mHdrStr, sizeof(Bootloader_MetaHeaderStart), config->args);
    
                if(mHdrStr.magicStr != BOOTLOADER_META_HDR_MAGIC_STR)
                {
                    status = SystemP_FAILURE;
                }
                else
                {
                    /* TODO */
                    /* Check for device Id later if needed, just a warning */
    
                    /* Read all the core offset addresses */
                    uint32_t i;
    
                    for(i=0U; i<mHdrStr.numFiles; i++)
                    {
                        status = config->fxns->imgReadFxn(&mHdrCore[i], sizeof(Bootloader_MetaHeaderCore), config->args);
                        /* TODO: Figure out how to add boot media specific offset */
                    }
    
                    /* Parse individual rprc files */
                    for(i=0U; i<mHdrStr.numFiles; i++)
                    {
                        /* Load the load only linux images */
                        if(mHdrCore[i].coreId == RPRC_LINUX_LOAD_ONLY_IMAGE_ID)
                        {
                            Bootloader_CpuInfo load_only_image;
                            load_only_image.rprcOffset = mHdrCore[i].imageOffset;
                            load_only_image.entryPoint = 0;
    
                            /* Set CPU ID as A53 as linux runs on A53 */
                            load_only_image.cpuId = CSL_CORE_ID_A53SS0_0;
    
                            /**************/
                            if (status == SystemP_SUCCESS)
                            {
                                status = Bootloader_rprcImageLoad(handle, &load_only_image);
                            }
    
                            continue;
                        }
    
                        if(mHdrCore[i].coreId != (0xFFFFFFFFU))
                        {
                            uint32_t cslCoreId = Bootloader_socRprcToCslCoreId(mHdrCore[i].coreId);
                            Bootloader_CpuInfo *cpuInfo = &bootImageInfo->cpuInfo[cslCoreId];
                            cpuInfo->rprcOffset = mHdrCore[i].imageOffset;
                            cpuInfo->entryPoint = 0;
                            cpuInfo->cpuId      = cslCoreId;
                            config->coresPresentMap |= (1 << cslCoreId);
                        }
                    }
                }
            }
            else
            {
                status = SystemP_FAILURE;
            }
        }
    
        return status;
    }
    
    int32_t Bootloader_runSelfCpuWithLinux(void)
    {
        int32_t status = SystemP_SUCCESS;
    
        DebugP_logInfo("All done, reseting self ...\r\n\n");
        status = Bootloader_socCpuResetReleaseSelf();
        /* control will not reach here */
    
        return status;
    }
    
    #endif

    Looking forward to the new logs.

    Regards,

    Vaibhav

  • Hi Vaibhav,

    Here's the working output:

    Cache Aligned length: 786560 !!
    Certificate length is valid
    Image authentication done, results authStatus: 0
    Image Authentication passed !!
    Status value: 0 !!
    Image verified, status is: 0 !!
    Image parsed successfully !!
    Starting to read all the core offset addresses !!
    Starting to parse individual rprc files !!

    Here is the nonworking mode 4S-4S-4S at 50MHz

    Cache Aligned length: 786560 !!
    Certificate length is valid
    Image authentication done, results authStatus: -1
    Image Authentication Failed !!
    Status value: -1 !!
    Image verified, status is: -1 !!

    I can't seem to attach a json file.

    Thanks,

    Joe

  • Hello Joe,

    Thank you very much for doing the debugging and running the application with the updated code I provided.

    I really appreciate it.

    So, as we can see that the problem is happening while image authentication.

    So our next step would be to dig deeper inside of this API which does the image authentication.

    Before that can you pleasemake sure to provide me the complete logs?

    Because the line DebugP_log("Certificate Length: %d and Image Length: %d !! \n\r", certLen, imageLen);

    is executed after your prints like "Cache aligned length: 786560"

    So, this is not seen in your logs.

    Can you please update the logs.

    Thanks,

    Vaibhav

  • HI Vaibhav, I have noticed that I have to step through boot one line at a time.  If I don't then the debug log is overrun and doesn't print.  I will try to spot the line you mentioned and step passed it manually.

    Thanks

    Joe

  • Hi Vaibhav,

    Here's the result of a slow step through:

    Starting to verify the image by calling Bootloader_verifyMulticoreImage() !!
    Bootmedia is Flash !!
    Bootmedia is not eMMC hence compute certificate and image length !!
    Certificate Length: 1654 and Image Length: 784984 !!
    Cache Aligned length: 786688 !!
    Certificate length is valid
    Image authentication done, results authStatus: -1
    Image Authentication Failed !!

    I can also see that Sciclient_procBootAuthAndStart is returning -1 for failure. It's challenging to debug Sciclient code.  Is it due to optimization that you cannot step through it linearly?  

    Thanks,

    Joe

  • Hello Joe,

    Thank you very much for your patience.

    Base don the logs you have provided, I am seeing that the image authentication is failing. I also see that the certificate length is valid and we are past that point.

    I also appreciate you taking out time to debug the code changes I sent you.

    I am populating some logs inside the API Bootloader_socAuthImage() because that is where you are seeing failures.

    Can you confirm if all the images you are flashing are hs fs?

    Regards,

    Vaibhav

  • Hi Vaibhav,

    This is the setting I'm using in the Bootloader.

    Thanks,

    Joe

  • Can you confirm if all the images you are flashing are hs fs?

    Can you please confirm this?

  • Hi Vaibhav,

    The app image is hs_fs.  Does changing sysconfig OSPI settings have any impact on the X509 cert or any other aspect of security?  The reason I ask is the same application loads without issue when running 4S-4D-4D mode.  If OSPI settings and the Flash driver settings have no impact on security I think we might be chasing the wrong issue with image authentication. 

    It would seem to me this is either a hardware issue or OSPI driver issue.

    Thanks,

    Joe

  • Hello Joe,

    We can do one thing at this point.

    I think it will be a good practise to start comparing the result of the two modes here.

    So I am preparing a detailed table for you to carry out the test results for us to debug properly.

    Allow me sometime on the same.

    Regards,

    Vaibhav

  • Mode of operation Tests (Perform the test while you are debugging the bootloader code in main.c) Image Flashed Offset
    4S-4S-4S (Does not work) Take a look at image contents by putting the address (0x60000000 + offset x for Image 1, 0x60000000 + offset y for Image 2, and so on) = Result 1  Image 1, Image 2, ... flashed Image 1 offset x, Image 2 offset y, .. 
    4S-4D-4D (Works) Take a look at image contents by putting the address (0x60000000 + offset x for Image 1, 0x60000000 + offset y for Image 2, and so on) = Result 2 Image 1, Image 2, ... flashed Image 1 offset x, Image 2 offset y, .. 

    Compare the results Result 1 with Result 2: If both of them are same, then you can proceed to disable Image authentication in the SysConfig.

    But if you see that Result 1 != Result 2 then we can debug further.

    Please help me gather the results as soon as possible for further debug steps(if needed).

    Let me know if you need help in performing the tests.

    Regards,

    Vaibhav

  • Ok, Vaibhav.  I will capture results.  My initial test showed the first x480 bytes of flash were the same between the protocols.  I proceeded to disable image authentication.  The result was that the app crashed part way through boot.  

    I will try to run a compare of the entire image this time and see if there's data corruption beyond that point.

    Thank you,

    Joe

  • Hi Vaibhav,

    I have a number of results to share.

    First, using the dfu-util console output I captured the exact number of bytes for the single concatenated app image at the FSS address + offset.  I converted that number of bytes to 32 bit words and used that value as the length when saving memory using the Memory Browser tool.

    • Comparing 4S4D4D mode at 20MHz to 4S4S4S mode at 50MHz, the diff discovered dozens of single bit errors
    • Dividing the reference clock by 6, 8, and 16 I was able to capture 4S4S4S memory that was identical to 4S4D4D mode.
    • Allowing the OSPI driver to determine its own value for Tap Delay (Delay_FLD), the result was multiple bit errors compared to 4S4D4D mode.  It would select a Tap Delay of 4, when only 2 and 3 were valid.
    • Determining the proper Tap Delay in excel, and making the API call: OSPI_setRdDataCaptureDelay. I was able to get 4S4S4S memory to match 4S4D4D using refdiv by 6,8,and 16.

    Once I was able to produce identical readback images in memory for both protocols, I proceeded to let Bootloader_parseMultiCoreAppImage() to execute.  Unfortunately, this yielded a status of -1 failure again.

    I went back to SysConfig and Disabled Auth for the Application Image.  This resulted in my app loading and operating as expected.  Now that OSPI hardware timing issues appear to be removed, something is indeed not working in parseMultiCoreAppImage.

    Thanks,

    Joe

  • Hi Vaibhav,

    It still fails with the App_authenticateAppImage() function.


    DMSC Firmware Version 10.0.8--v10.00.08 (Fiery Fox)
    DMSC Firmware revision 0xa
    DMSC ABI revision 4.0

    Certificate address: 0x60080000
    Authentication failed

  • Hello Joe,

    Then we can try to see the logs and the logs can help us identify where it might be failing. It can lead us to some clues for sure.

    Please read through this on how to enable the System Firmware logs: https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1385153/mcu-plus-sdk-am243x-app-image-authentication-by-bootloader_socauthimage/5316653#5316653

    Regards,

    Vaibhav

  • Hi Vaibhav,

    Not sure if I captured this correctly, but I saved the memory directly in binary format.

    tracetest3.txt
    21BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x44000
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x44000
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x44000
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x44000
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x44000
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x44000
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42FD0
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42FD0
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F90
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F90
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F80
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F50
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F50
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F30
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F30
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F20
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F10
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F10
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F00
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42EF0
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F00
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F30
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F30
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F40
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F40
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F50
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F60
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F60
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F70
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F70
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F80
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42F80
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42FB0
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x42FB0
     0x0
     0x421BD4
     0x4
    
    Exception  0x1020100
     0x30000
     0x44000
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x44000
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x44000
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x44000
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x44000
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x44000
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x44000
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x44000
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x44000
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x44000
     0x0
     0x421BD4
     0x4
    
    Exception addr  0x45B00000
    FWL Exception  0x1020100
     0x30000
     0x44000
     0x0
     0x4