summaryrefslogtreecommitdiffstats
path: root/src/usr/util/utilmclmgr.C
blob: 334d0af1d174185751b1022f88da03580343e01b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/util/utilmclmgr.C $                                   */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2017,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#include <util/utilmclmgr.H>
#include <util/utillidmgr.H>
#include <util/util_reasoncodes.H>
#include "utilbase.H"
#include <sys/mm.h>
#include <sys/misc.h>
#include <errl/errlentry.H>
#include <errl/errlmanager.H>
#include <initservice/initserviceif.H>
#include <secureboot/trustedbootif.H>
#include <runtime/preverifiedlidmgr.H>
#include <limits.h>
#include <util/utiltce.H>

namespace MCL
{

uint8_t MasterContainerLidMgr::cv_pPhypHeader[PAGESIZE] = {0};

const size_t MclCompSectionPadSize = 16;

const ComponentID g_MclCompId {"MSTCONT"};
const ComponentID g_PowervmCompId {"POWERVM"};
const ComponentID g_OpalCompId {"OPAL"};
const ComponentID g_UcdCompId {"UCD9090"};
const ComponentID g_NvdimmCompId {"NVDIMM"};

void compIdToString(const ComponentID i_compId, CompIdString o_compIdStr)
{
    memcpy(o_compIdStr,
           i_compId.data(),
           sizeof(ComponentID));
}

uint64_t compIdToInt(const ComponentID i_compId)
{
    uint64_t l_compId {};

    memcpy(&l_compId, i_compId.data(), sizeof(l_compId));

    return l_compId;
}

RomVerifyIds extractLidIds(const std::vector<LidInfo>& i_lidIds)
{
    RomVerifyIds l_ids {};
    for (auto const& id : i_lidIds)
    {
        l_ids.push_back(id.id);
    }

    return l_ids;
}

////////////////////////////////////////////////////////////////////////////////
// CompInfo
////////////////////////////////////////////////////////////////////////////////

void CompInfo::print() const
{
    UTIL_FT("  - Flags: 0x%04X", flags);
    UTIL_FT("  - Mainstore Addr: 0x%llX", mainstoreAddr);
    UTIL_FT("  - Total Size: 0x%llX", totalSize);
    UTIL_FT("  - Protected Size: 0x%llX", protectedSize);
    UTIL_FT("  - Unprotected Size: 0x%llX", unprotectedSize);
    UTIL_FT("  - LidIds:");
    for (auto lidInfo : lidIds)
    {
        UTIL_FT("    - 0x%08X, size 0x%X", lidInfo.id, lidInfo.size);
    }
}

////////////////////////////////////////////////////////////////////////////////
// MasterContainerLidMgr
////////////////////////////////////////////////////////////////////////////////

MasterContainerLidMgr::MasterContainerLidMgr(const bool i_loadOnly)
: iv_mclSize(MCL_SIZE), iv_tmpSize(MCL_TMP_SIZE), iv_maxSize(0),
  iv_pMclVaddr(nullptr), iv_pTempVaddr(nullptr), iv_pVaddr(nullptr),
  iv_compInfoCache{}, iv_hasHeader(true), iv_loadOnly(i_loadOnly)
{
    // Need to make Memory spaces HRMOR-relative
    uint64_t hrmorVal = cpu_spr_value(CPU_SPR_HRMOR);
    iv_mclAddr = hrmorVal - VMM_HRMOR_OFFSET + MCL_ADDR;
    iv_tmpAddr = hrmorVal - VMM_HRMOR_OFFSET + MCL_TMP_ADDR;

    initMcl();
}

MasterContainerLidMgr::MasterContainerLidMgr(const void* i_pMcl,
                                             const size_t i_size)
: iv_mclSize(MCL_SIZE), iv_tmpSize(MCL_TMP_SIZE), iv_maxSize(0),
  iv_pMclVaddr(nullptr), iv_pTempVaddr(nullptr), iv_pVaddr(nullptr),
  iv_compInfoCache{}, iv_hasHeader(false)
{
    // Need to make Memory spaces HRMOR-relative
    uint64_t hrmorVal = cpu_spr_value(CPU_SPR_HRMOR);
    iv_mclAddr = hrmorVal - VMM_HRMOR_OFFSET + MCL_ADDR;
    iv_tmpAddr = hrmorVal - VMM_HRMOR_OFFSET + MCL_TMP_ADDR;


    initMcl(i_pMcl, i_size);
}

MasterContainerLidMgr::~MasterContainerLidMgr()
{
    // Release all address spaces
    releaseMem(iv_tmpAddr, iv_pMclVaddr);
    releaseMem(iv_tmpAddr, iv_pTempVaddr);
}

void MasterContainerLidMgr::initMcl(const void* i_pMcl, const size_t i_mclSize)
{
    UTIL_DT(ENTER_MRK"MasterContainerLidMgr::initMcl");

    errlHndl_t l_errl = nullptr;

    // Add MCL itself to Cache but don't add to comp order
    CompInfo l_compHdrInfo(CompFlags::SIGNED_PRE_VERIFY);
    LidInfo l_hdrLidInfo(Util::MCL_LIDID);
    l_compHdrInfo.lidIds.push_back(l_hdrLidInfo);
    iv_compInfoCache.insert(std::make_pair(g_MclCompId, l_compHdrInfo));

    // Cache Component ID string
    compIdToString(g_MclCompId, iv_curCompIdStr);

    // Initialize MCL address space
    initMem(iv_mclAddr, iv_mclSize, iv_pMclVaddr);

    // Use MCL address and size for parsing
    iv_pVaddr = iv_pMclVaddr;
    iv_maxSize = iv_mclSize;

    if(i_pMcl != nullptr)
    {
        // set cached MCL pointer with custom MCL
        memcpy(iv_pMclVaddr, i_pMcl, i_mclSize);
    }
    else
    {
        // No custom MCL, load default way
        l_errl = processComponent(g_MclCompId,
                                  iv_compInfoCache.at(g_MclCompId));
        if (l_errl)
        {
            uint64_t l_reasonCode = l_errl->reasonCode();
            UTIL_FT(ERR_MRK"MasterContainerLidMgr::initMcl failed to process MCL shutting down rc=0x%08X",
                    l_reasonCode);
            errlCommit(l_errl,UTIL_COMP_ID);
            INITSERVICE::doShutdown(l_reasonCode);
        }
    }

    // Parse all Components in MCL
    parseMcl();

    // Initialize temporary space for processing other components
    initMem(iv_tmpAddr, iv_tmpSize, iv_pTempVaddr);

    // Switch to temp address and size for all other components
    iv_pVaddr = iv_pTempVaddr;
    iv_maxSize = iv_tmpSize;

    UTIL_DT(EXIT_MRK"MasterContainerLidMgr::initMcl");
}

void MasterContainerLidMgr::releaseMem(const uint64_t i_physAddr,
                                       void *&io_pVaddr)
{
    UTIL_DT(ENTER_MRK"MasterContainerLidMgr::releaseMem");

    errlHndl_t l_errl = nullptr;
    assert(i_physAddr != 0, "MasterContainerLidMgr physical address to release cannot be 0");

    do {
    if ( io_pVaddr != nullptr)
    {
        int l_mm_rc = mm_block_unmap(io_pVaddr);
        if(l_mm_rc != 0)
        {
            UTIL_FT("Fail from mm_block_unmap for Mcl Mgr, rc=%d Addr 0x%.16llX",
                    l_mm_rc, i_physAddr);
            /*@
             * @errortype
             * @moduleid          Util::UTIL_MCL_REL_MEM
             * @reasoncode        Util::UTIL_MM_BLOCK_UNMAP_FAILED
             * @userdata1         Address being removed
             * @userdata2         rc from mm_block_unmap
             * @devdesc           Error calling mm_block_unmap for Mcl Mgr
             * @custdesc          Firmware Error
             */
            l_errl = new ERRORLOG::ErrlEntry(
                           ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                           Util::UTIL_MCL_REL_MEM,
                           Util::UTIL_MM_BLOCK_UNMAP_FAILED,
                           i_physAddr,
                           l_mm_rc,
                           true); //software callout
            l_errl->collectTrace(UTIL_COMP_NAME);
            break;
        }
        io_pVaddr = nullptr;
    }
    } while(0);

    if (l_errl)
    {
        uint64_t l_reasonCode = l_errl->reasonCode();
        UTIL_FT(ERR_MRK"MasterContainerLidMgr::releaseMem failed to release memory rc=0x%08X",
                l_reasonCode);
        errlCommit(l_errl,UTIL_COMP_ID);
        INITSERVICE::doShutdown(l_reasonCode);
    }

    UTIL_DT(EXIT_MRK"MasterContainerLidMgr::releaseMem");
}

void MasterContainerLidMgr::initMem(const uint64_t i_physAddr,
                                    const size_t i_size,
                                    void *&io_pVaddr)
{
    UTIL_DT(ENTER_MRK"MasterContainerLidMgr::initMem");

    errlHndl_t l_errl = nullptr;
    assert(i_physAddr != 0, "MasterContainerLidMgr physical address cannot be 0");

    do {
    //Check if we already initialized vm space
    if (io_pVaddr == nullptr)
    {
        io_pVaddr = mm_block_map(reinterpret_cast<void*>(i_physAddr), i_size);
        if(io_pVaddr == nullptr)
        {
            UTIL_FT("MasterContainerLidMgr::initMem mm_block_map failed for Addr 0x%.16llX and size=0x%X ",
                    i_physAddr, i_size);
            /*@
             * @errortype
             * @moduleid          Util::UTIL_MCL_INIT_MEM
             * @reasoncode        Util::UTIL_MM_BLOCK_MAP_FAILED
             * @userdata1         Address being allocated
             * @userdata2         Size of block allocation
             * @devdesc           Error calling mm_block_map for Mcl Mgr
             * @custdesc          Firmware Error
             */
            l_errl = new ERRORLOG::ErrlEntry(
                           ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                           Util::UTIL_MCL_INIT_MEM,
                           Util::UTIL_MM_BLOCK_MAP_FAILED,
                           i_physAddr,
                           i_size,
                           true); //software callout
            l_errl->collectTrace(UTIL_COMP_NAME);
            break;
        }
        memset(io_pVaddr, 0, i_size);
    }
    } while(0);

    if (l_errl)
    {
        uint64_t l_reasonCode = l_errl->reasonCode();
        UTIL_FT(ERR_MRK"MasterContainerLidMgr::initMem failed to initialize memory rc=0x%08X",
                l_reasonCode);
        errlCommit(l_errl,UTIL_COMP_ID);
        INITSERVICE::doShutdown(l_reasonCode);
    }

    UTIL_DT(EXIT_MRK"MasterContainerLidMgr::initMem");
}

void MasterContainerLidMgr::parseMcl()
{
    UTIL_FT(ENTER_MRK"MasterContainerLidMgr::parseMcl");

    assert(iv_pMclVaddr != nullptr);

    auto l_pMcl = reinterpret_cast<const uint8_t*>(iv_pMclVaddr);

    // If MCL has a header make sure to skip over it for parsing
    if (iv_hasHeader)
    {
        l_pMcl += PAGESIZE;
    }

    // Parse MCL header
    auto l_pMclHdr = reinterpret_cast<const MclHeader*>(l_pMcl);
    uint8_t l_totalComponents = l_pMclHdr->numComponents;
    uint32_t l_offsetToCompSection =  l_pMclHdr->offsetToCompSection;
    l_pMcl += l_offsetToCompSection;

    // Parse Each Component in MCL header
    for (uint8_t comp = 0; comp < l_totalComponents; ++comp)
    {
        auto l_pMclSec = reinterpret_cast<const MclCompSection*>(l_pMcl);

        // Construct Comp Info with a subset of information
        CompInfo l_compInfo (l_pMclSec->flags);

        // Parse all lids
        auto l_pId = l_pMclSec->lidArray;
        for (uint8_t lid = 0; lid < l_pMclSec->numLids; ++lid)
        {
            LidInfo l_lidInfo(*l_pId);
            l_compInfo.lidIds.push_back(l_lidInfo);
            l_pId++;
        }

        // Insert component into Comp Info Cache
        iv_compInfoCache.insert(std::make_pair(l_pMclSec->compId, l_compInfo));

        // Increment past current component
        l_pMcl +=  l_pMclSec->sizeCompList;
    }

    printCompInfoCache();

    UTIL_FT(EXIT_MRK"MasterContainerLidMgr::parseMcl");
}

void MasterContainerLidMgr::printCompInfoCache()
{
    // Use ifdef as we do not want CompInfo print to be debug only
#ifdef HOSTBOOT_DEBUG
    UTIL_FT("> MCL Comp Info cache:");
    for (const auto &i : iv_compInfoCache)
    {
        UTIL_FBIN("- Comp Id:", &i.first, sizeof(ComponentID));
        i.second.print();
    }
#endif
}

errlHndl_t MasterContainerLidMgr::processSingleComponent(
    const ComponentID& i_compId,
          CompInfo&    o_info)
{
    errlHndl_t pError = nullptr;
    const CompInfo empty;
    o_info = empty;

    do {

    auto compInfoPairItr = iv_compInfoCache.find(i_compId);
    if(compInfoPairItr != iv_compInfoCache.end())
    {
        // Cache component ID string
        compIdToString(compInfoPairItr->first, iv_curCompIdStr);

        pError = processComponent(compInfoPairItr->first,
                                  compInfoPairItr->second);
        if (pError)
        {
            UTIL_FT(ERR_MRK "MasterContainerLidMgr::processSingleComponent: "
                "processComponent failed for component ID %s",
                iv_curCompIdStr);
            break;
        }

        // Print component Info after loading component and verifying
        UTIL_FT("MasterContainerLidMgr::processSingleComponent %s Info",
                iv_curCompIdStr);
        iv_compInfoCache.at(compInfoPairItr->first).print();

        // Tell caller what was loaded
        o_info = compInfoPairItr->second;
    }
    else
    {
        UTIL_FT(ERR_MRK "MasterContainerLidMgr::processSingleComponent: "
                "Could not find component 0x%016llX (1st 8 bytes) in MCL",
                compIdToInt(i_compId));
        /*@
         * @errortype
         * @moduleid   Util::UTIL_MCL_PROCESS_SINGLE_COMP
         * @reasoncode Util::UTIL_LIDMGR_INVAL_COMP
         * @userdata1  Component ID [truncated to 8 bytes]
         * @devdesc    Could not find requested component ID in master
         *     container LID
         * @custdesc   Firmware load error
         */
        pError = new ERRORLOG::ErrlEntry(
            ERRORLOG::ERRL_SEV_UNRECOVERABLE,
            Util::UTIL_MCL_PROCESS_SINGLE_COMP,
            Util::UTIL_LIDMGR_INVAL_COMP,
            compIdToInt(i_compId),
            0,
            ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
        pError->collectTrace(UTIL_COMP_NAME);
        break;
    }

    } while(0);

    return pError;
}

errlHndl_t MasterContainerLidMgr::processComponents()
{
    errlHndl_t l_errl = nullptr;
    for (auto & compInfoPair : iv_compInfoCache)
    {
        // Skip the MCL itself as it's already been processed
        if (compInfoPair.first == g_MclCompId)
        {
            continue;
        }

        // Cache Component ID string
        compIdToString(compInfoPair.first, iv_curCompIdStr);

        l_errl = processComponent(compInfoPair.first, compInfoPair.second);
        if (l_errl)
        {
            UTIL_FT(ERR_MRK"MasterContainerLidMgr::processComponents - failed for componentId %s",
                    iv_curCompIdStr);
            break;
        }
        // Print Comp Info after loading lid and verifying
        UTIL_FT("MasterContainerLidMgr::processComponents %s Info",
                iv_curCompIdStr);
        iv_compInfoCache.at(compInfoPair.first).print();
    }

    return l_errl;
}

errlHndl_t MasterContainerLidMgr::processComponent(
    const ComponentID& i_compId,
          CompInfo&    io_compInfo)
{
    UTIL_FT(ENTER_MRK"MasterContainerLidMgr::processComponent %s",
            iv_curCompIdStr);

    errlHndl_t l_errl = nullptr;
    do {

    // Check if Component is POWERVM (aka PHYP)
    bool isPhypComp = (i_compId == g_PowervmCompId) ? true : false;

    // Only process components if they are marked PRE_VERIFY or we're in load only mode
    if(   (   (io_compInfo.flags & CompFlags::PRE_VERIFY)
           != CompFlags::PRE_VERIFY)
       && (!iv_loadOnly))
    {
        UTIL_FT("MasterContainerLidMgr::processComponent not a pre-verify section skipping...");
        break;
    }

    // Total size of all LIDs in component reported by the FSP
    size_t l_reportedSize = 0;
    // Load lids into temp mainstore memory
    l_errl = loadLids(io_compInfo, l_reportedSize, isPhypComp);
    if (l_errl)
    {
        break;
    }

    // Set total size of component.
    // Note: It will be reassigned later if a secure header is present
    io_compInfo.totalSize = l_reportedSize;

    // Phyp component has already been loaded and verified before MCL mgr
    if (!isPhypComp)
    {
        // Verify component's lids
        l_errl = verifyExtend(i_compId, io_compInfo);
        if (l_errl)
        {
            break;
        }
    }

    // Ensure the total size of all lids fit in the mainstore memory region
    if (io_compInfo.totalSize > iv_maxSize)
    {
        UTIL_FT(ERR_MRK"MasterContainerLidMgr::processComponent - Invalid size. Component total size=0x%X, max size =0x%X",
                io_compInfo.totalSize, iv_maxSize);
        /*@
         * @errortype
         * @moduleid          Util::UTIL_MCL_PROCESS_COMP
         * @reasoncode        Util::UTIL_LIDMGR_INVAL_SIZE
         * @userdata1[0:31]   Total Size of Component
         * @userdata1[32:63]  Max size of memory region
         * @userdata2         Component ID [truncated to 8 bytes]
         * @devdesc           Error processing component for Mcl Mgr
         * @custdesc          Firmware Error
         */
        l_errl = new ERRORLOG::ErrlEntry(
                        ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                        Util::UTIL_MCL_PROCESS_COMP,
                        Util::UTIL_LIDMGR_INVAL_SIZE,
                        TWO_UINT32_TO_UINT64(
                            TO_UINT32(io_compInfo.totalSize),
                            TO_UINT32(iv_maxSize)),
                        compIdToInt(i_compId),
                        true); //software callout
        l_errl->collectTrace(UTIL_COMP_NAME);
        break;
    }

    // Ensure what was read by the FSP matches the total size found in the
    // Secure Header. If there is no secure header, this path should not be hit.
    // *NOTE: Skip check if lid loading was skipped
    if (io_compInfo.totalSize != l_reportedSize)
    {
        UTIL_FT(ERR_MRK"MasterContainerLidMgr::processComponent - Size Mismatch. Component total size=0x%X, size read by FSP=0x%X",
                io_compInfo.totalSize, l_reportedSize);
        /*@
         * @errortype
         * @moduleid          Util::UTIL_MCL_PROCESS_COMP
         * @reasoncode        Util::UTIL_MCL_SIZE_MISMATCH
         * @userdata1[0:31]   Total Size of Component
         * @userdata1[32:63]  Size read by FSP
         * @userdata2         Component ID [truncated to 8 bytes]
         * @devdesc           Error processing component for Mcl Mgr
         * @custdesc          Firmware Error
         */
        l_errl = new ERRORLOG::ErrlEntry(
                        ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                        Util::UTIL_MCL_PROCESS_COMP,
                        Util::UTIL_MCL_SIZE_MISMATCH,
                        TWO_UINT32_TO_UINT64(
                            TO_UINT32(io_compInfo.totalSize),
                            TO_UINT32(l_reportedSize)),
                        compIdToInt(i_compId),
                        true); //software callout
        l_errl->collectTrace(UTIL_COMP_NAME);
        break;
    }

    // Clear unused memory
    // Note: Phyp component has already been loaded and verified before MCL mgr
    if ( !isPhypComp && (io_compInfo.totalSize < iv_maxSize) )
    {
        // Get pointer to end of used space
        uint8_t* l_pUnused = reinterpret_cast<uint8_t*>(iv_pVaddr) +
                             io_compInfo.totalSize;
        memset(l_pUnused, 0, iv_maxSize - io_compInfo.totalSize);
    }

    // Only load lids into HB reserved memory if component is preverified
    // and MCL manager is not in load-only mode
    if(   (   (io_compInfo.flags & CompFlags::PRE_VERIFY)
           == CompFlags::PRE_VERIFY)
       && (!iv_loadOnly))
    {
        auto l_curAddr =  reinterpret_cast<uint64_t>(iv_pVaddr);
        bool l_firstLid = true;
        for (auto & lidInfo : io_compInfo.lidIds)
        {
            uint64_t l_addr = 0;
            // Load Pnor section into HB reserved memory
            l_errl = PreVerifiedLidMgr::loadFromMCL(lidInfo.id,
                                                    l_curAddr,
                                                    lidInfo.size,
                                                    isPhypComp,
                                                    l_firstLid,
                                                    l_addr);
            if(l_errl)
            {
                break;
            }
            // Increment tmp address by lid size
            l_curAddr += lidInfo.size;

            // Save starting address of entire component, not each lid
            if (l_firstLid)
            {
                // Set mainstore memory address in cache
                io_compInfo.mainstoreAddr = l_addr;
                l_firstLid = false;
            }
        }
        if(l_errl)
        {
            break;
        }
    }

    } while(0);

    UTIL_FT(EXIT_MRK"MasterContainerLidMgr::processComponent");

    return l_errl;
}

errlHndl_t MasterContainerLidMgr::loadLids(CompInfo& io_compInfo,
                                           size_t& o_totalSize,
                                           const bool i_isPhypComp)
{
    UTIL_DT(ENTER_MRK"MasterContainerLidMgr::loadLids");
    errlHndl_t l_errl = nullptr;

    // Force total size to zero
    o_totalSize = 0;
    // Pointer to mainstore memory temp space
    uint8_t* l_pLidVaddr = reinterpret_cast<uint8_t*>(iv_pVaddr);
    // Remaining size to load lids into
    size_t l_remainSize = iv_maxSize;

    // Iterate through all Lids associated with a component
    // NOTE: iterate by reference to update lidInfo
    for (auto & lidInfo : io_compInfo.lidIds)
    {
        // Get Lid from FSP
        UtilLidMgr l_lidMgr(lidInfo.id);
        // Get size of current lid to be loaded
        size_t l_lidSize = 0;
        l_errl = l_lidMgr.getLidSize(l_lidSize);
        if(l_errl)
        {
            UTIL_FT(ERR_MRK"MasterContainerLidMgr::loadLids - Error getting size of lidId=0x%.8x",
                    lidInfo.id);
            break;
        }
        // Update lid size
        lidInfo.size = l_lidSize;

        // Phyp component has already been loaded and verified before MCL mgr
        if (!i_isPhypComp)
        {
            // Load lid into vaddr location. API will check if remaining size is
            // enough; throwing an error if not.
            l_errl = l_lidMgr.getLid(reinterpret_cast<void*>(l_pLidVaddr),
                                     l_remainSize);
            if(l_errl)
            {
                UTIL_FT(ERR_MRK"MasterContainerLidMgr::loadLids - Error getting lidId=0x%.8x",
                        lidInfo.id);
                break;
            }

            // Store current LID load virtual address
            lidInfo.vAddr = l_pLidVaddr;

            // Increment vaddr pointer
            l_pLidVaddr += l_lidSize;

            // Decrement size remaining in mainstore memory temp space
            if (l_lidSize >= l_remainSize)
            {
                l_remainSize = 0;
            }
            else
            {
                l_remainSize -= l_lidSize;
            }
        }

        // Increment total size
        o_totalSize += l_lidSize;
    }

    UTIL_DT(EXIT_MRK"MasterContainerLidMgr::loadLids");

    return l_errl;
}

errlHndl_t MasterContainerLidMgr::verifyExtend(const ComponentID& i_compId,
                                               CompInfo& io_compInfo)
{
    UTIL_DT(ENTER_MRK"MasterContainerLidMgr::verifyExtend");

    errlHndl_t l_errl = nullptr;

    do {
    // Only Verify and Extend if Component is Signed and Preverified
    if( (io_compInfo.flags & CompFlags::SIGNED_PRE_VERIFY) ==
         CompFlags::SIGNED_PRE_VERIFY)
    {
        // Parse Container Header
        SECUREBOOT::ContainerHeader l_conHdr;
        l_errl = l_conHdr.setHeader(iv_pVaddr);
        if (l_errl)
        {
            UTIL_FT(ERR_MRK"MasterContainerLidMgr::verifyExtend - setheader failed");
            break;
        }

        // Cache size stats into comp info cache
        io_compInfo.totalSize = l_conHdr.totalContainerSize();
        io_compInfo.protectedSize = l_conHdr.payloadTextSize();
        io_compInfo.unprotectedSize = l_conHdr.totalContainerSize() -
                                      l_conHdr.payloadTextSize();

        // Only verify the lids if in secure mode
        if (SECUREBOOT::enabled())
        {
            UTIL_FT(ENTER_MRK"MasterContainerLidMgr::verifyExtend: "
                "Secure enabled, calling verifyContainer");

            // Verify Container - some combination of Lids
            l_errl = SECUREBOOT::verifyContainer(iv_pVaddr,
                                             extractLidIds(io_compInfo.lidIds));
            if (l_errl)
            {
                UTIL_FT(ERR_MRK"MasterContainerLidMgr::verifyExtend - failed verifyContainer");
                SECUREBOOT::handleSecurebootFailure(l_errl);
                assert(false,"Bug! handleSecurebootFailure shouldn't return!");
            }
            UTIL_FT(ENTER_MRK"MasterContainerLidMgr::verifyExtend: "
                "Secure enabled, calling verifyComponent");

            // Verify the component in the Secure Header matches the MCL
            l_errl = SECUREBOOT::verifyComponentId(l_conHdr, iv_curCompIdStr);
            if (l_errl)
            {
                l_errl->collectTrace(UTIL_COMP_NAME);
                break;
            }
        }

        l_errl = tpmExtend(i_compId, l_conHdr);
        if (l_errl)
        {
            l_errl->collectTrace(UTIL_COMP_NAME);
            break;
        }
    }
    } while(0);

    UTIL_DT(EXIT_MRK"MasterContainerLidMgr::verifyExtend");

    return l_errl;
}

errlHndl_t MasterContainerLidMgr::tpmExtend(const ComponentID& i_compId,
                            const SECUREBOOT::ContainerHeader& i_conHdr)
{
    UTIL_DT(ENTER_MRK"MasterContainerLidMgr::tpmExtend");

    errlHndl_t l_errl = nullptr;

    // PCR 4 Message <Component ID>
    uint8_t pcr4Msg[sizeof(ComponentID)+1];
    memset(pcr4Msg, 0, sizeof(pcr4Msg));
    memcpy(pcr4Msg, &i_compId, sizeof(ComponentID));

    // PCR 5 Message <Component ID FW KEY HASH>
    uint8_t pcr5Msg[sizeof(ComponentID)+strlen(TRUSTEDBOOT::FW_KEY_HASH_EXT)+1];
    memset(pcr5Msg, 0, sizeof(pcr5Msg));
    memcpy(pcr5Msg,pcr4Msg, sizeof(pcr4Msg));
    memcpy(pcr5Msg+sizeof(pcr4Msg),
           TRUSTEDBOOT::FW_KEY_HASH_EXT,
           sizeof(TRUSTEDBOOT::FW_KEY_HASH_EXT));

    do {

    // Extend protected payload hash
    l_errl = TRUSTEDBOOT::pcrExtend(TRUSTEDBOOT::PCR_4,
              TRUSTEDBOOT::EV_COMPACT_HASH,
              reinterpret_cast<const uint8_t*>(i_conHdr.payloadTextHash()),
              sizeof(SHA512_t),
              pcr4Msg,
              sizeof(pcr4Msg));
    if (l_errl)
    {
        UTIL_FT(ERR_MRK "MasterContainerLidMgr::tpmExtend - pcrExtend() (payload text hash) failed for component %s",
                  i_conHdr.componentId());
        break;
    }

    // Extend SW keys hash
    l_errl = TRUSTEDBOOT::pcrExtend(TRUSTEDBOOT::PCR_5,
              TRUSTEDBOOT::EV_COMPACT_HASH,
              reinterpret_cast<const uint8_t*>(i_conHdr.swKeyHash()),
              sizeof(SHA512_t),
              pcr5Msg,
              sizeof(pcr5Msg));
    if (l_errl)
    {
        UTIL_FT(ERR_MRK "MasterContainerLidMgr::tpmExtend - pcrExtend() (FW key hash) failed for component %s",
                i_conHdr.componentId());
        break;
    }

    } while(0);

    UTIL_DT(EXIT_MRK"MasterContainerLidMgr::tpmExtend");

    return l_errl;
}

} // end namespace MCL
OpenPOWER on IntegriCloud