Esempio n. 1
0
void initPnor()
{
    TRACFCOMP(g_trac_pnor, ENTER_MRK"initPnor");
    errlHndl_t l_errl = nullptr;

    // Only run PNOR init on non-FSP based systems
    if ( !INITSERVICE::spBaseServicesEnabled() )
    {
      // call static init() function to save PNOR section into memory
      RtPnor::init(l_errl);
      if (l_errl)
      {
        TRACFCOMP(g_trac_pnor,ERR_MRK"initPnor: "
                      "Failed RtPnor::init() with EID %.8X:%.4X",
                      ERRL_GETEID_SAFE(l_errl),
                      ERRL_GETRC_SAFE(l_errl) );
        errlCommit (l_errl, PNOR_COMP_ID);
      }
    }
    TRACFCOMP(g_trac_pnor, EXIT_MRK"initPnor");
}
Esempio n. 2
0
errlHndl_t initiateDrtm()
{
    SB_ENTER("initiateDrtm");

    errlHndl_t pError = nullptr;

    // For DRTM, the thread has to be pinned to a core (and therefore pinned to
    // a chip)
    task_affinity_pin();

    void* drtmPayloadVirtAddr = nullptr;

    do
    {
        const std::vector<SECUREBOOT::ProcSecurity> LLP {
            SECUREBOOT::ProcSecurity::LLPBit,
        };

        const std::vector<SECUREBOOT::ProcSecurity> LLS {
            SECUREBOOT::ProcSecurity::LLSBit,
        };

        // Determine which fabric group and chip this task is executing on and
        // create a filter to find the matching chip target
        auto cpuId = task_getcpuid();
        auto groupId = PIR_t::groupFromPir(cpuId);
        auto chipId = PIR_t::chipFromPir(cpuId);
        TARGETING::PredicateAttrVal<TARGETING::ATTR_FABRIC_GROUP_ID>
            matchesGroup(groupId);
        TARGETING::PredicateAttrVal<TARGETING::ATTR_FABRIC_CHIP_ID>
            matchesChip(chipId);
        TARGETING::PredicatePostfixExpr matchesGroupAndChip;
        matchesGroupAndChip.push(&matchesGroup).push(&matchesChip).And();

        // Get all the functional proc chips and find the chip we're running on
        TARGETING::TargetHandleList funcProcChips;
        TARGETING::getAllChips(funcProcChips,
                               TARGETING::TYPE_PROC);
        if(funcProcChips.empty())
        {
            // TODO: RTC 167205: GA error handling
            assert(false,"initiateDrtm: BUG! Functional proc chips is empty, "
                "yet this code is running on a functional chip!");
            break;
        }

        // NOTE: std::find_if requires predicates to be copy constructable, but
        // predicates are not; hence use a wrapper lambda function to bypass
        // that limitation
        auto pMatch =
            std::find_if(funcProcChips.begin(),funcProcChips.end(),
                [&matchesGroupAndChip] ( TARGETING::Target* pTarget )
                {
                    return matchesGroupAndChip(pTarget);
                } );

        if(pMatch == funcProcChips.end())
        {
            // TODO: RTC 167205: GA error handling
            assert(false, "initiateDrtm: BUG! No functional chip found "
                "to be running this code");
            break;
        }

        // Move the matching target to the end of the list.
        // NOTE: If reverse iterators were supported, we could have verified the
        // last element of the container is not the match, and done a
        // std::iter_swap of the match and the last element
        TARGETING::Target* const pMatchTarget = *pMatch;
        funcProcChips.erase(pMatch);
        funcProcChips.push_back(pMatchTarget);

        // Map to the DRTM payload area in mainstore
        const uint32_t drtmPayloadPhysAddrMb = DRTM_RIT_PAYLOAD_PHYS_ADDR_MB;
        drtmPayloadVirtAddr = mm_block_map(
            reinterpret_cast<void*>(drtmPayloadPhysAddrMb*BYTES_PER_MEGABYTE),
            PAGESIZE);
        if(drtmPayloadVirtAddr == nullptr)
        {
            // TODO: RTC 167205: GA error handling
            assert(false, "initiateDrtm: BUG! Failed in call to mm_block_map "
                "to map the DRTM payload.");
            break;
        }

        // Copy the DRTM payload to the DRTM payload area
        memcpy(
            reinterpret_cast<uint32_t*>(drtmPayloadVirtAddr),
            DRTM_RIT_PAYLOAD,
            sizeof(DRTM_RIT_PAYLOAD));

        // The required generic sequencing to initiate DRTM is as follows:
        // 1) Initiating task must pin itself to a core (to ensure it
        //     will not be accidentally queisced by SBE)
        // 2) It must set the DRTM payload information in the master processor
        //     mailbox scratch registers (registers 7 and 8) before it goes
        //     offline
        // 3) It must determine the processor it's currently running on
        // 4) It must set the late launch bit (LL) on all other processors
        //     4a) If the given processor is an active master, it must set
        //         late launch primary (LLP) bit
        //     4b) Otherwise it must set late launch secondary (LLS) bit
        // 5) Finally, it must its own processor's LL bit last, according to the
        //     rules of step 4.
        for(auto &pFuncProc :funcProcChips)
        {
            const auto procMasterType = pFuncProc->getAttr<
                TARGETING::ATTR_PROC_MASTER_TYPE>();

            // If master chip, set the DRTM payload address and validity
            if(procMasterType == TARGETING::PROC_MASTER_TYPE_ACTING_MASTER)
            {
                (void)setDrtmPayloadPhysAddrMb(drtmPayloadPhysAddrMb);
            }

            pError = SECUREBOOT::setSecuritySwitchBits(procMasterType ==
                         TARGETING::PROC_MASTER_TYPE_ACTING_MASTER ?
                            LLP : LLS,
                         pFuncProc);
            if(pError)
            {
                SB_ERR("initiateDrtm: setSecuritySwitchBits() failed for proc "
                    "= 0x%08X. Tried to set LLP or LLS.",
                    get_huid(pFuncProc));
                break;
            }
        }

        if(pError)
        {
            break;
        }


        SB_INF("initiateDrtm: SBE should eventually quiesce all cores; until "
            "then, endlessly yield the task");
        while(1)
        {
            task_yield();
        }

    } while(0);

    // If we -do- come back from this function (on error path only), then we
    // should unpin
    task_affinity_unpin();

    if(drtmPayloadVirtAddr)
    {
        auto rc = mm_block_unmap(const_cast<void*>(drtmPayloadVirtAddr));
        if(rc != 0)
        {
            // TODO: RTC 167205: GA error handling
            assert(false,"initiateDrtm: BUG! mm_block_unmap failed for virtual "
                "address 0x%16llX.",
                drtmPayloadVirtAddr);
        }
    }

    if(pError)
    {
        SB_ERR("initiateDrtm: plid=0x%08X, eid=0x%08X, reason=0x%04X",
               ERRL_GETPLID_SAFE(pError),
               ERRL_GETEID_SAFE(pError),
               ERRL_GETRC_SAFE(pError));
    }

    SB_EXIT("initiateDrtm");

    return pError;
}
Esempio n. 3
0
errlHndl_t validateDrtmPayload()
{
    SB_ENTER("validateDrtmPayload");

    errlHndl_t pError = nullptr;
    const void* drtmPayloadVirtAddr = nullptr;

    do
    {
        bool drtmMpIpl = false;
        isDrtmMpipl(drtmMpIpl);

        if(drtmMpIpl)
        {
            SB_DBG("validateDrtmPayload: DRTM active, validating DRTM payload."
                "proc chips.");

            TARGETING::Target* pSysTarget = nullptr;
            TARGETING::targetService().getTopLevelTarget(pSysTarget);

            if(pSysTarget == nullptr)
            {
                // TODO: RTC 167205: GA error handling
                assert(false,"validateDrtmPayload: BUG! nullptr system target "
                    "detected");
                break;
            }

            const auto drtmPayloadPhysAddrMb = pSysTarget->getAttr<
                TARGETING::ATTR_DRTM_PAYLOAD_ADDR_MB_HB>();

            if(drtmPayloadPhysAddrMb == 0)
            {
                assert(false,"validateDrtmPayload: BUG! DRTM payload physical "
                    "address should not be 0.");
                break;
            }

            const uint64_t drtmPayloadPhysAddr =
                drtmPayloadPhysAddrMb*BYTES_PER_MEGABYTE;

            SB_INF("validateDrtmPayload: DRTM payload available at physical "
                "address of %d MB (0x%16llX).",
                drtmPayloadPhysAddrMb,drtmPayloadPhysAddr);

            // Compute DRTM payload size
            // TODO: RTC 167205: Once the DRTM save area is known/defined,
            // need to figure out a better initial size to map.  For example,
            // perhaps we map just one page to begin with, in order to read out
            // the actual total size.  Also, a size is available, assert if the
            // size is 0.
            uint64_t drtmPayloadSize = 0;
            #ifdef CONFIG_DRTM_TRIGGERING
            drtmPayloadSize = ALIGN_PAGE(sizeof(DRTM_RIT_PAYLOAD));
            #endif

            // Map in the physical memory to virtual memory
            drtmPayloadVirtAddr = mm_block_map (
                reinterpret_cast<void*>(drtmPayloadPhysAddr),drtmPayloadSize);
            if(drtmPayloadVirtAddr == nullptr)
            {
                // TODO: RTC 167205: GA error handling
                assert(false,"validateDrtmPayload: BUG! mm_block_map returned "
                    "nullptr for physical address 0x%016llX and size "
                    "0x%016llX.",
                    drtmPayloadPhysAddr,drtmPayloadSize);
                break;
            }

            #ifdef CONFIG_DRTM_TRIGGERING

            // Verify the payload matches expected result
            if(memcmp(drtmPayloadVirtAddr,DRTM_RIT_PAYLOAD,
                   sizeof(DRTM_RIT_PAYLOAD) != 0))
            {
                const uint32_t* pAddrAct = reinterpret_cast<const uint32_t*>(
                    drtmPayloadVirtAddr);
                const uint32_t* pAddrExp = reinterpret_cast<const uint32_t*>(
                    &DRTM_RIT_PAYLOAD);

                SB_ERR("validateDrtmPayload: DRTM RIT: payload content at "
                    "0x%16llX was not as expected.  Expected value = 0x%08X, "
                    "actual = 0x%08X",
                    drtmPayloadVirtAddr,
                    *pAddrAct,
                    *pAddrExp);

                // TODO: RTC 167205: GA error handling
                assert(false,"validateDrtmPayload: BUG: DRTM payload content "
                    "at 0x%16llX was not as expected.  Expected value = "
                    "0x%08X, actual = 0x%08X",
                    drtmPayloadVirtAddr,
                    *pAddrAct,
                    *pAddrExp);
                break;
            }

            // Extend (arbitrary) measurement to PCR17
            SHA512_t hash = {0};
            memcpy(hash,DRTM_RIT_PAYLOAD,sizeof(DRTM_RIT_PAYLOAD));
            pError = TRUSTEDBOOT::pcrExtend(TRUSTEDBOOT::PCR_DRTM_17,
                                            TRUSTEDBOOT::EV_COMPACT_HASH,
                                            hash,
                                            sizeof(SHA512_t),DRTM_RIT_LOG_TEXT);
            if(pError)
            {
                SB_ERR("validateDrtmPayload: Failed in pcrExtend() for PCR 17");
                break;
            }

            #else

            // TODO: RTC 167205: Securely verify the measured launch environment
            // TODO: RTC 167205: Really measure+extend the payload

            #endif
        }
        else
        {
            SB_INF("validateDrtmPayload: DRTM not active, skipping DRTM "
                "payload verification ");
        }

    } while(0);

    if(drtmPayloadVirtAddr)
    {
        auto rc = mm_block_unmap(const_cast<void*>(drtmPayloadVirtAddr));
        if(rc != 0)
        {
            // TODO: RTC 167205: GA error handling
            assert(false,"validateDrtmPayload: BUG! mm_block_unmap failed for "
                "virtual address 0x%16llX.",
                drtmPayloadVirtAddr);

        }
    }

    if(pError)
    {
        SB_ERR("validateDrtmPayload: plid=0x%08X, eid=0x%08X, reason=0x%04X",
               ERRL_GETPLID_SAFE(pError),
               ERRL_GETEID_SAFE(pError),
               ERRL_GETRC_SAFE(pError));
    }

    SB_EXIT("validateDrtmPayload");

    return pError;
}
Esempio n. 4
0
errlHndl_t completeDrtm()
{
    SB_ENTER("completeDrtm");

    errlHndl_t pError = nullptr;

    do
    {
        bool drtmMpIpl = false;
        isDrtmMpipl(drtmMpIpl);

        if(drtmMpIpl)
        {
            SB_INF("completeDrtm: Clearing L4A and LQA on node's functional "
                   "proc chips.");

            const std::vector<SECUREBOOT::ProcSecurity> bitsToClear {
                SECUREBOOT::ProcSecurity::L4ABit,
                SECUREBOOT::ProcSecurity::LQABit
            };

            TARGETING::TargetHandleList funcProcChips;
            TARGETING::getAllChips(funcProcChips,
                                   TARGETING::TYPE_PROC);

            for(auto &pFuncProc :funcProcChips)
            {
                pError = SECUREBOOT::clearSecuritySwitchBits(bitsToClear,
                             pFuncProc);
                if(pError)
                {
                    // TODO: RTC 167205: GA error handling to attempt on every
                    // processor
                    SB_ERR("completeDrtm: clearSecuritySwitchBits() failed for "
                        "proc = 0x%08X. Tried to clear LQA + L4A.",
                        get_huid(pFuncProc));
                    break;
                }
            }

            if(pError)
            {
                break;
            }

        }
        else
        {
            SB_INF("completeDrtm: DRTM not active, not clearing LQA or L4A "
                "bits.");
        }

    } while(0);

    if(pError)
    {
        SB_ERR("completeDrtm: plid=0x%08X, eid=0x%08X, reason=0x%04X",
               ERRL_GETPLID_SAFE(pError),
               ERRL_GETEID_SAFE(pError),
               ERRL_GETRC_SAFE(pError));
    }

    SB_EXIT("completeDrtm");

    return pError;
}
Esempio n. 5
0
errlHndl_t validateDrtmHwSignature()
{
    SB_ENTER("validateDrtmHwSignature");

    errlHndl_t pError = nullptr;

    do
    {
        bool drtmMpIpl = false;
        isDrtmMpipl(drtmMpIpl);

        if(drtmMpIpl)
        {
            SB_DBG("validateDrtmHwSignature: DRTM active, checking L4A, LQA, "
                "SUL, LLS and LLP on node's functional proc chips.");

            TARGETING::TargetHandleList funcProcChips;
            TARGETING::getAllChips(funcProcChips,
                                   TARGETING::TYPE_PROC);
            for(auto &pFuncProc :funcProcChips)
            {
                uint64_t securitySwitches = 0;
                pError = SECUREBOOT::getSecuritySwitch(securitySwitches,
                             pFuncProc);
                if(pError)
                {
                    SB_ERR("validateDrtmHwSignature: getSecuritySwitch() "
                        "failed for proc = 0x%08X.",
                        get_huid(pFuncProc));
                    break;
                }

                const bool L4A = securitySwitches
                    & static_cast<uint64_t>(SECUREBOOT::ProcSecurity::L4ABit);
                const bool LQA = securitySwitches
                    & static_cast<uint64_t>(SECUREBOOT::ProcSecurity::LQABit);
                const bool SUL = securitySwitches
                    & static_cast<uint64_t>(SECUREBOOT::ProcSecurity::SULBit);
                const bool LLP = securitySwitches
                    & static_cast<uint64_t>(SECUREBOOT::ProcSecurity::LLPBit);
                const bool LLS = securitySwitches
                    & static_cast<uint64_t>(SECUREBOOT::ProcSecurity::LLSBit);

                SB_INF("validateDrtmHwSignature: Proc 0x%08X has L4A = %d, "
                    "LQA = %d, SUL = %d, LLP = %d, LLS = %d.",
                    get_huid(pFuncProc),L4A,LQA,SUL,LLP,LLS);

                if(!L4A || !LQA || !SUL || LLP || LLS)
                {
                    // TODO: RTC 167205: GA error handling, including whether
                    // to attempt on every processor
                    assert(false,"validateDrtmHwSignature: BUG! In DRTM flow, "
                        "all functional proc chips should have L4A, LQA, and "
                        "SUL set + LLP and LLS clear, however proc 0x%08X has "
                        "L4A = %d, LQA = %d, SUL = %d, LLP = %d, LLS = %d.",
                        get_huid(pFuncProc),L4A,LQA,SUL,LLP,LLS);
                    break;
                }
            }

            if(pError)
            {
                break;
            }
        }
        else
        {
            SB_INF("validateDrtmHwSignature: DRTM not active, skipping check "
                "for L4A, LQA, SUL, LLP and LLS on node's functional procs");
        }

    } while(0);

    if(pError)
    {
        SB_ERR("validateDrtmHwSignature:  plid=0x%08X, eid=0x%08X, "
            "reason=0x%04X",
            ERRL_GETPLID_SAFE(pError),
            ERRL_GETEID_SAFE(pError),
            ERRL_GETRC_SAFE(pError));
    }

    SB_EXIT("validateDrtmHwSignature");

    return pError;
}