Correct AsciiStrnCpy.
[mirror_edk2.git] / IntelFspPkg / Library / BaseCacheLib / CacheLib.c
1 /** @file
2
3 Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php.
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 **/
13
14 #include <Uefi.h>
15 #include <Library/BaseLib.h>
16 #include <Library/CacheLib.h>
17 #include <Library/CacheAsRamLib.h>
18 #include "CacheLibInternal.h"
19
20 /**
21 Calculate the maximum value which is a power of 2, but less the Input.
22
23 @param[in] Input The number to pass in.
24 @return The maximum value which is align to power of 2 and less the Input
25 **/
26 UINT32
27 SetPower2 (
28 IN UINT32 Input
29 );
30
31 /**
32 Search the memory cache type for specific memory from MTRR.
33
34 @param[in] MemoryAddress the address of target memory
35 @param[in] MemoryLength the length of target memory
36 @param[in] ValidMtrrAddressMask the MTRR address mask
37 @param[out] UsedMsrNum the used MSR number
38 @param[out] UsedMemoryCacheType the cache type for the target memory
39
40 @retval EFI_SUCCESS The memory is found in MTRR and cache type is returned
41 @retval EFI_NOT_FOUND The memory is not found in MTRR
42
43 **/
44 EFI_STATUS
45 SearchForExactMtrr (
46 IN EFI_PHYSICAL_ADDRESS MemoryAddress,
47 IN UINT64 MemoryLength,
48 IN UINT64 ValidMtrrAddressMask,
49 OUT UINT32 *UsedMsrNum,
50 OUT EFI_MEMORY_CACHE_TYPE *MemoryCacheType
51 );
52
53 /**
54 Check if CacheType match current default setting.
55
56 @param[in] MemoryCacheType input cache type to be checked.
57
58 @retval TRUE MemoryCacheType is default MTRR setting.
59 @retval TRUE MemoryCacheType is NOT default MTRR setting.
60 **/
61 BOOLEAN
62 IsDefaultType (
63 IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
64 );
65
66 /**
67 Return MTRR alignment requirement for base address and size.
68
69 @param[in] BaseAddress Base address.
70 @param[in] Size Size.
71
72 @retval Zero Alligned.
73 @retval Non-Zero Not alligned.
74
75 **/
76 UINT32
77 CheckMtrrAlignment (
78 IN UINT64 BaseAddress,
79 IN UINT64 Size
80 );
81
82 typedef struct {
83 UINT32 Msr;
84 UINT32 BaseAddress;
85 UINT32 Length;
86 } EFI_FIXED_MTRR;
87
88 EFI_FIXED_MTRR mFixedMtrrTable[] = {
89 { EFI_MSR_IA32_MTRR_FIX64K_00000, 0, 0x10000},
90 { EFI_MSR_IA32_MTRR_FIX16K_80000, 0x80000, 0x4000},
91 { EFI_MSR_IA32_MTRR_FIX16K_A0000, 0xA0000, 0x4000},
92 { EFI_MSR_IA32_MTRR_FIX4K_C0000, 0xC0000, 0x1000},
93 { EFI_MSR_IA32_MTRR_FIX4K_C8000, 0xC8000, 0x1000},
94 { EFI_MSR_IA32_MTRR_FIX4K_D0000, 0xD0000, 0x1000},
95 { EFI_MSR_IA32_MTRR_FIX4K_D8000, 0xD8000, 0x1000},
96 { EFI_MSR_IA32_MTRR_FIX4K_E0000, 0xE0000, 0x1000},
97 { EFI_MSR_IA32_MTRR_FIX4K_E8000, 0xE8000, 0x1000},
98 { EFI_MSR_IA32_MTRR_FIX4K_F0000, 0xF0000, 0x1000},
99 { EFI_MSR_IA32_MTRR_FIX4K_F8000, 0xF8000, 0x1000}
100 };
101
102 /**
103 Given the input, check if the number of MTRR is lesser.
104 if positive or subtractive.
105
106 @param[in] Input Length of Memory to program MTRR.
107
108 @retval Zero do positive.
109 @retval Non-Zero do subtractive.
110
111 **/
112 INT8
113 CheckDirection (
114 IN UINT64 Input
115 )
116 {
117 return 0;
118 }
119
120 /**
121 Disable cache and its mtrr.
122
123 @param[out] OldMtrr To return the Old MTRR value
124
125 **/
126 VOID
127 EfiDisableCacheMtrr (
128 OUT UINT64 *OldMtrr
129 )
130 {
131 UINT64 TempQword;
132
133 //
134 // Disable Cache MTRR
135 //
136 *OldMtrr = AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE);
137 TempQword = (*OldMtrr) & ~B_EFI_MSR_GLOBAL_MTRR_ENABLE & ~B_EFI_MSR_FIXED_MTRR_ENABLE;
138 AsmWriteMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, TempQword);
139 AsmDisableCache ();
140 }
141
142 /**
143 Recover cache MTRR.
144
145 @param[in] EnableMtrr Whether to enable the MTRR
146 @param[in] OldMtrr The saved old MTRR value to restore when not to enable the MTRR
147
148 **/
149 VOID
150 EfiRecoverCacheMtrr (
151 IN BOOLEAN EnableMtrr,
152 IN UINT64 OldMtrr
153 )
154 {
155 UINT64 TempQword;
156
157 //
158 // Enable Cache MTRR
159 //
160 if (EnableMtrr) {
161 TempQword = AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE);
162 TempQword |= (UINT64)(B_EFI_MSR_GLOBAL_MTRR_ENABLE | B_EFI_MSR_FIXED_MTRR_ENABLE);
163 } else {
164 TempQword = OldMtrr;
165 }
166
167 AsmWriteMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, TempQword);
168
169 AsmEnableCache ();
170 }
171
172 /**
173 Programming MTRR according to Memory address, length, and type.
174
175 @param[in] MtrrNumber the variable MTRR index number
176 @param[in] MemoryAddress the address of target memory
177 @param[in] MemoryLength the length of target memory
178 @param[in] MemoryCacheType the cache type of target memory
179 @param[in] ValidMtrrAddressMask the MTRR address mask
180
181 **/
182 VOID
183 EfiProgramMtrr (
184 IN UINTN MtrrNumber,
185 IN EFI_PHYSICAL_ADDRESS MemoryAddress,
186 IN UINT64 MemoryLength,
187 IN EFI_MEMORY_CACHE_TYPE MemoryCacheType,
188 IN UINT64 ValidMtrrAddressMask
189 )
190 {
191 UINT64 TempQword;
192 UINT64 OldMtrr;
193
194 if (MemoryLength == 0) {
195 return;
196 }
197
198 EfiDisableCacheMtrr (&OldMtrr);
199
200 //
201 // MTRR Physical Base
202 //
203 TempQword = (MemoryAddress & ValidMtrrAddressMask) | MemoryCacheType;
204 AsmWriteMsr64 (MtrrNumber, TempQword);
205
206 //
207 // MTRR Physical Mask
208 //
209 TempQword = ~(MemoryLength - 1);
210 AsmWriteMsr64 (MtrrNumber + 1, (TempQword & ValidMtrrAddressMask) | B_EFI_MSR_CACHE_MTRR_VALID);
211
212 EfiRecoverCacheMtrr (TRUE, OldMtrr);
213 }
214
215 /**
216 Calculate the maximum value which is a power of 2, but less the MemoryLength.
217
218 @param[in] MemoryAddress Memory address.
219 @param[in] MemoryLength The number to pass in.
220
221 @return The maximum value which is align to power of 2 and less the MemoryLength
222
223 **/
224 UINT64
225 Power2MaxMemory (
226 IN UINT64 MemoryAddress,
227 IN UINT64 MemoryLength
228 )
229 {
230 UINT64 Result;
231
232 if (MemoryLength == 0) {
233 return EFI_INVALID_PARAMETER;
234 }
235
236 //
237 // Compute inital power of 2 size to return
238 //
239 if (RShiftU64(MemoryLength, 32)) {
240 Result = LShiftU64((UINT64)SetPower2((UINT32) RShiftU64(MemoryLength, 32)), 32);
241 } else {
242 Result = (UINT64)SetPower2((UINT32)MemoryLength);
243 }
244
245 //
246 // Special case base of 0 as all ranges are valid
247 //
248 if (MemoryAddress == 0) {
249 return Result;
250 }
251
252 //
253 // Loop till a value that can be mapped to this base address is found
254 //
255 while (CheckMtrrAlignment (MemoryAddress, Result) != 0) {
256 //
257 // Need to try the next smaller power of 2
258 //
259 Result = RShiftU64 (Result, 1);
260 }
261
262 return Result;
263 }
264
265 /**
266 Return MTRR alignment requirement for base address and size.
267
268 @param[in] BaseAddress Base address.
269 @param[in] Size Size.
270
271 @retval Zero Alligned.
272 @retval Non-Zero Not alligned.
273
274 **/
275 UINT32
276 CheckMtrrAlignment (
277 IN UINT64 BaseAddress,
278 IN UINT64 Size
279 )
280 {
281 UINT32 ShiftedBase;
282 UINT32 ShiftedSize;
283
284 //
285 // Shift base and size right 12 bits to allow for larger memory sizes. The
286 // MTRRs do not use the first 12 bits so this is safe for now. Only supports
287 // up to 52 bits of physical address space.
288 //
289 ShiftedBase = (UINT32) RShiftU64 (BaseAddress, 12);
290 ShiftedSize = (UINT32) RShiftU64 (Size, 12);
291
292 //
293 // Return the results to the caller of the MOD
294 //
295 return ShiftedBase % ShiftedSize;
296 }
297
298 /**
299 Calculate the maximum value which is a power of 2, but less the Input.
300
301 @param[in] Input The number to pass in.
302
303 @return The maximum value which is align to power of 2 and less the Input.
304 **/
305 UINT32
306 SetPower2 (
307 IN UINT32 Input
308 )
309 {
310 UINT32 Result;
311
312 Result = 0;
313 #if defined(__GCC__)
314 asm("bsr %1, \
315 %%eax; \
316 bts %%eax, \
317 %0;" :"=r"(Result) :
318 "r"(Input)
319 );
320 #elif defined(_MSC_VER)
321 _asm {
322 bsr eax, Input
323 bts Result, eax
324 }
325 #endif
326 return Result;
327 }
328
329 /**
330 Programs fixed MTRRs registers.
331
332 @param[in] MemoryCacheType The memory type to set.
333 @param[in] Base The base address of memory range.
334 @param[in] Length The length of memory range.
335
336 @retval RETURN_SUCCESS The cache type was updated successfully
337 @retval RETURN_UNSUPPORTED The requested range or cache type was invalid
338 for the fixed MTRRs.
339
340 **/
341 EFI_STATUS
342 ProgramFixedMtrr (
343 IN EFI_MEMORY_CACHE_TYPE MemoryCacheType,
344 IN UINT64 *Base,
345 IN UINT64 *Len
346 )
347 {
348 UINT32 MsrNum;
349 UINT32 ByteShift;
350 UINT64 TempQword;
351 UINT64 OrMask;
352 UINT64 ClearMask;
353
354 TempQword = 0;
355 OrMask = 0;
356 ClearMask = 0;
357
358 for (MsrNum = 0; MsrNum < V_EFI_FIXED_MTRR_NUMBER; MsrNum++) {
359 if ((*Base >= mFixedMtrrTable[MsrNum].BaseAddress) &&
360 (*Base < (mFixedMtrrTable[MsrNum].BaseAddress + 8 * mFixedMtrrTable[MsrNum].Length))) {
361 break;
362 }
363 }
364 if (MsrNum == V_EFI_FIXED_MTRR_NUMBER ) {
365 return EFI_DEVICE_ERROR;
366 }
367 //
368 // We found the fixed MTRR to be programmed
369 //
370 for (ByteShift=0; ByteShift < 8; ByteShift++) {
371 if ( *Base == (mFixedMtrrTable[MsrNum].BaseAddress + ByteShift * mFixedMtrrTable[MsrNum].Length)) {
372 break;
373 }
374 }
375 if (ByteShift == 8 ) {
376 return EFI_DEVICE_ERROR;
377 }
378 for (; ((ByteShift<8) && (*Len >= mFixedMtrrTable[MsrNum].Length));ByteShift++) {
379 OrMask |= LShiftU64((UINT64) MemoryCacheType, (UINT32) (ByteShift* 8));
380 ClearMask |= LShiftU64((UINT64) 0xFF, (UINT32) (ByteShift * 8));
381 *Len -= mFixedMtrrTable[MsrNum].Length;
382 *Base += mFixedMtrrTable[MsrNum].Length;
383 }
384 TempQword = AsmReadMsr64 (mFixedMtrrTable[MsrNum].Msr) & (~ClearMask | OrMask);
385 AsmWriteMsr64 (mFixedMtrrTable[MsrNum].Msr, TempQword);
386
387 return EFI_SUCCESS;
388 }
389
390 /**
391 Check if there is a valid variable MTRR that overlaps the given range.
392
393 @param[in] Start Base Address of the range to check.
394 @param[in] End End address of the range to check.
395
396 @retval TRUE Mtrr overlap.
397 @retval FALSE Mtrr not overlap.
398 **/
399 BOOLEAN
400 CheckMtrrOverlap (
401 IN EFI_PHYSICAL_ADDRESS Start,
402 IN EFI_PHYSICAL_ADDRESS End
403 )
404 {
405 return FALSE;
406 }
407
408 /**
409 Given the memory range and cache type, programs the MTRRs.
410
411 @param[in] MemoryAddress Base Address of Memory to program MTRR.
412 @param[in] MemoryLength Length of Memory to program MTRR.
413 @param[in] MemoryCacheType Cache Type.
414
415 @retval EFI_SUCCESS Mtrr are set successfully.
416 @retval EFI_LOAD_ERROR No empty MTRRs to use.
417 @retval EFI_INVALID_PARAMETER The input parameter is not valid.
418 @retval others An error occurs when setting MTTR.
419
420 **/
421 EFI_STATUS
422 EFIAPI
423 SetCacheAttributes (
424 IN EFI_PHYSICAL_ADDRESS MemoryAddress,
425 IN UINT64 MemoryLength,
426 IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
427 )
428 {
429 EFI_STATUS Status;
430 UINT32 MsrNum, MsrNumEnd;
431 UINT64 TempQword;
432 UINT32 LastVariableMtrrForBios;
433 UINT64 OldMtrr;
434 UINT32 UsedMsrNum;
435 EFI_MEMORY_CACHE_TYPE UsedMemoryCacheType;
436 UINT64 ValidMtrrAddressMask;
437 UINT32 Cpuid_RegEax;
438
439 AsmCpuid (CPUID_EXTENDED_FUNCTION, &Cpuid_RegEax, NULL, NULL, NULL);
440 if (Cpuid_RegEax >= CPUID_VIR_PHY_ADDRESS_SIZE) {
441 AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &Cpuid_RegEax, NULL, NULL, NULL);
442 ValidMtrrAddressMask = (LShiftU64((UINT64) 1, (Cpuid_RegEax & 0xFF)) - 1) & (~(UINT64)0x0FFF);
443 } else {
444 ValidMtrrAddressMask = (LShiftU64((UINT64) 1, 36) - 1) & (~(UINT64)0x0FFF);
445 }
446
447 //
448 // Check for invalid parameter
449 //
450 if ((MemoryAddress & ~ValidMtrrAddressMask) != 0 || (MemoryLength & ~ValidMtrrAddressMask) != 0) {
451 return EFI_INVALID_PARAMETER;
452 }
453
454 if (MemoryLength == 0) {
455 return EFI_INVALID_PARAMETER;
456 }
457
458 switch (MemoryCacheType) {
459 case EFI_CACHE_UNCACHEABLE:
460 case EFI_CACHE_WRITECOMBINING:
461 case EFI_CACHE_WRITETHROUGH:
462 case EFI_CACHE_WRITEPROTECTED:
463 case EFI_CACHE_WRITEBACK:
464 break;
465
466 default:
467 return EFI_INVALID_PARAMETER;
468 }
469
470 //
471 // Check if Fixed MTRR
472 //
473 if ((MemoryAddress + MemoryLength) <= (1 << 20)) {
474 Status = EFI_SUCCESS;
475 EfiDisableCacheMtrr (&OldMtrr);
476 while ((MemoryLength > 0) && (Status == EFI_SUCCESS)) {
477 Status = ProgramFixedMtrr (MemoryCacheType, &MemoryAddress, &MemoryLength);
478 }
479 EfiRecoverCacheMtrr (TRUE, OldMtrr);
480 return Status;
481 }
482
483 //
484 // Search if the range attribute has been set before
485 //
486 Status = SearchForExactMtrr(
487 MemoryAddress,
488 MemoryLength,
489 ValidMtrrAddressMask,
490 &UsedMsrNum,
491 &UsedMemoryCacheType
492 );
493
494 if (!EFI_ERROR(Status)) {
495 //
496 // Compare if it has the same type as current setting
497 //
498 if (UsedMemoryCacheType == MemoryCacheType) {
499 return EFI_SUCCESS;
500 } else {
501 //
502 // Different type
503 //
504
505 //
506 // Check if the set type is the same as Default Type
507 //
508 if (IsDefaultType(MemoryCacheType)) {
509 //
510 // Clear the MTRR
511 //
512 AsmWriteMsr64(UsedMsrNum, 0);
513 AsmWriteMsr64(UsedMsrNum + 1, 0);
514
515 return EFI_SUCCESS;
516 } else {
517 //
518 // Modify the MTRR type
519 //
520 EfiProgramMtrr(UsedMsrNum,
521 MemoryAddress,
522 MemoryLength,
523 MemoryCacheType,
524 ValidMtrrAddressMask
525 );
526 return EFI_SUCCESS;
527 }
528 }
529 }
530
531 #if 0
532 //
533 // @bug - Need to create memory map so that when checking for overlap we
534 // can determine if an overlap exists based on all caching requests.
535 //
536 // Don't waste a variable MTRR if the caching attrib is same as default in MTRR_DEF_TYPE
537 //
538 if (MemoryCacheType == (AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE) & B_EFI_MSR_CACHE_MEMORY_TYPE)) {
539 if (!CheckMtrrOverlap (MemoryAddress, MemoryAddress+MemoryLength-1)) {
540 return EFI_SUCCESS;
541 }
542 }
543 #endif
544
545 //
546 // Find first unused MTRR
547 //
548 MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT));
549 for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum +=2) {
550 if ((AsmReadMsr64(MsrNum+1) & B_EFI_MSR_CACHE_MTRR_VALID) == 0 ) {
551 break;
552 }
553 }
554
555 //
556 // Reserve 1 MTRR pair for OS.
557 //
558 LastVariableMtrrForBios = MsrNumEnd - 1 - (EFI_CACHE_NUM_VAR_MTRR_PAIRS_FOR_OS * 2);
559 if (MsrNum > LastVariableMtrrForBios) {
560 return EFI_LOAD_ERROR;
561 }
562
563 //
564 // Special case for 1 MB base address
565 //
566 if (MemoryAddress == BASE_1MB) {
567 MemoryAddress = 0;
568 }
569
570 //
571 // Program MTRRs
572 //
573 TempQword = MemoryLength;
574
575 if (TempQword == Power2MaxMemory(MemoryAddress, TempQword)) {
576 EfiProgramMtrr(MsrNum,
577 MemoryAddress,
578 MemoryLength,
579 MemoryCacheType,
580 ValidMtrrAddressMask
581 );
582
583 } else {
584 //
585 // Fill in MTRRs with values. Direction can not be checked for this method
586 // as we are using WB as the default cache type and only setting areas to UC.
587 //
588 do {
589 //
590 // Do boundary check so we don't go past last MTRR register
591 // for BIOS use. Leave one MTRR pair for OS use.
592 //
593 if (MsrNum > LastVariableMtrrForBios) {
594 return EFI_LOAD_ERROR;
595 }
596
597 //
598 // Set next power of 2 region
599 //
600 MemoryLength = Power2MaxMemory(MemoryAddress, TempQword);
601 EfiProgramMtrr(MsrNum,
602 MemoryAddress,
603 MemoryLength,
604 MemoryCacheType,
605 ValidMtrrAddressMask
606 );
607 MemoryAddress += MemoryLength;
608 TempQword -= MemoryLength;
609 MsrNum += 2;
610 } while (TempQword != 0);
611 }
612
613 return EFI_SUCCESS;
614 }
615
616 /**
617 Reset all the MTRRs to a known state.
618
619 @retval EFI_SUCCESS All MTRRs have been reset successfully.
620
621 **/
622 EFI_STATUS
623 EFIAPI
624 ResetCacheAttributes (
625 VOID
626 )
627 {
628 UINT32 MsrNum, MsrNumEnd;
629 UINT16 Index;
630 UINT64 OldMtrr;
631 UINT64 CacheType;
632 BOOLEAN DisableCar;
633 Index = 0;
634 DisableCar = TRUE;
635
636 //
637 // Determine default cache type
638 //
639 CacheType = EFI_CACHE_UNCACHEABLE;
640
641 //
642 // Set default cache type
643 //
644 AsmWriteMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, CacheType);
645
646 //
647 // Disable CAR
648 //
649 DisableCacheAsRam (DisableCar);
650
651 EfiDisableCacheMtrr (&OldMtrr);
652
653 //
654 // Reset Fixed MTRRs
655 //
656 for (Index = 0; Index < V_EFI_FIXED_MTRR_NUMBER; Index++) {
657 AsmWriteMsr64 (mFixedMtrrTable[Index].Msr, 0);
658 }
659
660 //
661 // Reset Variable MTRRs
662 //
663 MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT));
664 for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum++) {
665 AsmWriteMsr64 (MsrNum, 0);
666 }
667
668 //
669 // Enable Fixed and Variable MTRRs
670 //
671 EfiRecoverCacheMtrr (TRUE, OldMtrr);
672
673 return EFI_SUCCESS;
674 }
675
676 /**
677 Search the memory cache type for specific memory from MTRR.
678
679 @param[in] MemoryAddress the address of target memory
680 @param[in] MemoryLength the length of target memory
681 @param[in] ValidMtrrAddressMask the MTRR address mask
682 @param[out] UsedMsrNum the used MSR number
683 @param[out] UsedMemoryCacheType the cache type for the target memory
684
685 @retval EFI_SUCCESS The memory is found in MTRR and cache type is returned
686 @retval EFI_NOT_FOUND The memory is not found in MTRR
687
688 **/
689 EFI_STATUS
690 SearchForExactMtrr (
691 IN EFI_PHYSICAL_ADDRESS MemoryAddress,
692 IN UINT64 MemoryLength,
693 IN UINT64 ValidMtrrAddressMask,
694 OUT UINT32 *UsedMsrNum,
695 OUT EFI_MEMORY_CACHE_TYPE *UsedMemoryCacheType
696 )
697 {
698 UINT32 MsrNum, MsrNumEnd;
699 UINT64 TempQword;
700
701 if (MemoryLength == 0) {
702 return EFI_INVALID_PARAMETER;
703 }
704
705 MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT));
706 for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum +=2) {
707 TempQword = AsmReadMsr64(MsrNum+1);
708 if ((TempQword & B_EFI_MSR_CACHE_MTRR_VALID) == 0) {
709 continue;
710 }
711
712 if ((TempQword & ValidMtrrAddressMask) != ((~(MemoryLength - 1)) & ValidMtrrAddressMask)) {
713 continue;
714 }
715
716 TempQword = AsmReadMsr64 (MsrNum);
717 if ((TempQword & ValidMtrrAddressMask) != (MemoryAddress & ValidMtrrAddressMask)) {
718 continue;
719 }
720
721 *UsedMemoryCacheType = (EFI_MEMORY_CACHE_TYPE)(TempQword & B_EFI_MSR_CACHE_MEMORY_TYPE);
722 *UsedMsrNum = MsrNum;
723
724 return EFI_SUCCESS;
725 }
726
727 return EFI_NOT_FOUND;
728 }
729
730 /**
731 Check if CacheType match current default setting.
732
733 @param[in] MemoryCacheType input cache type to be checked.
734
735 @retval TRUE MemoryCacheType is default MTRR setting.
736 @retval TRUE MemoryCacheType is NOT default MTRR setting.
737 **/
738 BOOLEAN
739 IsDefaultType (
740 IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
741 )
742 {
743 if ((AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE) & B_EFI_MSR_CACHE_MEMORY_TYPE) != MemoryCacheType) {
744 return FALSE;
745 }
746
747 return TRUE;
748 }
749