NorFlashQemuLib.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /** @file
  2. Copyright (c) 2014-2018, Linaro Ltd. All rights reserved.<BR>
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. **/
  5. #include <Library/BaseLib.h>
  6. #include <Library/DebugLib.h>
  7. #include <Library/NorFlashPlatformLib.h>
  8. #include <Library/UefiBootServicesTableLib.h>
  9. #include <Protocol/FdtClient.h>
  10. #define QEMU_NOR_BLOCK_SIZE SIZE_256KB
  11. #define MAX_FLASH_BANKS 4
  12. EFI_STATUS
  13. NorFlashPlatformInitialization (
  14. VOID
  15. )
  16. {
  17. return EFI_SUCCESS;
  18. }
  19. NOR_FLASH_DESCRIPTION mNorFlashDevices[MAX_FLASH_BANKS];
  20. EFI_STATUS
  21. NorFlashPlatformGetDevices (
  22. OUT NOR_FLASH_DESCRIPTION **NorFlashDescriptions,
  23. OUT UINT32 *Count
  24. )
  25. {
  26. FDT_CLIENT_PROTOCOL *FdtClient;
  27. INT32 Node;
  28. EFI_STATUS Status;
  29. EFI_STATUS FindNodeStatus;
  30. CONST UINT32 *Reg;
  31. UINT32 PropSize;
  32. UINT32 Num;
  33. UINT64 Base;
  34. UINT64 Size;
  35. Status = gBS->LocateProtocol (
  36. &gFdtClientProtocolGuid,
  37. NULL,
  38. (VOID **)&FdtClient
  39. );
  40. ASSERT_EFI_ERROR (Status);
  41. Num = 0;
  42. for (FindNodeStatus = FdtClient->FindCompatibleNode (
  43. FdtClient,
  44. "cfi-flash",
  45. &Node
  46. );
  47. !EFI_ERROR (FindNodeStatus) && Num < MAX_FLASH_BANKS;
  48. FindNodeStatus = FdtClient->FindNextCompatibleNode (
  49. FdtClient,
  50. "cfi-flash",
  51. Node,
  52. &Node
  53. ))
  54. {
  55. Status = FdtClient->GetNodeProperty (
  56. FdtClient,
  57. Node,
  58. "reg",
  59. (CONST VOID **)&Reg,
  60. &PropSize
  61. );
  62. if (EFI_ERROR (Status)) {
  63. DEBUG ((
  64. DEBUG_ERROR,
  65. "%a: GetNodeProperty () failed (Status == %r)\n",
  66. __FUNCTION__,
  67. Status
  68. ));
  69. continue;
  70. }
  71. ASSERT ((PropSize % (4 * sizeof (UINT32))) == 0);
  72. while (PropSize >= (4 * sizeof (UINT32)) && Num < MAX_FLASH_BANKS) {
  73. Base = SwapBytes64 (ReadUnaligned64 ((VOID *)&Reg[0]));
  74. Size = SwapBytes64 (ReadUnaligned64 ((VOID *)&Reg[2]));
  75. Reg += 4;
  76. PropSize -= 4 * sizeof (UINT32);
  77. //
  78. // Disregard any flash devices that overlap with the primary FV.
  79. // The firmware is not updatable from inside the guest anyway.
  80. //
  81. if ((PcdGet64 (PcdFvBaseAddress) + PcdGet32 (PcdFvSize) > Base) &&
  82. ((Base + Size) > PcdGet64 (PcdFvBaseAddress)))
  83. {
  84. continue;
  85. }
  86. mNorFlashDevices[Num].DeviceBaseAddress = (UINTN)Base;
  87. mNorFlashDevices[Num].RegionBaseAddress = (UINTN)Base;
  88. mNorFlashDevices[Num].Size = (UINTN)Size;
  89. mNorFlashDevices[Num].BlockSize = QEMU_NOR_BLOCK_SIZE;
  90. Num++;
  91. }
  92. //
  93. // UEFI takes ownership of the NOR flash, and exposes its functionality
  94. // through the UEFI Runtime Services GetVariable, SetVariable, etc. This
  95. // means we need to disable it in the device tree to prevent the OS from
  96. // attaching its device driver as well.
  97. // Note that this also hides other flash banks, but the only other flash
  98. // bank we expect to encounter is the one that carries the UEFI executable
  99. // code, which is not intended to be guest updatable, and is usually backed
  100. // in a readonly manner by QEMU anyway.
  101. //
  102. Status = FdtClient->SetNodeProperty (
  103. FdtClient,
  104. Node,
  105. "status",
  106. "disabled",
  107. sizeof ("disabled")
  108. );
  109. if (EFI_ERROR (Status)) {
  110. DEBUG ((DEBUG_WARN, "Failed to set NOR flash status to 'disabled'\n"));
  111. }
  112. }
  113. *NorFlashDescriptions = mNorFlashDevices;
  114. *Count = Num;
  115. return EFI_SUCCESS;
  116. }