summaryrefslogtreecommitdiff
path: root/Platform/ARM/Drivers/StandaloneMmDmc620RasDriver/StandaloneMmDmc620RasDriver.c
blob: fc2ea7cb69f53277964808d06457720bd30a46b7 (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
/** @file
*
*  Copyright (c) 2017-2018, ARM Limited. All rights reserved.
*
*  This program and the accompanying materials
*  are licensed and made available under the terms and conditions of the BSD License
*  which accompanies this distribution.  The full text of the license may be found at
*  http://opensource.org/licenses/bsd-license.php
*
*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*
**/

#include "StandaloneMmDmc620RasDriver.h"

//
// Private copy of the MM system table for future use
//
EFI_MM_SYSTEM_TABLE *mMmst = NULL;

static EFI_GUID DMC620_CPER_GUID[RAS_DMC620_ERROR_SOURCE_TOTAL] =
{
  { 0xb4c19352, 0xf224, 0x4586, { 0x9f, 0x7e, 0x13, 0xb3, 0xa3, 0xc9, 0x2d, 0xbd }}, // 804 Event
  { 0xce920f02, 0x6203, 0x46ed, { 0xac, 0x63, 0x67, 0x0a, 0x0f, 0xea, 0x35, 0x30 }}  // 805 Event
};

EFI_MM_RAS_ERROR_SOURCE_INFO_PROTOCOL mEfiMmDmcErrorSourceInfo = {
  EFI_MM_RAS_ERROR_SOURCE_INFO_REVISION,
  Dmc620ErrorSourceInfoGet
};

static EFI_GUID ErrorSectionType[1] = {
  EFI_ERROR_SECTION_PLATFORM_MEMORY_GUID
};

struct ErrorDataStruct {
  EFI_PLATFORM_MEMORY_ERROR_DATA MemoryError;
};

static struct ErrorDataStruct ErrorData;

static SECTIONS_INFO ErrorSectionInfo = { 1, sizeof(ErrorData), ErrorSectionType, &ErrorData };

EFI_HANDLE mDmcHandle = NULL;

static
EFI_STATUS
EFIAPI
GenerateCperBlob (
  IN OUT SECTIONS_INFO  **SectionInfo
  )
{
  DEBUG((DEBUG_INFO, "Configure CPER\n"));
  *SectionInfo = &ErrorSectionInfo;

  ErrorData.MemoryError.ValidFields = EFI_PLATFORM_MEMORY_PHY_ADDRESS_VALID |
                                      EFI_PLATFORM_MEMORY_PHY_ADDRESS_MASK_VALID |
                                      EFI_PLATFORM_MEMORY_ERROR_TYPE_VALID;
  ErrorData.MemoryError.ErrorStatus.Type = ErrorMemStorage;
  ErrorData.MemoryError.ErrorStatus.DataSignal = 1;
  ErrorData.MemoryError.ErrorStatus.DetectedByResponder = 1;
  ErrorData.MemoryError.PhysicalAddress = 0x4001FFF0;
  ErrorData.MemoryError.PhysicalAddressMask = 0xFFFFFFFFFFFFF000;
  ErrorData.MemoryError.Node = 0;
  ErrorData.MemoryError.Card = 0;
  ErrorData.MemoryError.ModuleRank = 0;
  ErrorData.MemoryError.Bank =  5;
  ErrorData.MemoryError.Device =  0;
  ErrorData.MemoryError.Row =  0xA;
  ErrorData.MemoryError.Column =  5;
  ErrorData.MemoryError.BitPosition = 8;
  ErrorData.MemoryError.RequestorId = 0xFFFFFFFFFFFFFFFF;
  ErrorData.MemoryError.ResponderId = 0xAA55AA55AA55AA55;
  ErrorData.MemoryError.TargetId = 0xFFFFFFFFFFFFFFFF;
  ErrorData.MemoryError.ErrorType = EFI_PLATFORM_MEMORY_ERROR_PARITY;
  ErrorData.MemoryError.Extended = 0;
  ErrorData.MemoryError.RankNum = 0;
  ErrorData.MemoryError.CardHandle = 0;
  ErrorData.MemoryError.ModuleHandle = 0;

  return EFI_SUCCESS;
}

/**
  This function sets the correctable errors threshold

  @param  DmcRegs       A pointer to the specific type of DMC error registers
  @param  ErrRecType    A type of the DMC error register
  @param  ErrThreshold  Error threshold value

  @return Status Code

**/
EFI_STATUS
Dmc620RasSetCorrectableErrorThreshold (
    IN volatile DMC620_ERR_REGS_TYPE *DmcRegs,
    IN ERR_RECORD_TABLE_TYPE         ErrRecType,
    IN UINT32                        ErrThreshold
    )
{
  if (DmcRegs == NULL) {
    DEBUG ((DEBUG_ERROR, "Dmc620SetCorrectableErrorCounterThreshold: Invalid DMC control registers address\n"));
    return EFI_INVALID_PARAMETER;
  }

  //TODO: Error counters for other errors
  switch (ErrRecType) {
    case DRAM_ECC_CORRECTED_FH:
      break;
    case DRAM_ECC_FH:
      break;
    case CHI_FH:
      break;
    case SRAM_ECC_CORRECTED_FH:
      DmcRegs->ErrMisc2 = 0x8000 - ErrThreshold;
      DEBUG ((DEBUG_INFO, "DMC620 RAS correctable error counter: 0x%x\n", DmcRegs->ErrMisc2));
      break;
    case SRAM_ECC_FH:
      break;
    case DMC_ERROR_RECOVERY:
      break;
    default:
      break;
  }

  return EFI_SUCCESS;
}

/**
  This function will drain the last DMC command

  @param  DmcCtrl      A pointer to DMC620 control registers

  @return none

**/
VOID
Dmc620DrainCmd (
    IN volatile DMC620_REGS_TYPE *DmcCtrl
    )
{
  DmcCtrl->MemcCmd = EXECUTE_DRAIN;
  while (((UINT32)DmcCtrl->MemcStatus & STATE_MASK) != READY_STATE) {
    continue;
  }
}

/**
  This function gets the DMC Status string

  @param  DmcCtrl      A pointer to DMC620 control registers
  @param  StatusMask   A bit mask for the status

  @return none

**/
static
CONST
CHAR16*
GetSupportStatusString (
    IN volatile DMC620_REGS_TYPE *DmcCtrl,
    IN UINT32                    StatusMask
    )
{
  static CHAR16 Controllable[] = L"CONTROLLABLE";
  static CHAR16 None[] = L"NONE";

  if ((DmcCtrl->Err0Fr & StatusMask) == StatusMask) {
    return Controllable;
  }

  return None;
}

/**
  This function prints out DMC supported features

  @param  DmcCtrl      A pointer to DMC620 control registers

  @return none

**/
static
VOID
Dmc620RasSupportCheck (
    IN volatile DMC620_REGS_TYPE *DmcCtrl
    )
{
  DEBUG ((DEBUG_INFO, "DMC620 RAS Available Features:\n"));
  DEBUG ((DEBUG_INFO, "DMC620 RAS Error Detection : %s\n", GetSupportStatusString (DmcCtrl, ED_FE_ENABLED)));
  DEBUG ((DEBUG_INFO, "DMC620 RAS Error on Writes deferred : %s\n",
                                                           GetSupportStatusString (DmcCtrl, DE_FE_ENABLED)));
  DEBUG ((DEBUG_INFO, "DMC620 RAS Uncorrected Error Recovery Interrupt : %s\n",
                                                           GetSupportStatusString (DmcCtrl, UI_FE_ENABLED)));
  DEBUG ((DEBUG_INFO, "DMC620 RAS Fault Handling Interrupt : %s\n",
                                                           GetSupportStatusString (DmcCtrl, FI_FE_ENABLED)));
  DEBUG ((DEBUG_INFO, "DMC620 RAS Uncorrected Error Reporting : %s\n",
                                                           GetSupportStatusString (DmcCtrl, UE_FE_ENABLED)));
  DEBUG ((DEBUG_INFO, "DMC620 RAS Corrected Fault Handling Interrupt : %s\n",
                                                           GetSupportStatusString (DmcCtrl, CFI_FE_ENABLED)));
}

/**
  This function parses DMC RAS errors

  @param  DmcRegs       A pointer to the specific type of DMC error registers
  @param  DmcCtrl       A pointer to DMC620 control registers
  @param  ErrRecType    A type of the DMC error register

  @return none

**/
static
VOID
Dmc620RasProcessError (
    IN volatile DMC620_ERR_REGS_TYPE *DmcErrRegs,
    IN volatile DMC620_REGS_TYPE     *DmcCtrl,
    IN ERR_RECORD_TABLE_TYPE         ErrRecType
    )
{
  UINT32         ResetReg;
  UINT32         ErrorRank;
  BOOLEAN        CEValid;
  UINTN          NumMiscRegs;
  UINTN          RegsCount;
  UINT32         MiscReg[6];
  UINT32         ErrThreshold;
  EFI_STATUS     Status;
  SECTIONS_INFO  *SectionInfo;

  ErrorRank = 0xFFFF;
  CEValid = FALSE;
  NumMiscRegs = 0;

  while (DmcErrRegs->ErrStatus != 0) {
   GenerateCperBlob (&SectionInfo);
   if (DmcErrRegs->ErrStatus & ERR_STATUS_V) {
      DEBUG ((DEBUG_INFO, "*************************************\n"));
      switch (ErrRecType) {
        case DRAM_ECC_CORRECTED_FH:
          DEBUG ((DEBUG_INFO, "DMC620 RAS Error: DRAM ECC Corrected Fault\nError Dump:\n"));
          ErrorRank = (DmcErrRegs->ErrStatus & ERR_STATUS_IERR) >> ERR_STATUS_RANK_BIT;
          CEValid = TRUE;
          NumMiscRegs = 6;
          break;
        case DRAM_ECC_FH:
          DEBUG ((DEBUG_INFO, "DMC620 RAS Error: DRAM ECC Fault Handling\nError Dump:\n"));
          NumMiscRegs = 6;
          break;
        case CHI_FH:
          DEBUG ((DEBUG_INFO, "DMC620 RAS Error: CHI Fault\nError Dump:\n"));
          CEValid = TRUE;
          NumMiscRegs = 2;
          break;
        case SRAM_ECC_CORRECTED_FH:
          DEBUG ((DEBUG_INFO, "DMC620 RAS Error: SRAM ECC Corrected Fault\nError Dump:\n"));
          CEValid = TRUE;
          NumMiscRegs = 3;
          break;
        case SRAM_ECC_FH:
          DEBUG ((DEBUG_INFO, "DMC620 RAS Error: SRAM ECC Fault\nError Dump:\n"));
          NumMiscRegs = 3;
          break;
        case DMC_ERROR_RECOVERY:
          DEBUG ((DEBUG_INFO, "DMC620 RAS Error: DMC Error Recovery\nError Dump:\n"));
          NumMiscRegs = 2;
          break;
        default:
          break;
      }

      DEBUG ((DEBUG_INFO, "DMC620 RAS Error Type : "));
      if ((DmcErrRegs->ErrStatus & ERR_STATUS_ECC_ERR_SRAM) == ERR_STATUS_ECC_ERR_SRAM) {
        DEBUG ((DEBUG_INFO, "SRAM\n"));
      } else if ((DmcErrRegs->ErrStatus & ERR_STATUS_ECC_ERR_SDRAM) == ERR_STATUS_ECC_ERR_SDRAM) {
        DEBUG ((DEBUG_INFO, "DRAM\n"));
      } else if ((DmcErrRegs->ErrStatus & ERR_STATUS_ECC_ERR_DBP) == ERR_STATUS_ECC_ERR_DBP) {
        DEBUG ((DEBUG_INFO, "DPB\n"));
      } else {
        DEBUG ((DEBUG_INFO, "NONE\n"));
      }

      if (ErrorRank != 0xFFFF) {
        DEBUG ((DEBUG_INFO, "DMC620 RAS Error Rank : %d\n", ErrorRank));
      }

      if (CEValid) {
        DEBUG ((DEBUG_INFO, "DMC620 RAS Corrected Error Recorded : "));
        if ((DmcErrRegs->ErrStatus & ERR_STATUS_CE_PERSISTENT) == ERR_STATUS_CE_PERSISTENT) {
          DEBUG ((DEBUG_INFO, "PERSISTENT\n"));
        } else if ((DmcErrRegs->ErrStatus & ERR_STATUS_CE_CORRECTED) == ERR_STATUS_CE_CORRECTED) {
          DEBUG ((DEBUG_INFO, "CORRECTED\n"));
        } else if ((DmcErrRegs->ErrStatus & ERR_STATUS_CE_TRANSIENT) == ERR_STATUS_CE_TRANSIENT) {
          DEBUG ((DEBUG_INFO, "TRANSIENT\n"));
        } else {
          DEBUG ((DEBUG_INFO, "NONE\n"));
        }
      }

      DEBUG ((DEBUG_INFO, "DMC620 RAS Correctable Error Counter Overflow : "));
      if (DmcErrRegs->ErrStatus & ERR_STATUS_OF) {
        DEBUG ((DEBUG_INFO, "YES\n"));
      } else {
        DEBUG ((DEBUG_INFO, "NO\n"));
      }

      if ((DmcErrRegs->ErrStatus & ERR_STATUS_AV) == ERR_STATUS_AV) {
        DEBUG ((DEBUG_INFO, "DMC620 RAS Error Address Registers Are Valid\n"));
          DEBUG ((DEBUG_INFO, "---------------------------------\n"));
          DEBUG ((DEBUG_INFO, "DMC620 RAS Error Address 0 : 0x%x\n", DmcErrRegs->ErrAddr0));
          DEBUG ((DEBUG_INFO, "DMC620 RAS Error Address 1 : 0x%x\n", DmcErrRegs->ErrAddr1));
          DEBUG ((DEBUG_INFO, "---------------------------------\n"));
          ErrorData.MemoryError.PhysicalAddress = DmcErrRegs->ErrAddr1;
          ErrorData.MemoryError.PhysicalAddress = ErrorData.MemoryError.PhysicalAddress << 32 | DmcErrRegs->ErrAddr0;
          ErrorData.MemoryError.ErrorType = EFI_PLATFORM_MEMORY_ERROR_PARITY;
      }

      if ((DmcErrRegs->ErrStatus & ERR_STATUS_MV) == ERR_STATUS_MV) {
       DEBUG ((DEBUG_INFO, "DMC620 RAS Misc Registers Are Valid\n"));

       MiscReg[0] = DmcErrRegs->ErrMisc0;
       MiscReg[1] = DmcErrRegs->ErrMisc1;
       MiscReg[2] = DmcErrRegs->ErrMisc2;
       MiscReg[3] = DmcErrRegs->ErrMisc3;
       MiscReg[4] = DmcErrRegs->ErrMisc4;
       MiscReg[5] = DmcErrRegs->ErrMisc5;

       DEBUG ((DEBUG_INFO, "---------------------------------\n"));
       for (RegsCount = 0; RegsCount < NumMiscRegs; RegsCount++) {
         DEBUG ((DEBUG_INFO, "DMC620 RAS Error Misc %d : 0x%x\n", RegsCount, MiscReg[RegsCount]));
       }
       DEBUG ((DEBUG_INFO, "---------------------------------\n"));
      }
      DEBUG ((DEBUG_INFO, "*************************************\n"));
    }

    if (((UINT32)DmcErrRegs->ErrStatus & ERR_STATUS_OF) == ERR_STATUS_OF) {
      ErrThreshold = PcdGet32(PcdDmcCorrectableErrorThreshold);
      Dmc620RasSetCorrectableErrorThreshold (DmcErrRegs, ErrRecType, ErrThreshold);
    }

    ResetReg = DmcErrRegs->ErrStatus;
    DmcErrRegs->ErrStatus = ResetReg;
    Dmc620DrainCmd (DmcCtrl);
    Status = CperWrite(SectionInfo, PcdGet64 (PcdCperBufferBase));
    if (EFI_ERROR (Status)) {
      DEBUG ((DEBUG_ERROR, "Failed to Write CPER blob.\n"));
    }
  }
}

/**
  This function checks if DMC status is valid

  @param  DmcCtrl  A pointer to DMC620 control registers

  @return Status Code

**/
EFI_STATUS
Dmc620Status (
    IN volatile DMC620_REGS_TYPE *DmcCtrl
    )
{
  if (DmcCtrl == NULL) {
    DEBUG ((DEBUG_ERROR, "Dmc620EnableRAS: Invalid DMC control registers address\n"));
    return EFI_INVALID_PARAMETER;
  }

  if ((DmcCtrl->MemcStatus & STATE_MASK) != READY_STATE) {
    DEBUG ((DEBUG_ERROR, "Dmc620EnableRAS: Invalid DMC state\n"));
    return RETURN_DEVICE_ERROR;
  }

  DEBUG ((DEBUG_INFO, "DMC620 RAS ctrl0: 0x%x\n", DmcCtrl->Err0Ctlr0));
  DEBUG ((DEBUG_INFO, "DMC620 RAS ctrl1: 0x%x\n", DmcCtrl->Err0Ctlr1));

  return EFI_SUCCESS;
}


/**
  This is an initialize procedure for the driver.

  The driver handler will be dispatched by CPU driver and does not
  require and CPU save restore mechanisms.

**/
EFI_STATUS
Dmc620RasDriverInitialize (
  IN EFI_HANDLE              ImageHandle,
  IN EFI_MM_SYSTEM_TABLE     *SystemTable
  )
{
  EFI_STATUS                                Status;
  EFI_HANDLE                                DispatchHandle;
  volatile DMC620_REGS_TYPE                 *DmcCtrl;
  UINT32                                    ErrThreshold;

  ASSERT (SystemTable != NULL);
  mMmst = SystemTable;

  //TODO: Support all DMCX
  DmcCtrl = DMC620_0;

  // register the RAS event handle
  Status = mMmst->MmiHandlerRegister (Dmc620RasEventHandler, &gEfiMmDmcRasEventGuid, &DispatchHandle);
  if (EFI_ERROR(Status)) {
    DEBUG ((DEBUG_ERROR, "Dmc620RasDriverInitialize: DMC620 RAS registration failed\n"));
    return Status;
  }

  // Install error source information protocol
  Status = mMmst->MmInstallProtocolInterface (&mDmcHandle,
                                              &gEfiMmRasErrorSourceInfoProtocolGuid,
                                              EFI_NATIVE_INTERFACE,
                                              &mEfiMmDmcErrorSourceInfo);

  if (EFI_ERROR(Status)) {
    DEBUG ((DEBUG_ERROR, "Dmc620RasDriverInitialize: DMC620 RAS error source info protocol failed\n"));
    return Status;
  }

  DEBUG ((DEBUG_INFO, "DMC620 RAS registered\n"));

  // register the inject error handle
  Status = mMmst->MmiHandlerRegister (Dmc620ErrorInjectEventHandler,
                                      &gEfiMmDmcErrorInjectEventGuid,
                                      &DispatchHandle);
  if (EFI_ERROR(Status)) {
    DEBUG ((DEBUG_ERROR, "MM DMC620 error injection registration failed\n"));
    return Status;
  }

  // Set error threshold for correctable errors
  ErrThreshold = PcdGet32 (PcdDmcCorrectableErrorThreshold);
  Status = Dmc620RasSetCorrectableErrorThreshold ((DMC620_ERR_REGS_TYPE *)((UINTN)&DmcCtrl->Err4Fr),
                                                  SRAM_ECC_CORRECTED_FH,
                                                  ErrThreshold);
  if (EFI_ERROR(Status)) {
    DEBUG ((DEBUG_ERROR, "Dmc620RasDriverInitialize: Failed to set error threshold\n"));
    return Status;
  }

  DEBUG ((DEBUG_INFO, "DMC620 error injection registered\n"));

  return EFI_SUCCESS;
}

/**
  Get RAS Error Source Information.

  @param This               Instance pointer for this protocol

  @retval Buffer            RAE Error Source Information buffer.
  @retval ErrorSourceCount  Number of supported RAS Error Sources.
                            The Buffer parameter points to the begining
                            of Error Source records.
  @retval EFI_SUCCESS       Device supports RAS error sources.
  @retval EFI_UNSUPPORTED   Device does not support RAS error sources.
  @retval EFI_DEVICE_ERROR  Device device read error.
**/
EFI_STATUS
EFIAPI
Dmc620ErrorSourceInfoGet (
    IN  EFI_MM_RAS_ERROR_SOURCE_INFO_PROTOCOL *This,
    OUT EFI_APEI_ERROR_SOURCE                 **Buffer,
    OUT UINTN                                 *ErrorSourceCount
    )
{
  EFI_STATUS                    Status;
  EFI_APEI_ERROR_SOURCE         *Source;
  UINTN                         Index;
  UINTN                         NextErrorAddress;

  Status = mMmst->MmAllocatePool (EfiRuntimeServicesData,
                                  (sizeof(EFI_APEI_ERROR_SOURCE) * RAS_DMC620_ERROR_SOURCE_TOTAL),
                                  (VOID **) &Source);

  if (Buffer == NULL) {
    *ErrorSourceCount = RAS_DMC620_ERROR_SOURCE_TOTAL;
    return EFI_SUCCESS;
  }

  *Buffer = NULL;
  *ErrorSourceCount = 0;

  if (!EFI_ERROR(Status)) {
    *Buffer = Source;
    *ErrorSourceCount = RAS_DMC620_ERROR_SOURCE_TOTAL;

    for (Index = 0; Index < RAS_DMC620_ERROR_SOURCE_TOTAL; Index++) {
      NextErrorAddress = PcdGet64 (PcdCperBufferBase) +
                         (RAS_DMC620_ERROR_CPER_RECORD_SIZE + RAS_DMC620_ERROR_ACK_REGISTER_SIZE) * Index;

      Source->SourceId = 1 + Index;
      Source->GhesType = RAS_DMC620_ERROR_GHES_TYPE_V2;
      Source->EventId = RAS_DMC620_ERROR_SOURCE_START_EVENT + Index;
      Source->NumberRecordstoPreAllocate = 1;
      Source->MaxSectionsPerRecord = 1;
      Source->MaxRawDataLength =  RAS_DMC620_ERROR_CPER_RECORD_SIZE;
      Source->ErrorStatusBlockLength = RAS_DMC620_ERROR_CPER_RECORD_SIZE;

      // TODO: Implement a malloc type function for allocating a CPER memory from the CPER memory pool.
      // Replace the PCD variable with a malloc function.
      Source->ErrorStatusAddress.AddrerssSpaceId = RAS_DMC620_ERROR_ADDRESS_SPACE;
      Source->ErrorStatusAddress.RegisterBitWidth = RAS_DMC620_ERROR_REGISTER_WIDTH_BIT;
      Source->ErrorStatusAddress.RegisterBitOffset = RAS_DMC620_ERROR_REGISTER_OFFSET_BIT;
      Source->ErrorStatusAddress.AccessSize = RAS_DMC620_ERROR_ACCESS_SIZE;
      Source->ErrorStatusAddress.Address = NextErrorAddress;

      // GHESv2 acknowledgment register
      Source->ReadAckRegister.AddrerssSpaceId = RAS_DMC620_ERROR_ADDRESS_SPACE;
      Source->ReadAckRegister.RegisterBitWidth = RAS_DMC620_ERROR_REGISTER_WIDTH_BIT;
      Source->ReadAckRegister.RegisterBitOffset = RAS_DMC620_ERROR_REGISTER_OFFSET_BIT;
      Source->ReadAckRegister.AccessSize = RAS_DMC620_ERROR_ACCESS_SIZE;
      Source->ReadAckRegister.Address = NextErrorAddress + RAS_DMC620_ERROR_CPER_RECORD_SIZE;
      Source->ReadAckPreserve = 0;
      Source->ReadAckWrite = 0;
      CopyGuid(&Source->HandlerGuid, &DMC620_CPER_GUID[Index]);
      Source++;
    }
  } else {
    DEBUG ((DEBUG_ERROR, "Dmc620RasDriverInitialize: DMC620 RAS memory allocation failed\n"));
    return RETURN_OUT_OF_RESOURCES;
  }

  return EFI_SUCCESS;
}

/**
  This function is the entry point for DMC620 RAS event handler

  @param  DispatchHandle  The unique handle assigned to this handler by MmiHandlerRegister().
  @param  Context         Points to an optional handler context which was specified when the handler was registered.
  @param  CommBuffer      A pointer to a collection of data in memory that will
                          be conveyed from a non-MM environment into an MM environment.
  @param  CommBufferSize  The size of the CommBuffer.

  @return Status Code

**/
EFI_STATUS
EFIAPI
Dmc620RasEventHandler (
  IN     EFI_HANDLE               DispatchHandle,
  IN     CONST VOID               *Context,        OPTIONAL
  IN OUT VOID                     *CommBuffer,     OPTIONAL
  IN OUT UINTN                    *CommBufferSize  OPTIONAL
  )
{
  EFI_STATUS                     Status;
  volatile DMC620_REGS_TYPE      *DmcCtrl;
  volatile DMC620_ERR_REGS_TYPE  *DmcRasErrRegs;
  ERR_RECORD_TABLE_TYPE          ErrRecTypeIndex;
  UINTN                          ErrRecSize;
  UINTN                          ErrRecOffset;

  ASSERT (Context == NULL);

  Status = EFI_SUCCESS;
  /* TODO: Support all DMC620_X */
  DmcCtrl = DMC620_0;

  DEBUG ((DEBUG_INFO, "DMC620 RAS: CommBuffer - 0x%x, CommBufferSize - 0x%x\n",
         CommBuffer,
         *CommBufferSize));

  /* Check DMC controller status */
  Status = Dmc620Status (DmcCtrl);
  if (EFI_ERROR(Status)) {
      DEBUG ((DEBUG_ERROR, "Dmc620RasHandler: Invalid DMC status\n"));
      return Status;
  }

  /* Check DMC features */
  Dmc620RasSupportCheck(DmcCtrl);

  ErrRecSize = (UINTN)&DmcCtrl->Err2Fr - (UINTN)&DmcCtrl->Err1Fr;
  // Checking for 0x8000000 is a work around for the FVP issue JIRA SDDKW-42565, remove when fixed
  if (DmcCtrl->Errgsr || DmcCtrl->Err4Status == 0x8000000) {
    for (ErrRecTypeIndex = DRAM_ECC_CORRECTED_FH; ErrRecTypeIndex < DMC_ERROR_RECOVERY; ErrRecTypeIndex++) {
      ErrRecOffset = ((UINTN)ErrRecTypeIndex - 1) * ErrRecSize;
      DmcRasErrRegs = (DMC620_ERR_REGS_TYPE *)((UINTN)&DmcCtrl->Err1Fr + ErrRecOffset);
      Dmc620RasProcessError (DmcRasErrRegs, DmcCtrl, ErrRecTypeIndex);
    }
  }

  return Status;
}