summaryrefslogtreecommitdiff
path: root/Core/EM/CmosManager/CmosBoard.c
blob: 84ad6687ca14a23ac2d3a8f7812ad65a1db041f1 (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
//*************************************************************************
//*************************************************************************
//**                                                                     **
//**        (C)Copyright 1985-2009, American Megatrends, Inc.            **
//**                                                                     **
//**                       All Rights Reserved.                          **
//**                                                                     **
//**      5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093           **
//**                                                                     **
//**                       Phone: (770)-246-8600                         **
//**                                                                     **
//*************************************************************************
//*************************************************************************

//**********************************************************************
// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/CmosManager/CmosBoard.c 1     10/25/12 9:02a Wesleychen $Revision: 0 $
//
// $Date: 10/25/12 9:02a $
//**********************************************************************
// Revision History
// ----------------
// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/CmosManager/CmosBoard.c $
// 
// 1     10/25/12 9:02a Wesleychen
// Update it to the rev19.
// 
// 19    6/08/12 4:48p Michaela
// [TAG]          EIP92072
// [Category]     Spec Update
// [Severity]     Normal
// [Description]  CMOS Manager Needs Code Changes for Coding Standards
// Compliance
// [Files]        Multiple
// 
// 18    5/23/12 12:02p Michaela
// [TAG]          EIP90679
// [Category]     Improvement
// [Description]  MonotonicCounter variable guid changed.
// [Files]        CmosBoard.c
// 
// 17    5/23/12 11:48a Michaela
// [TAG]          EIP90679
// [Category]     Improvement
// [Description]  MonotonicCounter variable guid changed.
// [Files]        CmosBoard.c
// 
// 16    6/15/10 2:22p Michaela
// 
// 15    3/08/10 1:08p Michaela
// 
// 14    3/08/10 12:56p Michaela
// Comment example gUnmanagedTable
// 
// 13    3/05/10 4:53p Michaela
// 
// 12    12/04/09 7:30p Michaela
// 
// 11    12/03/09 6:11p Michaela
// Added default implementation of CmosMgrIsColdBoot
// 
// 10    7/29/09 9:54a Michaela
// updates Aptio Enhancement EIP 22205
// (no code changes)
// 
// 9     6/15/09 5:10p Michaela
// 
// 8     6/02/09 3:25p Michaela
// For label: 4.6.3_CMOSMGR_11
// 
// 7     2/23/09 5:59p Michaela
// --ReadWriteSecondBankTranslated() is only included as a porting
//   example, and should be added to SBGeneric.c and prototyped in
//   SBCsplib.h (See notes)
// 
// 6     2/16/09 10:28p Michaela
// ReadWriteStandardRange()
//     - Modified to use CMOS_BANK0_INDEX
//       and CMOS_BANK0_DATA
//     - Validation of CmosRegister parameter
//     - OR CmosRegister with CMOS_NMI_BIT_VALUE
//       to specify NMI bit.
// ReadWriteSecondBankTranslated()
//     - Added to translate CmosRegister to
//       index port value for bank 2 access
//     - Use CMOS_BANK1_INDEX and CMOS_BANK1_DATA
//       to access bank 2
// 
// 5     1/21/09 2:47p Michaela
// change CMOS_CLOCK_RANGE_INDEX to CMOS_STD_INDEX
// and CMOS_CLOCK_RANGE_DATA to CMOS_STD_DATA
// 
// 4     1/21/09 2:38p Michaela
// update for release 4.6.3_CMOSMGR_11:
// 
// **Removed CMOS_CLOCK_RANGE_INDEX and 
//   CMOS_CLOCK_RANGE_DATA SDL Tokens. 
// **Changed the default value of CMOS_STD_INDEX and 
//   CMOS_STD_DATA to 0x70 and 0x71, respectively. 
//   Updated CMOS_PORT_MAPPING elinks to use 
//   ReadWriteStandardRange() for the 0x0 to 0x7f region. 
// **Added CMOS_MGR_SET_NMI_BIT to specify whether or 
//   not to set the NMI bit for access to 0x0 to 0x7f 
//   region. 
// **Removed ReadWriteClockRange() in CmosBoard.c 
// **Modified ReadWriteStandardRange() in CmosBoard.c 
//   to access the NMI range CMOS, where the NMI bit is 
//   set, as specified by the CMOS_MGR_SET_NMI_BIT 
//   Boolean token. 
// Modified ReadWriteStandardRange() in CmosBoard.c to access the NMI
// range CMOS, where the NMI bit is set, as specified by the
// CMOS_MGR_SET_NMI_BIT Boolean token. 
// 
// 3     1/08/09 10:51a Michaela
//   >Added function headers
//   >Updated function parameter modifiers
//   >renamed and updated to CmosBoard module part
//   >Core/Board SDL Tokens and CMOS Tokens are separated
// 
// 2     11/17/08 4:01p Michaela
// --Added default handlers for RTC range and Standard range CMOS
//   registers
// 
// 1     11/14/08 9:24a Michaela
// **Add support for board-specific access functions
// 
// 0     11/12/08 6:00p MichaelA
// Created
// 
//**********************************************************************

//<AMI_FHDR_START>
//---------------------------------------------------------------------------
//
// Name:    CmosBoard.c
//
// Description: Contains routines that are board-specific.
//
//---------------------------------------------------------------------------
//<AMI_FHDR_END>

#include "CmosBoard.h"

//---------------------------------------------------------------------------
// CmosBank is initialized using the CMOS_PORT_MAPPING SDL Elink.
// This array is used to determine which index/data port pair to use for a 
// specific CMOS register address.
//---------------------------------------------------------------------------
extern CMOS_PORT_MAP *gCmosBank;
extern UINT16 gCmosBankCount;


// <AMI_PHDR_START>
//----------------------------------------------------------------------------
// 
// Name: ReadWriteStandardRange
//
// Description:
//  This function is used to access addresses in the Standard CMOS 
//  register range (0x0-0x7f), for PEI and DXE boot phases.
//
// Input:   
//  IN EFI_PEI_SERVICES **PeiServices 
//                  --  PEI Services table pointer (NULL in DXE phase)
//  IN CMOS_ACCESS_TYPE AccessType 
//                  --  ReadType or WriteType to specify the type of access
//  IN UINT16 CmosRegister 
//                  --  The CMOS register to access
//  IN OUT UINT8 *CmosParameterValue 
//                  -- Pointer to the data variable to be accessed
//
// Output:
//      EFI_STATUS (Return Value)
//                  = EFI_SUCCESS if successful
//                  = or other valid EFI error code
//
// Modified:    None
//
// Referrals:   IoRead8, IoWrite8
//
// Notes:       N/A
//-------------------------------------------------------------------------- 
// <AMI_PHDR_END>

EFI_STATUS ReadWriteStandardRange (
    IN      EFI_PEI_SERVICES      **PeiServices,  // NULL in DXE phase
    IN      CMOS_ACCESS_TYPE      AccessType,
    IN      UINT16                CmosRegister,
    IN OUT  UINT8                 *CmosParameterValue )
{
    UINT8   TempValue;
    
    if (CmosRegister > 0x7f)
        return EFI_INVALID_PARAMETER;

    // If reading an RTC register, then check the Update in Progress bit in
    // Status register A to ensure a read is allowed.
    if(CmosRegister <= 9 && AccessType == ReadType) {
        do {
            IoWrite8(CMOS_BANK0_INDEX, 0xa | CMOS_NMI_BIT_VALUE);
            TempValue = IoRead8(CMOS_BANK0_DATA);
        } while (TempValue & 0x80);
    }

    IoWrite8( CMOS_BANK0_INDEX, (UINT8)CmosRegister | CMOS_NMI_BIT_VALUE );

    if (AccessType == ReadType){
        *CmosParameterValue = IoRead8( CMOS_BANK0_DATA );
    }
    else {
        IoWrite8( CMOS_BANK0_DATA, *CmosParameterValue );
    }

    return EFI_SUCCESS;
}

//----------------------------------------------------------------------------
// 
// Name: ReadWriteBank1Translated
//
// Description:
//  This function is used to access addresses in the CMOS register range 
//  (0x80-0xff), for PEI and DXE boot phases.
//
// Input:   
//  IN EFI_PEI_SERVICES **PeiServices
//                  --  Pointer to the PEI services table.  (This pointer
//                      is NULL in the DXE phase.)
//  IN CMOS_ACCESS_TYPE AccessType 
//                  --  ReadType or WriteType to specify the type of access
//  IN UINT16 CmosRegister 
//                  --  The CMOS register to access
//  IN OUT  UINT8 *CmosParameterValue 
//                  -- Pointer to the data variable to be accessed
//
// Output:
//  EFI_STATUS (return value) 
//                  EFI_SUCCESS - the access operation was successfull.
//                  Otherwise - a valid EFI error code is returned.
//
// Modified:    None
//
// Referrals:   IoRead8, IoWrite8
//
// Notes:       
//      This function is used when a translation from logical 
//      address to index port value is required.  For example, the 
//      ICH10 only allows values 0-7f for port 72/73 (upper bank) 
//      access, so logical CMOS address 0x80 must be translated to 
//      index port value 0, 0x81 becomes index port value 1, and 
//      so on.
//
//-------------------------------------------------------------------------- 


//============================================================================
// Southbridge porting notes
//============================================================================
// The following code is an example of how to implement code that
// translates from CMOS register number to access the physical
// CMOS location when the register number is not identical to the
// physical location.
//
// If access to the address range above 0x7f is required, and translation
// between CMOS register number and CMOS index port value must be made,
// then a function similar to this should be place in SBGeneric.c, SBCsplib.h,
// and the appropriate CMOS_PORT_MAPPING eLink should also be defined.
//============================================================================

/*
EFI_STATUS ReadWriteSecondBankTranslated (
    IN      EFI_PEI_SERVICES      **PeiServices,  // NULL in DXE phase
    IN      CMOS_ACCESS_TYPE      AccessType,
    IN      UINT16                CmosRegister,
    IN OUT  UINT8                 *CmosParameterValue )
{
    if (CmosRegister < 0x80 || CmosRegister > 0xff)
        return EFI_INVALID_PARAMETER;

    IoWrite8( CMOS_BANK1_INDEX, (UINT8)(CmosRegister-0x80));

    if (AccessType == ReadType){
        *CmosParameterValue = IoRead8( CMOS_BANK1_DATA );
    }
    else {
        IoWrite8( CMOS_BANK1_DATA, *CmosParameterValue );
    }

    return EFI_SUCCESS;
}
*/


// <AMI_PHDR_START>
//----------------------------------------------------------------------------
// 
// Name: CmosMgrBatteryIsGood
//
// Description:
//  This function is used to determing whether or not the CMOS battery is
//  good.
//
// Input:   
//  IN EFI_PEI_SERVICES **PeiServices
//                  --  Pointer to the PEI services table.  (This pointer
//                      is NULL in the DXE phase.)
//
// Output:
//      BOOLEAN (Return Value)
//                  = TRUE if the battery is good
//                  = TRUE if the battery is bad
//
// Modified:    None
//
// Referrals:   IoRead8, IoWrite8
//
// Notes:       Some chipsets need to check a PCI configuration space
//              register to determine the RTC power status.
//-------------------------------------------------------------------------- 
// <AMI_PHDR_END>

BOOLEAN CmosMgrBatteryIsGood (
    IN  EFI_PEI_SERVICES      **PeiServices  /* NULL in DXE */  )
{
    // PORTING PORTING PORTING

    IoWrite8( CMOS_BANK0_INDEX, 
        CMOS_RTC_STATUS_REGISTER + CMOS_NMI_BIT_VALUE );

    return ((IoRead8( CMOS_BANK0_DATA ) & 0x80) != 0) ? TRUE : FALSE;

    // PORTING PORTING PORTING
}

//<AMI_PHDR_START>
//---------------------------------------------------------------------------
//
// Procedure: CmosIsUsable
//
// Description:
//      This function determines whether or not the CMOS is usable. It may
//      be possible to use the CMOS even if the battery is bad.
//
// Input:
//      IN EFI_CMOS_MANAGER_INTERFACE *Manager
//                  -- Pointer to the Manager's interface
//
// Output:
//      BOOLEAN (Return value)
//                  = TRUE - CMOS is usable
//                  = FALSE - CMOS is not usable
//
// Notes:
//      Typically, register 0xd can be used to determine whether or not
//      CMOS is usable.  It may be possible to use the CMOS for reads/writes
//      if the battery is bad.
//
//---------------------------------------------------------------------------
//<AMI_PHDR_END>

BOOLEAN CmosIsUsable (
    IN  EFI_PEI_SERVICES      **PeiServices  /* NULL in DXE */  )
{
    IoWrite8( CMOS_BANK0_INDEX, 
        CMOS_RTC_STATUS_REGISTER + CMOS_NMI_BIT_VALUE );

    return ((IoRead8( CMOS_BANK0_DATA ) & 0x80) != 0) ? TRUE : FALSE;
}

//<AMI_PHDR_START>
//---------------------------------------------------------------------------
//
// Procedure: CmosMgrIsFirstBoot
//
// Description:
//      This function determines whether or not this is the first boot after
//      programming the boot device (flash part, ROM emulator, ...).
//
// Input:
//      IN  EFI_PEI_SERVICES **PeiServices
//                  --  Pointer to the PEI services table.  (This pointer
//                      is NULL in the DXE phase.)
//
// Output:
//      BOOLEAN (Return Value)
//                  = TRUE, if this is the first boot
//                  = FALSE, otherwise
//
// Notes:
//      For some chipsets, there may be additional issues to consider,
//      such as warm reboot during the PEI phase, multiple processor threads
//      and so on.  Therefore, this function can be implemented by an external
//      module (typically the Southbridge module).
//
//---------------------------------------------------------------------------
//<AMI_PHDR_END>

BOOLEAN CmosMgrIsFirstBoot (
    IN  EFI_PEI_SERVICES        **PeiServices )
{
    EFI_STATUS          Status = EFI_SUCCESS;

#ifdef PEI_COMPILE
    UINTN               Size = sizeof(UINT32);
#if ((CORE_COMBINED_VERSION > 262797) && defined(AMI_GLOBAL_VARIABLE_GUID))
    EFI_GUID            GlobalVariableGuid = AMI_GLOBAL_VARIABLE_GUID;
#else 
    EFI_GUID            GlobalVariableGuid = EFI_GLOBAL_VARIABLE;
#endif
    UINT32              Dummy;
    EFI_GUID            Guid = EFI_PEI_READ_ONLY_VARIABLE_PPI_GUID;
    EFI_PEI_READ_ONLY_VARIABLE_PPI  *ReadOnlyVariable = NULL;

    // If the MonotonicCounter variable is found then return false
    // to indicate that this is not the first boot.

    Status = (*PeiServices)->LocatePpi( PeiServices, &Guid,
                                        0, NULL, &ReadOnlyVariable);
    if (EFI_ERROR(Status))
        return TRUE;  // assume first boot if PPI not found

    Status = ReadOnlyVariable->GetVariable( PeiServices, 
                                            L"MonotonicCounter", 
                                            &GlobalVariableGuid, 
                                            NULL, 
                                            &Size, &Dummy );
#endif

    // If the CmosManagerStatus variable is not found and this is not the
    // DXE phase then this is the first boot.

    if ( EFI_ERROR(Status) )
        return TRUE;
    else       
        return FALSE;
}

//<AMI_PHDR_START>
//---------------------------------------------------------------------------
//
// Procedure: CmosMgrIsBsp
//
// Description:
//      This function returns TRUE if the currently executing CPU core
//      is the boot strap processor (BSP).
//
// Input:
//      IN  EFI_PEI_SERVICES  **PeiServices
//                  --  Pointer to the PEI services table.  (This pointer
//                      is NULL in the DXE phase.)
//
// Output:
//      BOOLEAN (Return Value)
//                  = TRUE, the BSP is executing
//                  = FALSE, otherwise
//
// Notes:
//      For some chipsets, this functions may need to be replaced.
//
//---------------------------------------------------------------------------
//<AMI_PHDR_END>

BOOLEAN CmosMgrIsBsp(
    IN  EFI_PEI_SERVICES  **PeiServices )
{
    // if bit 8 of the APIC base register is set, then the current
    // core is the BSP (for most chipsets)

    if ( ReadMsr(MSR_XAPIC_BASE) & XAPIC_BASE_BSP_BIT_MASK )
        return TRUE;
    else
        return FALSE;
}

//<AMI_PHDR_START>
//---------------------------------------------------------------------------
//
// Procedure: CmosMgrIsColdBoot
//
// Description:
//      This function returns TRUE to specify the platform is always perfoming
//      a cold boot.
//
// Input:
//      IN  EFI_PEI_SERVICES  **PeiServices
//                  --  Pointer to the PEI services table.  (This pointer
//                      is NULL in the DXE phase.)
//
// Output:
//      BOOLEAN (Return Value)
//                  = TRUE
//
// Notes:
//      For some chipsets, this functions may need to be replaced.
//
//---------------------------------------------------------------------------
//<AMI_PHDR_END>

BOOLEAN CmosMgrIsColdBoot(
    IN  EFI_PEI_SERVICES  **PeiServices )
{
    return TRUE;
}


//*************************************************************************
//*************************************************************************
//**                                                                     **
//**        (C)Copyright 1985-2009, American Megatrends, Inc.            **
//**                                                                     **
//**                       All Rights Reserved.                          **
//**                                                                     **
//**      5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093           **
//**                                                                     **
//**                       Phone: (770)-246-8600                         **
//**                                                                     **
//*************************************************************************
//*************************************************************************