summaryrefslogtreecommitdiffstats
path: root/src/usr/isteps/istep15/host_build_stop_image.C
blob: 6bc7553145670e69ee90f66d75291cccabc007a8 (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
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/isteps/istep15/host_build_stop_image.C $              */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,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                                                     */


////System
#include    <sys/misc.h>
#include    <sys/mmio.h>
#include    <sys/mm.h>
#include    <usr/vmmconst.h>
#include    <arch/pirformat.H>
#include    <arch/ppc.H>
#include    <isteps/pm/pm_common_ext.H>
#include    <config.h>

//Utilities
#include    <util/utilxipimage.H>

//Error handling and tracing
#include    <errl/errlentry.H>
#include    <errl/errluserdetails.H>
#include    <errl/errludtarget.H>
#include    <errl/errlmanager.H>
#include    <errl/errlreasoncodes.H>
#include    <isteps/hwpisteperror.H>
#include    <initservice/isteps_trace.H>

//PNOR Resource Provider
#include    <pnor/pnorif.H>

#include    <fapi2.H>
#include    <kernel/cpumgr.H>

//Targeting Support
#include    <targeting/common/utilFilter.H>
#include    <fapi2/target.H>

//HWP Invoker
#include    <fapi2/plat_hwp_invoker.H>

//Import directory (from EKB repository)
#include    <p9_hcode_image_build.H>
#include    <p9_stop_api.H>
#include    <p9_setup_runtime_wakeup_mode.H>
#include    <p9_xip_image.h>
#include    <p9_infrastruct_help.H>
#include    <p9_hcode_image_defines.H>
#include    <p9_xip_section_append.H>
#include    <p9n2_quad_scom_addresses_fld.H>

#include    <secureboot/smf_utils.H>
#include    <secureboot/smf.H>
#include    <isteps/mem_utils.H>
#include    <util/align.H>

#include    <limits.h>

using   namespace   ERRORLOG;
using   namespace   ISTEP;
using   namespace   ISTEP_ERROR;
using   namespace   TARGETING;
using   namespace   PNOR;
using   namespace   stopImageSection;
using   namespace   fapi2;

namespace ISTEP_15
{

/**
 *  @brief Load HCODE image and return a pointer to it, or NULL
 *
 *  @param[out] -   address of the HCODE image
 *
 *  @return      NULL if success, errorlog if failure
 *
 */
errlHndl_t  loadHcodeImage(  char                    *& o_rHcodeAddr)
{
    errlHndl_t l_errl = NULL;
    PNOR::SectionInfo_t l_info;

    do
    {

#ifdef CONFIG_SECUREBOOT
        l_errl = loadSecureSection(PNOR::HCODE);
        if (l_errl)
        {
            TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
                       ERR_MRK"loadHcodeImage() - Error from "
                       "loadSecureSection(PNOR::HCODE)");

            //No need to commit error here, it gets handled later
            //just break out to escape this function
            break;
        }
#endif

        // Get HCODE/WINK PNOR section info from PNOR RP
        l_errl = PNOR::getSectionInfo( PNOR::HCODE, l_info );
        if( l_errl )
        {
            //No need to commit error here, it gets handled later
            //just break out to escape this function
            break;
        }

        o_rHcodeAddr = reinterpret_cast<char*>(l_info.vaddr);

        TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
                   "HCODE addr = 0x%p ",
                   o_rHcodeAddr);

    } while ( 0 );

    return  l_errl;
}

/**
 * @brief   apply cpu reg information to the HCODE image using
 *          p9_stop_save_cpureg() .
 *
 * @param i_procChipTarg   -   proc target
 * @param io_image      -   pointer to the HCODE image
 * @param i_sizeImage   -   size of the HCODE image
 *
 * @return errorlog if error, NULL otherwise.
 *
 */
errlHndl_t  applyHcodeGenCpuRegs(  TARGETING::Target *i_procChipTarg,
                                   void      *io_image,
                                   uint32_t  i_sizeImage )
{
    errlHndl_t  l_errl = nullptr;

    do
    {

    //Use TARGETING code to look up CORE target handles
    TARGETING::TargetHandleList l_coreIds;
    getChildChiplets( l_coreIds,
                      i_procChipTarg,
                      TYPE_CORE,
                      false );

    TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
               "applyHcodeGenCpuRegs: Process cores=0x%x, threads=0x%x",
               l_coreIds.size(),
               cpu_thread_count() );

    //Thread tracking
    const size_t l_cpu_thread_count = cpu_thread_count();
    TARGETING::ATTR_CHIP_UNIT_type l_coreId    =   0;
    size_t      l_threadId  =   0;
    //Error Handling
    uint32_t    l_rc        =   0;
    uint32_t    l_failAddr  =   0;
    //Register Values
    uint64_t    l_msrVal    =   cpu_spr_value(CPU_SPR_MSR);
    uint64_t    l_lpcrVal   =   cpu_spr_value(CPU_SPR_LPCR);

    if(SECUREBOOT::SMF::isSmfEnabled())
    {
        l_errl = SECUREBOOT::SMF::checkRiskLevelForSmf();
        if(l_errl)
        {
            break;
        }

        // Set the secure bit (41) on if SMF is enabled
        l_msrVal |= MSR_SMF_MASK;
    }

    // See LPCR def, PECE "reg" in Power ISA AS Version: Power8 June 27, 2012
    //  and 23.7.3.5 - 6 in Murano Book 4
    l_lpcrVal   &=  ~(0x0000000000002000) ;
    l_lpcrVal   |=    0x0000400000000000  ;  //Allow Hyp virt to exit STOP

    //Get top-lvl system target with TARGETING code to find the enabled threads
    TARGETING::Target* sys = NULL;
    TARGETING::targetService().getTopLevelTarget(sys);
    assert( sys != NULL );
    uint64_t en_threads = sys->getAttr<ATTR_ENABLED_THREADS>();

    //look up the HRMOR value from the HRMOR CPU special purpose register(SPR)
    uint64_t    l_hrmorVal  =   cpu_spr_value(CPU_SPR_HRMOR);

    // create a mask to represent the ATTN enable bit in the HID register
    uint64_t  l_enblAttnMask = 0x8000000000000000ull >> P9N2_C_HID_EN_ATTN;

    //iterate through the cores while copying information from SPRs
    for (const auto & l_core: l_coreIds)
    {
        // trace the HUID of the core we are writing to
        TRACDCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                "target HUID %.8X", TARGETING::get_huid(l_core));

        l_threadId = 0;

        //Get core's parent processor target handle
        ConstTargetHandle_t l_processor = getParentChip(l_core);

        //Read core's chip unit id attribute and store it as the core's id
         CHIP_UNIT_ATTR l_coreId =
                (l_core)->getAttr<TARGETING::ATTR_CHIP_UNIT>();
        //Read the processor's fabric group id
        FABRIC_GROUP_ID_ATTR l_logicalGroupId =
          l_processor->getAttr<TARGETING::ATTR_FABRIC_GROUP_ID>();

        //Read the processor's fabric chip id
        FABRIC_CHIP_ID_ATTR l_chipId =
          l_processor->getAttr<TARGETING::ATTR_FABRIC_CHIP_ID>();

        TRACDCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                  "chip unit: %d  fabric group: %d    chip id: %d",
                  l_coreId, l_logicalGroupId,l_chipId);

        //store the PIR value by passing the values read in above into the
        //PIR_t constructor and read the .word attribute on the new PIR struct
        uint64_t l_pirVal = PIR_t(l_logicalGroupId, l_chipId, l_coreId).word;

        //The underlying stop API knows about fused/normal cores.  Need to take
        //this into account for fused mode.  If we are in fused mode, then
        //the even core thead 0/1 correspond to physical core 0 and 1
        //respectively, so both need to be set to populate the STOP image
        size_t l_fuseThreadAdjust = 0x1;
        if(is_fused_mode())
        {
            //If even core set threads 0,1
            //If odd core skip by setting loop count to 0
            l_fuseThreadAdjust = (l_coreId%2 == 0x0) ? 2 : 0;
        }

        for(size_t l_fuseAdj = 0; l_fuseAdj < l_fuseThreadAdjust; l_fuseAdj++)
        {

            //Call p9_stop_save_cpureg to store the MSR SPR value
            l_rc = p9_stop_save_cpureg( io_image,
                                        P9_STOP_SPR_MSR,
                                        l_msrVal,
                                        l_pirVal | l_fuseAdj);
            if ( l_rc )
            {
                TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
                           "ERROR: MSR: core=0x%x,thread=0x%x,l_rc=0x%x",
                           l_coreId, l_threadId, l_rc );
                l_failAddr = P9_STOP_SPR_MSR;
                break;
            }

            //Call p9_stop_save_cpureg to store the HRMOR SPR value
            l_rc = p9_stop_save_cpureg( io_image,
                                        P9_STOP_SPR_HRMOR,
                                        l_hrmorVal,
                                        l_pirVal | l_fuseAdj);

            if ( l_rc ){
                TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
                           "ERROR: HRMOR: core=0x%x,thread=0x%x,l_rc=0x%x",
                           l_coreId, l_threadId, l_rc );
                l_failAddr = P9_STOP_SPR_HRMOR;
                break;
            }

            //Call p9_stop_save_cpureg to store the HID SPR value
            //  (minus ATTN enable bit)
            uint64_t l_curHidVal =  cpu_spr_value( CPU_SPR_HID );
            uint64_t l_hidVal = l_curHidVal & (~(l_enblAttnMask));
            l_rc = p9_stop_save_cpureg( io_image,
                                        P9_STOP_SPR_HID,
                                        l_hidVal,
                                        l_pirVal | l_fuseAdj);

            if ( l_rc ){
                TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
                           "ERROR: HID: core=0x%x,thread=0x%x,l_rc=0x%x",
                           l_coreId, l_threadId, l_rc );
                l_failAddr = P9_STOP_SPR_HID;
                break;
            }

            // Call p9_stop_save_cpureg to store the URMOR SPR value
            l_rc = p9_stop_save_cpureg(io_image,
                                       P9_STOP_SPR_URMOR,
                                       l_hrmorVal,
                                       l_pirVal | l_fuseAdj);
            if(l_rc)
            {
                TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                          "ERROR: URMOR: core=0x%x,thread=0x%x,l_rc=0x%x",
                          l_coreId, l_threadId, l_rc);
                l_failAddr = P9_STOP_SPR_HRMOR;
                break;
            }
        }

        //  fill in lpcr for each thread
        for ( l_threadId=0; l_threadId < l_cpu_thread_count; l_threadId++ )
        {
            // Skip threads that we shouldn't be starting
            if( !(en_threads & (0x8000000000000000>>l_threadId)) )
            {
                continue;
            }

            TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
                       "applyHcodeGenCpuRegs: core=0x%x,thread=0x%x: ",
                       l_coreId, l_threadId );
            TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
                       "applyHcodeGenCpuRegs: msrc=0x%x,lpcr=0x%x,hrmor=0x%x",
                       l_msrVal, l_lpcrVal, l_hrmorVal  );

            //the thread ID is the last 3 bytes of pirVal so you can just OR
            uint64_t l_pirValThread = l_pirVal | l_threadId;

            //Call p9_stop_save_cpureg from p9_stop_api
            //to store the LPCR SPR value
            l_rc = p9_stop_save_cpureg( io_image,
                                        P9_STOP_SPR_LPCR,
                                        l_lpcrVal,
                                        l_pirValThread);
            if ( l_rc )
            {
                TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
                           "ERROR: LPCR: core=0x%x,thread=0x%x,l_rc=0x%x",
                           l_coreId, l_threadId, l_rc );
                l_failAddr = P9_STOP_SPR_LPCR;
                break;
            }
        }   // end for l_threadId

        //  if error writing thread break out of l_coreId loop
        if ( l_rc !=0 )
        {
            break;
        }

    }   // end for l_coreIds

    if ( l_rc ){
        TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
                   "ERROR: p9 stop api fail core=0x%x, thread=0x%x, l_rc=0x%x",
                   l_coreId, l_threadId, l_rc );
        /*@
        * @errortype
        * @reasoncode  ISTEP::RC_BAD_RC
        * @severity    ERRORLOG::ERRL_SEV_UNRECOVERABLE
        * @moduleid    ISTEP::MOD_BUILD_HCODE_IMAGES
        * @userdata1   Hi 32 bits: return code from p8_pore_gen_scom_fixed
        *              Lo 32 bits: Address of EX_CORE_FIR_ACTION1_0x10013107
        * @userdata2   Hi 32 bits: ID of core
        *              Lo 32 bits: Thread id
        * @devdesc     Unable to force core checkstops by updating ACTION1
        *              when it comes out of winkle
        * @custdesc    A problem occurred during the IPL
        *              of the system.
        */
        l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                                ISTEP::MOD_BUILD_HCODE_IMAGES,
                                ISTEP::RC_BAD_RC,
                                TWO_UINT32_TO_UINT64(l_rc,l_failAddr),
                                TWO_UINT32_TO_UINT64(l_coreId,l_threadId),
                                true);
        l_errl->collectTrace(FAPI_TRACE_NAME,256);
        l_errl->collectTrace(FAPI_IMP_TRACE_NAME,256);
        l_errl->collectTrace("ISTEPS_TRACE",256);
    }

    }while(0);

    return  l_errl;
}

void* host_build_stop_image (void *io_pArgs)
{
    errlHndl_t  l_errl           = NULL;
    ISTEP_ERROR::IStepError     l_StepError;

    // unload of HCODE PNOR section only necessary if SECUREBOOT compiled in
#ifdef CONFIG_SECUREBOOT
    bool unload_hcode_pnor_section = false;
#endif

    char*       l_pHcodeImage     = NULL;
    void*       l_pRealMemBase   = NULL;
    void*       l_pVirtMemBase   = NULL;

    TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "host_build_stop_image entry" );

    // allocate four temporary work buffers
    void* l_temp_buffer1 = malloc(HW_IMG_RING_SIZE);
    void* l_temp_buffer2 = malloc(MAX_RING_BUF_SIZE);
    void* l_temp_buffer3 = malloc(MAX_RING_BUF_SIZE);
    void* l_temp_buffer4 = malloc(MAX_RING_BUF_SIZE);

    do  {
        //Determine top-level system target
        TARGETING::Target* l_sys = NULL;
        TARGETING::targetService().getTopLevelTarget(l_sys);
        assert( l_sys != NULL );

        if (l_sys->getAttr<TARGETING::ATTR_IS_MPIPL_HB>())
        {
            l_errl = HBPM::resetPMAll(HBPM::RESET_AND_CLEAR_ATTRIBUTES);
            if(l_errl)
            {
                //Break out of the do-while loop..
                //we should have been able to do a PM reset
                break;
            }
        }

        // Get the node-offset for our instance by looking at the HRMOR
        uint64_t l_memBase = cpu_spr_value(CPU_SPR_HRMOR);
        TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "HRMOR=%.16X", l_memBase );
        // Now offset up to our hardcoded region
        l_memBase += VMM_HOMER_REGION_START_OFFSET;

        //  Get a chunk of real memory big enough to store all the possible
        //  HCODE images. (4MB is size of HOMER)
        assert(VMM_HOMER_REGION_SIZE <= (P9_MAX_PROCS * (4 * MEGABYTE)),
               "host_build_stop_image: Unsupported HOMER Region size");

        //If running Sapphire need to place this at the top of memory instead
        if(is_sapphire_load())
        {
            //Because the way P9N/P9C are init'ed for backwards HB / SBE
            //compatibility (SMF never enabled -- thus unsecure homer to
            //secure homer sc2 (system call to Ultravisor) doesn't work) during
            //istep 15 need to "trick" hostboot into placing HOMER into normal
            //memory @HRMOR (instead of secure SMF memory).  When HB goes
            //through istep 16 it will enter UV mode if SMF is enabled, and then
            //when PM complex is restarted in istep 21, HOMER is moved to right
            //spot. No movement of HOME oocurs in non-SMF mode; HOMER lands in
            //non-secure memory.

            l_memBase = get_top_mem_addr();
            assert (l_memBase != 0,
                    "host_build_stop_image: Top of memory was 0!");

            l_memBase -= VMM_ALL_HOMER_OCC_MEMORY_SIZE;
        }
        TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
                   "HOMER base = 0x%.16llX", l_memBase);
        l_pRealMemBase = reinterpret_cast<void * const>(l_memBase );

        //Convert the real memory pointer to a pointer in virtual memory
        l_pVirtMemBase =
              mm_block_map(l_pRealMemBase, VMM_HOMER_REGION_SIZE);

        TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
                   "Got virtual mem  buffer for %d cpus = 0x%p",
                   P9_MAX_PROCS,
                   l_pVirtMemBase  );

        //Since we have the HOMER location defined, set the
        // OCC common attribute to be used later by pm code
        l_sys->setAttr<TARGETING::ATTR_OCC_COMMON_AREA_PHYS_ADDR>
            (reinterpret_cast<uint64_t>(l_pRealMemBase)
                + VMM_HOMER_REGION_SIZE);

        //  Continue, build hcode images
        //
        //Load the reference image from PNOR
        l_errl  =   loadHcodeImage(  l_pHcodeImage );
        if ( l_errl )
        {
            TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                      "host_build_stop_image ERROR : errorlog PLID=0x%x",
                      l_errl->plid() );
            // drop out of do block with errorlog.
            break;
        }
#ifdef CONFIG_SECUREBOOT
        unload_hcode_pnor_section = true;
#endif

        // Pull build information from XIP header and trace it
        Util::imageBuild_t l_imageBuild;
        Util::pullTraceBuildInfo(l_pHcodeImage,
                                 l_imageBuild,
                                 ISTEPS_TRACE::g_trac_isteps_trace);

        //  Loop through all functional Procs and generate images for them.
        //get a list of all the functional Procs
        TARGETING::TargetHandleList l_procChips;
        getAllChips( l_procChips,
                     TARGETING::TYPE_PROC   );

        TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
                   "Found %d functional procs in system",
                   l_procChips.size()   );

        for (const auto & l_procChip: l_procChips)
        {
            do  {
                // write the HUID of the core we are writing to
                TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                        "Build STOP image for proc "
                        "target HUID %.8X", TARGETING::get_huid(l_procChip));

                //  calculate size and location of the HCODE output buffer
                uint32_t    l_procNum =
                  l_procChip->getAttr<TARGETING::ATTR_POSITION>();
                uint64_t    l_procOffsetAddr =
                  ( l_procNum *VMM_HOMER_INSTANCE_SIZE );

                uint64_t    l_procRealMemAddr  =
                  reinterpret_cast<uint64_t>(l_pRealMemBase)
                  + l_procOffsetAddr;

                void *l_pImageOut =
                  reinterpret_cast<void * const>
                  (reinterpret_cast<uint64_t>(l_pVirtMemBase)
                   + l_procOffsetAddr) ;

                uint32_t    l_sizeImageOut  =
                  ((P9_MAX_PROCS * (4 * MEGABYTE)));

                //Make sure that the HOMER is zeroed out for the MPIPL path
                memset(l_pImageOut, 0, 4 * MEGABYTE);

                //Set default values, used later by p9_hcode_build
                l_procChip->setAttr<TARGETING::ATTR_HOMER_PHYS_ADDR>
                                                        (l_procRealMemAddr);

                TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
                           "Real mem  buffer for cpu 0x%08x = %p, virtAddr=%p",
                           l_procNum,
                           l_procRealMemAddr,
                           l_pImageOut);

                //Cast OUR type of target to a FAPI2 type of target.
                const fapi2::Target<TARGET_TYPE_PROC_CHIP>
                l_fapiProcTarget( const_cast<TARGETING::Target*>(l_procChip));

                //Default constructor sets the appropriate settings
                ImageType_t img_type;

                // Check if we have a valid ring override section and
                //  include it in if so
                void* l_ringOverrides = NULL;
                l_errl = HBPM::getRingOvd(l_ringOverrides);
                if(l_errl)
                {
                    TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
                               ERR_MRK"host_build_stop_image(): "
                               "Error in call to getRingOvd!");
                    break;
                }

                //Set unsecure HOMER address to real HOMER, as this
                //will allow SMF inits to become active (results in
                //URMOR == HRMOR in non SMF memory). The processor self-restore
                //code is 2MB into HOMER, so point the unsecure HOMER there.
                l_procChip->setAttr<TARGETING::ATTR_UNSECURE_HOMER_ADDRESS>
                  (l_procRealMemAddr + (2 * MEGABYTE));

                //Call p9_hcode_image_build.C HWP
                FAPI_INVOKE_HWP( l_errl,
                                 p9_hcode_image_build,
                                 l_fapiProcTarget,
                                 reinterpret_cast<void*>(l_pHcodeImage),
                                 l_pImageOut, //homer image buffer
                                 l_ringOverrides,
                                 PHASE_IPL,
                                 img_type,
                                 l_temp_buffer1,
                                 HW_IMG_RING_SIZE,
                                 l_temp_buffer2,
                                 MAX_RING_BUF_SIZE,
                                 l_temp_buffer3,
                                 MAX_RING_BUF_SIZE,
                                 l_temp_buffer4,
                                 MAX_RING_BUF_SIZE);

                if ( l_errl )
                {
                    TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                              "host_build_stop_image ERROR occured during p9_hcode_image_build : errorlog PLID=0x%x",
                              l_errl->plid() );

                    //  drop out of block with errorlog.
                    break;
                }

                l_errl = applyHcodeGenCpuRegs( l_procChip,
                                               l_pImageOut,
                                               l_sizeImageOut );
                if ( l_errl )
                {
                    TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                              "applyHcodeGenCpuRegs ERROR : errorlog PLID=0x%x",
                              l_errl->plid() );

                    //  drop out of block with errorlog.
                    break;
                }
                else
                {
                    TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
                               "applyHcodeGenCpuRegs SUCCESS " );
                }

                // Set wakeup mode for processor based on SMF enablement
                FAPI_INVOKE_HWP(l_errl,
                                p9_setup_runtime_wakeup_mode,
                                l_fapiProcTarget);

                if ( l_errl )
                {
                    TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                              "host_build_stop_image ERROR occured during p9_setup_runtime_wakeup_mode : errorlog PLID=0x%x",
                              l_errl->plid() );

                    //  drop out of block with errorlog.
                    break;
                }

            }   while (0) ;

            // broke out due to an error, store all the details away, store
            //  the errlog in IStepError, and continue to next proc
            if (l_errl)
            {
                // capture the target data in the elog
                ErrlUserDetailsTarget(l_procChip).addToLog( l_errl );

                l_errl->addFFDC( ERRL_COMP_ID,
                                 reinterpret_cast<void *>(&l_imageBuild),
                                 sizeof(Util::imageBuild_t),
                                 0,                   // Version
                                 ERRL_UDT_BUILD,      // parse XIP image build
                                 false );             // merge

                // Create IStep error log and cross ref error that occurred
                l_StepError.addErrorDetails( l_errl );

                // Commit Error
                errlCommit( l_errl, HWPF_COMP_ID );
            }

        } ;  // endfor

    }  while (0);
    // @@@@@    END CUSTOM BLOCK:   @@@@@

    if (l_errl)
    {
        // Create IStep error log and cross ref error that occurred
        l_StepError.addErrorDetails( l_errl );

        // Commit Error
        errlCommit( l_errl, HWPF_COMP_ID );
    }

    // delete working buffers
    if( l_temp_buffer1 ) { free(l_temp_buffer1); }
    if( l_temp_buffer2 ) { free(l_temp_buffer2); }
    if( l_temp_buffer3 ) { free(l_temp_buffer3); }
    if( l_temp_buffer4 ) { free(l_temp_buffer4); }

#ifdef CONFIG_SECUREBOOT
    // securely unload HCODE PNOR section, if necessary
    if ( unload_hcode_pnor_section == true )
    {
        l_errl = unloadSecureSection(PNOR::HCODE);
        if (l_errl)
        {
            TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
                       ERR_MRK"host_build_stop_image() - Error from "
                       "unloadSecureSection(PNOR::HCODE)");

            // Create IStep error log and cross reference error that occurred
            l_StepError.addErrorDetails( l_errl );

            // Commit error
            errlCommit( l_errl, ISTEP_COMP_ID );
        }
    }
#endif


    if(l_pVirtMemBase)
    {
        int rc = 0;
        rc =  mm_block_unmap(l_pVirtMemBase);
        if (rc != 0)
        {
            /*@
             * @errortype
             * @reasoncode   ISTEP::RC_MM_UNMAP_ERR
             * @moduleid     ISTEP::MOD_BUILD_HCODE_IMAGES
             * @severity     ERRORLOG::ERRL_SEV_UNRECOVERABLE
             * @userdata1    Return Code
             * @userdata2    Unmap address
             * @devdesc      mm_block_unmap() returns error
             * @custdesc    A problem occurred during the IPL
             *              of the system.
             */
            l_errl =
              new ERRORLOG::ErrlEntry(
                                      ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                                      ISTEP::MOD_BUILD_HCODE_IMAGES,
                                      ISTEP::RC_MM_UNMAP_ERR,
                                      rc,
                                      reinterpret_cast<uint64_t>
                                      (l_pVirtMemBase));

            // Create IStep error log and cross reference error that occurred
            l_StepError.addErrorDetails( l_errl );

            // Commit error
            errlCommit( l_errl, ISTEP_COMP_ID );
        }
    }

    TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
               "host_build_stop_image exit" );

    // end task, returning any errorlogs to IStepDisp
    return l_StepError.getErrorHandle();
}

};
OpenPOWER on IntegriCloud