Assert efi error status invalid parameter

I was told to report the ASSERT error here because "even if it’s user error, it should properly prompt an error or halt". I mostly assume i've done something wrong but wont hurt to po...

@james090500

I was told to report the ASSERT error here because «even if it’s user error, it should properly prompt an error or halt».

I mostly assume i’ve done something wrong but wont hurt to post this.

Specs
CPU: Xeon E5606
RAM: 8GB

opencore-2021-02-06-123800.txt
EFI.zip

@vit9696

Hi. Yeah, this clearly looks like a bug on our end (some memory is tried to be freed that is not allocated). It should not crash like this. However, it is not possible to determine the location with just this log, so your help is needed, most likely involving running some test builds to produce more logs to determine the problem.

If you are up to this, could you tell me a bit more about what you are trying to do:

  • This looks like a VMware-like hypervisor trying to boot a dmg recovery, is it right? Could you tell me about the versions for both?
  • How much memory is the VM assigned? Does increasing RAM help?
  • Could you try to load the DMG recovery for macOS 10.15 or macOS 11 and provide me the log?

@james090500

Thanks for getting back to me. I am happy to do anything to see what we can do.

Yes, I am running an extremely unsupported environment here but just trying to see how far I can actually get. Mentally prepare yourself…

I am running Hyper-V on Windows. The Host has 44GB of RAM and 8GB of that is statically assigned to the VM. Increase/decreasing memory doesn’t help unfortunately. However setting the memory before about 4500MB results in a verbosed error. OCB LoadImage failed - Unsupported

This is further than it previously got. I can try with 10.15 and 11 a bit later this evening or tomorrow. I have attached a log of booting the VM with 4096MB of RAM which seems to help a bit.

opencore-2021-02-06-185610.txt

@vit9696

Yeah, there is no point in reducing the memory size, it dies earlier actually with an out of memory report. Provide a log with 11 dmg, and I will see what more prints I need to add to figure this out.

@james090500

@vit9696

Okay, here is a build with more logging added. Please replace your OpenCore.efi and redo the log with 11. Please make sure that AppleDebug = YES is set. I will not promise this one will be enough to locate the bug, but I added relevant prints. Please let me know how it goes.

OpenCore-LT-r1.zip

@james090500

@vit9696

@james090500

@vit9696

I found and fixed one bug with this code. However, I am quite unsure whether this is the one you observe. Yours might be a bug in the firmware itself. In addition to fixing the issue I also added even more logging.

OpenCore-LT-r3.zip

@james090500

@vit9696

It really makes no sense. We allocate and what we allocated is freed by us soon after. Yet the firmware reports it is an anvalid tree. I kind of get it that there may be some memory corruption, but to me it sounds like a memory corruption outside of OpenCore.

@james090500

Hm, I’ll do a memtest to check. That might explain why lowering the ram doesn’t crash opencore

@vit9696

Not sure it is a hardware issue actually. Lowering the RAM makes OpenCore stop earlier due to not enough memory. Here I would say a bug would be in the firmware code rather than hardware. Maybe try to understand what exactly breaks it at least. Try this version. It will likely error differently. include the log.

OpenCore-LT-r4.zip

@james090500

@vit9696

@james090500

@vit9696

So, EFI_BOOT_SERVICES::GetMemoryMap on your side somehow corrupts the allocated memory. Now the question is what can we do to it…

@vit9696

@james090500

@vit9696

@james090500

@vit9696

Np… But I am out of ideas for the time being. We simply call the firmware, and it overwrites random data out of bounds @_@. I will provide some build to try to diagnose it in a better way later, but there hardly is a way to deal with such an obvious firmware bug.

@james090500

I’m no expert with any sort of UEFI booting. I have done some googling of «GetMemoryMap and Hyper-V» and some bug reports of different Linux having to do some patches. Not sure if any of that could help?

Hopefully you’ll figure something out xD

@james090500

@chilledHamza

I have same error with Debug version on my Haier Y11C laptop, here is the log
opencore-2021-02-07-214439.txt

Actually, I get black screen (with boot chime being played in a loop) when I enable OpenCanopy with PickerMode : External property. I have unlocked BIOS, so if I enable CSM. OpenCore menu is shown but it’s really slow and laggy. Enabling CSM isn’t right solution anyway.
With OC v0.6.5 I fixed by setting Resolution : 1366x768 (max resolution of internal display), and it worked well even with CSM disabled. updated to OC v0.6.6, issue is back now and even Resolution property have no effect now. that’s the reason I went for Debug version to check logs and ended up with this ASSERT_EFI_ERROR
I understand that I should create separate issue for Black-Screen, just trying to state whole problem and actually I didn’t get positive response from my last reply Keypad. on Lenovo Y530 doesn’t work #303.

I didn’t get this ASSERT_EFI_ERROR once, so here is the log if you need it. with Resolution : Max
opencore-2021-02-07-215002.txt

@vit9696

Just a random update. Installed Hyper-V on my Windows 10 PC and I actually get much further. It starts calling the Kernel. See log attached. The biggest different (aside from the hardware) is this is Hyper-V config version 9 where as the other machine has 8.

Hmm, in this case I would rather leave this unchanged on our side. Basically «a fix» would be some hack workarounding a firmware bug. We do add such hacks, but mainly for real firmwares. If the firmware is software only and the bug is fixed in a newer release, it is better to leave it unmodified on our side.

At this step it is clear that older Hyper-V within the call to VmAllocateMemoryPool inside OcGetCurrentMemoryMapAlloc corrupts the pool allocated memory as soon as GetMemoryMap is called, making this memory no longer available for free. You can probably workaround it by changing FreePool here to gBS->FreePool, simply ignoring the memory corruption, but I do not want to merge it.

@vit9696

@chilledHamza your PS2 issue was forgotten about. Sorry. Replied.

As for ASSERT, it is not in the log, so we need a photo. Create a separate issue for it.

Содержание

  1. Русские Блоги
  2. UEFI реализует несколько последовательных портов одновременно и вывода
  3. Внедрение платформы с длинным клетками
  4. Как UEFI поддерживает многосериальные устройства
  5. (1) Последовательный порт, используемый на стадии сборки
  6. (2) Печать последовательного порта, используемая на стадии C
  7. UEFI issues with KANOTIX ISO images on older systems #187
  8. Comments
  9. ASSERT_EFI_ERROR (Status = Invalid Parameter) #1476
  10. Comments
  11. Footer

Русские Блоги

UEFI реализует несколько последовательных портов одновременно и вывода

Внедрение платформы с длинным клетками

Недавно, в сочетании с BMC для отладки функции SOL, вам необходимо вывести журнал BIOS на устройство UART BMC, а затем необходимо удаленно вывести соответствующие последовательные данные на веб -страницу на BMC, то есть функция удаленного управления биос. Конечно, этот последовательный порт должен одновременно поддерживать операции ввода и вывода. Потому что на платформе Dragon Core, последовательный порт, используемый последовательным портом отладки по умолчанию, находится внутри процессора. Когда ЦП инициализирует базовую конфигурацию, вернитесь, чтобы инициализировать этот последовательный порт в качестве тестового последовательного порта. Конечно, каждый озабоченный человек знает, как неудобно отладить программу, если нет отладочного последовательного порта. В связи с спросом, последовательный порт ЦП и последовательный порт ЦП необходимы для поддержки операции ввода и вывода.

Как UEFI поддерживает многосериальные устройства

(1) Последовательный порт, используемый на стадии сборки

Последовательный порт ЦП инициализируется в файле start.s UEFI, и его можно использовать, и его можно использовать на стадии сборки. Режим, используемый здесь, заключается в том, что общий принцип состоит в том, чтобы потерять данные в реестре последовательного порта, поэтому данные будут выброшены. Конкретный код инициализации выглядит следующим образом:

После инициализации серийный порт в основном доступен. Так что, если вы хотите распечатать строку в это время или несколько чисел, как ее использовать? Следующий код:

Приведенный выше код подробно представляет PrintStr («Выключите подчиненные ядер r n»). Он распечатана. Посмотрите на код, чтобы увидеть.
Это раздел строки. Если вы хотите распечатать кусок данных, вы можете напрямую вызвать функцию Hexserial. Вам нужно распечатать данные в регистр A0. A0 — это регистр, который сначала передает платформу MIPS.

(2) Печать последовательного порта, используемая на стадии C

В тот момент, когда UEFI вошел в среду C, инициализация последовательного порта была быстро названа. Здесь вызов относительно расплывчат, и он не будет найден на некоторое время. Вызов функции вызова выглядит следующим образом:

Функция ProceslibraryConstructorList здесь вызывает функцию инициализации последовательного порта. Эта функция реализована в LIB серийного порта. Он содержит Defuglib в secmain.inf. Путь отладки объявляется в файле DSC.

Давайте посмотрим на подробный процесс вызова ProcessLibraryConstructorList:

Приведенный выше код реализован в Secmain/Debug/Autogen.c, который представляет собой автоматический код компиляции. SerialPortinitialize — это функция инициализации библиотеки хранения. Библиотека на нашей платформе реализует инициализацию CPU UART0. В настоящее время нам нужно инициализировать последовательный порт BMC, поэтому нам нужно реализовать только библиотеку для инициализации UART BMC. Но потому что BMC UART ссылается на автобус LPC Bridge. И если мы хотим получить доступ к этому устройству, нам нужно подождать, пока устройство LPC получит его, чтобы инициализировать его, поэтому его нельзя инициализировать на стадии SEC для инициализации последовательного порта BMC. Мы находимся на стадии DXE, потому что после того, как мост инициализируется на стадии PEI, пространство IO LPC может быть доступно. Давайте посмотрим, как стадия DXE инициализирует последовательный порт BMC и как зарегистрироваться в консоли.
Мы осознали драйвер отдельно. Оригинальный драйвер и оригинальный драйвер последовательного порта очень похожи на адрес серийного адреса и некоторую инициализацию контроллера SUPIO, поскольку этот UART является контроллером SUPIO через шину LPC. Итак, сначала инициализируйте контроллер Supio. Подробный код заключается в следующем:

Из приведенного выше кода видно, что функция консоли, поддерживающей несколько последовательных устройств, в основном реализуется следующим кодом. Протокол в UEFI может поддерживать регистрацию нескольких интерфейсов. Резерсие и другие функции зарегистрированы через MSerialOtemplate. Точно так же тот же интерфейс зарегистрирован на последовательном приводе CPU UART, но конкретная операция — это разные устройства.

Так как же это устройство UART зарегистрировано в консоли? Эта регистрация зарегистрирована в драйвере терминала. Подробный код заключается в следующем:

Вот открытый gefiserialioprotocolguid. В настоящее время он получает интерфейс. В настоящее время получены два адреса, что соответствует адресу глобальной переменной, зарегистрированной в предыдущей регистрации.

Позднее интерфейс был предоставлен TerminalDevice-> Serialio, так что серийное устройство устанавливает связь с тройным устройством.
Устройство терминала зарегистрировано в задней части, которая включает в себя устройства ввода и выходные устройства. Кодовое шоу, как ниже:

Таким образом, консоль поддерживает вход и вывод нескольких последовательных портов.
Давайте посмотрим на инициализацию BMC UART. Вам нужно обратить внимание на некоторые моменты здесь:
(1) Логика работы контроллера Supio, каждое устройство Supio имеет концепцию логического устройства. Вам нужно читать и писать регистры в соответствии с логикой, соответствующей протоколу.

(2) В то же время количество прерывания устройства Supio под LPC составляет 3, а некоторые — 4, а все архитектуры одинаковы. Наше устройство 4, чип по умолчанию.
(3) Характеристики триггера прерываний, некоторые чипсы по умолчанию имеют высокие триггеры, некоторые из них низкие, некоторые из них поднимаются, некоторые из которых являются нисходящими краями. требует внимания.
(4) Необходимо настроить часы контроллера SUPIO. Он должен быть известен без настройки часов по умолчанию, поскольку расчет скорости гонка UART требует часов.

Ниже приведен подробный код инициализации:

Вся функция журнала печати UEFI выводится через функцию DebugPrint, за исключением фазы компиляции, тогда здесь вызывает функцию SolSerialPortWrite, и UART BMC также выведет ту же информацию об этом UART. Мы сделали переключатель здесь, чтобы управлять выходом журнала BMC.
Вход — это вход, полученный консолью. Конец консоли будет вызывать функцию ввода, соответствующую последовательному порту. Процесс кода очень сложный, включая множество протоколов. Я следил за этим раньше, вот подробное введение по временным причинам.

Источник

UEFI issues with KANOTIX ISO images on older systems #187

After enabling «vtdebug on» in grub.cfg I found an error with my boards for Sandy Bridge, Ivy Bridge and Haswell CPUs. My boards for Skylake and newer can boot fine.

FSBindingSupported
FSBindingStart
Could not read block at address 00000040: [2]
error: not a ISO9660 filesystem.

The text was updated successfully, but these errors were encountered:

Can you try ventoy-1.0.13?

The error is now different. Currently it is not possible to boot KANOTIX at all — even with a newer system using EFI.

ASSERT_EFI_ERROR (Status = Invalid Parameter)
ASSERT [Ventoy] . MemoryAllocationLib.c(813): !EFI_ERROR (Status)
No bootfile found for UEFI!
Maybe the image does not support X64 UEFI!

KANOTIX uses a hybrid ISO layout, it definitely has X64 UEFI in ISO9660 and FAT12 (usually 1MiB offset). (The 32 bit images have got the 32 bit UEFI). The «live» folder is similar to Debian live.

Ventoy up to 1.0.12 used the /dev/mapper/ventoy approach to boot.

Btw. compared to other images KANOTIX has even an Apple Partition Map with appended HFS+ partition (with USB-Stick ImageWriter for Mac). Unpatched parted tools usually crash. Created by

ISO=kanotix64-silverfire-nightly-KDE-extra.iso
blkid —probe —offset=$(($(stat -c %s $ISO)-1048576)) $ISO

Maybe the hack in line 148 of isohybrid-acritox is problematic for Ventoy.

Источник

ASSERT_EFI_ERROR (Status = Invalid Parameter) #1476

I was told to report the ASSERT error here because «even if it’s user error, it should properly prompt an error or halt».

I mostly assume i’ve done something wrong but wont hurt to post this.

Specs
CPU: Xeon E5606
RAM: 8GB

The text was updated successfully, but these errors were encountered:

Hi. Yeah, this clearly looks like a bug on our end (some memory is tried to be freed that is not allocated). It should not crash like this. However, it is not possible to determine the location with just this log, so your help is needed, most likely involving running some test builds to produce more logs to determine the problem.

If you are up to this, could you tell me a bit more about what you are trying to do:

  • This looks like a VMware-like hypervisor trying to boot a dmg recovery, is it right? Could you tell me about the versions for both?
  • How much memory is the VM assigned? Does increasing RAM help?
  • Could you try to load the DMG recovery for macOS 10.15 or macOS 11 and provide me the log?

Thanks for getting back to me. I am happy to do anything to see what we can do.

Yes, I am running an extremely unsupported environment here but just trying to see how far I can actually get. Mentally prepare yourself.

I am running Hyper-V on Windows. The Host has 44GB of RAM and 8GB of that is statically assigned to the VM. Increase/decreasing memory doesn’t help unfortunately. However setting the memory before about 4500MB results in a verbosed error. OCB LoadImage failed — Unsupported

This is further than it previously got. I can try with 10.15 and 11 a bit later this evening or tomorrow. I have attached a log of booting the VM with 4096MB of RAM which seems to help a bit.

Yeah, there is no point in reducing the memory size, it dies earlier actually with an out of memory report. Provide a log with 11 dmg, and I will see what more prints I need to add to figure this out.

Attached both with relevant names

Okay, here is a build with more logging added. Please replace your OpenCore.efi and redo the log with 11. Please make sure that AppleDebug = YES is set. I will not promise this one will be enough to locate the bug, but I added relevant prints. Please let me know how it goes.

A bit confused, try this one (also need logs).
OpenCore-LT-r2.zip

I found and fixed one bug with this code. However, I am quite unsure whether this is the one you observe. Yours might be a bug in the firmware itself. In addition to fixing the issue I also added even more logging.

It really makes no sense. We allocate and what we allocated is freed by us soon after. Yet the firmware reports it is an anvalid tree. I kind of get it that there may be some memory corruption, but to me it sounds like a memory corruption outside of OpenCore.

Hm, I’ll do a memtest to check. That might explain why lowering the ram doesn’t crash opencore

Not sure it is a hardware issue actually. Lowering the RAM makes OpenCore stop earlier due to not enough memory. Here I would say a bug would be in the firmware code rather than hardware. Maybe try to understand what exactly breaks it at least. Try this version. It will likely error differently. include the log.

Here’s the log, I’ve also shutdown any VMS just incase

Okay, what about this one?

Ok we’ve got a much different error.

So, EFI_BOOT_SERVICES::GetMemoryMap on your side somehow corrupts the allocated memory. Now the question is what can we do to it…

Maybe try to increase the reserve 😡 Try this one. Need logs.

What about this?

Np… But I am out of ideas for the time being. We simply call the firmware, and it overwrites random data out of bounds @_@. I will provide some build to try to diagnose it in a better way later, but there hardly is a way to deal with such an obvious firmware bug.

I’m no expert with any sort of UEFI booting. I have done some googling of «GetMemoryMap and Hyper-V» and some bug reports of different Linux having to do some patches. Not sure if any of that could help?

Hopefully you’ll figure something out xD

Just a random update. Installed Hyper-V on my Windows 10 PC and I actually get much further. It starts calling the Kernel. See log attached. The biggest different (aside from the hardware) is this is Hyper-V config version 9 where as the other machine has 8.

I have same error with Debug version on my Haier Y11C laptop, here is the log
opencore-2021-02-07-214439.txt

Actually, I get black screen (with boot chime being played in a loop) when I enable OpenCanopy with PickerMode : External property. I have unlocked BIOS, so if I enable CSM. OpenCore menu is shown but it’s really slow and laggy. Enabling CSM isn’t right solution anyway.
With OC v0.6.5 I fixed by setting Resolution : 1366×768 (max resolution of internal display), and it worked well even with CSM disabled. updated to OC v0.6.6, issue is back now and even Resolution property have no effect now. that’s the reason I went for Debug version to check logs and ended up with this ASSERT_EFI_ERROR
I understand that I should create separate issue for Black-Screen, just trying to state whole problem and actually I didn’t get positive response from my last reply Keypad. on Lenovo Y530 doesn’t work #303.

I didn’t get this ASSERT_EFI_ERROR once, so here is the log if you need it. with Resolution : Max
opencore-2021-02-07-215002.txt

Just a random update. Installed Hyper-V on my Windows 10 PC and I actually get much further. It starts calling the Kernel. See log attached. The biggest different (aside from the hardware) is this is Hyper-V config version 9 where as the other machine has 8.

Hmm, in this case I would rather leave this unchanged on our side. Basically «a fix» would be some hack workarounding a firmware bug. We do add such hacks, but mainly for real firmwares. If the firmware is software only and the bug is fixed in a newer release, it is better to leave it unmodified on our side.

At this step it is clear that older Hyper-V within the call to VmAllocateMemoryPool inside OcGetCurrentMemoryMapAlloc corrupts the pool allocated memory as soon as GetMemoryMap is called, making this memory no longer available for free. You can probably workaround it by changing FreePool here to gBS->FreePool, simply ignoring the memory corruption, but I do not want to merge it.

@chilledHamza your PS2 issue was forgotten about. Sorry. Replied.

As for ASSERT, it is not in the log, so we need a photo. Create a separate issue for it.

© 2023 GitHub, Inc.

You can’t perform that action at this time.

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.

Источник

Posts: 16
Threads: 5
Joined: Apr 2020

Reputation:

0

08-05-2020, 11:09 AM
(This post was last modified: 08-05-2020, 11:10 AM by Nierewa.)

Hi,

I love ventoy.
But there’s a problem I have.

I made an Multiboot-USB Stick. With ventoy so easy.
But if I edit an ISO the error: «No bootfile found for UEFI! Maybe the image does not support X64 UEFI!» occured.

In this case it’s Acronis 2019.
Inside iso is a file for Mac: AcronisTrueImage2019-17000.dmg
I delete this one to safe space. Now I bood end get the error.

Kaspersky rescue disc the same.

But I did the same thing with Acronis 2017 ago… this worked fine.

I use PowerISO or UltraIso to edit the isos.

Can someone help me with this?

Best regards Big Grin

Posts: 16
Threads: 5
Joined: Apr 2020

Reputation:

0

08-10-2020, 11:55 AM
(This post was last modified: 08-10-2020, 11:55 AM by Nierewa.)

I made a new GPT ventoy stick with Ventoy-1.0.18_Modified_EN and Support for SecureBoot.
Now I get this error message:

ASSERT_EFI_ERROR (Status = Invalid Parameter)
ASSERT [Ventoy] /home/share/Ventoy/EDKII/edk2-edk2-stable201911/MdePkg/Library/UefiMemoryAllocationLib/MemoryAllocationLib.c(813): !EFI_ERROR (Status)
No bootfile found for UEFI!
Maybe the image does not support X64 UEFI!

Posts: 51
Threads: 5
Joined: May 2020

Reputation:

2

(08-05-2020, 11:09 AM)Nierewa Wrote: Hi,

I love ventoy.
But there’s a problem I have.

I made an Multiboot-USB Stick. With ventoy so easy.
But if I edit an ISO the error: «No bootfile found for UEFI! Maybe the image does not support X64 UEFI!» occured.

In this case it’s Acronis 2019.
Inside iso is a file for Mac: AcronisTrueImage2019-17000.dmg
I delete this one to safe space. Now I bood end get the error.

Kaspersky rescue disc the same.

But I did the same thing with Acronis 2017 ago… this worked fine.

I use PowerISO or UltraIso to edit the isos.

Can someone help me with this?

Best regards Big Grin

  1. Kaspersky Rescue DiskFor krd.iso, grub signature check was enabled in UEFI mode by default. Ventoy must do some hook to avoid «kernel.dat not found» error, but the hook will be denied by the check.So in UEFI mode, after the kaspersky boot menu was shown, you need to run set check_signatures=no in the grub shell before boot.

Posts: 37
Threads: 5
Joined: May 2020

Reputation:

3

(08-10-2020, 11:55 AM)Nierewa Wrote: I made a new GPT ventoy stick with Ventoy-1.0.18_Modified_EN and Support for SecureBoot.
Now I get this error message:

ASSERT_EFI_ERROR (Status = Invalid Parameter)
ASSERT [Ventoy] /home/share/Ventoy/EDKII/edk2-edk2-stable201911/MdePkg/Library/UefiMemoryAllocationLib/MemoryAllocationLib.c(813): !EFI_ERROR (Status)
No bootfile found for UEFI!
Maybe the image does not support X64 UEFI!

Modifiye ventoy çalışmayı yüklerken sisteminizde çalışan antivirüs veya defender usb sürücünüze erişimi engelleyip dosyaların yüklenmesini engellemiş olabilir ! önce dosyaların usb aygıtınıza yüklendiğine emin olun.
Dosyalar hatasız yüklenmişse hata aldığınız iso dosyasının adı nedir ? ve müdahele edilmiş bir iso dosyasımı bilmiyoruz.
Ventoy tarafından desteklenmeyen veya standart uefi kurulumu olmayan iso dosyaları için F6 kısa yol tuşuna basıp grubfm çalıştırıp iso dosyasını yüklemek için alternatif yükleme seçeneklerini deneyin ve ventoy,da F1 memdisk metodununu kullanarak ayrıca test edin.
Burada yazmak yerine paylaşım yapılan sitede ventoy konusunda sorunu yazabilirsiniz, bildiğim bir konu ise yardımcı olmaya çalışırım.

Posts: 16
Threads: 5
Joined: Apr 2020

Reputation:

0

Sorry, I can’t speak turkish and the Google translater shows a mess.
May you write in english please?

Внедрение платформы с длинным клетками

Недавно, в сочетании с BMC для отладки функции SOL, вам необходимо вывести журнал BIOS на устройство UART BMC, а затем необходимо удаленно вывести соответствующие последовательные данные на веб -страницу на BMC, то есть функция удаленного управления биос. Конечно, этот последовательный порт должен одновременно поддерживать операции ввода и вывода. Потому что на платформе Dragon Core, последовательный порт, используемый последовательным портом отладки по умолчанию, находится внутри процессора. Когда ЦП инициализирует базовую конфигурацию, вернитесь, чтобы инициализировать этот последовательный порт в качестве тестового последовательного порта. Конечно, каждый озабоченный человек знает, как неудобно отладить программу, если нет отладочного последовательного порта. В связи с спросом, последовательный порт ЦП и последовательный порт ЦП необходимы для поддержки операции ввода и вывода.

Как UEFI поддерживает многосериальные устройства

(1) Последовательный порт, используемый на стадии сборки

Последовательный порт ЦП инициализируется в файле start.s UEFI, и его можно использовать, и его можно использовать на стадии сборки. Режим, используемый здесь, заключается в том, что общий принцип состоит в том, чтобы потерять данные в реестре последовательного порта, поэтому данные будут выброшены. Конкретный код инициализации выглядит следующим образом:

LEAF(initserial)
  .set mips64
  .set noreorder
  dli  a0, 0x900000001fe001e0

  li   t1, 128 
  sb   t1, 3(a0)
#ifdef BONITO_100M
  /* divider, highest possible baud rate,for 100M crystal*/
  li   t1, 0x36
#else
  /* divider, highest possible baud rate,for 25M crystal*/
  li   t1, 0x0d
#endif
  sb   t1, 0(a0)
  /* divider, highest possible baud rate*/
  li   t1, 0x0 
  sb   t1, 1(a0)
  li   t1, 3
  sb   t1, 3(a0)

  li   t1, 0
  sb   t1, 1(a0)

  li   t1, 71
  sb   t1, 2(a0)
  jr   ra  
  nop 
END(initserial)

После инициализации серийный порт в основном доступен. Так что, если вы хотите распечатать строку в это время или несколько чисел, как ее использовать? Следующий код:

LEAF(tgt_putchar)
  .set mips64
  .set noreorder
  dli  v0, 0x900000001fe001e0
1:
  lbu  v1, 0x5(v0)
  and  v1, 0x20
  beqz v1, 1b
  nop

  sb   a0, 0x0(v0)
  move v1, v0

  jr   ra
  nop                                                                                                                                                                                                                                         
END(tgt_putchar)
LEAF(hexserial)
  .set   mips64
  .set   noreorder
#ifdef ASM_DEBUG
  move   a2, ra
  move   a1, a0
  li     a3, 8
1:
  rol    a0, a1, 4
  move   a1, a0
  and    a0, 0xf

  dla    v0, hexchar
  li     s0, FV_OFFSET
  daddu  s0, FLASH_CODE_SECFV_BASE_ADDRESS
  dli    v1, 0xfffff
  and    v0,v1
  daddu  v0, s0

  daddu  v0, a0
  lbu    a0, 0(v0)
  bal    tgt_putchar
  nop

  daddu  a3, -1
  bnez   a3, 1b
  nop

  move   ra, a2
#endif
  jr     ra
  nop
END(hexserial)

PRINTSTR("Shut down slave coresrn")

#define  PRINTSTR TTYDBG

#define_TTYDBG(x) 
  .rdata;98: .asciz x; .text; dla a0, 98b; bal stringserial; nop
  LEAF(stringserial)
  .set   mips64
  .set   noreorder
  move   a2, ra
  li     s0, FV_OFFSET
  daddu  s0, FLASH_CODE_SECFV_BASE_ADDRESS
  and    a0, 0xfffff
  daddu  a1, a0, s0
  lbu    a0, 0(a1)
1:
  beqz   a0, 2f
  nop 
  bal    tgt_putchar
  nop 
  addiu  a1, 1
  lbu    a0, 0(a1)
  b      1b  
  nop 

2:
  move   ra, a2
  jr     ra  
  nop 
END(stringserial)

Приведенный выше код подробно представляет PrintStr («Выключите подчиненные ядер r n»). Он распечатана. Посмотрите на код, чтобы увидеть.
Это раздел строки. Если вы хотите распечатать кусок данных, вы можете напрямую вызвать функцию Hexserial. Вам нужно распечатать данные в регистр A0. A0 — это регистр, который сначала передает платформу MIPS.

(2) Печать последовательного порта, используемая на стадии C

В тот момент, когда UEFI вошел в среду C, инициализация последовательного порта была быстро названа. Здесь вызов относительно расплывчат, и он не будет найден на некоторое время. Вызов функции вызова выглядит следующим образом:

VOID
EFIAPI
SecCoreStartupWithStack(
  IN EFI_FIRMWARE_VOLUME_HEADER       *BootFv,
  IN VOID                             *TopOfCurrentStack
  )
{
  EFI_SEC_PEI_HAND_OFF             SecCoreData;
  EFI_FIRMWARE_VOLUME_HEADER       *BootPeiFv = (EFI_FIRMWARE_VOLUME_HEADER*) BootFv;
  ProcessLibraryConstructorList(NULL, NULL);
  DbgPrint(EFI_D_INFO, "Entering C environmentn");
  // |-------------|       <-- TopOfCurrentStack
  // |   Stack     |
  // |    of       | 64k
  // |    APs      |
  // |-------------|       <-- TopOfBSP'sStack
  // |   Stack     | 32k
  // |-------------|
  // |    Heap     | 32k
  // |-------------|       <-- SecCoreData.TemporaryRamBase
  //  

  //  
  // Initialize SEC hand-off state
  //  
  SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);
  DbgPrint(EFI_D_INFO,
    "&SecCoreData.DataSize=%lx SecCoreData.DataSize=%lxn",
    (UINT64)&(SecCoreData.DataSize),
    (UINT64)(SecCoreData.DataSize));

Функция ProceslibraryConstructorList здесь вызывает функцию инициализации последовательного порта. Эта функция реализована в LIB серийного порта. Он содержит Defuglib в secmain.inf. Путь отладки объявляется в файле DSC.

DebugLib                         | MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf

Давайте посмотрим на подробный процесс вызова ProcessLibraryConstructorList:

VOID
EFIAPI
ProcessLibraryConstructorList (
  VOID
  )
{
  EFI_STATUS  Status;

  Status = BaseDebugLibSerialPortConstructor ();                                                                                                                                                                                              
  ASSERT_EFI_ERROR (Status);
  
}
RETURN_STATUS
EFIAPI
BaseDebugLibSerialPortConstructor (
  VOID
  )
{                                                                                                                                                                                                                                             
  return SerialPortInitialize ();
} 

} 

Приведенный выше код реализован в Secmain/Debug/Autogen.c, который представляет собой автоматический код компиляции. SerialPortinitialize — это функция инициализации библиотеки хранения. Библиотека на нашей платформе реализует инициализацию CPU UART0. В настоящее время нам нужно инициализировать последовательный порт BMC, поэтому нам нужно реализовать только библиотеку для инициализации UART BMC. Но потому что BMC UART ссылается на автобус LPC Bridge. И если мы хотим получить доступ к этому устройству, нам нужно подождать, пока устройство LPC получит его, чтобы инициализировать его, поэтому его нельзя инициализировать на стадии SEC для инициализации последовательного порта BMC. Мы находимся на стадии DXE, потому что после того, как мост инициализируется на стадии PEI, пространство IO LPC может быть доступно. Давайте посмотрим, как стадия DXE инициализирует последовательный порт BMC и как зарегистрироваться в консоли.
Мы осознали драйвер отдельно. Оригинальный драйвер и оригинальный драйвер последовательного порта очень похожи на адрес серийного адреса и некоторую инициализацию контроллера SUPIO, поскольку этот UART является контроллером SUPIO через шину LPC. Итак, сначала инициализируйте контроллер Supio. Подробный код заключается в следующем:

Путь драйвера заключается в следующем:

LoongsonPlatformPkg/Drivers/SolSerialDxe/SerialDxe.inf

 Файл INF выглядит следующим образом: (здесь он зависит от SolSerialPortLib, этот LIB должен реализовать функции, связанные с BMC UART и чтение и запись)

[Defines]
  INF_VERSION                    = 0x00010005
  BASE_NAME                      = SolSerialDxe
  MODULE_UNI_FILE                = SerialDxe.uni
  FILE_GUID                      = D3987D4B-971A-435F-8CAF-4967EB627242
  MODULE_TYPE                    = DXE_DRIVER
  VERSION_STRING                 = 1.0 

  ENTRY_POINT                    = SerialDxeInitialize

[Sources.common]
  SerialIo.c

[Packages]
  MdePkg/MdePkg.dec
  LoongsonDemoBoardPkg/Script/Loongson.dec

[LibraryClasses]
  UefiDriverEntryPoint
  UefiBootServicesTableLib
  DebugLib
  PcdLib
  SolSerialPortLib

 Давайте посмотрим на основной код этого драйвера:
FI_STATUS
EFIAPI
SerialDxeInitialize (
  IN EFI_HANDLE         ImageHandle,
  IN EFI_SYSTEM_TABLE   *SystemTable
  )
{
  EFI_STATUS            Status;

  mSerialIoMode.BaudRate = PcdGet64 (PcdUartDefaultBaudRate);
  mSerialIoMode.DataBits = (UINT32) PcdGet8 (PcdUartDefaultDataBits);
  mSerialIoMode.Parity   = (UINT32) PcdGet8 (PcdUartDefaultParity);
  mSerialIoMode.StopBits = (UINT32) PcdGet8 (PcdUartDefaultStopBits);
  mSerialIoMode.ReceiveFifoDepth = PcdGet16 (PcdUartDefaultReceiveFifoDepth);
  mSerialDevicePath.Uart.BaudRate = PcdGet64 (PcdUartDefaultBaudRate);
  mSerialDevicePath.Uart.DataBits = PcdGet8 (PcdUartDefaultDataBits);
  mSerialDevicePath.Uart.Parity   = PcdGet8 (PcdUartDefaultParity);
  mSerialDevicePath.Uart.StopBits = PcdGet8 (PcdUartDefaultStopBits);

  //  
  // Issue a reset to initialize the Serial Port
  //  
  Status = mSerialIoTemplate.Reset (&mSerialIoTemplate);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //  
  // Make a new handle with Serial IO protocol and its device path on it.
  //  
  Status = gBS->InstallMultipleProtocolInterfaces (
                  &mSerialHandle,
                  &gEfiSerialIoProtocolGuid,   &mSerialIoTemplate,                                                                                                                                                                            
                  &gEfiDevicePathProtocolGuid, &mSerialDevicePath,
                  NULL
                  );  
  ASSERT_EFI_ERROR (Status);

  return Status;
}
EFI_SERIAL_IO_PROTOCOL mSerialIoTemplate = {                                                                                                                                                                                                  
  SERIAL_IO_INTERFACE_REVISION,
  SerialReset,
  SerialSetAttributes,
  SerialSetControl,
  SerialGetControl,
  SerialWrite,
  SerialRead,
  &mSerialIoMode
};

EFI_STATUS
EFIAPI
SerialReset (
  IN EFI_SERIAL_IO_PROTOCOL *This
  )
{
  EFI_STATUS    Status;

  Status = SolSerialPortInitialize ();
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Go set the current attributes
  //
  Status = This->SetAttributes (
                   This,
                   This->Mode->BaudRate,
                   This->Mode->ReceiveFifoDepth,
                   This->Mode->Timeout,
                   (EFI_PARITY_TYPE) This->Mode->Parity,
                   (UINT8) This->Mode->DataBits,
                   (EFI_STOP_BITS_TYPE) This->Mode->StopBits
                   );

  //
  // The serial device may not support some of the attributes. To prevent
  // later failure, always return EFI_SUCCESS when SetAttributes is returning
  // EFI_INVALID_PARAMETER.
  //
  if (Status == EFI_INVALID_PARAMETER) {
    return EFI_SUCCESS;
  }

  return Status;
}

Из приведенного выше кода видно, что функция консоли, поддерживающей несколько последовательных устройств, в основном реализуется следующим кодом. Протокол в UEFI может поддерживать регистрацию нескольких интерфейсов. Резерсие и другие функции зарегистрированы через MSerialOtemplate. Точно так же тот же интерфейс зарегистрирован на последовательном приводе CPU UART, но конкретная операция — это разные устройства.

Status = gBS->InstallMultipleProtocolInterfaces (
                  &mSerialHandle,
                  &gEfiSerialIoProtocolGuid,   &mSerialIoTemplate,                                                                                                                                                                            
                  &gEfiDevicePathProtocolGuid, &mSerialDevicePath,
                  NULL
                  );  

Так как же это устройство UART зарегистрировано в консоли? Эта регистрация зарегистрирована в драйвере терминала. Подробный код заключается в следующем:

TerminalDriverBindingStart (
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
  IN EFI_HANDLE                     Controller,
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
  )
{
  EFI_STATUS                          Status;
  EFI_SERIAL_IO_PROTOCOL              *SerialIo;
  EFI_DEVICE_PATH_PROTOCOL            *ParentDevicePath;
  EFI_DEVICE_PATH_PROTOCOL            *Vendor;
  EFI_HANDLE                          SerialIoHandle;
  EFI_SERIAL_IO_MODE                  *Mode;
  UINTN                               SerialInTimeOut;
  TERMINAL_DEV                        *TerminalDevice;
  UINT8                               TerminalType;
  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
  UINTN                               EntryCount;
  UINTN                               Index;
  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL     *SimpleTextOutput;
  EFI_SIMPLE_TEXT_INPUT_PROTOCOL      *SimpleTextInput;
  EFI_UNICODE_STRING_TABLE            *ControllerNameTable;

  //
  // Get the Device Path Protocol to build the device path of the child device
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiDevicePathProtocolGuid,
                  (VOID **) &ParentDevicePath,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );   
  ASSERT ((Status == EFI_SUCCESS) || (Status == EFI_ALREADY_STARTED));

  //
  // Open the Serial I/O Protocol BY_DRIVER.  It might already be started.
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiSerialIoProtocolGuid,
                  (VOID **) &SerialIo,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );

Вот открытый gefiserialioprotocolguid. В настоящее время он получает интерфейс. В настоящее время получены два адреса, что соответствует адресу глобальной переменной, зарегистрированной в предыдущей регистрации.

Позднее интерфейс был предоставлен TerminalDevice-> Serialio, так что серийное устройство устанавливает связь с тройным устройством.
Устройство терминала зарегистрировано в задней части, которая включает в себя устройства ввода и выходные устройства. Кодовое шоу, как ниже:

Таким образом, консоль поддерживает вход и вывод нескольких последовательных портов.
Давайте посмотрим на инициализацию BMC UART. Вам нужно обратить внимание на некоторые моменты здесь:
(1) Логика работы контроллера Supio, каждое устройство Supio имеет концепцию логического устройства. Вам нужно читать и писать регистры в соответствии с логикой, соответствующей протоколу.

UINT8 SuperioWrite(UINT64 Dev, UINT64 Addr,UINT8 Data)
{

  MmioWrite8 ((UINTN) (LPC_IO_BASE +  0x2e), 0xa5);
  MmioWrite8 ((UINTN) (LPC_IO_BASE +  0x2e), 0xa5);

  MmioWrite8 ((UINTN) (LPC_IO_BASE +  0x2e), 0x7);
  MmioWrite8 ((UINTN) (LPC_IO_BASE +  0x2f), Dev);

  MmioWrite8 ((UINTN) (LPC_IO_BASE +  0x2e), Addr);
  MmioWrite8 ((UINTN) (LPC_IO_BASE +  0x2f), Data);

  MmioWrite8 ((UINTN) (LPC_IO_BASE +  0x2e), 0xaa);

  return 0;
}

UINT8 SuperioRead(UINT64 Dev, UINT64 Addr)
{
  UINT8 Data = 0;

  MmioWrite8 ((UINTN) (LPC_IO_BASE + 0x2e), 0xa5);
  MmioWrite8 ((UINTN) (LPC_IO_BASE + 0x2e), 0xa5);

  MmioWrite8 ((UINTN) (LPC_IO_BASE + 0x2e), 0x7);
  MmioWrite8 ((UINTN) (LPC_IO_BASE + 0x2f), Dev);

  MmioWrite8 ((UINTN) (LPC_IO_BASE + 0x2e), Addr);
  Data = MmioRead8 (LPC_IO_BASE + 0x2f);

  MmioWrite8 ((UINTN) (LPC_IO_BASE + 0x2e), 0xaa);

  return Data;                                                                                                                                                                                                                                
}

(2) В то же время количество прерывания устройства Supio под LPC составляет 3, а некоторые — 4, а все архитектуры одинаковы. Наше устройство 4, чип по умолчанию.
(3) Характеристики триггера прерываний, некоторые чипсы по умолчанию имеют высокие триггеры, некоторые из них низкие, некоторые из них поднимаются, некоторые из которых являются нисходящими краями. требует внимания.
(4) Необходимо настроить часы контроллера SUPIO. Он должен быть известен без настройки часов по умолчанию, поскольку расчет скорости гонка UART требует часов.

        ** Формула расчета скорости гончара: divisor = (superio_uart_clk) / (16 *(vgbps)); здесь делитель - это значение регистра частотного деления, VGBPS - это скорость готтера: 115200: 115200
                 Superio_uart_clk - это часы. **

Ниже приведен подробный код инициализации:

RETURN_STATUS
EFIAPI
SolSerialPortInitialize (
  VOID
  )
{
  UINTN          SerialRegisterBase;
  UINT16         Divisor;

  // enable superio contrller
  SuperioWrite(2, 0x30, 0x1);

  // set superio clk 24M
  SuperioWrite(2, 0xf0, 0x2);

  // set superio irq num default is 4
  SuperioWrite(2, 0x70, 0x04);

  // set superio irq trig low 
  // 0x1:low 0x3:high
  SuperioWrite(2, 0x71, 0x01);

  Divisor  = (SUPERIO_UART_CLK) / (16 * (VgBps));                                                                                                                                                                                             

  //
  // Get the base address of the serial port in either I/O or MMIO space
  //
  SerialRegisterBase = SolGetSerialRegisterBase ();

  SolSerialPortWriteRegister (SerialRegisterBase, NS16550_FIFO, FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_4);
  SolSerialPortWriteRegister (SerialRegisterBase, NS16550_CFCR, CFCR_DLAB);
  SolSerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_HIGH, (UINT8) (Divisor >> 8));
  SolSerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_LOW, (UINT8) (Divisor & 0xff));
  SolSerialPortWriteRegister (SerialRegisterBase, NS16550_CFCR, CFCR_8BITS);
  SolSerialPortWriteRegister (SerialRegisterBase, NS16550_MCR, MCR_DTR|MCR_RTS);
  SolSerialPortWriteRegister (SerialRegisterBase, NS16550_IER, 0x00);

  *(volatile UINT32 *)(SOL_UART_SWITCH_ADDR) = TURN_ON;

  return RETURN_SUCCESS;
}

 Код, в котором печатается напечатана, и код потери данных из этого последовательного порта, заключается в следующем:

VOID
EFIAPI
DebugPrint (
  IN  UINTN        ErrorLevel,
  IN  CONST CHAR8  *Format,
  ... 
  )
{
  CHAR8    Buffer[MAX_DEBUG_MESSAGE_LENGTH];
  VA_LIST  Marker;

  //  
  // If Format is NULL, then ASSERT().
  //  
  ASSERT (Format != NULL);

  //  
  // Check driver debug mask value and global mask
  //  
  if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) {
    return;
  }

  //  
  // Convert the DEBUG() message to an ASCII String
  //  
  VA_START (Marker, Format);
  AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker);
  VA_END (Marker);                                                                                                                                                                                                                            

  //  
  // Send the print string to a Serial Port 
  //  
  SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));

  if(*(volatile UINT32 *)(SOL_UART_SWITCH_ADDR) == TURN_ON){
    SolSerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));
  }
}

Вся функция журнала печати UEFI выводится через функцию DebugPrint, за исключением фазы компиляции, тогда здесь вызывает функцию SolSerialPortWrite, и UART BMC также выведет ту же информацию об этом UART. Мы сделали переключатель здесь, чтобы управлять выходом журнала BMC.
Вход — это вход, полученный консолью. Конец консоли будет вызывать функцию ввода, соответствующую последовательному порту. Процесс кода очень сложный, включая множество протоколов. Я следил за этим раньше, вот подробное введение по временным причинам.

#1

nierewa

    Frequent Member

  • Advanced user
  • 107 posts
  •  


    Germany

Posted 10 August 2020 — 07:27 AM

Hi,

I’ve been using ventoy for a while now and I love it.
But there’s a problem I have.

I made an Multiboot-USB Stick. With ventoy so easy.
But if I edit an ISO the error: «No bootfile found for UEFI! Maybe the image does not support X64 UEFI!» occured.

In this case it’s Acronis 2019.
Inside iso is a file for Mac: AcronisTrueImage2019-17000.dmg
I delete this one to safe space. Now I boot and get the error.

Kaspersky rescue disc the same.

But I did the same thing with Acronis 2017 ago… this worked fine.

I use PowerISO or UltraIso to edit the isos.

Can someone help me with this?

Best regards biggrin.png

  • Back to top


#2


steve6375

steve6375

    Platinum Member

  • Developer
  • 7565 posts
  • Location:UK
  • Interests:computers, programming (masm,vb6,C,vbs), photography,TV,films
  •  


    United Kingdom

Posted 10 August 2020 — 07:34 AM

Are you testing booting on a real system?

  • Back to top


#3


nierewa

nierewa

    Frequent Member

  • Advanced user
  • 107 posts
  •  


    Germany

Posted 10 August 2020 — 08:05 AM

Hi :D

On a real system.

  • Back to top


#4


steve6375

steve6375

    Platinum Member

  • Developer
  • 7565 posts
  • Location:UK
  • Interests:computers, programming (masm,vb6,C,vbs), photography,TV,films
  •  


    United Kingdom

Posted 10 August 2020 — 08:07 AM

Does the modified ISO UEFI-boot from an Easy2Boot v2 USB drive?

  • Back to top


#5


nierewa

nierewa

    Frequent Member

  • Advanced user
  • 107 posts
  •  


    Germany

Posted 10 August 2020 — 08:10 AM

Can’t test because I have no Easy2Boot USb drive.

  • Back to top


#6


nierewa

nierewa

    Frequent Member

  • Advanced user
  • 107 posts
  •  


    Germany

Posted 10 August 2020 — 09:38 AM

So I’ve tested with Easy2Boot v2… same problem.
«No bootfile found for UEFI»

  • Back to top


#7


steve6375

steve6375

    Platinum Member

  • Developer
  • 7565 posts
  • Location:UK
  • Interests:computers, programming (masm,vb6,C,vbs), photography,TV,films
  •  


    United Kingdom

Posted 10 August 2020 — 09:40 AM

OK — so if you extract the files from each ISO and compare the contents, what differences do you see?

  • Back to top


#8


nierewa

nierewa

    Frequent Member

  • Advanced user
  • 107 posts
  •  


    Germany

Posted 10 August 2020 — 10:52 AM

Content is the same.
Only folder doc and the file AcronisTrueImage2019-17000.dmg are deleted.

I had a screenshot but no idea how to attaching it :confused1:

  • Back to top


#9


nierewa

nierewa

    Frequent Member

  • Advanced user
  • 107 posts
  •  


    Germany

Posted 10 August 2020 — 11:25 AM

I made a new GPT ventoy stick with Ventoy-1.0.18_Modified_EN and Support for SecureBoot.

Now I get this error message:

ASSERT_EFI_ERROR (Status = Invalid Parameter)

ASSERT [Ventoy] /home/share/Ventoy/EDKII/edk2-edk2-stable201911/MdePkg/Library/UefiMemoryAllocationLib/MemoryAllocationLib.c(813): !EFI_ERROR (Status)

No bootfile found for UEFI!

Maybe the image does not support X64 UEFI!

  • Back to top


#10


steve6375

steve6375

    Platinum Member

  • Developer
  • 7565 posts
  • Location:UK
  • Interests:computers, programming (masm,vb6,C,vbs), photography,TV,films
  •  


    United Kingdom

Posted 10 August 2020 — 12:55 PM

Are you sure the unmodified ISO boots OK?

I have downloaded AcronisTrueImage2019_14110.iso and it also gives a UEFI boot error in E2B UEFI64 agFM grub2 (unmodified).

It does not contain any dmg file. I think you can get ISOs for PC or for MAC — maybe yours is the MAC one?

AcronisTrueImage2019_14110.iso UEFI64 boots OK if I use the agFM .isomem boot option however.

  • Back to top


#11


nierewa

nierewa

    Frequent Member

  • Advanced user
  • 107 posts
  •  


    Germany

Posted 13 August 2020 — 08:01 PM

Yes, it boots ok.

No, Its not the MAC one.

Only the modified doesn’t boot uefi.

Screenshot merged ISOs

  • Back to top


#12


steve6375

steve6375

    Platinum Member

  • Developer
  • 7565 posts
  • Location:UK
  • Interests:computers, programming (masm,vb6,C,vbs), photography,TV,films
  •  


    United Kingdom

Posted 13 August 2020 — 10:33 PM

Check file contents using 7zip — so you can see [BOOT] files.

  • Back to top


#13


nierewa

nierewa

    Frequent Member

  • Advanced user
  • 107 posts
  •  


    Germany

Posted 13 August 2020 — 11:15 PM

The files in [BOOT] folder are the same in both ISOs:

1. 1-Boot-NoEmul.img size: 2048
2. 2-Boot-NoEmul.img size: 0

Hmm, can it be some kind of signature?

  • Back to top


#14


steve6375

steve6375

    Platinum Member

  • Developer
  • 7565 posts
  • Location:UK
  • Interests:computers, programming (masm,vb6,C,vbs), photography,TV,films
  •  


    United Kingdom

Posted 13 August 2020 — 11:27 PM

How can it UEFI-boot if there are no .EFI boot files???

  • Back to top


#15


alacran

alacran

    Platinum Member

  • .script developer
  • 2710 posts
  •  


    Mexico

Posted 13 August 2020 — 11:57 PM

UEFI boot files should be located into efi folder and I didn’t see it on the pictures link on Post No, 11

See attached pictures from AcronisBootableMedia2016.iso

alacran

Attached Thumbnails

  • Back to top


#16


nierewa

nierewa

    Frequent Member

  • Advanced user
  • 107 posts
  •  


    Germany

Posted 14 August 2020 — 08:00 AM

UEFI boot files should be located into efi folder

It sems that there are more then one ISO-Versions outside.

As I wrote in Post 1 the Acronis 2017 ISO has the same content like your 2016 ISO.
The Acronis 2019 ISO unmodified boots UEFI.

AcronisTrueImage2019_14110.iso UEFI64 boots OK if I use the agFM .isomem boot option however.

As I wrote I use the modified ventoy Version.
If I boot .isomem nothing happens. Can you tell me how you did this?

  • Back to top


#17


steve6375

steve6375

    Platinum Member

  • Developer
  • 7565 posts
  • Location:UK
  • Interests:computers, programming (masm,vb6,C,vbs), photography,TV,films
  •  


    United Kingdom

Posted 14 August 2020 — 08:15 AM

My ISO contains a EFI folder. I don’t see how your ISO can UEFI boot as it does not have EFI files — are you SURE it UEFI boots when unmodified?

To test:

I just made an E2B v2.04 USB drive using Windows 10

Added the ISO to _ISOBACKUP folder

UEFI64 booted

and chose the .isomem  option.

Attached Thumbnails

  • acroniscontents.JPG

  • Back to top


#18


Wonko the Sane

Wonko the Sane

    The Finder

  • Advanced user
  • 16065 posts
  • Location:The Outside of the Asylum (gate is closed)
  •  


    Italy

Posted 14 August 2020 — 08:45 AM

I use PowerISO or UltraIso to edit the isos.
 

Then don’t and instead of editing a .iso (that by definition cannot be edited) re-create one.

Making a .iso that dual boots BIOS and UEFI is «tough» and it is very likely — not to say probable — that the original .iso has *some* settings[1] that «generic automagic» tools like PowerIso or UltraIso simply miss, or at least that was the case before:
https://msfn.org/boa…comment=1080917

Compare with:
http://reboot.pro/topic/21664-makeiso/

http://reboot.pro/to…-under-windows/

Basically you need to understand how (EXACTLY) the original .iso is made and then find a way to recreate it with mkisofs or oscdimg, start here:
https://msfn.org/boa…-torito-images/

:duff:

Wonko

[1] possibly unrelated, but Acronis has historically made «strange» .iso’s:
http://reboot.pro/to…-grub2-at-uefi/

https://msfn.org/boa…oot-on-uefi-pc/

  • Back to top


#19


cdob

cdob

    Gold Member

  • Expert
  • 1469 posts

Posted 14 August 2020 — 05:02 PM

2. 2-Boot-NoEmul.img size: 0

.

Compare this at ImDisk or ISOBuster.

.
This is the EFI boot image, It’s a approximate 400 MB floppy image.

  • Back to top


#20


nierewa

nierewa

    Frequent Member

  • Advanced user
  • 107 posts
  •  


    Germany

Posted 16 August 2020 — 07:20 PM

Compare this at ImDisk or ISOBuster.

Comparing with IsoBuster shows the difference

isobuster.jpg

There only three entrys in Spur 1 in the modified ISO and the BiitImage.img with 0kib

Strange

  • Back to top


#21


nierewa

nierewa

    Frequent Member

  • Advanced user
  • 107 posts
  •  


    Germany

Posted 16 August 2020 — 07:20 PM

Compare this at ImDisk or ISOBuster.

Comparing with IsoBuster shows the difference

isobuster.jpg

There only three entrys in Spur 1 in the modified ISO and the BiitImage.img with 0kib

Strange

Attached Thumbnails

  • isobuster.jpg

  • Back to top


#22


Wonko the Sane

Wonko the Sane

    The Finder

  • Advanced user
  • 16065 posts
  • Location:The Outside of the Asylum (gate is closed)
  •  


    Italy

Posted 17 August 2020 — 10:27 AM

Strange

Please read as «normal for Acronis», as seen in the given threads.

What very likely happens is that the size of the boot image is mis-reported, not entirely unlike what happened here:
http://reboot.pro/to…ting-iso-files/

with a «more normal» isolinux .iso.

:duff:

Wonko

  • Back to top


#23


cdob

cdob

    Gold Member

  • Expert
  • 1469 posts

Posted 17 August 2020 — 08:07 PM

Comparing with IsoBuster shows the difference

The original ISO contains two ~ 400 MB boot images.

Guessed: one PC and another Mac one. Then one image should be mountable at ImDisk.

The boot images are missing at  the edited ISO, UEFI boot fails. 

  • Back to top


#24


nierewa

nierewa

    Frequent Member

  • Advanced user
  • 107 posts
  •  


    Germany

Posted 19 August 2020 — 09:18 AM
  Best Answer

Ok, I give up.
So I use the original Image instead.

Thanks all for your help :thumbup:

  • Back to top


#25


cdob

cdob

    Gold Member

  • Expert
  • 1469 posts

Posted 19 August 2020 — 04:32 PM

I wonder the file size: why a 1.6 GB ISO image?

Dosn’t Acronis offer a about 700 MB CD image anymore?

  • Back to top


/**
  Fault Tolerant Write protocol notification event handler.

  Non-Volatile variable write may needs FTW protocol to reclaim when 
  writting variable.

  @param[in] Event    Event whose notification function is being invoked.
  @param[in] Context  Pointer to the notification function's context.
  
**/
VOID
EFIAPI
FtwNotificationEvent (
  IN  EFI_EVENT                           Event,
  IN  VOID                                *Context
  )
{
  EFI_STATUS                              Status;
  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL      *FvbProtocol;
  EFI_FAULT_TOLERANT_WRITE_PROTOCOL       *FtwProtocol;
  EFI_PHYSICAL_ADDRESS                    NvStorageVariableBase;
  EFI_GCD_MEMORY_SPACE_DESCRIPTOR         GcdDescriptor;
  EFI_PHYSICAL_ADDRESS                    BaseAddress;
  UINT64                                  Length;
  EFI_PHYSICAL_ADDRESS                    VariableStoreBase;
  UINT64                                  VariableStoreLength;

  //
  // Ensure FTW protocol is installed.
  //
  Status = GetFtwProtocol ((VOID**) &FtwProtocol);
  if (EFI_ERROR (Status)) {
    return ;
  }
  
  //
  // Find the proper FVB protocol for variable.
  //
  NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);
  if (NvStorageVariableBase == 0) {
    NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
  }
  Status = GetFvbInfoByAddress (NvStorageVariableBase, NULL, &FvbProtocol);
  if (EFI_ERROR (Status)) {
    return ;
  }
  mVariableModuleGlobal->FvbInstance = FvbProtocol;

  //
  // Mark the variable storage region of the FLASH as RUNTIME.
  //
  VariableStoreBase   = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;
  VariableStoreLength = ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase)->Size;
  BaseAddress = VariableStoreBase & (~EFI_PAGE_MASK);
  Length      = VariableStoreLength + (VariableStoreBase - BaseAddress);
  Length      = (Length + EFI_PAGE_SIZE - 1) & (~EFI_PAGE_MASK);

  Status      = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.n"));
  } else {
    Status = gDS->SetMemorySpaceAttributes (
                    BaseAddress,
                    Length,
                    GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME
                    );
    if (EFI_ERROR (Status)) {
      DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.n"));
    }
  }
  
  Status = VariableWriteServiceInitialize ();
  ASSERT_EFI_ERROR (Status);
 
  //
  // Install the Variable Write Architectural protocol.
  //
  Status = gBS->InstallProtocolInterface (
                  &mHandle,
                  &gEfiVariableWriteArchProtocolGuid, 
                  EFI_NATIVE_INTERFACE,
                  NULL
                  );
  ASSERT_EFI_ERROR (Status);
  
  //
  // Close the notify event to avoid install gEfiVariableWriteArchProtocolGuid again.
  //
  gBS->CloseEvent (Event);

}
/**
  Main entry point to DXE Core.

  @param  HobStart               Pointer to the beginning of the HOB List from PEI.

  @return This function should never return.

**/
VOID
EFIAPI
DxeMain (
  IN  VOID *HobStart
  )
{
  EFI_STATUS                    Status;
  EFI_PHYSICAL_ADDRESS          MemoryBaseAddress;
  UINT64                        MemoryLength;
  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
  UINTN                         Index;
  EFI_HOB_GUID_TYPE             *GuidHob;
  EFI_VECTOR_HANDOFF_INFO       *VectorInfoList;
  EFI_VECTOR_HANDOFF_INFO       *VectorInfo;

  //
  // Setup the default exception handlers
  //
  VectorInfoList = NULL;
  GuidHob = GetNextGuidHob (&gEfiVectorHandoffInfoPpiGuid, HobStart);
  if (GuidHob != NULL) {
    VectorInfoList = (EFI_VECTOR_HANDOFF_INFO *) (GET_GUID_HOB_DATA(GuidHob));
  }
  Status = InitializeCpuExceptionHandlers (VectorInfoList);
  ASSERT_EFI_ERROR (Status);
  
  //
  // Initialize Debug Agent to support source level debug in DXE phase
  //
  InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_CORE, HobStart, NULL);

  //
  // Initialize Memory Services
  //
  CoreInitializeMemoryServices (&HobStart, &MemoryBaseAddress, &MemoryLength);

  //
  // Allocate the EFI System Table and EFI Runtime Service Table from EfiRuntimeServicesData
  // Use the templates to initialize the contents of the EFI System Table and EFI Runtime Services Table
  //
  gDxeCoreST = AllocateRuntimeCopyPool (sizeof (EFI_SYSTEM_TABLE), &mEfiSystemTableTemplate);
  ASSERT (gDxeCoreST != NULL);

  gDxeCoreRT = AllocateRuntimeCopyPool (sizeof (EFI_RUNTIME_SERVICES), &mEfiRuntimeServicesTableTemplate);
  ASSERT (gDxeCoreRT != NULL);

  gDxeCoreST->RuntimeServices = gDxeCoreRT;

  //
  // Start the Image Services.
  //
  Status = CoreInitializeImageServices (HobStart);
  ASSERT_EFI_ERROR (Status);

  //
  // Call constructor for all libraries
  //
  ProcessLibraryConstructorList (gDxeCoreImageHandle, gDxeCoreST);
  PERF_END   (NULL,"PEI", NULL, 0) ;
  PERF_START (NULL,"DXE", NULL, 0) ;

  //
  // Report DXE Core image information to the PE/COFF Extra Action Library
  //
  ZeroMem (&ImageContext, sizeof (ImageContext));
  ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)gDxeCoreLoadedImage->ImageBase;
  ImageContext.PdbPointer   = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
  PeCoffLoaderRelocateImageExtraAction (&ImageContext);

  //
  // Initialize the Global Coherency Domain Services
  //
  Status = CoreInitializeGcdServices (&HobStart, MemoryBaseAddress, MemoryLength);
  ASSERT_EFI_ERROR (Status);

  //
  // Install the DXE Services Table into the EFI System Tables's Configuration Table
  //
  Status = CoreInstallConfigurationTable (&gEfiDxeServicesTableGuid, gDxeCoreDS);
  ASSERT_EFI_ERROR (Status);

  //
  // Install the HOB List into the EFI System Tables's Configuration Table
  //
  Status = CoreInstallConfigurationTable (&gEfiHobListGuid, HobStart);
  ASSERT_EFI_ERROR (Status);

  //
  // Install Memory Type Information Table into the EFI System Tables's Configuration Table
  //
  Status = CoreInstallConfigurationTable (&gEfiMemoryTypeInformationGuid, &gMemoryTypeInformation);
  ASSERT_EFI_ERROR (Status);

  //
  // If Loading modules At fixed address feature is enabled, install Load moduels at fixed address
  // Configuration Table so that user could easily to retrieve the top address to load Dxe and PEI
  // Code and Tseg base to load SMM driver.
  //
  if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
    Status = CoreInstallConfigurationTable (&gLoadFixedAddressConfigurationTableGuid, &gLoadModuleAtFixAddressConfigurationTable);
    ASSERT_EFI_ERROR (Status);
  }
  //
  // Report Status Code here for DXE_ENTRY_POINT once it is available
  //
  REPORT_STATUS_CODE (
    EFI_PROGRESS_CODE,
    (EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_ENTRY_POINT)
    );

  //
  // Create the aligned system table pointer structure that is used by external
  // debuggers to locate the system table...  Also, install debug image info
  // configuration table.
  //
  CoreInitializeDebugImageInfoTable ();
  CoreNewDebugImageInfoEntry (
    EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL,
    gDxeCoreLoadedImage,
    gDxeCoreImageHandle
    );

  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "HOBLIST address in DXE = 0x%pn", HobStart));

  DEBUG_CODE_BEGIN ();
    EFI_PEI_HOB_POINTERS               Hob;

    for (Hob.Raw = HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
      if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
        DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Memory Allocation 0x%08x 0x%0lx - 0x%0lxn", 
          Hob.MemoryAllocation->AllocDescriptor.MemoryType,                      
          Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress,               
          Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress + Hob.MemoryAllocation->AllocDescriptor.MemoryLength - 1));
      }
    }
    for (Hob.Raw = HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
      if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV2) {
        DEBUG ((DEBUG_INFO | DEBUG_LOAD, "FV2 Hob           0x%0lx - 0x%0lxn", Hob.FirmwareVolume2->BaseAddress, Hob.FirmwareVolume2->BaseAddress + Hob.FirmwareVolume2->Length - 1));
      } else if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) {
        DEBUG ((DEBUG_INFO | DEBUG_LOAD, "FV Hob            0x%0lx - 0x%0lxn", Hob.FirmwareVolume->BaseAddress, Hob.FirmwareVolume->BaseAddress + Hob.FirmwareVolume2->Length - 1));
      }
    }
  DEBUG_CODE_END ();

  //
  // Initialize the Event Services
  //
  Status = CoreInitializeEventServices ();
  ASSERT_EFI_ERROR (Status);

  //
  // Get persisted vector hand-off info from GUIDeed HOB again due to HobStart may be updated,
  // and install configuration table
  //
  GuidHob = GetNextGuidHob (&gEfiVectorHandoffInfoPpiGuid, HobStart);
  if (GuidHob != NULL) {
    VectorInfoList = (EFI_VECTOR_HANDOFF_INFO *) (GET_GUID_HOB_DATA(GuidHob));
    VectorInfo = VectorInfoList;
    Index = 1;
    while (VectorInfo->Attribute != EFI_VECTOR_HANDOFF_LAST_ENTRY) {
      VectorInfo ++;
      Index ++;
    }
    VectorInfo = AllocateCopyPool (sizeof (EFI_VECTOR_HANDOFF_INFO) * Index, (VOID *) VectorInfoList);
    ASSERT (VectorInfo != NULL);
    Status = CoreInstallConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID *) VectorInfo);
    ASSERT_EFI_ERROR (Status);
  }

  //
  // Get the Protocols that were passed in from PEI to DXE through GUIDed HOBs
  //
  // These Protocols are not architectural. This implementation is sharing code between
  // PEI and DXE in order to save FLASH space. These Protocols could also be implemented
  // as part of the DXE Core. However, that would also require the DXE Core to be ported
  // each time a different CPU is used, a different Decompression algorithm is used, or a
  // different Image type is used. By placing these Protocols in PEI, the DXE Core remains
  // generic, and only PEI and the Arch Protocols need to be ported from Platform to Platform,
  // and from CPU to CPU.
  //

  //
  // Publish the EFI, Tiano, and Custom Decompress protocols for use by other DXE components
  //
  Status = CoreInstallMultipleProtocolInterfaces (
             &mDecompressHandle,
             &gEfiDecompressProtocolGuid,           &gEfiDecompress,
             NULL
             );
  ASSERT_EFI_ERROR (Status);

  //
  // Register for the GUIDs of the Architectural Protocols, so the rest of the
  // EFI Boot Services and EFI Runtime Services tables can be filled in.
  // Also register for the GUIDs of optional protocols.
  //
  CoreNotifyOnProtocolInstallation ();

  //
  // Produce Firmware Volume Protocols, one for each FV in the HOB list.
  //
  Status = FwVolBlockDriverInit (gDxeCoreImageHandle, gDxeCoreST);
  ASSERT_EFI_ERROR (Status);

  Status = FwVolDriverInit (gDxeCoreImageHandle, gDxeCoreST);
  ASSERT_EFI_ERROR (Status);

  //
  // Produce the Section Extraction Protocol
  //
  Status = InitializeSectionExtraction (gDxeCoreImageHandle, gDxeCoreST);
  ASSERT_EFI_ERROR (Status);

  //
  // Initialize the DXE Dispatcher
  //
  PERF_START (NULL,"CoreInitializeDispatcher", "DxeMain", 0) ;
  CoreInitializeDispatcher ();
  PERF_END (NULL,"CoreInitializeDispatcher", "DxeMain", 0) ;

  //
  // Invoke the DXE Dispatcher
  //
  PERF_START (NULL, "CoreDispatcher", "DxeMain", 0);
  CoreDispatcher ();
  PERF_END (NULL, "CoreDispatcher", "DxeMain", 0);

  //
  // Display Architectural protocols that were not loaded if this is DEBUG build
  //
  DEBUG_CODE_BEGIN ();
    CoreDisplayMissingArchProtocols ();
  DEBUG_CODE_END ();

  //
  // Display any drivers that were not dispatched because dependency expression
  // evaluated to false if this is a debug build
  //
  DEBUG_CODE_BEGIN ();
    CoreDisplayDiscoveredNotDispatched ();
  DEBUG_CODE_END ();

  //
  // Assert if the Architectural Protocols are not present.
  //
  Status = CoreAllEfiServicesAvailable ();
  if (EFI_ERROR(Status)) {
    //
    // Report Status code that some Architectural Protocols are not present.
    //
    REPORT_STATUS_CODE (
      EFI_ERROR_CODE | EFI_ERROR_MAJOR,
      (EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_EC_NO_ARCH)
      );    
  }
  ASSERT_EFI_ERROR (Status);

  //
  // Report Status code before transfer control to BDS
  //
  REPORT_STATUS_CODE (
    EFI_PROGRESS_CODE,
    (EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_HANDOFF_TO_NEXT)
    );

  //
  // Transfer control to the BDS Architectural Protocol
  //
  gBds->Entry (gBds);

  //
  // BDS should never return
  //
  ASSERT (FALSE);
  CpuDeadLoop ();
}
/**
  Entry point of this module.

  @param[in] FileHandle   Handle of the file being invoked.
  @param[in] PeiServices  Describes the list of possible PEI Services.

  @return Status.

**/
EFI_STATUS
EFIAPI
PeimEntryMA (
    IN       EFI_PEI_FILE_HANDLE      FileHandle,
    IN CONST EFI_PEI_SERVICES         **PeiServices
)
{
    EFI_STATUS                        Status;
    EFI_BOOT_MODE                     BootMode;
    TIS_TPM_HANDLE                    TpmHandle;

    if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)) {
        DEBUG ((EFI_D_ERROR, "No TPM12 instance required!n"));
        return EFI_UNSUPPORTED;
    }

    if (PcdGetBool (PcdHideTpmSupport) && PcdGetBool (PcdHideTpm)) {
        return EFI_UNSUPPORTED;
    }

    //
    // Initialize TPM device
    //
    Status = PeiServicesGetBootMode (&BootMode);
    ASSERT_EFI_ERROR (Status);

    //
    // In S3 path, skip shadow logic. no measurement is required
    //
    if (BootMode != BOOT_ON_S3_RESUME) {
        Status = (**PeiServices).RegisterForShadow(FileHandle);
        if (Status == EFI_ALREADY_STARTED) {
            mImageInMemory = TRUE;
        } else if (Status == EFI_NOT_FOUND) {
            ASSERT_EFI_ERROR (Status);
        }
    }

    if (!mImageInMemory) {
        TpmHandle = (TIS_TPM_HANDLE)(UINTN)TPM_BASE_ADDRESS;
        Status = TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR)TpmHandle);
        if (EFI_ERROR (Status)) {
            DEBUG ((DEBUG_ERROR, "TPM not detected!n"));
            return Status;
        }

        if (PcdGet8 (PcdTpmInitializationPolicy) == 1) {
            Status = TpmCommStartup ((EFI_PEI_SERVICES**)PeiServices, TpmHandle, BootMode);
            if (EFI_ERROR (Status) ) {
                return Status;
            }
        }

        //
        // TpmSelfTest is optional on S3 path, skip it to save S3 time
        //
        if (BootMode != BOOT_ON_S3_RESUME) {
            Status = TpmCommContinueSelfTest ((EFI_PEI_SERVICES**)PeiServices, TpmHandle);
            if (EFI_ERROR (Status)) {
                return Status;
            }
        }

        Status = PeiServicesInstallPpi (&mTpmInitializedPpiList);
        ASSERT_EFI_ERROR (Status);
    }

    if (mImageInMemory) {
        Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices);
        if (EFI_ERROR (Status)) {
            return Status;
        }
    }

    return Status;
}
STATIC
UINT64*
GetBlockEntryListFromAddress (
  IN  UINT64       *RootTable,
  IN  UINT64        RegionStart,
  OUT UINTN        *TableLevel,
  IN OUT UINT64    *BlockEntrySize,
  IN OUT UINT64   **LastBlockEntry
  )
{
  UINTN   RootTableLevel;
  UINTN   RootTableEntryCount;
  UINT64 *TranslationTable;
  UINT64 *BlockEntry;
  UINT64  BlockEntryAddress;
  UINTN   BaseAddressAlignment;
  UINTN   PageLevel;
  UINTN   Index;
  UINTN   IndexLevel;
  UINTN   T0SZ;
  UINT64  Attributes;
  UINT64  TableAttributes;

  // Initialize variable
  BlockEntry = NULL;

  // Ensure the parameters are valid
  if (!(TableLevel && BlockEntrySize && LastBlockEntry)) {
    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
    return NULL;
  }

  // Ensure the Region is aligned on 4KB boundary
  if ((RegionStart & (SIZE_4KB - 1)) != 0) {
    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
    return NULL;
  }

  // Ensure the required size is aligned on 4KB boundary
  if ((*BlockEntrySize & (SIZE_4KB - 1)) != 0) {
    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
    return NULL;
  }

  //
  // Calculate LastBlockEntry from T0SZ - this is the last block entry of the root Translation table
  //
  T0SZ = ArmGetTCR () & TCR_T0SZ_MASK;
  // Get the Table info from T0SZ
  GetRootTranslationTableInfo (T0SZ, &RootTableLevel, &RootTableEntryCount);
  // The last block of the root table depends on the number of entry in this table
  *LastBlockEntry = TT_LAST_BLOCK_ADDRESS(RootTable, RootTableEntryCount);

  // If the start address is 0x0 then we use the size of the region to identify the alignment
  if (RegionStart == 0) {
    // Identify the highest possible alignment for the Region Size
    for (BaseAddressAlignment = 0; BaseAddressAlignment < 64; BaseAddressAlignment++) {
      if ((1 << BaseAddressAlignment) & *BlockEntrySize) {
        break;
      }
    }
  } else {
    // Identify the highest possible alignment for the Base Address
    for (BaseAddressAlignment = 0; BaseAddressAlignment < 64; BaseAddressAlignment++) {
      if ((1 << BaseAddressAlignment) & RegionStart) {
        break;
      }
    }
  }

  // Identify the Page Level the RegionStart must belongs to
  PageLevel = 3 - ((BaseAddressAlignment - 12) / 9);

  // If the required size is smaller than the current block size then we need to go to the page below.
  // The PageLevel was calculated on the Base Address alignment but did not take in account the alignment
  // of the allocation size
  if (*BlockEntrySize < TT_BLOCK_ENTRY_SIZE_AT_LEVEL (PageLevel)) {
    // It does not fit so we need to go a page level above
    PageLevel++;
  }

  // Expose the found PageLevel to the caller
  *TableLevel = PageLevel;

  // Now, we have the Table Level we can get the Block Size associated to this table
  *BlockEntrySize = TT_BLOCK_ENTRY_SIZE_AT_LEVEL (PageLevel);

  //
  // Get the Table Descriptor for the corresponding PageLevel. We need to decompose RegionStart to get appropriate entries
  //

  TranslationTable = RootTable;
  for (IndexLevel = RootTableLevel; IndexLevel <= PageLevel; IndexLevel++) {
    BlockEntry = (UINT64*)TT_GET_ENTRY_FOR_ADDRESS (TranslationTable, IndexLevel, RegionStart);

    if ((IndexLevel != 3) && ((*BlockEntry & TT_TYPE_MASK) == TT_TYPE_TABLE_ENTRY)) {
      // Go to the next table
      TranslationTable = (UINT64*)(*BlockEntry & TT_ADDRESS_MASK_DESCRIPTION_TABLE);

      // If we are at the last level then update the output
      if (IndexLevel == PageLevel) {
        // And get the appropriate BlockEntry at the next level
        BlockEntry = (UINT64*)TT_GET_ENTRY_FOR_ADDRESS (TranslationTable, IndexLevel + 1, RegionStart);

        // Set the last block for this new table
        *LastBlockEntry = TT_LAST_BLOCK_ADDRESS(TranslationTable, TT_ENTRY_COUNT);
      }
    } else if ((*BlockEntry & TT_TYPE_MASK) == TT_TYPE_BLOCK_ENTRY) {
      // If we are not at the last level then we need to split this BlockEntry
      if (IndexLevel != PageLevel) {
        // Retrieve the attributes from the block entry
        Attributes = *BlockEntry & TT_ATTRIBUTES_MASK;

        // Convert the block entry attributes into Table descriptor attributes
        TableAttributes = TT_TABLE_AP_NO_PERMISSION;
        if (Attributes & TT_PXN_MASK) {
          TableAttributes = TT_TABLE_PXN;
        }
        if (Attributes & TT_UXN_MASK) {
          TableAttributes = TT_TABLE_XN;
        }
        if (Attributes & TT_NS) {
          TableAttributes = TT_TABLE_NS;
        }

        // Get the address corresponding at this entry
        BlockEntryAddress = RegionStart;
        BlockEntryAddress = BlockEntryAddress >> TT_ADDRESS_OFFSET_AT_LEVEL(IndexLevel);
        // Shift back to right to set zero before the effective address
        BlockEntryAddress = BlockEntryAddress << TT_ADDRESS_OFFSET_AT_LEVEL(IndexLevel);

        // Set the correct entry type for the next page level
        if ((IndexLevel + 1) == 3) {
          Attributes |= TT_TYPE_BLOCK_ENTRY_LEVEL3;
        } else {
          Attributes |= TT_TYPE_BLOCK_ENTRY;
        }

        // Create a new translation table
        TranslationTable = (UINT64*)AllocatePages (EFI_SIZE_TO_PAGES((TT_ENTRY_COUNT * sizeof(UINT64)) + TT_ALIGNMENT_DESCRIPTION_TABLE));
        if (TranslationTable == NULL) {
          return NULL;
        }
        TranslationTable = (UINT64*)((UINTN)TranslationTable & TT_ADDRESS_MASK_DESCRIPTION_TABLE);

        // Fill the BlockEntry with the new TranslationTable
        *BlockEntry = ((UINTN)TranslationTable & TT_ADDRESS_MASK_DESCRIPTION_TABLE) | TableAttributes | TT_TYPE_TABLE_ENTRY;
        // Update the last block entry with the newly created translation table
        *LastBlockEntry = TT_LAST_BLOCK_ADDRESS(TranslationTable, TT_ENTRY_COUNT);

        // Populate the newly created lower level table
        BlockEntry = TranslationTable;
        for (Index = 0; Index < TT_ENTRY_COUNT; Index++) {
          *BlockEntry = Attributes | (BlockEntryAddress + (Index << TT_ADDRESS_OFFSET_AT_LEVEL(IndexLevel + 1)));
          BlockEntry++;
        }
        // Block Entry points at the beginning of the Translation Table
        BlockEntry = TranslationTable;
      }
    } else {
      if (IndexLevel != PageLevel) {
/**
  This notification function is invoked when an instance of the
  EFI_DEVICE_PATH_PROTOCOL is produced.

  @param  Event                 The event that occured
  @param  Context               For EFI compatiblity.  Not used.

**/
VOID
EFIAPI
NotifyDevPath (
  IN  EFI_EVENT Event,
  IN  VOID      *Context
  )
{
  EFI_HANDLE                            Handle;
  EFI_STATUS                            Status;
  UINTN                                 BufferSize;
  EFI_DEVICE_PATH_PROTOCOL             *DevPathNode;
  ATAPI_DEVICE_PATH                    *Atapi;

  //
  // Examine all new handles
  //
  for (;;) {
    //
    // Get the next handle
    //
    BufferSize = sizeof (Handle);
    Status = gBS->LocateHandle (
              ByRegisterNotify,
              NULL,
              mEfiDevPathNotifyReg,
              &BufferSize,
              &Handle
              );

    //
    // If not found, we're done
    //
    if (EFI_NOT_FOUND == Status) {
      break;
    }

    if (EFI_ERROR (Status)) {
      continue;
    }

    //
    // Get the DevicePath protocol on that handle
    //
    Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);
    ASSERT_EFI_ERROR (Status);

    while (!IsDevicePathEnd (DevPathNode)) {
      //
      // Find the handler to dump this device path node
      //
      if (
           (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&
           (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)
         ) {
        Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;
        PciOr16 (
          PCI_LIB_ADDRESS (
            0,
            1,
            1,
            (Atapi->PrimarySecondary == 1) ? 0x42: 0x40
            ),
          BIT15
          );
      }

      //
      // Next device path node
      //
      DevPathNode = NextDevicePathNode (DevPathNode);
    }
  }

  return;
}
/**
  Communicates with a registered handler.

  This function provides a service to send and receive messages from a registered UEFI service.

  @param[in] This                The EFI_PEI_SMM_COMMUNICATION_PPI instance.
  @param[in, out] CommBuffer     A pointer to the buffer to convey into SMRAM.
  @param[in, out] CommSize       The size of the data buffer being passed in.On exit, the size of data
                                 being returned. Zero if the handler does not wish to reply with any data.

  @retval EFI_SUCCESS            The message was successfully posted.
  @retval EFI_INVALID_PARAMETER  The CommBuffer was NULL.
  @retval EFI_NOT_STARTED        The service is NOT started.
**/
EFI_STATUS
EFIAPI
Communicate (
  IN CONST EFI_PEI_SMM_COMMUNICATION_PPI   *This,
  IN OUT VOID                              *CommBuffer,
  IN OUT UINTN                             *CommSize
  )
{
  EFI_STATUS                       Status;
  PEI_SMM_CONTROL_PPI              *SmmControl;
  PEI_SMM_ACCESS_PPI               *SmmAccess;
  UINT8                            SmiCommand;
  UINTN                            Size;
  EFI_SMM_COMMUNICATION_CONTEXT    *SmmCommunicationContext;

  DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei Communicate Entern"));

  if (CommBuffer == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Get needed resource
  //
  Status = PeiServicesLocatePpi (
             &gPeiSmmControlPpiGuid,
             0,
             NULL,
             (VOID **)&SmmControl
             );
  if (EFI_ERROR (Status)) {
    return EFI_NOT_STARTED;
  }

  Status = PeiServicesLocatePpi (
             &gPeiSmmAccessPpiGuid,
             0,
             NULL,
             (VOID **)&SmmAccess
             );
  if (EFI_ERROR (Status)) {
    return EFI_NOT_STARTED;
  }

  //
  // Check SMRAM locked, it should be done after SMRAM lock.
  //
  if (!SmmAccess->LockState) {
    DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei LockState - %xn", (UINTN)SmmAccess->LockState));
    return EFI_NOT_STARTED;
  }

  SmmCommunicationContext = GetCommunicationContext ();
  DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei BufferPtrAddress - 0x%016lx, BufferPtr: 0x%016lxn", SmmCommunicationContext->BufferPtrAddress, *(EFI_PHYSICAL_ADDRESS *)(UINTN)SmmCommunicationContext->BufferPtrAddress));

  //
  // No need to check if BufferPtr is 0, because it is in PEI phase.
  //
  *(EFI_PHYSICAL_ADDRESS *)(UINTN)SmmCommunicationContext->BufferPtrAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CommBuffer;
  DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei CommBuffer - %xn", (UINTN)CommBuffer));

  //
  // Send command
  //
  SmiCommand = (UINT8)SmmCommunicationContext->SwSmiNumber;
  Size = sizeof(SmiCommand);
  Status = SmmControl->Trigger (
                         (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),
                         SmmControl,
                         (INT8 *)&SmiCommand,
                         &Size,
                         FALSE,
                         0
                         );
  ASSERT_EFI_ERROR (Status);

  //
  // Setting BufferPtr to 0 means this transaction is done.
  //
  *(EFI_PHYSICAL_ADDRESS *)(UINTN)SmmCommunicationContext->BufferPtrAddress = 0;

  DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei Communicate Exitn"));

  return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
WinNtTimerDriverInitialize (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
/*++

Routine Description:

  Initialize the Timer Architectural Protocol driver

Arguments:

  ImageHandle - ImageHandle of the loaded driver

  SystemTable - Pointer to the System Table

Returns:

  EFI_SUCCESS           - Timer Architectural Protocol created

  EFI_OUT_OF_RESOURCES  - Not enough resources available to initialize driver.
  
  EFI_DEVICE_ERROR      - A device error occured attempting to initialize the driver.

--*/
{
  EFI_STATUS  Status;
  UINTN       Result;
  EFI_HANDLE  Handle;
  EFI_HANDLE  hSourceProcessHandle;
  EFI_HANDLE  hSourceHandle;
  EFI_HANDLE  hTargetProcessHandle;
  //
  // Make sure the Timer Architectural Protocol is not already installed in the system
  //
  ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiTimerArchProtocolGuid);

  //
  // Get the CPU Architectural Protocol instance
  //
  Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID**)&mCpu);
  ASSERT_EFI_ERROR (Status);

  //
  //  Get our handle so the timer tick thread can suspend
  //
  hSourceProcessHandle = gWinNt->GetCurrentProcess ();
  hSourceHandle        = gWinNt->GetCurrentThread ();
  hTargetProcessHandle = gWinNt->GetCurrentProcess ();
  Result = gWinNt->DuplicateHandle (
                    hSourceProcessHandle,
                    hSourceHandle,
                    hTargetProcessHandle,
                    &mNtMainThreadHandle,
                    0,
                    FALSE,
                    DUPLICATE_SAME_ACCESS
                    );
  if (Result == 0) {
    return EFI_DEVICE_ERROR;
  }

  //
  // Initialize Critical Section used to update variables shared between the main
  // thread and the timer interrupt thread.
  //
  gWinNt->InitializeCriticalSection (&mNtCriticalSection);

  //
  // Start the timer thread at the default timer period
  //
  Status = mTimer.SetTimerPeriod (&mTimer, DEFAULT_TIMER_TICK_DURATION);
  if (EFI_ERROR (Status)) {
    gWinNt->DeleteCriticalSection (&mNtCriticalSection);
    return Status;
  }

  //
  // Install the Timer Architectural Protocol onto a new handle
  //
  Handle = NULL;
  Status = gBS->InstallProtocolInterface (
                  &Handle,
                  &gEfiTimerArchProtocolGuid,
                  EFI_NATIVE_INTERFACE,
                  &mTimer
                  );
  if (EFI_ERROR (Status)) {
    //
    // Cancel the timer
    //
    mTimer.SetTimerPeriod (&mTimer, 0);
    gWinNt->DeleteCriticalSection (&mNtCriticalSection);
    return Status;
  }

  return EFI_SUCCESS;
}
/**
  PEI termination callback.

  @param[in]  PeiServices          General purpose services available to every PEIM.
  @param[in]  NotifyDescriptor     Not uesed.
  @param[in]  Ppi                  Not uesed.

  @retval  EFI_SUCCESS             If the interface could be successfully
                                   installed.

**/
EFI_STATUS
EndOfPeiPpiNotifyCallback (
  IN CONST EFI_PEI_SERVICES     **PeiServices,
  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
  IN VOID                       *Ppi
  )
{
  EFI_STATUS                  Status;
  UINT64                      MemoryTop;
  UINT64                      LowUncableBase;
  EFI_PLATFORM_INFO_HOB       *PlatformInfo;
  UINT32                      HecBaseHigh;
  EFI_BOOT_MODE               BootMode;

  Status = (*PeiServices)->GetBootMode (PeiServices, &BootMode);

  ASSERT_EFI_ERROR (Status);

  //
  // Set the some PCI and chipset range as UC
  // And align to 1M at leaset
  //
  PlatformInfo = PcdGetPtr (PcdPlatformInfo);

  UpdateDefaultSetupValue (PlatformInfo);

  DEBUG ((EFI_D_ERROR, "Memory TOLM: %Xn", PlatformInfo->MemData.MemTolm));
  DEBUG ((EFI_D_ERROR, "PCIE OSBASE: %lXn", PlatformInfo->PciData.PciExpressBase));
  DEBUG (
    (EFI_D_ERROR,
    "PCIE   BASE: %lX     Size : %Xn",
    PlatformInfo->PciData.PciExpressBase,
    PlatformInfo->PciData.PciExpressSize)
    );
  DEBUG (
    (EFI_D_ERROR,
    "PCI32  BASE: %X     Limit: %Xn",
    PlatformInfo->PciData.PciResourceMem32Base,
    PlatformInfo->PciData.PciResourceMem32Limit)
    );
  DEBUG (
    (EFI_D_ERROR,
    "PCI64  BASE: %lX     Limit: %lXn",
    PlatformInfo->PciData.PciResourceMem64Base,
    PlatformInfo->PciData.PciResourceMem64Limit)
    );
  DEBUG ((EFI_D_ERROR, "UC    START: %lX     End  : %lXn", PlatformInfo->MemData.MemMir0, PlatformInfo->MemData.MemMir1));

  LowUncableBase = PlatformInfo->MemData.MemMaxTolm;
  LowUncableBase &= (0x0FFF00000);
  MemoryTop = (0x100000000);

  if (BootMode != BOOT_ON_S3_RESUME) {
    //
    // In BIOS, HECBASE will be always below 4GB
    //
    HecBaseHigh = (UINT32) RShiftU64 (PlatformInfo->PciData.PciExpressBase, 28);
    ASSERT (HecBaseHigh < 16);

    //
    // Programe HECBASE for DXE phase
    //
  }

  return Status;
}
EFI_STATUS
EFIAPI
SpiProtocolInit (
  IN EFI_SPI_PROTOCOL       *This,
  IN SPI_INIT_TABLE         *InitTable
  )
/*++

Routine Description:

  Initialize the host controller to execute SPI command.

Arguments:

  This                    Pointer to the EFI_SPI_PROTOCOL instance.
  InitTable               Initialization data to be programmed into the SPI host controller.

Returns:

  EFI_SUCCESS             Initialization completed.
  EFI_ACCESS_DENIED       The SPI static configuration interface has been locked-down.
  EFI_INVALID_PARAMETER   Bad input parameters.
  EFI_UNSUPPORTED         Can't get Descriptor mode VSCC values
--*/
{
  EFI_STATUS    Status;
  UINT8         Index;
  UINT16        OpcodeType;
  SPI_INSTANCE  *SpiInstance;
  UINTN         PchRootComplexBar;
  UINT8         UnlockCmdOpcodeIndex;
  UINT8         FlashPartId[3];

  SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
  PchRootComplexBar = SpiInstance->PchRootComplexBar;

  if (InitTable != NULL) {
    //
    // Copy table into SPI driver Private data structure
    //
    CopyMem (
      &SpiInstance->SpiInitTable,
      InitTable,
      sizeof (SPI_INIT_TABLE)
      );
  } else {
    return EFI_INVALID_PARAMETER;
  }
  //
  // Check if the SPI interface has been locked-down.
  //
  if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) != 0) {
    ASSERT_EFI_ERROR (EFI_ACCESS_DENIED);
    return EFI_ACCESS_DENIED;
  }
  //
  // Clear all the status bits for status regs.
  //
  MmioOr16 (
    (UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS),
    (UINT16) ((B_QNC_RCRB_SPIS_CDS | B_QNC_RCRB_SPIS_BAS))
    );
  MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS);

  //
  // Set the Prefix Opcode registers.
  //
  MmioWrite16 (
    PchRootComplexBar + R_QNC_RCRB_SPIPREOP,
    (SpiInstance->SpiInitTable.PrefixOpcode[1] << 8) | InitTable->PrefixOpcode[0]
    );
  MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIPREOP);

  //
  // Set Opcode Type Configuration registers.
  //
  for (Index = 0, OpcodeType = 0; Index < SPI_NUM_OPCODE; Index++) {
    switch (SpiInstance->SpiInitTable.OpcodeMenu[Index].Type) {
    case EnumSpiOpcodeRead:
      OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_ADD_READ << (Index * 2));
      break;
    case EnumSpiOpcodeWrite:
      OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_ADD_WRITE << (Index * 2));
      break;
    case EnumSpiOpcodeWriteNoAddr:
      OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_NOADD_WRITE << (Index * 2));
      break;
    default:
      OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_NOADD_READ << (Index * 2));
      break;
    }
  }
  MmioWrite16 (PchRootComplexBar + R_QNC_RCRB_SPIOPTYPE, OpcodeType);
  MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIOPTYPE);

  //
  // Setup the Opcode Menu registers.
  //
  UnlockCmdOpcodeIndex = SPI_NUM_OPCODE;
  for (Index = 0; Index < SPI_NUM_OPCODE; Index++) {
    MmioWrite8 (
      PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + Index,
      SpiInstance->SpiInitTable.OpcodeMenu[Index].Code
      );
    MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + Index);
    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationJedecId) {
      Status = SpiProtocolExecute (
                This,
                Index,
                0,
                TRUE,
                TRUE,
                FALSE,
                (UINTN) 0,
                3,
                FlashPartId,
                EnumSpiRegionDescriptor
                );
      if (EFI_ERROR (Status)) {
        return Status;
      }
      if (FlashPartId[0] != SpiInstance->SpiInitTable.VendorId  ||
          FlashPartId[1] != SpiInstance->SpiInitTable.DeviceId0 ||
          FlashPartId[2] != SpiInstance->SpiInitTable.DeviceId1) {
        return EFI_INVALID_PARAMETER;
      }
    }

    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationWriteStatus) {
      UnlockCmdOpcodeIndex = Index;
    }
  }

  Status = UnlockFlashComponents (
            This,
            UnlockCmdOpcodeIndex
            );
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "Unlock flash components fail!n"));
  }

  SpiPhaseInit ();
  FillOutPublicInfoStruct (SpiInstance);
  SpiInstance->InitDone = TRUE;
  return EFI_SUCCESS;
}
/**
  Dispatch initialization request to sub status code devices based on 
  customized feature flags.
 
**/
VOID
InitializationDispatcherWorker (
  VOID
  )
{
  EFI_PEI_HOB_POINTERS              Hob;
  EFI_STATUS                        Status;
  MEMORY_STATUSCODE_PACKET_HEADER   *PacketHeader;
  MEMORY_STATUSCODE_RECORD          *Record;
  UINTN                             Index;
  UINTN                             MaxRecordNumber;

  //
  // If enable UseSerial, then initialize serial port.
  // if enable UseRuntimeMemory, then initialize runtime memory status code worker.
  //
  if (FeaturePcdGet (PcdStatusCodeUseSerial)) {
    //
    // Call Serial Port Lib API to initialize serial port.
    //
    Status = SerialPortInitialize ();
    ASSERT_EFI_ERROR (Status);
  }
  if (FeaturePcdGet (PcdStatusCodeUseMemory)) {
    Status = RtMemoryStatusCodeInitializeWorker ();
    ASSERT_EFI_ERROR (Status);
  }

  //
  // Replay Status code which saved in GUID'ed HOB to all supported devices. 
  //
  if (FeaturePcdGet (PcdStatusCodeReplayIn)) {
    // 
    // Journal GUID'ed HOBs to find all record entry, if found, 
    // then output record to support replay device.
    //
    Hob.Raw   = GetFirstGuidHob (&gMemoryStatusCodeRecordGuid);
    if (Hob.Raw != NULL) {
      PacketHeader = (MEMORY_STATUSCODE_PACKET_HEADER *) GET_GUID_HOB_DATA (Hob.Guid);
      Record = (MEMORY_STATUSCODE_RECORD *) (PacketHeader + 1);
      MaxRecordNumber = (UINTN) PacketHeader->RecordIndex;
      if (PacketHeader->PacketIndex > 0) {
        //
        // Record has been wrapped around. So, record number has arrived at max number.
        //
        MaxRecordNumber = (UINTN) PacketHeader->MaxRecordsNumber;
      }
      for (Index = 0; Index < MaxRecordNumber; Index++) {
        //
        // Dispatch records to devices based on feature flag.
        //
        if (FeaturePcdGet (PcdStatusCodeUseSerial)) {
          SerialStatusCodeReportWorker (
            Record[Index].CodeType,
            Record[Index].Value,
            Record[Index].Instance,
            NULL,
            NULL
            );
        }
        if (FeaturePcdGet (PcdStatusCodeUseMemory)) {
          RtMemoryStatusCodeReportWorker (
            Record[Index].CodeType,
            Record[Index].Value,
            Record[Index].Instance,
            NULL,
            NULL
            );
        }
      }
    }
  }
}
EFI_STATUS
EFIAPI
VBoxVgaGraphicsOutputBlt (
  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL         *BltBuffer, OPTIONAL
  IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION     BltOperation,
  IN  UINTN                                 SourceX,
  IN  UINTN                                 SourceY,
  IN  UINTN                                 DestinationX,
  IN  UINTN                                 DestinationY,
  IN  UINTN                                 Width,
  IN  UINTN                                 Height,
  IN  UINTN                                 Delta
  )
/*++

Routine Description:

  Graphics Output protocol instance to block transfer for CirrusLogic device

Arguments:

  This          - Pointer to Graphics Output protocol instance
  BltBuffer     - The data to transfer to screen
  BltOperation  - The operation to perform
  SourceX       - The X coordinate of the source for BltOperation
  SourceY       - The Y coordinate of the source for BltOperation
  DestinationX  - The X coordinate of the destination for BltOperation
  DestinationY  - The Y coordinate of the destination for BltOperation
  Width         - The width of a rectangle in the blt rectangle in pixels
  Height        - The height of a rectangle in the blt rectangle in pixels
  Delta         - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
                  If a Delta of 0 is used, the entire BltBuffer will be operated on.
                  If a subrectangle of the BltBuffer is used, then Delta represents
                  the number of bytes in a row of the BltBuffer.

Returns:

  EFI_INVALID_PARAMETER - Invalid parameter passed in
  EFI_SUCCESS - Blt operation success

--*/
{
  VBOX_VGA_PRIVATE_DATA     *Private;
  EFI_TPL                   OriginalTPL;
  UINTN                     DstY;
  UINTN                     SrcY;
  UINT32                    CurrentMode;
  UINTN                     ScreenWidth;
  UINTN                     ScreenHeight;
  EFI_STATUS                Status;

  Private = VBOX_VGA_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
  CurrentMode = This->Mode->Mode;
  ScreenWidth = Private->ModeData[CurrentMode].HorizontalResolution;
  ScreenHeight = Private->ModeData[CurrentMode].VerticalResolution;

  if ((BltOperation < 0) || (BltOperation >= EfiGraphicsOutputBltOperationMax)) {
    return EFI_INVALID_PARAMETER;
  }
  if (Width == 0 || Height == 0) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // If Delta is zero, then the entire BltBuffer is being used, so Delta
  // is the number of bytes in each row of BltBuffer.  Since BltBuffer is Width pixels size,
  // the number of bytes in each row can be computed.
  //
  if (Delta == 0) {
    Delta = Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
  }
  // code below assumes a Delta value in pixels, not bytes
  Delta /= sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);

  //
  // Make sure the SourceX, SourceY, DestinationX, DestinationY, Width, and Height parameters
  // are valid for the operation and the current screen geometry.
  //
  if (BltOperation == EfiBltVideoToBltBuffer || BltOperation == EfiBltVideoToVideo) {
    if (SourceY + Height > ScreenHeight) {
      return EFI_INVALID_PARAMETER;
    }

    if (SourceX + Width > ScreenWidth) {
      return EFI_INVALID_PARAMETER;
    }
  }
  if (BltOperation == EfiBltBufferToVideo || BltOperation == EfiBltVideoToVideo || BltOperation == EfiBltVideoFill) {
    if (DestinationY + Height > ScreenHeight) {
      return EFI_INVALID_PARAMETER;
    }

    if (DestinationX + Width > ScreenWidth) {
      return EFI_INVALID_PARAMETER;
    }
  }

  //
  // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
  // We would not want a timer based event (Cursor, ...) to come in while we are
  // doing this operation.
  //
  OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);

  switch (BltOperation) {
  case EfiBltVideoToBltBuffer:
    //
    // Video to BltBuffer: Source is Video, destination is BltBuffer
    //
    for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY) && BltBuffer; SrcY++, DstY++) {
      /// @todo assumes that color depth is 32 (*4, EfiPciIoWidthUint32) and format matches EFI_GRAPHICS_OUTPUT_BLT_PIXEL
      Status = Private->PciIo->Mem.Read (
                                    Private->PciIo,
                                    EfiPciIoWidthUint32,
                                    Private->BarIndexFB,
                                    ((SrcY * ScreenWidth) + SourceX) * 4,
                                    Width,
                                    BltBuffer + (DstY * Delta) + DestinationX
                                    );
      ASSERT_EFI_ERROR((Status));
    }
    break;

  case EfiBltBufferToVideo:
    //
    // BltBuffer to Video: Source is BltBuffer, destination is Video
    //
    for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
      /// @todo assumes that color depth is 32 (*4, EfiPciIoWidthUint32) and format matches EFI_GRAPHICS_OUTPUT_BLT_PIXEL
      Status = Private->PciIo->Mem.Write (
                                    Private->PciIo,
                                    EfiPciIoWidthUint32,
                                    Private->BarIndexFB,
                                    ((DstY * ScreenWidth) + DestinationX) * 4,
                                    Width,
                                    BltBuffer + (SrcY * Delta) + SourceX
                                    );
      ASSERT_EFI_ERROR((Status));
    }
    break;

  case EfiBltVideoToVideo:
    //
    // Video to Video: Source is Video, destination is Video
    //
    if (DestinationY <= SourceY) {
      // forward copy
      for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
        /// @todo assumes that color depth is 32 (*4, EfiPciIoWidthUint32) and format matches EFI_GRAPHICS_OUTPUT_BLT_PIXEL
        Status = Private->PciIo->CopyMem (
                                    Private->PciIo,
                                    EfiPciIoWidthUint32,
                                    Private->BarIndexFB,
                                    ((DstY * ScreenWidth) + DestinationX) * 4,
                                    Private->BarIndexFB,
                                    ((SrcY * ScreenWidth) + SourceX) * 4,
                                    Width
                                    );
        ASSERT_EFI_ERROR((Status));
      }
    } else {
      // reverse copy
      for (SrcY = SourceY + Height - 1, DstY = DestinationY + Height - 1; SrcY >= SourceY && SrcY <= SourceY + Height - 1; SrcY--, DstY--) {
        /// @todo assumes that color depth is 32 (*4, EfiPciIoWidthUint32) and format matches EFI_GRAPHICS_OUTPUT_BLT_PIXEL
        Status = Private->PciIo->CopyMem (
                                    Private->PciIo,
                                    EfiPciIoWidthUint32,
                                    Private->BarIndexFB,
                                    ((DstY * ScreenWidth) + DestinationX) * 4,
                                    Private->BarIndexFB,
                                    ((SrcY * ScreenWidth) + SourceX) * 4,
                                    Width
                                    );
        ASSERT_EFI_ERROR((Status));
      }
    }
    break;

  case EfiBltVideoFill:
    //
    // Video Fill: Source is BltBuffer, destination is Video
    //
    if (DestinationX == 0 && Width == ScreenWidth) {
      /// @todo assumes that color depth is 32 (*4, EfiPciIoWidthFillUint32) and format matches EFI_GRAPHICS_OUTPUT_BLT_PIXEL
      Status = Private->PciIo->Mem.Write (
                                    Private->PciIo,
                                    EfiPciIoWidthFillUint32,
                                    Private->BarIndexFB,
                                    DestinationY * ScreenWidth * 4,
                                    (Width * Height),
                                    BltBuffer
                                    );
      ASSERT_EFI_ERROR((Status));
    } else {
      for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
        /// @todo assumes that color depth is 32 (*4, EfiPciIoWidthFillUint32) and format matches EFI_GRAPHICS_OUTPUT_BLT_PIXEL
        Status = Private->PciIo->Mem.Write (
                                      Private->PciIo,
                                      EfiPciIoWidthFillUint32,
                                      Private->BarIndexFB,
                                      ((DstY * ScreenWidth) + DestinationX) * 4,
                                      Width,
                                      BltBuffer
                                      );
        ASSERT_EFI_ERROR((Status));
      }
    }
    break;

  default:
    ASSERT (FALSE);
  }

  gBS->RestoreTPL (OriginalTPL);

  return EFI_SUCCESS;
}
/**
  The module Entry Point of the Firmware Performance Data Table DXE driver.

  @param[in]  ImageHandle    The firmware allocated handle for the EFI image.
  @param[in]  SystemTable    A pointer to the EFI System Table.

  @retval EFI_SUCCESS    The entry point is executed successfully.
  @retval Other          Some error occurs when executing this entry point.

**/
EFI_STATUS
EFIAPI
FirmwarePerformanceDxeEntryPoint (
  IN EFI_HANDLE          ImageHandle,
  IN EFI_SYSTEM_TABLE    *SystemTable
  )
{
  EFI_STATUS               Status;
  EFI_HOB_GUID_TYPE        *GuidHob;
  FIRMWARE_SEC_PERFORMANCE *Performance;

  //
  // Get Report Status Code Handler Protocol.
  //
  Status = gBS->LocateProtocol (&gEfiRscHandlerProtocolGuid, NULL, (VOID **) &mRscHandlerProtocol);
  ASSERT_EFI_ERROR (Status);

  //
  // Register report status code listener for OS Loader load and start.
  //
  Status = mRscHandlerProtocol->Register (FpdtStatusCodeListenerDxe, TPL_HIGH_LEVEL);
  ASSERT_EFI_ERROR (Status);

  //
  // Register the notify function to update FPDT on ExitBootServices Event.
  //
  Status = gBS->CreateEventEx (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  FpdtExitBootServicesEventNotify,
                  NULL,
                  &gEfiEventExitBootServicesGuid,
                  &mExitBootServicesEvent
                  );
  ASSERT_EFI_ERROR (Status);

  //
  // Create ready to boot event to install ACPI FPDT table.
  //
  Status = gBS->CreateEventEx (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  FpdtReadyToBootEventNotify,
                  NULL,
                  &gEfiEventReadyToBootGuid,
                  &mReadyToBootEvent
                  );
  ASSERT_EFI_ERROR (Status);

  //
  // Create legacy boot event to log OsLoaderStartImageStart for legacy boot.
  //
  Status = gBS->CreateEventEx (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  FpdtLegacyBootEventNotify,
                  NULL,
                  &gEfiEventLegacyBootGuid,
                  &mLegacyBootEvent
                  );
  ASSERT_EFI_ERROR (Status);

  //
  // Retrieve GUID HOB data that contains the ResetEnd.
  //
  GuidHob = GetFirstGuidHob (&gEfiFirmwarePerformanceGuid);
  if (GuidHob != NULL) {
    Performance = (FIRMWARE_SEC_PERFORMANCE *) GET_GUID_HOB_DATA (GuidHob);
    mBootPerformanceTableTemplate.BasicBoot.ResetEnd = Performance->ResetEnd;
  } else {
    //
    // SEC Performance Data Hob not found, ResetEnd in ACPI FPDT table will be 0.
    //
    DEBUG ((EFI_D_ERROR, "FPDT: WARNING: SEC Performance Data Hob not found, ResetEnd will be set to 0!n"));
  }

  return EFI_SUCCESS;
}
/**
  Install ACPI Firmware Performance Data Table (FPDT).

  @return Status code.

**/
EFI_STATUS
InstallFirmwarePerformanceDataTable (
  VOID
  )
{
  EFI_STATUS                    Status;
  EFI_ACPI_TABLE_PROTOCOL       *AcpiTableProtocol;
  EFI_PHYSICAL_ADDRESS          Address;
  UINTN                         Size;
  UINT8                         SmmBootRecordCommBuffer[SMM_BOOT_RECORD_COMM_SIZE];
  EFI_SMM_COMMUNICATE_HEADER    *SmmCommBufferHeader;
  SMM_BOOT_RECORD_COMMUNICATE   *SmmCommData;
  UINTN                         CommSize;
  UINTN                         PerformanceRuntimeDataSize;
  UINT8                         *PerformanceRuntimeData; 
  UINT8                         *PerformanceRuntimeDataHead; 
  EFI_SMM_COMMUNICATION_PROTOCOL  *Communication;
  FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable;

  //
  // Get AcpiTable Protocol.
  //
  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Collect boot records from SMM drivers.
  //
  SmmCommData = NULL;
  Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &Communication);
  if (!EFI_ERROR (Status)) {
    //
    // Initialize communicate buffer 
    //
    SmmCommBufferHeader = (EFI_SMM_COMMUNICATE_HEADER*)SmmBootRecordCommBuffer;
    SmmCommData = (SMM_BOOT_RECORD_COMMUNICATE*)SmmCommBufferHeader->Data;
    ZeroMem((UINT8*)SmmCommData, sizeof(SMM_BOOT_RECORD_COMMUNICATE));

    CopyGuid (&SmmCommBufferHeader->HeaderGuid, &gEfiFirmwarePerformanceGuid);
    SmmCommBufferHeader->MessageLength = sizeof(SMM_BOOT_RECORD_COMMUNICATE);
    CommSize = SMM_BOOT_RECORD_COMM_SIZE;
  
    //
    // Get the size of boot records.
    //
    SmmCommData->Function       = SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE;
    SmmCommData->BootRecordData = NULL;
    Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize);
    ASSERT_EFI_ERROR (Status);
  
    if (!EFI_ERROR (SmmCommData->ReturnStatus) && SmmCommData->BootRecordSize != 0) {
      //
      // Get all boot records
      //
      SmmCommData->Function       = SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA;
      SmmCommData->BootRecordData = AllocateZeroPool(SmmCommData->BootRecordSize);
      ASSERT (SmmCommData->BootRecordData != NULL);
      
      Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize);
      ASSERT_EFI_ERROR (Status);
      ASSERT_EFI_ERROR(SmmCommData->ReturnStatus);
    }
  }

  //
  // Prepare memory for runtime Performance Record. 
  // Runtime performance records includes two tables S3 performance table and Boot performance table. 
  // S3 Performance table includes S3Resume and S3Suspend records. 
  // Boot Performance table includes BasicBoot record, and one or more appended Boot Records. 
  //
  PerformanceRuntimeData = NULL;
  PerformanceRuntimeDataSize = sizeof (S3_PERFORMANCE_TABLE) + sizeof (BOOT_PERFORMANCE_TABLE) + mBootRecordSize + PcdGet32 (PcdExtFpdtBootRecordPadSize);
  if (SmmCommData != NULL) {
    PerformanceRuntimeDataSize += SmmCommData->BootRecordSize;
  }

  //
  // Try to allocate the same runtime buffer as last time boot.
  //
  ZeroMem (&PerformanceVariable, sizeof (PerformanceVariable));
  Size = sizeof (PerformanceVariable);
  Status = gRT->GetVariable (
                  EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,
                  &gEfiFirmwarePerformanceGuid,
                  NULL,
                  &Size,
                  &PerformanceVariable
                  );
  if (!EFI_ERROR (Status)) {
    Address = PerformanceVariable.S3PerformanceTablePointer;
    Status = gBS->AllocatePages (
                    AllocateAddress,
                    EfiReservedMemoryType,
                    EFI_SIZE_TO_PAGES (PerformanceRuntimeDataSize),
                    &Address
                    );
    if (!EFI_ERROR (Status)) {
      PerformanceRuntimeData = (UINT8 *) (UINTN) Address;
    }
  }

  if (PerformanceRuntimeData == NULL) {
    //
    // Fail to allocate at specified address, continue to allocate at any address.
    //
    PerformanceRuntimeData = FpdtAllocateReservedMemoryBelow4G (PerformanceRuntimeDataSize);
  }
  DEBUG ((EFI_D_INFO, "FPDT: Performance Runtime Data address = 0x%xn", PerformanceRuntimeData));

  if (PerformanceRuntimeData == NULL) {
    if (SmmCommData != NULL && SmmCommData->BootRecordData != NULL) {
      FreePool (SmmCommData->BootRecordData);
    }
    return EFI_OUT_OF_RESOURCES;
  }
  
  PerformanceRuntimeDataHead = PerformanceRuntimeData;

  if (FeaturePcdGet (PcdFirmwarePerformanceDataTableS3Support)) {
    //
    // Prepare S3 Performance Table.
    //
    mAcpiS3PerformanceTable = (S3_PERFORMANCE_TABLE *) PerformanceRuntimeData;
    CopyMem (mAcpiS3PerformanceTable, &mS3PerformanceTableTemplate, sizeof (mS3PerformanceTableTemplate));
    PerformanceRuntimeData  = PerformanceRuntimeData + mAcpiS3PerformanceTable->Header.Length;
    DEBUG ((EFI_D_INFO, "FPDT: ACPI S3 Performance Table address = 0x%xn", mAcpiS3PerformanceTable));
    //
    // Save S3 Performance Table address to Variable for use in Firmware Performance PEIM.
    //
    PerformanceVariable.S3PerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiS3PerformanceTable;
    //
    // Update S3 Performance Table Pointer in template.
    //
    mFirmwarePerformanceTableTemplate.S3PointerRecord.S3PerformanceTablePointer = (UINT64) PerformanceVariable.S3PerformanceTablePointer;
  } else {
    //
    // Exclude S3 Performance Table Pointer from FPDT table template.
    //
    mFirmwarePerformanceTableTemplate.Header.Length -= sizeof (EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD);
  }

  //
  // Prepare Boot Performance Table.
  //
  mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) PerformanceRuntimeData;
  //
  // Fill Basic Boot record to Boot Performance Table.
  //
  CopyMem (PerformanceRuntimeData, &mBootPerformanceTableTemplate, sizeof (mBootPerformanceTableTemplate));
  PerformanceRuntimeData = PerformanceRuntimeData + mAcpiBootPerformanceTable->Header.Length;
  //
  // Fill Boot records from boot drivers.
  //
  CopyMem (PerformanceRuntimeData, mBootRecordBuffer, mBootRecordSize);
  mAcpiBootPerformanceTable->Header.Length += mBootRecordSize;
  PerformanceRuntimeData = PerformanceRuntimeData + mBootRecordSize;
  if (SmmCommData != NULL && SmmCommData->BootRecordData != NULL) {
    //
    // Fill Boot records from SMM drivers.
    //
    CopyMem (PerformanceRuntimeData, SmmCommData->BootRecordData, SmmCommData->BootRecordSize);
    FreePool (SmmCommData->BootRecordData);
    mAcpiBootPerformanceTable->Header.Length = (UINT32) (mAcpiBootPerformanceTable->Header.Length + SmmCommData->BootRecordSize);
    PerformanceRuntimeData = PerformanceRuntimeData + SmmCommData->BootRecordSize;
  }
  //
  // Reserve space for boot records after ReadyToBoot.
  //
  PerformanceRuntimeData = PerformanceRuntimeData + PcdGet32 (PcdExtFpdtBootRecordPadSize);
  DEBUG ((EFI_D_INFO, "FPDT: ACPI Boot Performance Table address = 0x%xn", mAcpiBootPerformanceTable));
  //
  // Save Boot Performance Table address to Variable for use in S4 resume.
  //
  PerformanceVariable.BootPerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiBootPerformanceTable;
  //
  // Update Boot Performance Table Pointer in template.
  //
  mFirmwarePerformanceTableTemplate.BootPointerRecord.BootPerformanceTablePointer = (UINT64) (UINTN) mAcpiBootPerformanceTable;

  //
  // Save Runtime Performance Table pointers to Variable.
  //
  Status = gRT->SetVariable (
                  EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,
                  &gEfiFirmwarePerformanceGuid,
                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
                  sizeof (PerformanceVariable),
                  &PerformanceVariable
                  );
  ASSERT_EFI_ERROR (Status);

  //
  // Publish Firmware Performance Data Table.
  //
  FpdtAcpiTableChecksum ((UINT8 *) &mFirmwarePerformanceTableTemplate, mFirmwarePerformanceTableTemplate.Header.Length);
  Status = AcpiTableProtocol->InstallAcpiTable (
                                AcpiTableProtocol,
                                &mFirmwarePerformanceTableTemplate,
                                mFirmwarePerformanceTableTemplate.Header.Length,
                                &mFirmwarePerformanceTableTemplateKey
                                );
  if (EFI_ERROR (Status)) {
    FreePool (PerformanceRuntimeDataHead);
    mAcpiBootPerformanceTable = NULL;
    mAcpiS3PerformanceTable = NULL;
    return Status;
  }
  
  //
  // Free temp Boot record, and update Boot Record to point to Basic Boot performance table.
  //
  if (mBootRecordBuffer != NULL) {
    FreePool (mBootRecordBuffer);
  }
  mBootRecordBuffer  = (UINT8 *) mAcpiBootPerformanceTable;
  mBootRecordSize    = mAcpiBootPerformanceTable->Header.Length;
  mBootRecordMaxSize = mBootRecordSize + PcdGet32 (PcdExtFpdtBootRecordPadSize);
  
  return EFI_SUCCESS;
}
/**
  Variable Driver main entry point. The Variable driver places the 4 EFI
  runtime services in the EFI System Table and installs arch protocols 
  for variable read and write services being availible. It also registers
  a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.

  @param[in] ImageHandle    The firmware allocated handle for the EFI image.  
  @param[in] SystemTable    A pointer to the EFI System Table.
  
  @retval EFI_SUCCESS       Variable service successfully initialized.

**/
EFI_STATUS
EFIAPI
VariableServiceInitialize (
  IN EFI_HANDLE                         ImageHandle,
  IN EFI_SYSTEM_TABLE                   *SystemTable
  )
{
  EFI_STATUS                            Status;
  EFI_EVENT                             ReadyToBootEvent;    

  Status = VariableCommonInitialize ();
  ASSERT_EFI_ERROR (Status);

  SystemTable->RuntimeServices->GetVariable         = VariableServiceGetVariable;
  SystemTable->RuntimeServices->GetNextVariableName = VariableServiceGetNextVariableName;
  SystemTable->RuntimeServices->SetVariable         = VariableServiceSetVariable;
  SystemTable->RuntimeServices->QueryVariableInfo   = VariableServiceQueryVariableInfo;
    
  //
  // Now install the Variable Runtime Architectural protocol on a new handle.
  //
  Status = gBS->InstallProtocolInterface (
                  &mHandle,
                  &gEfiVariableArchProtocolGuid, 
                  EFI_NATIVE_INTERFACE,
                  NULL
                  );
  ASSERT_EFI_ERROR (Status);

  //
  // Register FtwNotificationEvent () notify function.
  // 
  EfiCreateProtocolNotifyEvent (
    &gEfiFaultTolerantWriteProtocolGuid,
    TPL_CALLBACK,
    FtwNotificationEvent,
    (VOID *)SystemTable,
    &mFtwRegistration
    );

  Status = gBS->CreateEventEx (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  VariableClassAddressChangeEvent,
                  NULL,
                  &gEfiEventVirtualAddressChangeGuid,
                  &mVirtualAddressChangeEvent
                  );
  ASSERT_EFI_ERROR (Status);

  //
  // Register the event handling function to reclaim variable for OS usage.
  //
  Status = EfiCreateEventReadyToBootEx (
             TPL_NOTIFY, 
             OnReadyToBoot, 
             NULL, 
             &ReadyToBootEvent
             );

  return EFI_SUCCESS;
}
/**
  Function to read a single line (up to but not including the n) from a file.

  If the position upon start is 0, then the Ascii Boolean will be set.  This should be
  maintained and not changed for all operations with the same file.
  The function will not return the r and n character in buffer. When an empty line is
  read a CHAR_NULL character will be returned in buffer.

  @param[in]       Handle        FileHandle to read from.
  @param[in, out]  Buffer        The pointer to buffer to read into.
  @param[in, out]  Size          The pointer to number of bytes in Buffer.
  @param[in]       Truncate      If the buffer is large enough, this has no effect.
                                 If the buffer is is too small and Truncate is TRUE,
                                 the line will be truncated.
                                 If the buffer is is too small and Truncate is FALSE,
                                 then no read will occur.

  @param[in, out]  Ascii         Boolean value for indicating whether the file is
                                 Ascii (TRUE) or UCS2 (FALSE).

  @retval EFI_SUCCESS           The operation was successful.  The line is stored in
                                Buffer.
  @retval EFI_INVALID_PARAMETER Handle was NULL.
  @retval EFI_INVALID_PARAMETER Size was NULL.
  @retval EFI_BUFFER_TOO_SMALL  Size was not large enough to store the line.
                                Size was updated to the minimum space required.
  @sa FileHandleRead
**/
EFI_STATUS
EFIAPI
FileHandleReadLine(
  IN EFI_FILE_HANDLE            Handle,
  IN OUT CHAR16                 *Buffer,
  IN OUT UINTN                  *Size,
  IN BOOLEAN                    Truncate,
  IN OUT BOOLEAN                *Ascii
  )
{
  EFI_STATUS  Status;
  CHAR16      CharBuffer;
  UINT64      FileSize;
  UINTN       CharSize;
  UINTN       CountSoFar;
  UINTN       CrCount;
  UINT64      OriginalFilePosition;

  if (Handle == NULL
    ||Size   == NULL
    ||(Buffer==NULL&&*Size!=0)
   ){
    return (EFI_INVALID_PARAMETER);
  } 
  
  if (Buffer != NULL && *Size != 0) {
    *Buffer = CHAR_NULL;
  } 
  
  Status = FileHandleGetSize (Handle, &FileSize);
  if (EFI_ERROR (Status)) {
    return Status;
  } else if (FileSize == 0) {
    *Ascii = TRUE;
    return EFI_SUCCESS;
  }  
  
  FileHandleGetPosition(Handle, &OriginalFilePosition);
  if (OriginalFilePosition == 0) {
    CharSize = sizeof(CHAR16);
    Status = FileHandleRead(Handle, &CharSize, &CharBuffer);
    ASSERT_EFI_ERROR(Status);
    if (CharBuffer == gUnicodeFileTag) {
      *Ascii = FALSE;
    } else {
      *Ascii = TRUE;
      FileHandleSetPosition(Handle, OriginalFilePosition);
    }
  }

  CrCount = 0;
  for (CountSoFar = 0;;CountSoFar++){
    CharBuffer = 0;
    if (*Ascii) {
      CharSize = sizeof(CHAR8);
    } else {
      CharSize = sizeof(CHAR16);
    }
    Status = FileHandleRead(Handle, &CharSize, &CharBuffer);
    if (  EFI_ERROR(Status)
       || CharSize == 0
       || (CharBuffer == L'n' && !(*Ascii))
       || (CharBuffer ==  'n' && *Ascii)
     ){
      break;
    } else if (
        (CharBuffer == L'r' && !(*Ascii)) ||
        (CharBuffer ==  'r' && *Ascii)
      ) {
      CrCount++;
      continue;
    }
    //
    // if we have space save it...
    //
    if ((CountSoFar+1-CrCount)*sizeof(CHAR16) < *Size){
      ASSERT(Buffer != NULL);
      ((CHAR16*)Buffer)[CountSoFar-CrCount] = CharBuffer;
      ((CHAR16*)Buffer)[CountSoFar+1-CrCount] = CHAR_NULL;
    }
  }

  //
  // if we ran out of space tell when...
  //
  if ((CountSoFar+1-CrCount)*sizeof(CHAR16) > *Size){
    *Size = (CountSoFar+1-CrCount)*sizeof(CHAR16);
    if (!Truncate) {
      if (Buffer != NULL && *Size != 0) {
        ZeroMem(Buffer, *Size);
      }
      FileHandleSetPosition(Handle, OriginalFilePosition);
      return (EFI_BUFFER_TOO_SMALL);
    } else {
      DEBUG((DEBUG_WARN, "The line was truncated in FileHandleReadLine"));
      return (EFI_SUCCESS);
    }
  }

  return (Status);
}
/**

  This function attempts to boot for the boot order specified
  by platform policy.

**/
VOID
BdsBootDeviceSelect (
  VOID
  )
{
  EFI_STATUS        Status;
  LIST_ENTRY        *Link;
  BDS_COMMON_OPTION *BootOption;
  UINTN             ExitDataSize;
  CHAR16            *ExitData;
  UINT16            Timeout;
  LIST_ENTRY        BootLists;
  CHAR16            Buffer[20];
  BOOLEAN           BootNextExist;
  LIST_ENTRY        *LinkBootNext;
  EFI_EVENT         ConnectConInEvent;

  //
  // Got the latest boot option
  //
  BootNextExist = FALSE;
  LinkBootNext  = NULL;
  ConnectConInEvent = NULL;
  InitializeListHead (&BootLists);

  //
  // First check the boot next option
  //
  ZeroMem (Buffer, sizeof (Buffer));

  //
  // Create Event to signal ConIn connection request
  //
  if (PcdGetBool (PcdConInConnectOnDemand)) {
    Status = gBS->CreateEventEx (
                    EVT_NOTIFY_SIGNAL,
                    TPL_CALLBACK,
                    BdsEmptyCallbackFunction,
                    NULL,
                    &gConnectConInEventGuid,
                    &ConnectConInEvent
                    );
    if (EFI_ERROR(Status)) {
      ConnectConInEvent = NULL;
    }
  }

  if (mBootNext != NULL) {
    //
    // Indicate we have the boot next variable, so this time
    // boot will always have this boot option
    //
    BootNextExist = TRUE;

    //
    // Clear the this variable so it's only exist in this time boot
    //
    Status = gRT->SetVariable (
          L"BootNext",
          &gEfiGlobalVariableGuid,
          EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
          0,
                    NULL
          );
    //
    // Deleting variable with current variable implementation shouldn't fail.
    //
    ASSERT_EFI_ERROR (Status);

    //
    // Add the boot next boot option
    //
    UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext);
    BootOption = BdsLibVariableToOption (&BootLists, Buffer);

    //
    // If fail to get boot option from variable, just return and do nothing.
    //
    if (BootOption == NULL) {
      return;
    }

    BootOption->BootCurrent = *mBootNext;
  }
  //
  // Parse the boot order to get boot option
  //
  BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");

  //
  // When we didn't have chance to build boot option variables in the first 
  // full configuration boot (e.g.: Reset in the first page or in Device Manager),
  // we have no boot options in the following mini configuration boot.
  // Give the last chance to enumerate the boot options.
  //
  if (IsListEmpty (&BootLists)) {
    BdsLibEnumerateAllBootOption (&BootLists);
  }

  Link = BootLists.ForwardLink;

  //
  // Parameter check, make sure the loop will be valid
  //
  if (Link == NULL) {
    return ;
  }
  //
  // Here we make the boot in a loop, every boot success will
  // return to the front page
  //
  for (;;) {
    //
    // Check the boot option list first
    //
    if (Link == &BootLists) {
      //
      // When LazyConIn enabled, signal connect ConIn event before enter UI
      //
      if (PcdGetBool (PcdConInConnectOnDemand) && ConnectConInEvent != NULL) {
        gBS->SignalEvent (ConnectConInEvent);
      }

      //
      // There are two ways to enter here:
      // 1. There is no active boot option, give user chance to
      //    add new boot option
      // 2. All the active boot option processed, and there is no
      //    one is success to boot, then we back here to allow user
      //    add new active boot option
      //
      Timeout = 0xffff;
      PlatformBdsEnterFrontPage (Timeout, FALSE);
      InitializeListHead (&BootLists);
      BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
      Link = BootLists.ForwardLink;
      continue;
    }
    //
    // Get the boot option from the link list
    //
    BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);

    //
    // According to EFI Specification, if a load option is not marked
    // as LOAD_OPTION_ACTIVE, the boot manager will not automatically
    // load the option.
    //
    if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
      //
      // skip the header of the link list, because it has no boot option
      //
      Link = Link->ForwardLink;
      continue;
    }
    //
    // Make sure the boot option device path connected,
    // but ignore the BBS device path
    //
    if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
      //
      // Notes: the internal shell can not been connected with device path
      // so we do not check the status here
      //
      BdsLibConnectDevicePath (BootOption->DevicePath);
    }

    //
    // Restore to original mode before launching boot option.
    //
//    BdsSetConsoleMode (FALSE);
    
    //
    // All the driver options should have been processed since
    // now boot will be performed.
    //
    Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);
    if (Status != EFI_SUCCESS) {
      //
      // Call platform action to indicate the boot fail
      //
      BootOption->StatusString = NULL; //GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
      //PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);

      //
      // Check the next boot option
      //
      Link = Link->ForwardLink;

    } else {
      //
      // Call platform action to indicate the boot success
      //
      BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
      PlatformBdsBootSuccess (BootOption);

      //
      // Boot success, then stop process the boot order, and
      // present the boot manager menu, front page
      //

      //
      // When LazyConIn enabled, signal connect ConIn Event before enter UI
      //
      if (PcdGetBool (PcdConInConnectOnDemand) && ConnectConInEvent != NULL) {
        gBS->SignalEvent (ConnectConInEvent);
      }

      Timeout = 0xffff;
      PlatformBdsEnterFrontPage (Timeout, FALSE);

      //
      // Rescan the boot option list, avoid potential risk of the boot
      // option change in front page
      //
      if (BootNextExist) {
        LinkBootNext = BootLists.ForwardLink;
      }

      InitializeListHead (&BootLists);
      if (LinkBootNext != NULL) {
        //
        // Reserve the boot next option
        //
        InsertTailList (&BootLists, LinkBootNext);
      }

      BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
      Link = BootLists.ForwardLink;
    }
  }

}
/**
  Provides the DMA controller-specific addresses needed to access system memory.

  Operation is relative to the DMA bus master.

  @param  Operation             Indicates if the bus master is going to read or write to system memory.
  @param  HostAddress           The system memory address to map to the DMA controller.
  @param  NumberOfBytes         On input the number of bytes to map. On output the number of bytes
                                that were mapped.
  @param  DeviceAddress         The resulting map address for the bus master controller to use to
                                access the hosts HostAddress.
  @param  Mapping               A resulting value to pass to Unmap().

  @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.
  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.
  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
  @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.

**/
EFI_STATUS
EFIAPI
DmaMap (
  IN     DMA_MAP_OPERATION              Operation,
  IN     VOID                           *HostAddress,
  IN OUT UINTN                          *NumberOfBytes,
  OUT    PHYSICAL_ADDRESS               *DeviceAddress,
  OUT    VOID                           **Mapping
  )
{
  EFI_STATUS                      Status;
  MAP_INFO_INSTANCE               *Map;
  VOID                            *Buffer;
  EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;

  if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL ) {
    return EFI_INVALID_PARAMETER;
  }

  if (Operation >= MapOperationMaximum) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // The debug implementation of UncachedMemoryAllocationLib in ArmPkg returns
  // a virtual uncached alias, and unmaps the cached ID mapping of the buffer,
  // in order to catch inadvertent references to the cached mapping.
  // Since HostToDeviceAddress () expects ID mapped input addresses, convert
  // the host address to an ID mapped address first.
  //
  *DeviceAddress = HostToDeviceAddress (ConvertToPhysicalAddress (HostAddress));

  // Remember range so we can flush on the other side
  Map = AllocatePool (sizeof (MAP_INFO_INSTANCE));
  if (Map == NULL) {
    return  EFI_OUT_OF_RESOURCES;
  }

  if ((((UINTN)HostAddress & (mCpu->DmaBufferAlignment - 1)) != 0) ||
      ((*NumberOfBytes & (mCpu->DmaBufferAlignment - 1)) != 0)) {

    // Get the cacheability of the region
    Status = gDS->GetMemorySpaceDescriptor ((UINTN)HostAddress, &GcdDescriptor);
    if (EFI_ERROR(Status)) {
      goto FreeMapInfo;
    }

    // If the mapped buffer is not an uncached buffer
    if ((GcdDescriptor.Attributes & (EFI_MEMORY_WB | EFI_MEMORY_WT)) != 0) {
      //
      // Operations of type MapOperationBusMasterCommonBuffer are only allowed
      // on uncached buffers.
      //
      if (Operation == MapOperationBusMasterCommonBuffer) {
        DEBUG ((EFI_D_ERROR,
          "%a: Operation type 'MapOperationBusMasterCommonBuffer' is only supportedn"
          "on memory regions that were allocated using DmaAllocateBuffer ()n",
          __FUNCTION__));
        Status = EFI_UNSUPPORTED;
        goto FreeMapInfo;
      }

      //
      // If the buffer does not fill entire cache lines we must double buffer into
      // uncached memory. Device (PCI) address becomes uncached page.
      //
      Map->DoubleBuffer  = TRUE;
      Status = DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (*NumberOfBytes), &Buffer);
      if (EFI_ERROR (Status)) {
        goto FreeMapInfo;
      }

      if (Operation == MapOperationBusMasterRead) {
        CopyMem (Buffer, HostAddress, *NumberOfBytes);
      }

      *DeviceAddress = HostToDeviceAddress (ConvertToPhysicalAddress (Buffer));
      Map->BufferAddress = Buffer;
    } else {
      Map->DoubleBuffer  = FALSE;
    }
  } else {
    Map->DoubleBuffer  = FALSE;

    DEBUG_CODE_BEGIN ();

    //
    // The operation type check above only executes if the buffer happens to be
    // misaligned with respect to CWG, but even if it is aligned, we should not
    // allow arbitrary buffers to be used for creating consistent mappings.
    // So duplicate the check here when running in DEBUG mode, just to assert
    // that we are not trying to create a consistent mapping for cached memory.
    //
    Status = gDS->GetMemorySpaceDescriptor ((UINTN)HostAddress, &GcdDescriptor);
    ASSERT_EFI_ERROR(Status);

    ASSERT (Operation != MapOperationBusMasterCommonBuffer ||
            (GcdDescriptor.Attributes & (EFI_MEMORY_WB | EFI_MEMORY_WT)) == 0);

    DEBUG_CODE_END ();

    // Flush the Data Cache (should not have any effect if the memory region is uncached)
    mCpu->FlushDataCache (mCpu, (UINTN)HostAddress, *NumberOfBytes,
            EfiCpuFlushTypeWriteBackInvalidate);
  }

  Map->HostAddress   = (UINTN)HostAddress;
  Map->NumberOfBytes = *NumberOfBytes;
  Map->Operation     = Operation;

  *Mapping = Map;

  return EFI_SUCCESS;

FreeMapInfo:
  FreePool (Map);

  return Status;
}
VOID
Flash_Start_OS (
  )
{
    UINT32              Index = 0;
    UINTN               FDTConfigTable = 0;
    EFI_STATUS Status;
    ESL_LINUX LinuxKernel = (ESL_LINUX)(0x80000); 

    if (!PcdGet32(PcdIsMPBoot))
    {
        for (Index = 0; Index < gST->NumberOfTableEntries; Index ++) 
        {
            if (CompareGuid (&gFdtTableGuid, &(gST->ConfigurationTable[Index].VendorGuid)))
            {
                FDTConfigTable = (UINTN)gST->ConfigurationTable[Index].VendorTable;
                DEBUG ((EFI_D_ERROR, "FDTConfigTable Address: 0x%lxn",FDTConfigTable));     
                break;
            }
        }
        gBS->CopyMem((void *)0x6000000,(void *)FDTConfigTable,0x100000);
        MicroSecondDelay(20000);
        
        gBS->CopyMem((void *)LinuxKernel,(void *)0x90100000,0x1F00000);
        MicroSecondDelay(200000);
        
        gBS->CopyMem((void *)0x7000000,(void *)0x92000000,0x4000000);
        MicroSecondDelay(200000);

        DEBUG((EFI_D_ERROR,"Update FDTn"));
        Status = EFIFdtUpdate(0x06000000);
        if(EFI_ERROR(Status))
        {
            DEBUG((EFI_D_ERROR,"EFIFdtUpdate ERRORn"));
            goto Exit;
        }
    }
    else
    {
        Status = LzmaDecompressKernel (LinuxKernel);
        if(EFI_ERROR(Status))
        {
            goto Exit;
        }

        gBS->CopyMem((void *)0x6000000, (void *)0xA47C0000, 0x20000);
        MicroSecondDelay(20000);

        gBS->CopyMem((void *)0x7000000, (void *)0xA4000000, 0x7C0000);
        MicroSecondDelay(200000);
    }

    Status = ShutdownUefiBootServices ();
    if(EFI_ERROR(Status)) 
    {
        DEBUG((EFI_D_ERROR,"ERROR: Can not shutdown UEFI boot services. Status=0x%Xn", Status));
        goto Exit;
    }

    //
    // Switch off interrupts, caches, mmu, etc
    //
    Status = PreparePlatformHardware ();
    ASSERT_EFI_ERROR(Status);

    LinuxKernel (0x06000000,0,0,0);
    // Kernel should never exit
    // After Life services are not provided
    ASSERT(FALSE);

Exit:
    // Only be here if we fail to start Linux
    Print (L"ERROR  : Can not start the kernel. Status=0x%Xn", Status);
  
    // Free Runtimee Memory (kernel and FDT)
    return ;
}
/**
  Function for 'drivers' command.

  @param[in] ImageHandle  Handle to the Image (NULL if Internal).
  @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
**/
SHELL_STATUS
EFIAPI
ShellCommandRunDrivers (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS          Status;
  LIST_ENTRY          *Package;
  CHAR16              *ProblemParam;
  SHELL_STATUS        ShellStatus;
  CHAR8               *Language;
  CONST CHAR16        *Lang;
  EFI_HANDLE          *HandleList;
  EFI_HANDLE          *HandleWalker;
  UINTN               ChildCount;
  UINTN               DeviceCount;
  CHAR16              *Temp2;
  CONST CHAR16        *FullDriverName;
  CHAR16              *TruncatedDriverName;
  CHAR16              *FormatString;
  UINT32              DriverVersion;
  BOOLEAN             DriverConfig;
  BOOLEAN             DriverDiag;
  BOOLEAN             SfoFlag;

  ShellStatus         = SHELL_SUCCESS;
  Status              = EFI_SUCCESS;
  Language            = NULL;
  FormatString        = NULL;
  SfoFlag             = FALSE;

  //
  // initialize the shell lib (we must be in non-auto-init...)
  //
  Status = ShellInitialize();
  ASSERT_EFI_ERROR(Status);

  Status = CommandInit();
  ASSERT_EFI_ERROR(Status);

  //
  // parse the command line
  //
  Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
  if (EFI_ERROR(Status)) {
    if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"drivers", ProblemParam);  
      FreePool(ProblemParam);
      ShellStatus = SHELL_INVALID_PARAMETER;
    } else {
      ASSERT(FALSE);
    }
  } else {
    if (ShellCommandLineGetCount(Package) > 1) {
      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"drivers");  
      ShellStatus = SHELL_INVALID_PARAMETER;
    } else {
      if (ShellCommandLineGetFlag(Package, L"-l")){
        Lang = ShellCommandLineGetValue(Package, L"-l");
        if (Lang != NULL) {
          Language = AllocateZeroPool(StrSize(Lang));
          AsciiSPrint(Language, StrSize(Lang), "%S", Lang);
        } else {
          ASSERT(Language == NULL);
          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"drivers", L"-l");  
          ShellCommandLineFreeVarList (Package);
          return (SHELL_INVALID_PARAMETER);
        }
      }

      if (ShellCommandLineGetFlag (Package, L"-sfo")) {
        SfoFlag = TRUE;
        FormatString = HiiGetString (gShellDriver1HiiHandle, STRING_TOKEN (STR_DRIVERS_ITEM_LINE_SFO), Language);
        //
        // print the SFO header
        //
        ShellPrintHiiEx (
          -1,
          -1,
          Language,
          STRING_TOKEN (STR_GEN_SFO_HEADER),
          gShellDriver1HiiHandle,
          L"drivers");
      } else {
        FormatString = HiiGetString (gShellDriver1HiiHandle, STRING_TOKEN (STR_DRIVERS_ITEM_LINE), Language);
        //
        // print the header row
        //
        ShellPrintHiiEx(
          -1,
          -1,
          Language,
          STRING_TOKEN (STR_DRIVERS_HEADER_LINES),
          gShellDriver1HiiHandle);
      }

      HandleList = GetHandleListByProtocol(&gEfiDriverBindingProtocolGuid);
      for (HandleWalker = HandleList ; HandleWalker != NULL && *HandleWalker != NULL ; HandleWalker++){
        ChildCount     = 0;
        DeviceCount    = 0;
        Status         = ParseHandleDatabaseForChildDevices (*HandleWalker, &ChildCount , NULL);
        Status         = PARSE_HANDLE_DATABASE_DEVICES      (*HandleWalker, &DeviceCount, NULL);
        Temp2          = GetDevicePathTextForHandle(*HandleWalker);
        DriverVersion  = ReturnDriverVersion(*HandleWalker);
        DriverConfig   = ReturnDriverConfig(*HandleWalker);
        DriverDiag     = ReturnDriverDiag  (*HandleWalker);
        FullDriverName = GetStringNameFromHandle(*HandleWalker, Language);

        TruncatedDriverName = NULL;
        if (!SfoFlag && (FullDriverName != NULL)) {
          TruncatedDriverName = AllocateZeroPool ((MAX_LEN_DRIVER_NAME + 1) * sizeof (CHAR16));
          StrnCpyS (TruncatedDriverName, MAX_LEN_DRIVER_NAME + 1, FullDriverName, MAX_LEN_DRIVER_NAME);
        }

        ShellPrintEx(
          -1,
          -1,
          FormatString,
          ConvertHandleToHandleIndex(*HandleWalker),
          DriverVersion,
          ChildCount > 0?L'B':(DeviceCount > 0?L'D':L'?'),
          DriverConfig?L'Y':L'N',
          DriverDiag?L'Y':L'N',
          DeviceCount,
          ChildCount,
          SfoFlag?FullDriverName:TruncatedDriverName,
          Temp2==NULL?L"":Temp2
         );
        if (TruncatedDriverName != NULL) {
          FreePool (TruncatedDriverName);
        }
        if (Temp2 != NULL) {
          FreePool(Temp2);
        }
        
        if (ShellGetExecutionBreakFlag ()) {
          ShellStatus = SHELL_ABORTED;
          break;
        }
      }
    }
    SHELL_FREE_NON_NULL(Language);
    ShellCommandLineFreeVarList (Package);
    SHELL_FREE_NON_NULL(FormatString);
  }

  return (ShellStatus);
}
VOID
ESL_Start_OS (
  )
{
    EFI_STATUS Status;
    UINTN     Reg_Value;
    ESL_LINUX LinuxKernel = (ESL_LINUX)(0x80000); 

    if(!PcdGet32(PcdIsMPBoot))
    {
        DEBUG((EFI_D_ERROR,"Update FDTn"));
        Status = EFIFdtUpdate(0x06000000);
        if(EFI_ERROR(Status))
        {
            DEBUG((EFI_D_ERROR,"EFIFdtUpdate ERRORn"));
            goto Exit;
        }
    }
    DEBUG((EFI_D_ERROR, "[%a]:[%dL] Start to boot Linuxn", __FUNCTION__, __LINE__));

    SmmuConfigForLinux();

    ITSCONFIG();

    if(PcdGet32(PcdIsMPBoot))
    {
        *(volatile UINT32 *)(0x60016220)   = 0x7;
        *(volatile UINT32 *)(0x60016230)   = 0x40016260;
        *(volatile UINT32 *)(0x60016234)   = 0X0;
        *(volatile UINT32 *)(0x60016238)   = 0x60016260;
        *(volatile UINT32 *)(0x6001623C)   = 0x400;
        *(volatile UINT32 *)(0x60016240)   = 0x40016260;
        *(volatile UINT32 *)(0x60016244)   = 0x400;

        *(volatile UINT32 *)(0x40016220)   = 0x7;
        *(volatile UINT32 *)(0x40016230)   = 0x60016260;
        *(volatile UINT32 *)(0x40016234)   = 0X0;
        *(volatile UINT32 *)(0x40016238)   = 0x60016260;
        *(volatile UINT32 *)(0x4001623C)   = 0x400;
        *(volatile UINT32 *)(0x40016240)   = 0x40016260;
        *(volatile UINT32 *)(0x40016244)   = 0x400;

        *(volatile UINT32 *)(0x60016220 + S1_BASE)   = 0x7;
        *(volatile UINT32 *)(0x60016230 + S1_BASE)   = 0x40016260;
        *(volatile UINT32 *)(0x60016234 + S1_BASE)   = 0X0;
        *(volatile UINT32 *)(0x60016238 + S1_BASE)   = 0x60016260;
        *(volatile UINT32 *)(0x6001623C + S1_BASE)   = 0x0;
        *(volatile UINT32 *)(0x60016240 + S1_BASE)   = 0x40016260;
        *(volatile UINT32 *)(0x60016244 + S1_BASE)   = 0x400;

        *(volatile UINT32 *)(0x40016220 + S1_BASE)   = 0x7;
        *(volatile UINT32 *)(0x40016230 + S1_BASE)   = 0x60016260;
        *(volatile UINT32 *)(0x40016234 + S1_BASE)   = 0X0;
        *(volatile UINT32 *)(0x40016238 + S1_BASE)   = 0x60016260;
        *(volatile UINT32 *)(0x4001623C + S1_BASE)   = 0x400;
        *(volatile UINT32 *)(0x40016240 + S1_BASE)   = 0x40016260;
        *(volatile UINT32 *)(0x40016244 + S1_BASE)   = 0x0;
    }
    
    Status = ShutdownUefiBootServices ();
    if(EFI_ERROR(Status)) 
    {
        DEBUG((EFI_D_ERROR,"ERROR: Can not shutdown UEFI boot services. Status=0x%Xn", Status));
        goto Exit;
    }

    //
    // Switch off interrupts, caches, mmu, etc
    //
    Status = PreparePlatformHardware ();
    ASSERT_EFI_ERROR(Status);

    *(volatile UINT32*)0xFFF8 = 0x0;
    *(volatile UINT32*)0xFFFC = 0x0;
    asm("DSB SY");
    asm("ISB");

    if (!PcdGet64 (PcdTrustedFirmwareEnable))
    {
        StartupAp();
    }

    Reg_Value = asm_read_reg();

    DEBUG((EFI_D_ERROR,"CPUECTLR_EL1 = 0x%llxn",Reg_Value));

    MN_CONFIG ();

    DEBUG((EFI_D_ERROR, "[%a]:[%dL] Start to jump Linux kerneln", __FUNCTION__, __LINE__));

    LinuxKernel (0x06000000,0,0,0);
    
    // Kernel should never exit
    // After Life services are not provided
    ASSERT(FALSE);

Exit:
    // Only be here if we fail to start Linux
    Print (L"ERROR  : Can not start the kernel. Status=0x%Xn", Status);

    // Free Runtimee Memory (kernel and FDT)
    return ;
}
/**
  Function for 'tftp' command.

  @param[in] ImageHandle  Handle to the Image (NULL if Internal).
  @param[in] SystemTable  Pointer to the System Table (NULL if Internal).

  @return  SHELL_SUCCESS            The 'tftp' command completed successfully.
  @return  SHELL_ABORTED            The Shell Library initialization failed.
  @return  SHELL_INVALID_PARAMETER  At least one of the command's arguments is
                                    not valid.
  @return  SHELL_OUT_OF_RESOURCES   A memory allocation failed.
  @return  SHELL_NOT_FOUND          Network Interface Card not found or server
                                    error or file error.

**/
SHELL_STATUS
EFIAPI
ShellCommandRunTftp (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  SHELL_STATUS            ShellStatus;
  EFI_STATUS              Status;
  LIST_ENTRY              *CheckPackage;
  CHAR16                  *ProblemParam;
  UINTN                   ParamCount;
  CONST CHAR16            *UserNicName;
  BOOLEAN                 NicFound;
  CONST CHAR16            *ValueStr;
  CONST CHAR16            *RemoteFilePath;
  CHAR8                   *AsciiRemoteFilePath;
  UINTN                   FilePathSize;
  CONST CHAR16            *Walker;
  CONST CHAR16            *LocalFilePath;
  EFI_MTFTP4_CONFIG_DATA  Mtftp4ConfigData;
  EFI_HANDLE              *Handles;
  UINTN                   HandleCount;
  UINTN                   NicNumber;
  CHAR16                  NicName[IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH];
  EFI_HANDLE              ControllerHandle;
  EFI_HANDLE              Mtftp4ChildHandle;
  EFI_MTFTP4_PROTOCOL     *Mtftp4;
  UINTN                   FileSize;
  VOID                    *Data;
  SHELL_FILE_HANDLE       FileHandle;
  UINT16                  BlockSize;

  ShellStatus         = SHELL_INVALID_PARAMETER;
  ProblemParam        = NULL;
  NicFound            = FALSE;
  AsciiRemoteFilePath = NULL;
  Handles             = NULL;
  FileSize            = 0;
  BlockSize           = MTFTP_DEFAULT_BLKSIZE;

  //
  // Initialize the Shell library (we must be in non-auto-init...)
  //
  Status = ShellInitialize ();
  if (EFI_ERROR (Status)) {
    ASSERT_EFI_ERROR (Status);
    return SHELL_ABORTED;
  }

  //
  // Parse the command line.
  //
  Status = ShellCommandLineParse (ParamList, &CheckPackage, &ProblemParam, TRUE);
  if (EFI_ERROR (Status)) {
    if ((Status == EFI_VOLUME_CORRUPTED) &&
        (ProblemParam != NULL) ) {
      ShellPrintHiiEx (
        -1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellTftpHiiHandle,
        L"tftp", ProblemParam
        );
      FreePool (ProblemParam);
    } else {
      ASSERT (FALSE);
    }
    goto Error;
  }

  //
  // Check the number of parameters
  //
  ParamCount = ShellCommandLineGetCount (CheckPackage);
  if (ParamCount > 4) {
    ShellPrintHiiEx (
      -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY),
      gShellTftpHiiHandle, L"tftp"
      );
    goto Error;
  }
  if (ParamCount < 3) {
    ShellPrintHiiEx (
      -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW),
      gShellTftpHiiHandle, L"tftp"
      );
    goto Error;
  }

  Mtftp4ConfigData = DefaultMtftp4ConfigData;

  //
  // Check the host IPv4 address
  //
  ValueStr = ShellCommandLineGetRawValue (CheckPackage, 1);
  Status = NetLibStrToIp4 (ValueStr, &Mtftp4ConfigData.ServerIp);
  if (EFI_ERROR (Status)) {
    ShellPrintHiiEx (
      -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
      gShellTftpHiiHandle, L"tftp", ValueStr
    );
    goto Error;
  }

  RemoteFilePath = ShellCommandLineGetRawValue (CheckPackage, 2);
  ASSERT(RemoteFilePath != NULL);
  FilePathSize = StrLen (RemoteFilePath) + 1;
  AsciiRemoteFilePath = AllocatePool (FilePathSize);
  if (AsciiRemoteFilePath == NULL) {
    ShellStatus = SHELL_OUT_OF_RESOURCES;
    goto Error;
  }
  UnicodeStrToAsciiStrS (RemoteFilePath, AsciiRemoteFilePath, FilePathSize);

  if (ParamCount == 4) {
    LocalFilePath = ShellCommandLineGetRawValue (CheckPackage, 3);
  } else {
    Walker = RemoteFilePath + StrLen (RemoteFilePath);
    while ((--Walker) >= RemoteFilePath) {
      if ((*Walker == L'\') ||
          (*Walker == L'/' )    ) {
        break;
      }
    }
    LocalFilePath = Walker + 1;
  }

  //
  // Get the name of the Network Interface Card to be used if any.
  //
  UserNicName = ShellCommandLineGetValue (CheckPackage, L"-i");

  ValueStr = ShellCommandLineGetValue (CheckPackage, L"-l");
  if (ValueStr != NULL) {
    if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.LocalPort)) {
      goto Error;
    }
  }

  ValueStr = ShellCommandLineGetValue (CheckPackage, L"-r");
  if (ValueStr != NULL) {
    if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.InitialServerPort)) {
      goto Error;
    }
  }

  ValueStr = ShellCommandLineGetValue (CheckPackage, L"-c");
  if (ValueStr != NULL) {
    if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.TryCount)) {
      goto Error;
    }
  }

  ValueStr = ShellCommandLineGetValue (CheckPackage, L"-t");
  if (ValueStr != NULL) {
    if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.TimeoutValue)) {
      goto Error;
    }
    if (Mtftp4ConfigData.TimeoutValue == 0) {
      ShellPrintHiiEx (
        -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
        gShellTftpHiiHandle, L"tftp", ValueStr
      );
      goto Error;
    }
  }

  ValueStr = ShellCommandLineGetValue (CheckPackage, L"-s");
  if (ValueStr != NULL) {
    if (!StringToUint16 (ValueStr, &BlockSize)) {
      goto Error;
    }
    if (BlockSize < MTFTP_MIN_BLKSIZE || BlockSize > MTFTP_MAX_BLKSIZE) {
      ShellPrintHiiEx (
        -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
        gShellTftpHiiHandle, L"tftp", ValueStr
      );
      goto Error;
    }
  }

  //
  // Locate all MTFTP4 Service Binding protocols
  //
  ShellStatus = SHELL_NOT_FOUND;
  Status = gBS->LocateHandleBuffer (
                 ByProtocol,
                 &gEfiManagedNetworkServiceBindingProtocolGuid,
                 NULL,
                 &HandleCount,
                 &Handles
                 );
  if (EFI_ERROR (Status) || (HandleCount == 0)) {
    ShellPrintHiiEx (
      -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NO_NIC),
      gShellTftpHiiHandle
    );
    goto Error;
  }

  for (NicNumber = 0;
       (NicNumber < HandleCount) && (ShellStatus != SHELL_SUCCESS);
       NicNumber++) {
    ControllerHandle = Handles[NicNumber];
    Data = NULL;

    Status = GetNicName (ControllerHandle, NicNumber, NicName);
    if (EFI_ERROR (Status)) {
      ShellPrintHiiEx (
        -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NIC_NAME),
        gShellTftpHiiHandle, NicNumber, Status
      );
      continue;
    }

    if (UserNicName != NULL) {
      if (StrCmp (NicName, UserNicName) != 0) {
        continue;
      }
      NicFound = TRUE;
    }

    Status = CreateServiceChildAndOpenProtocol (
               ControllerHandle,
               &gEfiMtftp4ServiceBindingProtocolGuid,
               &gEfiMtftp4ProtocolGuid,
               &Mtftp4ChildHandle,
               (VOID**)&Mtftp4
               );
    if (EFI_ERROR (Status)) {
      ShellPrintHiiEx (
        -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_OPEN_PROTOCOL),
        gShellTftpHiiHandle, NicName, Status
      );
      continue;
    }

    Status = Mtftp4->Configure (Mtftp4, &Mtftp4ConfigData);
    if (EFI_ERROR (Status)) {
      ShellPrintHiiEx (
        -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_CONFIGURE),
        gShellTftpHiiHandle, NicName, Status
      );
      goto NextHandle;
    }

    Status = GetFileSize (Mtftp4, AsciiRemoteFilePath, &FileSize);
    if (EFI_ERROR (Status)) {
      ShellPrintHiiEx (
        -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_FILE_SIZE),
        gShellTftpHiiHandle, RemoteFilePath, NicName, Status
      );
      goto NextHandle;
    }

    Status = DownloadFile (Mtftp4, RemoteFilePath, AsciiRemoteFilePath, FileSize, BlockSize, &Data);
    if (EFI_ERROR (Status)) {
      ShellPrintHiiEx (
        -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_DOWNLOAD),
        gShellTftpHiiHandle, RemoteFilePath, NicName, Status
      );
      goto NextHandle;
    }

    if (!EFI_ERROR (ShellFileExists (LocalFilePath))) {
      ShellDeleteFileByName (LocalFilePath);
    }

    Status = ShellOpenFileByName (
               LocalFilePath,
               &FileHandle,
               EFI_FILE_MODE_CREATE |
               EFI_FILE_MODE_WRITE  |
               EFI_FILE_MODE_READ,
               0
               );
    if (EFI_ERROR (Status)) {
      ShellPrintHiiEx (
        -1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL),
        gShellTftpHiiHandle, L"tftp", LocalFilePath
      );
      goto NextHandle;
    }

    Status = ShellWriteFile (FileHandle, &FileSize, Data);
    if (!EFI_ERROR (Status)) {
      ShellStatus = SHELL_SUCCESS;
    } else {
      ShellPrintHiiEx (
        -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_WRITE),
        gShellTftpHiiHandle, LocalFilePath, Status
      );
    }
    ShellCloseFile (&FileHandle);

    NextHandle:

    if (Data != NULL) {
      gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)Data, EFI_SIZE_TO_PAGES (FileSize));
    }

    CloseProtocolAndDestroyServiceChild (
      ControllerHandle,
      &gEfiMtftp4ServiceBindingProtocolGuid,
      &gEfiMtftp4ProtocolGuid,
      Mtftp4ChildHandle
      );
  }

  if ((UserNicName != NULL) && (!NicFound)) {
    ShellPrintHiiEx (
      -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NIC_NOT_FOUND),
      gShellTftpHiiHandle, UserNicName
    );
  }

  Error:

  ShellCommandLineFreeVarList (CheckPackage);
  if (AsciiRemoteFilePath != NULL) {
    FreePool (AsciiRemoteFilePath);
  }
  if (Handles != NULL) {
    FreePool (Handles);
  }

  return ShellStatus;
}
/**
  Function for 'attrib' command.

  @param[in] ImageHandle  Handle to the Image (NULL if Internal).
  @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
**/
SHELL_STATUS
EFIAPI
ShellCommandRunAttrib (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  UINT64              FileAttributesToAdd;
  UINT64              FileAttributesToRemove;
  EFI_STATUS          Status;
  LIST_ENTRY          *Package;
  CHAR16              *ProblemParam;
  SHELL_STATUS        ShellStatus;
  UINTN               ParamNumberCount;
  CONST CHAR16        *FileName;
  EFI_SHELL_FILE_INFO *ListOfFiles;
  EFI_SHELL_FILE_INFO *FileNode;
  EFI_FILE_INFO       *FileInfo;

  ListOfFiles   = NULL;
  ShellStatus   = SHELL_SUCCESS;
  ProblemParam  = NULL;

  //
  // initialize the shell lib (we must be in non-auto-init...)
  //
  Status = ShellInitialize();
  ASSERT_EFI_ERROR(Status);

  //
  // parse the command line
  //
  Status = ShellCommandLineParse (AttribParamList, &Package, &ProblemParam, TRUE);
  if (EFI_ERROR(Status)) {
    if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"attrib", ProblemParam);
      FreePool(ProblemParam);
      ShellStatus = SHELL_INVALID_PARAMETER;
    } else {
      ASSERT(FALSE);
    }
  } else {

    //
    // check for "-?"
    //
    if (ShellCommandLineGetFlag(Package, L"-?")) {
      ASSERT(FALSE);
    } else {
      FileAttributesToAdd = 0;
      FileAttributesToRemove = 0;

      //
      // apply or remove each flag
      //
      if (ShellCommandLineGetFlag(Package, L"+a")) {
        FileAttributesToAdd |= EFI_FILE_ARCHIVE;
      }
      if (ShellCommandLineGetFlag(Package, L"-a")) {
        FileAttributesToRemove |= EFI_FILE_ARCHIVE;
      }
      if (ShellCommandLineGetFlag(Package, L"+s")) {
        FileAttributesToAdd |= EFI_FILE_SYSTEM;
      }
      if (ShellCommandLineGetFlag(Package, L"-s")) {
        FileAttributesToRemove |= EFI_FILE_SYSTEM;
      }
      if (ShellCommandLineGetFlag(Package, L"+h")) {
        FileAttributesToAdd |= EFI_FILE_HIDDEN;
      }
      if (ShellCommandLineGetFlag(Package, L"-h")) {
        FileAttributesToRemove |= EFI_FILE_HIDDEN;
      }
      if (ShellCommandLineGetFlag(Package, L"+r")) {
        FileAttributesToAdd |= EFI_FILE_READ_ONLY;
      }
      if (ShellCommandLineGetFlag(Package, L"-r")) {
        FileAttributesToRemove |= EFI_FILE_READ_ONLY;
      }

      if (FileAttributesToRemove == 0 && FileAttributesToAdd == 0) {
        //
        // Do display as we have no attributes to change
        //
        for ( ParamNumberCount = 1
            ;
            ; ParamNumberCount++
           ){
          FileName = ShellCommandLineGetRawValue(Package, ParamNumberCount);
          // if we dont have anything left, move on...
          if (FileName == NULL && ParamNumberCount == 1) {
            FileName = (CHAR16*)AllFiles;
          } else if (FileName == NULL) {
            break;
          }
          ASSERT(ListOfFiles == NULL);
          Status = ShellOpenFileMetaArg((CHAR16*)FileName, EFI_FILE_MODE_READ, &ListOfFiles);
          if (EFI_ERROR(Status)) {
            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount));
            ShellStatus = SHELL_NOT_FOUND;
          } else {
            for (FileNode = (EFI_SHELL_FILE_INFO*)GetFirstNode(&ListOfFiles->Link)
              ;  !IsNull(&ListOfFiles->Link, &FileNode->Link)
              ;  FileNode = (EFI_SHELL_FILE_INFO*)GetNextNode(&ListOfFiles->Link, &FileNode->Link)
             ){
              ShellPrintHiiEx(
                -1,
                -1,
                NULL,
                STRING_TOKEN (STR_ATTRIB_OUTPUT_LINE),
                gShellLevel2HiiHandle,
                FileNode->Info->Attribute&EFI_FILE_DIRECTORY? L'D':L' ',
                FileNode->Info->Attribute&EFI_FILE_ARCHIVE?   L'A':L' ',
                FileNode->Info->Attribute&EFI_FILE_SYSTEM?    L'S':L' ',
                FileNode->Info->Attribute&EFI_FILE_HIDDEN?    L'H':L' ',
                FileNode->Info->Attribute&EFI_FILE_READ_ONLY? L'R':L' ',
                FileNode->FileName
               );

              if (ShellGetExecutionBreakFlag()) {
                  ShellStatus = SHELL_ABORTED;
                  break;
              }
            }
            Status = ShellCloseFileMetaArg(&ListOfFiles);
            ListOfFiles = NULL;
            if (EFI_ERROR(Status)) {
              ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_CLOSE_FAIL), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount));
              ShellStatus = SHELL_NOT_FOUND;
            }
          } // for loop for handling wildcard filenames
        } // for loop for printing out the info
      } else if ((FileAttributesToRemove & FileAttributesToAdd) != 0) {
        //
        // fail as we have conflcting params.
        //
        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel2HiiHandle, L"attrib");
        ShellStatus = SHELL_INVALID_PARAMETER;
      } else {
        //
        // enumerate through all the files/directories and apply the attributes
        //
        for ( ParamNumberCount = 1
            ;
            ; ParamNumberCount++
           ){
          FileName = ShellCommandLineGetRawValue(Package, ParamNumberCount);
          // if we dont have anything left, move on...
          if (FileName == NULL) {
            //
            // make sure we are not failing on the first one we do... if yes that's an error...
            //
            if (ParamNumberCount == 1) {
              ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"attrib");
              ShellStatus = SHELL_INVALID_PARAMETER;
            }
            break;
          }

          //
          // OpenFileByName / GetFileInfo / Change attributes / SetFileInfo / CloseFile / free memory
          // for each file or directory on the line.
          //

          //
          // Open the file(s)
          //
          ASSERT(ListOfFiles == NULL);
          Status = ShellOpenFileMetaArg((CHAR16*)FileName, EFI_FILE_MODE_READ, &ListOfFiles);
          if (EFI_ERROR(Status)) {
            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount));
            ShellStatus = SHELL_NOT_FOUND;
          } else {
            for (FileNode = (EFI_SHELL_FILE_INFO*)GetFirstNode(&ListOfFiles->Link)
              ;  !IsNull(&ListOfFiles->Link, &FileNode->Link)
              ;  FileNode = (EFI_SHELL_FILE_INFO*)GetNextNode(&ListOfFiles->Link, &FileNode->Link)
             ){
              //
              // skip the directory traversing stuff...
              //
              if (StrCmp(FileNode->FileName, L".") == 0 || StrCmp(FileNode->FileName, L"..") == 0) {
                continue;
              }

              FileInfo = gEfiShellProtocol->GetFileInfo(FileNode->Handle);

              //
              // if we are removing Read-Only we need to do that alone
              //
              if ((FileAttributesToRemove & EFI_FILE_READ_ONLY) == EFI_FILE_READ_ONLY) {
                FileInfo->Attribute &= ~EFI_FILE_READ_ONLY;
                //
                // SetFileInfo
                //
                Status = ShellSetFileInfo(FileNode->Handle, FileInfo);
                if (EFI_ERROR(Status)) {
                  ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_AD), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount));
                  ShellStatus = SHELL_ACCESS_DENIED;
                }
              }

              //
              // change the attribute
              //
              FileInfo->Attribute &= ~FileAttributesToRemove;
              FileInfo->Attribute |= FileAttributesToAdd;

              //
              // SetFileInfo
              //
              Status = ShellSetFileInfo(FileNode->Handle, FileInfo);
              if (EFI_ERROR(Status)) {;
                ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_AD), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount));
                ShellStatus = SHELL_ACCESS_DENIED;
              }

              SHELL_FREE_NON_NULL(FileInfo);
            }
            Status = ShellCloseFileMetaArg(&ListOfFiles);
            ListOfFiles = NULL;
            if (EFI_ERROR(Status)) {
              ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_CLOSE_FAIL), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount));
              ShellStatus = SHELL_NOT_FOUND;
            }
          } // for loop for handling wildcard filenames
        }
      }
    }
  }

  //
  // free the command line package
  //
  ShellCommandLineFreeVarList (Package);

  //
  // return the status
  //
  return (ShellStatus);
}
EFI_STATUS
BootOptionStart (
  IN BDS_LOAD_OPTION *BootOption
  )
{
  EFI_STATUS                            Status;
  EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL*   EfiDevicePathFromTextProtocol;
  UINT32                                LoaderType;
  ARM_BDS_LOADER_OPTIONAL_DATA*         OptionalData;
  ARM_BDS_LINUX_ARGUMENTS*              LinuxArguments;
  EFI_DEVICE_PATH_PROTOCOL*             FdtDevicePath;
  EFI_DEVICE_PATH_PROTOCOL*             DefaultFdtDevicePath;
  UINTN                                 FdtDevicePathSize;
  UINTN                                 CmdLineSize;
  UINTN                                 InitrdSize;
  EFI_DEVICE_PATH*                      Initrd;
  UINT16                                LoadOptionIndexSize;

  if (IS_ARM_BDS_BOOTENTRY (BootOption)) {
    Status = EFI_UNSUPPORTED;
    OptionalData = BootOption->OptionalData;
    LoaderType = ReadUnaligned32 ((CONST UINT32*)&OptionalData->Header.LoaderType);

    if (LoaderType == BDS_LOADER_EFI_APPLICATION) {
      // Need to connect every drivers to ensure no dependencies are missing for the application
      BdsConnectAllDrivers();

      Status = BdsStartEfiApplication (mImageHandle, BootOption->FilePathList, 0, NULL);
    } else if (LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) {
      LinuxArguments = &(OptionalData->Arguments.LinuxArguments);
      CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize);
      InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize);

      if (InitrdSize > 0) {
        Initrd = GetAlignedDevicePath ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize));
      } else {
        Initrd = NULL;
      }

      Status = BdsBootLinuxAtag (BootOption->FilePathList,
                                 Initrd, // Initrd
                                 (CHAR8*)(LinuxArguments + 1)); // CmdLine
    } else if (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT) {
      LinuxArguments = &(OptionalData->Arguments.LinuxArguments);
      CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize);
      InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize);

      if (InitrdSize > 0) {
        Initrd = GetAlignedDevicePath ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize));
      } else {
        Initrd = NULL;
      }

      // Get the default FDT device path
      Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);
      ASSERT_EFI_ERROR(Status);
      DefaultFdtDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdFdtDevicePath));

      // Get the FDT device path
      FdtDevicePathSize = GetDevicePathSize (DefaultFdtDevicePath);
      Status = GetEnvironmentVariable ((CHAR16 *)L"Fdt", &gArmGlobalVariableGuid,
                 DefaultFdtDevicePath, &FdtDevicePathSize, (VOID **)&FdtDevicePath);
      ASSERT_EFI_ERROR(Status);

      Status = BdsBootLinuxFdt (BootOption->FilePathList,
                                Initrd, // Initrd
                                (CHAR8*)(LinuxArguments + 1),
                                FdtDevicePath);

      FreePool (FdtDevicePath);
    }
  } else {
    // Set BootCurrent variable
    LoadOptionIndexSize = sizeof(UINT16);
    gRT->SetVariable (L"BootCurrent", &gEfiGlobalVariableGuid,
              EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
              LoadOptionIndexSize, &(BootOption->LoadOptionIndex));

    Status = BdsStartEfiApplication (mImageHandle, BootOption->FilePathList, BootOption->OptionalDataSize, BootOption->OptionalData);

    // Clear BootCurrent variable
    LoadOptionIndexSize = sizeof(UINT16);
    gRT->SetVariable (L"BootCurrent", &gEfiGlobalVariableGuid,
              EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
              0, NULL);
  }

  return Status;
}
/**
  Main entry point.

  @param[in] ImageHandle    The firmware allocated handle for the EFI image.  
  @param[in] SystemTable    A pointer to the EFI System Table.
  
  @retval EFI_SUCCESS       Successfully initialized.

**/
EFI_STATUS
EFIAPI
FvbInitialize (
  IN EFI_HANDLE         ImageHandle,
  IN EFI_SYSTEM_TABLE   *SystemTable
  )
{
  EFI_STATUS                          Status;
  VOID                                *Ptr;
  VOID                                *SubPtr;
  BOOLEAN                             Initialize;
  EFI_HANDLE                          Handle;
  EFI_PHYSICAL_ADDRESS                Address;

  DEBUG ((EFI_D_INFO, "EMU Variable FVB Startedn"));

  //
  // Verify that the PCD's are set correctly.
  //
  if (
       (PcdGet32 (PcdVariableStoreSize) +
        PcdGet32 (PcdFlashNvStorageFtwWorkingSize)
       ) >
       EMU_FVB_BLOCK_SIZE
     ) {
    DEBUG ((EFI_D_ERROR, "EMU Variable invalid PCD sizesn"));
    return EFI_INVALID_PARAMETER;
  }

  //
  // By default we will initialize the FV contents.  But, if
  // PcdEmuVariableNvStoreReserved is non-zero, then we will
  // use this location for our buffer.
  //
  // If this location does not have a proper FV header, then
  // we will initialize it.
  //
  Initialize = TRUE;
  if (PcdGet64 (PcdEmuVariableNvStoreReserved) != 0) {
    Ptr = (VOID*)(UINTN) PcdGet64 (PcdEmuVariableNvStoreReserved);
    DEBUG ((
      EFI_D_INFO,
      "EMU Variable FVB: Using pre-reserved block at %pn",
      Ptr
      ));
    Status = ValidateFvHeader (Ptr);
    if (!EFI_ERROR (Status)) {
      DEBUG ((EFI_D_INFO, "EMU Variable FVB: Found valid pre-existing FVn"));
      Initialize = FALSE;
    }
  } else {
    Ptr = AllocateAlignedRuntimePages (
            EFI_SIZE_TO_PAGES (EMU_FVB_SIZE),
            SIZE_64KB
            );
  }

  mEmuVarsFvb.BufferPtr = Ptr;

  //
  // Initialize the main FV header and variable store header
  //
  if (Initialize) {
    SetMem (Ptr, EMU_FVB_SIZE, ERASED_UINT8);
    InitializeFvAndVariableStoreHeaders (Ptr);
  }
  PcdSet32 (PcdFlashNvStorageVariableBase, (UINT32)(UINTN) Ptr);

  //
  // Initialize the Fault Tolerant Write data area
  //
  SubPtr = (VOID*) ((UINT8*) Ptr + PcdGet32 (PcdVariableStoreSize));
  if (Initialize) {
    InitializeFtwState (SubPtr);
  }
  PcdSet32 (PcdFlashNvStorageFtwWorkingBase, (UINT32)(UINTN) SubPtr);

  //
  // Initialize the Fault Tolerant Write spare block
  //
  SubPtr = (VOID*) ((UINT8*) Ptr + EMU_FVB_BLOCK_SIZE);
  PcdSet32 (PcdFlashNvStorageFtwSpareBase, (UINT32)(UINTN) SubPtr);

  //
  // Setup FVB device path
  //
  Address = (EFI_PHYSICAL_ADDRESS)(UINTN) Ptr;
  mEmuVarsFvb.DevicePath.MemMapDevPath.StartingAddress = Address;
  mEmuVarsFvb.DevicePath.MemMapDevPath.EndingAddress = Address + EMU_FVB_SIZE - 1;

  //
  // Install the protocols
  //
  DEBUG ((EFI_D_INFO, "Installing FVB for EMU Variable supportn"));
  Handle = 0;
  Status = gBS->InstallMultipleProtocolInterfaces (
                  &Handle,
                  &gEfiFirmwareVolumeBlockProtocolGuid,
                  &mEmuVarsFvb.FwVolBlockInstance,
                  &gEfiDevicePathProtocolGuid,
                  &mEmuVarsFvb.DevicePath,
                  NULL
                  );
  ASSERT_EFI_ERROR (Status);

  //
  // Register for the virtual address change event
  //
  Status = gBS->CreateEventEx (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  FvbVirtualAddressChangeEvent,
                  NULL,
                  &gEfiEventVirtualAddressChangeGuid,
                  &mEmuVarsFvbAddrChangeEvent
                  );
  ASSERT_EFI_ERROR (Status);

  return EFI_SUCCESS;
}
/**
  Do platform specific PCI Device check and add them to
  ConOut, ConIn, ErrOut.

  @param[in]  Handle - Handle of PCI device instance
  @param[in]  PciIo - PCI IO protocol instance
  @param[in]  Pci - PCI Header register block

  @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
  @retval EFI_STATUS - PCI Device check or Console variable update fail.

**/
EFI_STATUS
EFIAPI
DetectAndPreparePlatformPciDevicePath (
  IN EFI_HANDLE           Handle,
  IN EFI_PCI_IO_PROTOCOL  *PciIo,
  IN PCI_TYPE00           *Pci
  )
{
  EFI_STATUS                Status;

  Status = PciIo->Attributes (
    PciIo,
    EfiPciIoAttributeOperationEnable,
    EFI_PCI_DEVICE_ENABLE,
    NULL
    );
  ASSERT_EFI_ERROR (Status);

  if (!mDetectVgaOnly) {
    //
    // Here we decide whether it is LPC Bridge
    //
    if ((IS_PCI_LPC (Pci)) ||
        ((IS_PCI_ISA_PDECODE (Pci)) &&
         (Pci->Hdr.VendorId == 0x8086) &&
         (Pci->Hdr.DeviceId == 0x7000)
        )
       ) {
      //
      // Add IsaKeyboard to ConIn,
      // add IsaSerial to ConOut, ConIn, ErrOut
      //
      DEBUG ((EFI_D_INFO, "Found LPC Bridge devicen"));
      PrepareLpcBridgeDevicePath (Handle);
      return EFI_SUCCESS;
    }
    //
    // Here we decide which Serial device to enable in PCI bus
    //
    if (IS_PCI_16550SERIAL (Pci)) {
      //
      // Add them to ConOut, ConIn, ErrOut.
      //
      DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL devicen"));
      PreparePciSerialDevicePath (Handle);
      return EFI_SUCCESS;
    }
  }

  //
  // Here we decide which VGA device to enable in PCI bus
  //
  if (IS_PCI_VGA (Pci)) {
    //
    // Add them to ConOut.
    //
    DEBUG ((EFI_D_INFO, "Found PCI VGA devicen"));
    PreparePciVgaDevicePath (Handle);
    return EFI_SUCCESS;
  }

  return Status;
}
/**
  The user Entry Point for English module.
 
  This function initializes unicode character mapping and then installs Unicode
  Collation & Unicode Collation 2 Protocols based on the feature flags.  

  @param  ImageHandle    The firmware allocated handle for the EFI image.  
  @param  SystemTable    A pointer to the EFI System Table.
  
  @retval EFI_SUCCESS    The entry point is executed successfully.
  @retval other          Some error occurs when executing this entry point.

**/
EFI_STATUS
EFIAPI
InitializeUnicodeCollationEng (
  IN EFI_HANDLE       ImageHandle,
  IN EFI_SYSTEM_TABLE *SystemTable
  )
{
  EFI_STATUS  Status;
  UINTN       Index;
  UINTN       Index2;

  //
  // Initialize mapping tables for the supported languages
  //
  for (Index = 0; Index < MAP_TABLE_SIZE; Index++) {
    mEngUpperMap[Index] = (CHAR8) Index;
    mEngLowerMap[Index] = (CHAR8) Index;
    mEngInfoMap[Index]  = 0;

    if ((Index >= 'a' && Index <= 'z') || (Index >= 0xe0 && Index <= 0xf6) || (Index >= 0xf8 && Index <= 0xfe)) {

      Index2                = Index - 0x20;
      mEngUpperMap[Index]   = (CHAR8) Index2;
      mEngLowerMap[Index2]  = (CHAR8) Index;

      mEngInfoMap[Index] |= CHAR_FAT_VALID;
      mEngInfoMap[Index2] |= CHAR_FAT_VALID;
    }
  }

  for (Index = 0; mOtherChars[Index] != 0; Index++) {
    Index2 = mOtherChars[Index];
    mEngInfoMap[Index2] |= CHAR_FAT_VALID;
  }

  if (FeaturePcdGet (PcdUnicodeCollation2Support)) {
    if (FeaturePcdGet (PcdUnicodeCollationSupport)) {
      Status = gBS->InstallMultipleProtocolInterfaces (
                      &mHandle,
                      &gEfiUnicodeCollationProtocolGuid,
                      &UnicodeEng,
                      &gEfiUnicodeCollation2ProtocolGuid,
                      &Unicode2Eng,
                      NULL
                      );
      ASSERT_EFI_ERROR (Status);
    } else {
      Status = gBS->InstallMultipleProtocolInterfaces (
                      &mHandle,
                      &gEfiUnicodeCollation2ProtocolGuid,
                      &Unicode2Eng,
                      NULL
                      );
      ASSERT_EFI_ERROR (Status);
    }
  } else {
    if (FeaturePcdGet (PcdUnicodeCollationSupport)) {
      Status = gBS->InstallMultipleProtocolInterfaces (
                      &mHandle,
                      &gEfiUnicodeCollationProtocolGuid,
                      &UnicodeEng,
                      NULL
                      );
      ASSERT_EFI_ERROR (Status);
    } else {
      //
      // This module must support to produce at least one of Unicode Collation Protocol
      // and Unicode Collation 2 Protocol.
      //
      ASSERT (FALSE);
      Status = EFI_UNSUPPORTED;
    }
  }

  return Status;
}
/**
  Measure FV image.
  Add it into the measured FV list after the FV is measured successfully.

  @param[in]  FvBase            Base address of FV image.
  @param[in]  FvLength          Length of FV image.

  @retval EFI_SUCCESS           Fv image is measured successfully
                                or it has been already measured.
  @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
  @retval EFI_DEVICE_ERROR      The command was unsuccessful.

**/
EFI_STATUS
EFIAPI
MeasureFvImage (
    IN EFI_PHYSICAL_ADDRESS           FvBase,
    IN UINT64                         FvLength
)
{
    UINT32                            Index;
    EFI_STATUS                        Status;
    EFI_PLATFORM_FIRMWARE_BLOB        FvBlob;
    TCG_PCR_EVENT_HDR                 TcgEventHdr;
    TIS_TPM_HANDLE                    TpmHandle;

    TpmHandle = (TIS_TPM_HANDLE) (UINTN) TPM_BASE_ADDRESS;

    //
    // Check if it is in Excluded FV list
    //
    if (mMeasurementExcludedFvPpi != NULL) {
        for (Index = 0; Index < mMeasurementExcludedFvPpi->Count; Index ++) {
            if (mMeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase) {
                DEBUG ((DEBUG_INFO, "The FV which is excluded by TcgPei starts at: 0x%xn", FvBase));
                DEBUG ((DEBUG_INFO, "The FV which is excluded by TcgPei has the size: 0x%xn", FvLength));
                return EFI_SUCCESS;
            }
        }
    }

    //
    // Check whether FV is in the measured FV list.
    //
    for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) {
        if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase) {
            return EFI_SUCCESS;
        }
    }

    //
    // Measure and record the FV to the TPM
    //
    FvBlob.BlobBase   = FvBase;
    FvBlob.BlobLength = FvLength;

    DEBUG ((DEBUG_INFO, "The FV which is measured by TcgPei starts at: 0x%xn", FvBlob.BlobBase));
    DEBUG ((DEBUG_INFO, "The FV which is measured by TcgPei has the size: 0x%xn", FvBlob.BlobLength));

    TcgEventHdr.PCRIndex = 0;
    TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
    TcgEventHdr.EventSize = sizeof (FvBlob);

    Status = HashLogExtendEvent (
                 (EFI_PEI_SERVICES **) GetPeiServicesTablePointer(),
                 (UINT8*) (UINTN) FvBlob.BlobBase,
                 (UINTN) FvBlob.BlobLength,
                 TpmHandle,
                 &TcgEventHdr,
                 (UINT8*) &FvBlob
             );
    ASSERT_EFI_ERROR (Status);

    //
    // Add new FV into the measured FV list.
    //
    ASSERT (mMeasuredBaseFvIndex < FixedPcdGet32 (PcdPeiCoreMaxFvSupported));
    if (mMeasuredBaseFvIndex < FixedPcdGet32 (PcdPeiCoreMaxFvSupported)) {
        mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobBase   = FvBase;
        mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobLength = FvLength;
        mMeasuredBaseFvIndex++;
    }

    return Status;
}
/**
  Function to write a line of text to a file.
  
  If the file is a Unicode file (with UNICODE file tag) then write the unicode 
  text.
  If the file is an ASCII file then write the ASCII text.
  If the size of file is zero (without file tag at the beginning) then write 
  ASCII text as default.

  @param[in]     Handle         FileHandle to write to.
  @param[in]     Buffer         Buffer to write, if NULL the function will
                                take no action and return EFI_SUCCESS.

  @retval  EFI_SUCCESS            The data was written.
                                  Buffer is NULL.
  @retval  EFI_INVALID_PARAMETER  Handle is NULL.
  @retval  EFI_OUT_OF_RESOURCES   Unable to allocate temporary space for ASCII 
                                  string due to out of resources.

  @sa FileHandleWrite
**/
EFI_STATUS
EFIAPI
FileHandleWriteLine(
  IN EFI_FILE_HANDLE Handle,
  IN CHAR16          *Buffer
  )
{
  EFI_STATUS  Status;
  CHAR16      CharBuffer;
  UINTN       Size;
  UINTN       Index;
  UINTN       CharSize;
  UINT64      FileSize;
  UINT64      OriginalFilePosition;
  BOOLEAN     Ascii;
  CHAR8       *AsciiBuffer;

  if (Buffer == NULL) {
    return (EFI_SUCCESS);
  }

  if (Handle == NULL) {
    return (EFI_INVALID_PARAMETER);
  }
  
  Ascii = FALSE;
  AsciiBuffer = NULL;
  
  Status = FileHandleGetPosition(Handle, &OriginalFilePosition);
  if (EFI_ERROR(Status)) {
    return Status;
  }
  
  Status = FileHandleSetPosition(Handle, 0);
  if (EFI_ERROR(Status)) {
    return Status;
  }
  
  Status = FileHandleGetSize(Handle, &FileSize);
  if (EFI_ERROR(Status)) {
    return Status;
  }
  
  if (FileSize == 0) {
    Ascii = TRUE;
  } else {
    CharSize = sizeof (CHAR16);
    Status = FileHandleRead (Handle, &CharSize, &CharBuffer);
    ASSERT_EFI_ERROR (Status);
    if (CharBuffer == gUnicodeFileTag) {
      Ascii = FALSE;
    } else {
      Ascii = TRUE;
    }
  }
  
  Status = FileHandleSetPosition(Handle, OriginalFilePosition);
  if (EFI_ERROR(Status)) {
    return Status;
  }
  
  if (Ascii) {
    Size = ( StrSize(Buffer) / sizeof(CHAR16) ) * sizeof(CHAR8);
    AsciiBuffer = (CHAR8 *)AllocateZeroPool(Size);
    if (AsciiBuffer == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }
    UnicodeStrToAsciiStrS (Buffer, AsciiBuffer, Size);
    for (Index = 0; Index < Size; Index++) {
      if ((AsciiBuffer[Index] & BIT7) != 0) {
        FreePool(AsciiBuffer);
        return EFI_INVALID_PARAMETER;
      }
    }
    
    Size = AsciiStrSize(AsciiBuffer) - sizeof(CHAR8);
    Status = FileHandleWrite(Handle, &Size, AsciiBuffer);
    if (EFI_ERROR(Status)) {
      FreePool (AsciiBuffer);
      return (Status);
    }
    Size = AsciiStrSize("rn") - sizeof(CHAR8);
    Status = FileHandleWrite(Handle, &Size, "rn");
  } else {
    if (OriginalFilePosition == 0) {
      Status = FileHandleSetPosition (Handle, sizeof(CHAR16));
      if (EFI_ERROR(Status)) {
        return Status;
      }
    }
    Size = StrSize(Buffer) - sizeof(CHAR16);
    Status = FileHandleWrite(Handle, &Size, Buffer);
    if (EFI_ERROR(Status)) {
      return (Status);
    }
    Size = StrSize(L"rn") - sizeof(CHAR16);
    Status = FileHandleWrite(Handle, &Size, L"rn");
  }
  
  if (AsciiBuffer != NULL) {
    FreePool (AsciiBuffer);
  }
  return Status;
}
/**
  Provides the controller-specific addresses required to access system memory
  from a DMA bus master. On SEV guest, the DMA operations must be performed on
  shared buffer hence we allocate a bounce buffer to map the HostAddress to a
  DeviceAddress. The Encryption attribute is removed from the DeviceAddress
  buffer.

  @param  This                  The protocol instance pointer.
  @param  Operation             Indicates if the bus master is going to read or
                                write to system memory.
  @param  HostAddress           The system memory address to map to the PCI
                                controller.
  @param  NumberOfBytes         On input the number of bytes to map. On output
                                the number of bytes that were mapped.
  @param  DeviceAddress         The resulting map address for the bus master
                                PCI controller to use to access the hosts
                                HostAddress.
  @param  Mapping               A resulting value to pass to Unmap().

  @retval EFI_SUCCESS           The range was mapped for the returned
                                NumberOfBytes.
  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common
                                buffer.
  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a
                                lack of resources.
  @retval EFI_DEVICE_ERROR      The system hardware could not map the requested
                                address.

**/
EFI_STATUS
EFIAPI
IoMmuMap (
  IN     EDKII_IOMMU_PROTOCOL                       *This,
  IN     EDKII_IOMMU_OPERATION                      Operation,
  IN     VOID                                       *HostAddress,
  IN OUT UINTN                                      *NumberOfBytes,
  OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
  OUT    VOID                                       **Mapping
  )
{
  EFI_STATUS                                        Status;
  MAP_INFO                                          *MapInfo;
  EFI_ALLOCATE_TYPE                                 AllocateType;
  COMMON_BUFFER_HEADER                              *CommonBufferHeader;
  VOID                                              *DecryptionSource;

  DEBUG ((
    DEBUG_VERBOSE,
    "%a: Operation=%a Host=0x%p Bytes=0x%Lxn",
    __FUNCTION__,
    ((Operation >= 0 &&
      Operation < ARRAY_SIZE (mBusMasterOperationName)) ?
     mBusMasterOperationName[Operation] :
     "Invalid"),
    HostAddress,
    (UINT64)((NumberOfBytes == NULL) ? 0 : *NumberOfBytes)
    ));

  if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL ||
      Mapping == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
  // called later.
  //
  MapInfo = AllocatePool (sizeof (MAP_INFO));
  if (MapInfo == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Failed;
  }

  //
  // Initialize the MAP_INFO structure, except the PlainTextAddress field
  //
  ZeroMem (&MapInfo->Link, sizeof MapInfo->Link);
  MapInfo->Signature         = MAP_INFO_SIG;
  MapInfo->Operation         = Operation;
  MapInfo->NumberOfBytes     = *NumberOfBytes;
  MapInfo->NumberOfPages     = EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes);
  MapInfo->CryptedAddress    = (UINTN)HostAddress;

  //
  // In the switch statement below, we point "MapInfo->PlainTextAddress" to the
  // plaintext buffer, according to Operation. We also set "DecryptionSource".
  //
  MapInfo->PlainTextAddress = MAX_ADDRESS;
  AllocateType = AllocateAnyPages;
  DecryptionSource = (VOID *)(UINTN)MapInfo->CryptedAddress;
  switch (Operation) {
  //
  // For BusMasterRead[64] and BusMasterWrite[64] operations, a bounce buffer
  // is necessary regardless of whether the original (crypted) buffer crosses
  // the 4GB limit or not -- we have to allocate a separate plaintext buffer.
  // The only variable is whether the plaintext buffer should be under 4GB.
  //
  case EdkiiIoMmuOperationBusMasterRead:
  case EdkiiIoMmuOperationBusMasterWrite:
    MapInfo->PlainTextAddress = BASE_4GB - 1;
    AllocateType = AllocateMaxAddress;
    //
    // fall through
    //
  case EdkiiIoMmuOperationBusMasterRead64:
  case EdkiiIoMmuOperationBusMasterWrite64:
    //
    // Allocate the implicit plaintext bounce buffer.
    //
    Status = gBS->AllocatePages (
                    AllocateType,
                    EfiBootServicesData,
                    MapInfo->NumberOfPages,
                    &MapInfo->PlainTextAddress
                    );
    if (EFI_ERROR (Status)) {
      goto FreeMapInfo;
    }
    break;

  //
  // For BusMasterCommonBuffer[64] operations, a to-be-plaintext buffer and a
  // stash buffer (for in-place decryption) have been allocated already, with
  // AllocateBuffer(). We only check whether the address of the to-be-plaintext
  // buffer is low enough for the requested operation.
  //
  case EdkiiIoMmuOperationBusMasterCommonBuffer:
    if ((MapInfo->CryptedAddress > BASE_4GB) ||
        (EFI_PAGES_TO_SIZE (MapInfo->NumberOfPages) >
         BASE_4GB - MapInfo->CryptedAddress)) {
      //
      // CommonBuffer operations cannot be remapped. If the common buffer is
      // above 4GB, then it is not possible to generate a mapping, so return an
      // error.
      //
      Status = EFI_UNSUPPORTED;
      goto FreeMapInfo;
    }
    //
    // fall through
    //
  case EdkiiIoMmuOperationBusMasterCommonBuffer64:
    //
    // The buffer at MapInfo->CryptedAddress comes from AllocateBuffer().
    //
    MapInfo->PlainTextAddress = MapInfo->CryptedAddress;
    //
    // Stash the crypted data.
    //
    CommonBufferHeader = (COMMON_BUFFER_HEADER *)(
                           (UINTN)MapInfo->CryptedAddress - EFI_PAGE_SIZE
                           );
    ASSERT (CommonBufferHeader->Signature == COMMON_BUFFER_SIG);
    CopyMem (
      CommonBufferHeader->StashBuffer,
      (VOID *)(UINTN)MapInfo->CryptedAddress,
      MapInfo->NumberOfBytes
      );
    //
    // Point "DecryptionSource" to the stash buffer so that we decrypt
    // it to the original location, after the switch statement.
    //
    DecryptionSource = CommonBufferHeader->StashBuffer;
    break;

  default:
    //
    // Operation is invalid
    //
    Status = EFI_INVALID_PARAMETER;
    goto FreeMapInfo;
  }

  //
  // Clear the memory encryption mask on the plaintext buffer.
  //
  Status = MemEncryptSevClearPageEncMask (
             0,
             MapInfo->PlainTextAddress,
             MapInfo->NumberOfPages,
             TRUE
             );
  ASSERT_EFI_ERROR (Status);
  if (EFI_ERROR (Status)) {
    CpuDeadLoop ();
  }

  //
  // If this is a read operation from the Bus Master's point of view,
  // then copy the contents of the real buffer into the mapped buffer
  // so the Bus Master can read the contents of the real buffer.
  //
  // For BusMasterCommonBuffer[64] operations, the CopyMem() below will decrypt
  // the original data (from the stash buffer) back to the original location.
  //
  if (Operation == EdkiiIoMmuOperationBusMasterRead ||
      Operation == EdkiiIoMmuOperationBusMasterRead64 ||
      Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||
      Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {
    CopyMem (
      (VOID *) (UINTN) MapInfo->PlainTextAddress,
      DecryptionSource,
      MapInfo->NumberOfBytes
      );
  }

  //
  // Track all MAP_INFO structures.
  //
  InsertHeadList (&mMapInfos, &MapInfo->Link);
  //
  // Populate output parameters.
  //
  *DeviceAddress = MapInfo->PlainTextAddress;
  *Mapping       = MapInfo;

  DEBUG ((
    DEBUG_VERBOSE,
    "%a: Mapping=0x%p Device(PlainText)=0x%Lx Crypted=0x%Lx Pages=0x%Lxn",
    __FUNCTION__,
    MapInfo,
    MapInfo->PlainTextAddress,
    MapInfo->CryptedAddress,
    (UINT64)MapInfo->NumberOfPages
    ));

  return EFI_SUCCESS;

FreeMapInfo:
  FreePool (MapInfo);

Failed:
  *NumberOfBytes = 0;
  return Status;
}
/**
  The RegisterKeystrokeNotify() function registers a function
  which will be called when a specified keystroke will occur.

  @param This                     A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.

  @param KeyData                  A pointer to a buffer that is filled in with
                                  the keystroke information for the key that was
                                  pressed.

  @param KeyNotificationFunction  Points to the function to be
                                  called when the key sequence
                                  is typed specified by KeyData.


  @param NotifyHandle             Points to the unique handle assigned to
                                  the registered notification.

  @retval EFI_SUCCESS           The device state was set
                                appropriately.

  @retval EFI_OUT_OF_RESOURCES  Unable to allocate necessary
                                data structures.

**/
EFI_STATUS
EFIAPI
EmuGopSimpleTextInExRegisterKeyNotify (
  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
  IN EFI_KEY_DATA                       *KeyData,
  IN EFI_KEY_NOTIFY_FUNCTION            KeyNotificationFunction,
  OUT EFI_HANDLE                        *NotifyHandle
  )
{
  EFI_STATUS                          Status;
  GOP_PRIVATE_DATA                    *Private;
  EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY     *CurrentNotify;
  LIST_ENTRY                          *Link;
  EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY     *NewNotify;

  if (KeyData == NULL || KeyNotificationFunction == NULL || NotifyHandle == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This);

  //
  // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
  //
  for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
    CurrentNotify = CR (
                      Link,
                      EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY,
                      NotifyEntry,
                      EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE
                      );
    if (GopPrivateIsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
      if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
        *NotifyHandle = CurrentNotify->NotifyHandle;
        return EFI_SUCCESS;
      }
    }
  }

  //
  // Allocate resource to save the notification function
  //
  NewNotify = (EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY *) AllocateZeroPool (sizeof (EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY));
  if (NewNotify == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  NewNotify->Signature         = EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE;
  NewNotify->KeyNotificationFn = KeyNotificationFunction;
  NewNotify->NotifyHandle      = (EFI_HANDLE) NewNotify;
  CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData));
  InsertTailList (&Private->NotifyList, &NewNotify->NotifyEntry);

  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  EmuGopRegisterKeyCallback,
                  NewNotify,
                  &NewNotify->Event
                  );
  ASSERT_EFI_ERROR (Status);


  *NotifyHandle = NewNotify->NotifyHandle;

  return EFI_SUCCESS;

}

    Представляю версию 64-разрядного дистрибутива Runtu LITE 22.04 х64, собранную на пакетной базе релиза Jammy Jellyfish 22.04 LTS. Сборка имеет базовый набор пользовательского ПО с возможностью установки на жёсткий диск.

    Основные элементы системы:

Менеджер дисплея               LightDM 1.30
Оконный менеджер              Openbox 3.6.1
Файловый менеджер            PCManFM 1.3.2
Панель рабочего стола        LXPanel 0.10.1
Менеджер сети                     NetworkManager 1.36.4 (pptp, l2tp, ssh, openvpn и vpnc)
Текстовый редактор             Geany 1.38
Браузер                                Firefox 99.0.1
Видеоплеер                          VLC 3.0.16
Аудиоплеер                          DeaDBeeF 1.8.8

Менеджер питания               xfce4-power-manager
Менеджер Bluetooth              Blueman
Звуковой сервер                  PulseAudio

Версия ядра:                       5.15.0-25-generic
Версия Xorg:                       2:21.1.3

     Минимальные системные требования:

RAM — 1024Mb
CPU — x64
HDD — 5Gb

Логин:    runtu
Пароль:  пустой

   Скриншоты рабочего окружения:

===========================

                   

                   

===========================

    Служебные комментарии:

— заблокирована возможность установки snap-приложений на уровне приоритетов APT. При необходимости поддержки данного типа пакетов нужно удалить конфиг /etc/apt/preferences.d/nosnap.pref и обновить индекс пакетной базы;

— браузер Firefox установлен в виде deb-пакета из подключенного PPA-репозитория Mozillateam, т.к. штатно в релизе 22.04 Firefox поставляется в виде snap. Предустановлено расширение uBlock Origin.

В меню «Офис» добавлены ярлыки для установки LibreOffice и подсистемы печати. Если установка данного ПО не планируется и ярлыки в меню не нужны, следует удалить файлы printinstall и lo_install в каталоге /var/lib/misc/.

Пожелания, предложения по составу и функционалу дистрибутива приветствуются.

 Ссылки на загрузку:

Загрузить с Sourceforge.net
Загрузить с Зеркала на mephi.ru

Файл:          runtu-lite-22.04-amd64_20220424.iso

Размер:       1151 Мб

md5:           889295457f02cd9c3d9c25498a0d0475
sha1:          0be5c2d87ba85b0c5a00c3a762cd1a89b5e35cfd

Поддержать проект: ссылка на тему форума.

Description of problem:
Guest didn't boot up when passthrough device using vfio-pci with ovmf

Version-Release number of selected component (if applicable):
kernel-3.10.0-433.el7.x86_64
qemu-kvm-rhev-2.6.0-5.el7.x86_64
OVMF-20160608-1.git988715a.el7.noarch.rpm

How reproducible:
3/3

Steps to Reproduce:
1. Boot guest with following cli
[root@localhost home]# cat q35-ovmf.sh 
/usr/libexec/qemu-kvm 
-M q35 
-cpu Nehalem 
-monitor stdio 
-m 4G 
-vga qxl 
-drive file=/usr/share/OVMF/OVMF_CODE.secboot.fd,if=pflash,format=raw,unit=0,readonly=on 
-drive file=/usr/share/OVMF/OVMF_VARS.fd,if=pflash,format=raw,unit=1 
-debugcon file:/home/q35.ovmf.log 
-global isa-debugcon.iobase=0x402 
-spice port=5932,disable-ticketing 
-smp 4,sockets=4,cores=1,threads=1 
-device ioh3420,bus=pcie.0,id=root1.0,slot=1 
-device x3130-upstream,bus=root1.0,id=upstream1.1 
-device xio3130-downstream,bus=upstream1.1,id=downstream1.1,chassis=2 
-device virtio-net-pci,bus=downstream1.1,netdev=tap10,mac=9a:6a:6b:6c:6d:6e -netdev tap,id=tap10 
-device ioh3420,bus=pcie.0,id=root1.1,slot=2 
-device x3130-upstream,bus=root1.1,id=upstream1.2 
-device xio3130-downstream,bus=upstream1.2,id=downstream1.2,chassis=3 
-device xio3130-downstream,bus=upstream1.2,id=downstream1.3,chassis=4 
-drive if=none,id=drive0,file=/home/pxb-ovmf.qcow2 
-device virtio-blk-pci,drive=drive0,scsi=off,bus=downstream1.2,disable-legacy=on,disable-modern=off  
-device ioh3420,bus=pcie.0,id=root1.2,slot=3 
-device vfio-pci,host=0000:03:00.0,id=vfio,bus=downstream1.3


Actual results:
Guest didn't boot up successfully, please check the attachment of ovmf log

Expected results:
Gust can boot up successfully

Additional info:


Comment 3


Laszlo Ersek



2016-06-15 11:05:13 UTC

Jing Zhao,

two remarks / questions:

- Your use of OVMF_VARS.fd is not correct. Please refer to bug 1308678 comment 23 bullet (1) for details. (This is independent from the functionality being tested -- it's a general remark, but I think it's worth pointing out.)

- I checked the attached OVMF log file, from comment 1. It says

PciHostBridgeGetRootBridges: 2 extra root buses reported by QEMU
InitRootBridge: populated root bus 0, with room for 7 subordinate bus(es)
InitRootBridge: populated root bus 8, with room for 11 subordinate bus(es)
InitRootBridge: populated root bus 20, with room for 235 subordinate bus(es)

However, this doesn't seem to match the command line given in comment 0 -- on that command line, you do not have any pxb-pcie devices.

At the moment it appears to me that you tried VFIO device assignment in combination with pxb-pcie, and you ran into the bus_nr problem that we've been discussing in bug 1345738. Looking at the OVMF debug log, this is the impression I'm getting. And I think you ended up pasting a different QEMU command line (without pxb-pcie devices) into comment 0.

Can you please clarify? Thanks.


Comment 4


Laszlo Ersek



2016-06-15 11:23:28 UTC

Jing Zhao,

another remark: *assuming* that you intend to place (a) the assigned device, and/or (b) the *modern* virtio-blk device, behind a pxb-pcie extra root bridge, please be aware of bug 1323976.

Namely, unlike SeaBIOS, the edk2 PCI infrastructure built into OVMF prefers to allocate 64-bit MMIO BARs of PCI devices outside of the 32-bit address space. This works fine if you place such PCI device directly on the "main" root bridge (bus_nr=0), but it can break if the PCI device with 64-bit MMIO BARs is elsewhere. The possible breakage is due to QEMU's ACPI generator producing incorrect resource descriptors --> see bug 1323976.

This may affect both modern virtio devices, and assigned physical devices. There are two work-arounds:

- Plug these devices directly into "pcie.0".
- Alternatively, pass the following switch to QEMU, disabling the 64-bit MMIO
  aperture for OVMF:

  -fw_cfg name=opt/ovmf/X-PciMmio64Mb,string=0

Thanks.


Comment 5


Laszlo Ersek



2016-06-15 11:25:39 UTC

Sigh, I CC'd Marcel while writing my previous comment, but of course Bugzilla had to apply some automatic changes meanwhile, so my metadata changes went lost. Adding the CC now.


Comment 6


Alex Williamson



2016-06-15 12:56:07 UTC

(In reply to jingzhao from comment #0)
> -device vfio-pci,host=0000:03:00.0,id=vfio,bus=downstream1.3

What is this device?  Please always identify the device being assigned.

Laszlo has additional questions in comment 3 that also needinfo regarding the consistency of the original report.


Comment 7


Alex Williamson



2016-06-15 22:05:10 UTC

Created attachment 1168522 [details]
ovmf debug log

Reproduced with 82576 PF:

# lspci -vs 7:00.0
07:00.0 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01)
	Subsystem: Intel Corporation Gigabit ET Dual Port Server Adapter
	Physical Slot: 5
	Flags: fast devsel, IRQ 16
	Memory at ef420000 (32-bit, non-prefetchable) [disabled] [size=128K]
	Memory at ef000000 (32-bit, non-prefetchable) [disabled] [size=4M]
	I/O ports at 8020 [disabled] [size=32]
	Memory at ef4c4000 (32-bit, non-prefetchable) [disabled] [size=16K]
	Expansion ROM at eec00000 [disabled] [size=4M]

OVMF log ends with:

PciHostBridge: SubmitResources for PciRoot(0x0)
 I/O: Granularity/SpecificFlag = 0 / 01
      Length/Alignment = 0x3000 / 0xFFF
 Mem: Granularity/SpecificFlag = 32 / 00
      Length/Alignment = 0x1E8200000 / 0xEF49FFFF
PciBus: HostBridge->SubmitResources() - Invalid Parameter

ASSERT_EFI_ERROR (Status = Invalid Parameter)
ASSERT /builddir/build/BUILD/ovmf-988715a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c(561): !EFI_ERROR (Status)

VM boots with SeaBIOS.

OVMF-20160608-1.git988715a.el7.noarch
qemu-kvm-rhev-2.6.0-6.el7.x86_64


Comment 8


Alex Williamson



2016-06-15 22:06:47 UTC

Seems like an OVMF bug, reassigning


Comment 9


Alex Williamson



2016-06-15 22:23:39 UTC

The command works with either a non-SR-IOV capable device (82579LM) or a VF (82576), is it the SR-IOV enumeration that kills OVMF?  Did I get lucky picking an SR-IOV PF on my first try?


Comment 10


Alex Williamson



2016-06-15 22:28:47 UTC

NB, vfio exposes the SR-IOV capability as read-only, in case that's confusing OVMF, but it would seem unusual for OVMF to blindly attempt to enable SR-IOV.


Comment 11


Alex Williamson



2016-06-15 22:53:38 UTC

Yes, if vfio hides the sr-iov capability on the device, OVMF boots.


Comment 12


jingzhao



2016-06-16 01:10:23 UTC

Thanks Laszlo

Correct information of bug

1) the nic information which passthrough to the guest 

[root@hp-z800-01 home]# lspci -vvv -s 03:00.0
03:00.0 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01)
	Subsystem: Intel Corporation Gigabit ET Dual Port Server Adapter
	Physical Slot: 1
	Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
	Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Interrupt: pin A routed to IRQ 29
	Region 0: Memory at e4800000 (32-bit, non-prefetchable) [disabled] [size=128K]
	Region 1: Memory at e4000000 (32-bit, non-prefetchable) [disabled] [size=4M]
	Region 2: I/O ports at c000 [disabled] [size=32]
	Region 3: Memory at e4840000 (32-bit, non-prefetchable) [disabled] [size=16K]
	Capabilities: [40] Power Management version 3
		Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
		Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=1 PME-
	Capabilities: [50] MSI: Enable- Count=1/1 Maskable+ 64bit+
		Address: 0000000000000000  Data: 0000
		Masking: 00000000  Pending: 00000000
	Capabilities: [70] MSI-X: Enable- Count=10 Masked-
		Vector table: BAR=3 offset=00000000
		PBA: BAR=3 offset=00002000
	Capabilities: [a0] Express (v2) Endpoint, MSI 00
		DevCap:	MaxPayload 512 bytes, PhantFunc 0, Latency L0s <512ns, L1 <64us
			ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset+
		DevCtl:	Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
			RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+ FLReset-
			MaxPayload 256 bytes, MaxReadReq 512 bytes
		DevSta:	CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr+ TransPend-
		LnkCap:	Port #0, Speed 2.5GT/s, Width x4, ASPM L0s L1, Exit Latency L0s <4us, L1 <64us
			ClockPM- Surprise- LLActRep- BwNot-
		LnkCtl:	ASPM Disabled; RCB 64 bytes Disabled- CommClk+
			ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
		LnkSta:	Speed 2.5GT/s, Width x4, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
		DevCap2: Completion Timeout: Range ABCD, TimeoutDis+, LTR-, OBFF Not Supported
		DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled
		LnkCtl2: Target Link Speed: 2.5GT/s, EnterCompliance- SpeedDis-
			 Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
			 Compliance De-emphasis: -6dB
		LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
			 EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
	Capabilities: [100 v1] Advanced Error Reporting
		UESta:	DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
		UEMsk:	DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
		UESvrt:	DLP+ SDES- TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
		CESta:	RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
		CEMsk:	RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
		AERCap:	First Error Pointer: 00, GenCap- CGenEn- ChkCap- ChkEn-
	Capabilities: [140 v1] Device Serial Number 00-1b-21-ff-ff-42-33-84
	Capabilities: [150 v1] Alternative Routing-ID Interpretation (ARI)
		ARICap:	MFVC- ACS-, Next Function: 1
		ARICtl:	MFVC- ACS-, Function Group: 0
	Capabilities: [160 v1] Single Root I/O Virtualization (SR-IOV)
		IOVCap:	Migration-, Interrupt Message Number: 000
		IOVCtl:	Enable- Migration- Interrupt- MSE- ARIHierarchy+
		IOVSta:	Migration-
		Initial VFs: 8, Total VFs: 8, Number of VFs: 0, Function Dependency Link: 00
		VF offset: 128, stride: 2, Device ID: 10ca
		Supported Page Size: 00000553, System Page Size: 00000001
		Region 0: Memory at 00000000e4848000 (64-bit, non-prefetchable)
		Region 3: Memory at 00000000e4868000 (64-bit, non-prefetchable)
		VF Migration: offset: 00000000, BIR: 0
	Kernel driver in use: vfio-pci


2. the test command line 

/usr/libexec/qemu-kvm 
-M q35 
-cpu Nehalem 
-monitor stdio 
-m 4G 
-vga qxl 
-drive file=/usr/share/OVMF/OVMF_CODE.secboot.fd,if=pflash,format=raw,unit=0,readonly=on 
-drive file=/home/my_varstore.fd,if=pflash,format=raw,unit=1 
-debugcon file:/home/q35.ovmf.log 
-global isa-debugcon.iobase=0x402 
-spice port=5932,disable-ticketing 
-smp 4,sockets=4,cores=1,threads=1 
-device ioh3420,bus=pcie.0,id=root1.0,slot=1 
-device x3130-upstream,bus=root1.0,id=upstream1.1 
-device xio3130-downstream,bus=upstream1.1,id=downstream1.1,chassis=2 
-device virtio-net-pci,bus=downstream1.1,netdev=tap10,mac=9a:6a:6b:6c:6d:6e -netdev tap,id=tap10 
-device ioh3420,bus=pcie.0,id=root1.1,slot=2 
-device x3130-upstream,bus=root1.1,id=upstream1.2 
-device xio3130-downstream,bus=upstream1.2,id=downstream1.2,chassis=3 
-device xio3130-downstream,bus=upstream1.2,id=downstream1.3,chassis=4 
-drive if=none,id=drive0,file=/home/pxb-ovmf.qcow2 
-device virtio-blk-pci,drive=drive0,scsi=off,bus=downstream1.2,disable-legacy=on,disable-modern=off  
-device ioh3420,bus=pcie.0,id=root1.2,slot=3 
-device vfio-pci,host=0000:03:00.0,id=vfio,bus=downstream1.3

3. Update the ovmf log of my testing


Thanks
Jing Zhao


Comment 14


Laszlo Ersek



2016-06-17 18:52:13 UTC

(In reply to Alex Williamson from comment #9)

> Did I get lucky picking an SR-IOV PF on my first try?

Yes. In both OVMF log files (comment 7, comment 13), I can see messages such
as:

> PciBus: Discovered PCI @ [07|00|00]
>  ARI: CapOffset = 0x150
>  SR-IOV: SupportedPageSize = 0x553; SystemPageSize = 0x1; FirstVFOffset =
>          0x180; InitialVFs = 0x8; ReservedBusNum = 0x2; CapOffset = 0x160
>    BAR[0]: Type =  Mem32; Alignment = 0x1FFFF;	Length =
>    0x20000;	Offset = 0x10
>    BAR[1]: Type =  Mem32; Alignment = 0x3FFFFF;	Length =
>    0x400000;	Offset = 0x14
>    BAR[2]: Type =   Io32; Alignment = 0x1F;	Length = 0x20;	Offset =
>    0x18
>    BAR[3]: Type =  Mem32; Alignment = 0x3FFF;	Length = 0x4000;
>    Offset = 0x1C
>  VFBAR[0]: Type =  Mem64; Alignment = 0xEF49FFFF;	Length =
>  0xEF4A0000;	Offset = 0x184
>  VFBAR[2]: Type =  Mem64; Alignment = 0xEF47FFFF;	Length =
>  0xEF480000;	Offset = 0x190

(which is the very first time I see VFBARs in this section of the log).
Then, when the collected resources are submitted to PciHostBridgeDxe, it
blows up:

> PciHostBridge: SubmitResources for PciRoot(0x0)
>  I/O: Granularity/SpecificFlag = 0 / 01
>       Length/Alignment = 0x3000 / 0xFFF
>  Mem: Granularity/SpecificFlag = 32 / 00
>       Length/Alignment = 0x1E8200000 / 0xEF49FFFF
> PciBus: HostBridge->SubmitResources() - Invalid Parameter
>
> ASSERT_EFI_ERROR (Status = Invalid Parameter)
> ASSERT
> /builddir/build/BUILD/ovmf-988715a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c(561):
> /EFI_ERROR (Status)

The direct reason being that the Length field (which is the sum of MMIO
resources for the bridge, 0x1E8200000) is greater than 4GB, but the resource
type is 32-bit MMIO (Granularity=32).

It seems that the Length and Alignment fields have special meanings for VF
BARs (I skimmed the SR-IOV spec very-very superficially).

... Hm, I think I might even suspect what causes this. I believe it is
<https://github.com/tianocore/edk2/commit/05070c1b471b0>. The 64-bit MMIO
BAR is degraded to 32-bit if it is a VFBAR and the device has an option ROM.
(See the DegradeResource() function in the linked patch.)

I don't understand the reasoning behind this. I'll take the discussion to
the upstream list.

Meanwhile, Alex, Jing Zhao, can you please repeat your tests, with the small
modification that the ROM BAR for the assigned device be turned off?

  -device vfio-pci,...,rombar=0
                       ^^^^^^^^

Thanks!


Comment 15


Alex Williamson



2016-06-17 19:23:04 UTC

Laszlo, note that 82576 has very modest MMIO requirements for the MMIO space, this is typically the "works anywhere" SR-IOV device because it requires <= 2MB of MMIO space, which is the minimum bridge granularity.  If we're coming up with needing more than 4G, it's probably because the read-only SR-IOV capability is being misinterpreted, ie. no sanity checks on the sizing.


Comment 18


Alex Williamson



2016-06-18 00:07:33 UTC

FWIW, I'm also open to the idea that QEMU hide the SR-IOV capability from the VM.  We have no support for the VM enabling SR-IOV, so there's really no dependency on exposing this capability.  Kernel-level vfio exposes the capability read-only to prevent users from creating VFs, but it's still up to the hypervisor whether to further expose such capabilities to the VM.


Comment 19


Laszlo Ersek



2016-06-18 00:18:53 UTC

I'll try to follow whatever you deem best -- I guess first we should hear back from the maintainers of PciBusDxe in edk2, about their goals with VF BARs to begin with.

In edk2 there is a feature flag, defined in "MdeModulePkg/MdeModulePkg.dec":

  ## Indicates if the Single Root I/O virtualization is supported.<BR><BR>
  #   TRUE  - Single Root I/O virtualization is supported.<BR>
  #   FALSE - Single Root I/O virtualization is not supported.<BR>
  # @Prompt Enable SRIOV support.
  gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSupport|TRUE|BOOLEAN|0x10000044

OVMF inherits the default value (TRUE) without overriding it, for the time being. (It can override it if we want it to.) I don't know precisely what this feature flag controls.

But, if it controls the "creation of VFs", then I guess we should disable it? Based on your comment 18.


Comment 20


jingzhao



2016-06-20 03:24:21 UTC

(In reply to Laszlo Ersek from comment #14)
> (In reply to Alex Williamson from comment #9)
> 
> > Did I get lucky picking an SR-IOV PF on my first try?
> 
> Yes. In both OVMF log files (comment 7, comment 13), I can see messages such
> as:
> 
> > PciBus: Discovered PCI @ [07|00|00]
> >  ARI: CapOffset = 0x150
> >  SR-IOV: SupportedPageSize = 0x553; SystemPageSize = 0x1; FirstVFOffset =
> >          0x180; InitialVFs = 0x8; ReservedBusNum = 0x2; CapOffset = 0x160
> >    BAR[0]: Type =  Mem32; Alignment = 0x1FFFF;	Length =
> >    0x20000;	Offset = 0x10
> >    BAR[1]: Type =  Mem32; Alignment = 0x3FFFFF;	Length =
> >    0x400000;	Offset = 0x14
> >    BAR[2]: Type =   Io32; Alignment = 0x1F;	Length = 0x20;	Offset =
> >    0x18
> >    BAR[3]: Type =  Mem32; Alignment = 0x3FFF;	Length = 0x4000;
> >    Offset = 0x1C
> >  VFBAR[0]: Type =  Mem64; Alignment = 0xEF49FFFF;	Length =
> >  0xEF4A0000;	Offset = 0x184
> >  VFBAR[2]: Type =  Mem64; Alignment = 0xEF47FFFF;	Length =
> >  0xEF480000;	Offset = 0x190
> 
> (which is the very first time I see VFBARs in this section of the log).
> Then, when the collected resources are submitted to PciHostBridgeDxe, it
> blows up:
> 
> > PciHostBridge: SubmitResources for PciRoot(0x0)
> >  I/O: Granularity/SpecificFlag = 0 / 01
> >       Length/Alignment = 0x3000 / 0xFFF
> >  Mem: Granularity/SpecificFlag = 32 / 00
> >       Length/Alignment = 0x1E8200000 / 0xEF49FFFF
> > PciBus: HostBridge->SubmitResources() - Invalid Parameter
> >
> > ASSERT_EFI_ERROR (Status = Invalid Parameter)
> > ASSERT
> > /builddir/build/BUILD/ovmf-988715a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c(561):
> > /EFI_ERROR (Status)
> 
> The direct reason being that the Length field (which is the sum of MMIO
> resources for the bridge, 0x1E8200000) is greater than 4GB, but the resource
> type is 32-bit MMIO (Granularity=32).
> 
> It seems that the Length and Alignment fields have special meanings for VF
> BARs (I skimmed the SR-IOV spec very-very superficially).
> 
> ... Hm, I think I might even suspect what causes this. I believe it is
> <https://github.com/tianocore/edk2/commit/05070c1b471b0>. The 64-bit MMIO
> BAR is degraded to 32-bit if it is a VFBAR and the device has an option ROM.
> (See the DegradeResource() function in the linked patch.)
> 
> I don't understand the reasoning behind this. I'll take the discussion to
> the upstream list.
> 
> Meanwhile, Alex, Jing Zhao, can you please repeat your tests, with the small
> modification that the ROM BAR for the assigned device be turned off?
> 
>   -device vfio-pci,...,rombar=0
>                        ^^^^^^^^
> 
> Thanks!

Repeat the test with above changed, and failed. please check the ovmf log of add rombar parameter


Comment 22


Laszlo Ersek



2016-06-20 09:51:06 UTC

Thank you for checking; the symptoms in the log file are identical. So it looks like rombar=0 makes no difference, and I should instrument the edk2 code with debug messages and experiment a little with it.


Comment 25


Alex Williamson



2016-06-20 14:31:15 UTC

(In reply to Laszlo Ersek from comment #24)
> Upstream thread #2, from a different angle:
> http://thread.gmane.org/gmane.comp.bios.edk2.devel/13437

Lazslo, some folks think that allowing the guest to enable sr-iov on an assigned device is not a completely insane thing to do, see http://www.spinics.net/lists/kvm/msg134370.html

The more I think about it, the more I think vfio is asking ovmf to detect something non-standard per the spec.  Sure, it might be robust to detect that the VFBARs aren't getting sized correctly, but is that something we can reasonably expect of guest software?  We can have QEMU hide the SR-IOV capability, though this also gets a little ugly because extended capabilities always start at 0x100 in PCI config space and it's not feasible to relocated capabilities, which means we need to support stubbing that first entry to something a guest will traverse, but not recognize.  If we hope that the guest follows the spec to the letter, we could use capability ID 0x0, except QEMU-pci uses this internally.  ID 0xFFFF also has special meaning for root complex register block based capabilities, which might mean a guest would assume no capabilities at all.  That leaves unlikely to be assigned values, like 0xFFFE.  It's all generally unappealing, but we do some hiding of capabilities in the kernel too, so I'll look to see whether we have a better algorithm there.

Another possibility is that we virtualize the VFBARs to allow them to be sized, but leave the rest of the capability read-only.  I'll need to look through the spec to see if we have any leeway to do this.


Comment 26


Laszlo Ersek



2016-06-20 17:40:57 UTC

Sounds great to me, thanks for looking into this! (And yes, the blurb on the
referenced patch set seems reasonable as well.0

Regarding any possible stubbing out for the SR-IOV capability: the
CreatePciIoDevice() function in
[MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c] has a section like
this:

>   //
>   // Initialization for SR-IOV
>   //
>
>   if (PcdGetBool (PcdSrIovSupport)) {
>     Status = LocatePciExpressCapabilityRegBlock (
>                PciIoDevice,
>                EFI_PCIE_CAPABILITY_ID_SRIOV,
>                &PciIoDevice->SrIovCapabilityOffset,
>                NULL
>                );
>     if (!EFI_ERROR (Status)) {

If you can make that LocatePciExpressCapabilityRegBlock() function call to
fail, then SR-IOV will not be used, I think. (Similarly to the effect of
setting PcdSrIovSupport to FALSE in the OVMF platform description files.)

The LocatePciExpressCapabilityRegBlock() function is at the end of
"MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.c", and it seems to perform a
"fairly standard" traversal of the PCI Express config space.

AFAICT, LocatePciExpressCapabilityRegBlock() is called in three places in total, looking for:
- EFI_PCIE_CAPABILITY_ID_ARI (0x0E)
- EFI_PCIE_CAPABILITY_ID_SRIOV (0x10)
- EFI_PCIE_CAPABILITY_ID_MRIOV (0x11)

These macro definitions are in
"MdePkg/Include/IndustryStandard/PciExpress21.h". Grepping header files for
"EFI_PCIE_CAPABILITY_ID_", I find no other header files with definitions.
And, all the definitions I find in this header, are:

> #define EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY          0x10
> #define EFI_PCIE_CAPABILITY_ID_ARI        0x0E
> #define EFI_PCIE_CAPABILITY_ID_ATS        0x0F
> #define EFI_PCIE_CAPABILITY_ID_SRIOV      0x10
> #define EFI_PCIE_CAPABILITY_ID_MRIOV      0x11
> #define EFI_PCIE_CAPABILITY_ID_SRIOV_CAPABILITIES               0x04
> #define EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL                    0x08
> #define EFI_PCIE_CAPABILITY_ID_SRIOV_STATUS                     0x0A
> #define EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS                 0x0C
> #define EFI_PCIE_CAPABILITY_ID_SRIOV_TOTALVFS                   0x0E
> #define EFI_PCIE_CAPABILITY_ID_SRIOV_NUMVFS                     0x10
> #define EFI_PCIE_CAPABILITY_ID_SRIOV_FUNCTION_DEPENDENCY_LINK   0x12
> #define EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF                    0x14
> #define EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE                   0x16
> #define EFI_PCIE_CAPABILITY_ID_SRIOV_VFDEVICEID                 0x1A
> #define EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE        0x1C
> #define EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE           0x20
> #define EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0                       0x24
> #define EFI_PCIE_CAPABILITY_ID_SRIOV_BAR1                       0x28
> #define EFI_PCIE_CAPABILITY_ID_SRIOV_BAR2                       0x2C
> #define EFI_PCIE_CAPABILITY_ID_SRIOV_BAR3                       0x30
> #define EFI_PCIE_CAPABILITY_ID_SRIOV_BAR4                       0x34
> #define EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5                       0x38
> #define EFI_PCIE_CAPABILITY_ID_SRIOV_VF_MIGRATION_STATE         0x3C

I think it might be worth a shot to try 0xFFFE or similar.

... But, given how the effect of that would be practically identical to
setting PcdSrIovSupport to FALSE in OvmfPkg/*.dsc (for the time being
anyway!), I don't see a problem with that either. I'm happy to try out both,
assuming I get access to a machine with a suitable NIC. (Obviously for the
stubbing, you would have to provide the QEMU patch :))

Thanks!


Comment 29


Laszlo Ersek



2016-06-28 14:46:49 UTC

I managed to reproduce this error, in the following environment:

- assigned device (I350-T2V2 (8086:1521) PF):
  03:00.0 Ethernet controller:
  Intel Corporation I350 Gigabit Network Connection (rev 01)

- domain XML snippet (Q35):

  <controller type='pci' index='3' model='pcie-root-port'>
    <model name='ioh3420'/>
    <target chassis='3' port='0xe8'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x0'/>
  </controller>
  <controller type='pci' index='4' model='pcie-switch-upstream-port'>
    <model name='x3130-upstream'/>
    <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
  </controller>
  <controller type='pci' index='5' model='pcie-switch-downstream-port'>
    <model name='xio3130-downstream'/>
    <target chassis='5' port='0x0'/>
    <address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
  </controller>

  <hostdev mode='subsystem' type='pci' managed='yes'>
    <source>
      <address domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
    </source>
    <address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/>
  </hostdev>

  This generates a QEMU command line like

  -device ioh3420,port=0xe8,chassis=3,id=pci.3,bus=pcie.0,addr=0x1d 
  -device x3130-upstream,id=pci.4,bus=pci.3,addr=0x0 
  -device xio3130-downstream,port=0x0,chassis=5,id=pci.5,bus=pci.4,addr=0x0 
  -device vfio-pci,host=03:00.0,id=hostdev3,bus=pci.5,addr=0x0 

- QEMU: upstream v2.6.0-1395-g40428fe

- host kernel: 4.4.5-200.fc22.x86_64

I confirm that toggling the ROM BAR on/off makes no difference, so the error
is not due to any 64->32 bit resource degradation like I initially
suspected.

I'll go ahead and test Alex's upstream patch (comment 28).


Comment 30


Laszlo Ersek



2016-06-28 16:29:57 UTC

Yes, the patch works:

> PciBus: Discovered PCI @ [03|00|00]
>  ARI: forwarding enabled for PPB[02:00:00]
>  ARI: CapOffset = 0x150
>    BAR[0]: Type =  Mem32; Alignment = 0xFFFFF;  Length = 0x100000;      Offset = 0x10
>    BAR[3]: Type =  Mem32; Alignment = 0x3FFF;   Length = 0x4000;        Offset = 0x1C
>
> [...]
>
> PciBus: Resource Map for Bridge [02|00|00]
> Type =  Mem32; Base = 0x99200000;       Length = 0x200000;      Alignment = 0xFFFFF
>    Base = 0x99200000;   Length = 0x100000;      Alignment = 0xFFFFF;    Owner = PCI [03|00|00:10]
>    Base = 0x99300000;   Length = 0x4000;        Alignment = 0x3FFF;     Owner = PCI [03|00|00:1C]

The Windows Server 2012 R2 guest OS was also launched. The driver for the
NIC was installed automatically. The device looks fine in Device Manager.

I'm still having network connectivity problems though -- I'm debugging them.
(Almost certainly an issue with the dnsmasq / iptables setup on my the
gateway machine.) I'd like to have an all-positive result before replying on
the list.


Comment 31


Miroslav Rezanina



2016-07-08 08:39:48 UTC

Fix included in qemu-kvm-rhev-2.6.0-12.el7


Comment 33


jingzhao



2016-08-10 09:15:52 UTC

Verified it 
kernel-3.10.0-489.el7.x86_64
qemu-img-rhev-2.6.0-19.el7.x86_64
OVMF-20160608-3.git988715a.el7.noarch

Following is the verfied steps:

1. Boot guest with following cmd:
/usr/libexec/qemu-kvm 
-M q35 
-cpu Nehalem 
-monitor stdio 
-m 4G 
-vga qxl 
-drive file=/usr/share/OVMF/OVMF_CODE.secboot.fd,if=pflash,format=raw,unit=0,readonly=on 
-drive file=/home/OVMF_VARS.fd,if=pflash,format=raw,unit=1 
-debugcon file:/home/q35.ovmf.log 
-global isa-debugcon.iobase=0x402 
-spice port=5932,disable-ticketing 
-smp 4,sockets=4,cores=1,threads=1 
-device ioh3420,bus=pcie.0,id=root1.0,slot=1 
-device x3130-upstream,bus=root1.0,id=upstream1.1 
-device xio3130-downstream,bus=upstream1.1,id=downstream1.1,chassis=2 
-device virtio-net-pci,bus=downstream1.1,netdev=tap10,mac=9a:6a:6b:6c:6d:6e -netdev tap,id=tap10 
-device ioh3420,bus=pcie.0,id=root1.1,slot=2 
-device x3130-upstream,bus=root1.1,id=upstream1.2 
-device xio3130-downstream,bus=upstream1.2,id=downstream1.2,chassis=3 
-device xio3130-downstream,bus=upstream1.2,id=downstream1.3,chassis=4 
-drive if=none,id=drive0,file=/home/pxb-ovmf.qcow2 
-device virtio-blk-pci,drive=drive0,scsi=off,bus=downstream1.2,disable-legacy=on,disable-modern=off  
-device ioh3420,bus=pcie.0,id=root1.2,slot=3 
-device vfio-pci,host=03:00.0,id=vf-00.0,bus=root1.2 


2. guest can boot up successfully

3. check the nic which passthrough from host in the guest
[root@dhcp-66-145-44 ~]# lspci 
00:00.0 Host bridge: Intel Corporation 82G33/G31/P35/P31 Express DRAM Controller
00:01.0 VGA compatible controller: Red Hat, Inc. QXL paravirtual graphic card (rev 04)
00:02.0 PCI bridge: Intel Corporation 7500/5520/5500/X58 I/O Hub PCI Express Root Port 0 (rev 02)
00:03.0 PCI bridge: Intel Corporation 7500/5520/5500/X58 I/O Hub PCI Express Root Port 0 (rev 02)
00:04.0 PCI bridge: Intel Corporation 7500/5520/5500/X58 I/O Hub PCI Express Root Port 0 (rev 02)
00:1f.0 ISA bridge: Intel Corporation 82801IB (ICH9) LPC Interface Controller (rev 02)
00:1f.2 SATA controller: Intel Corporation 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode] (rev 02)
00:1f.3 SMBus: Intel Corporation 82801I (ICH9 Family) SMBus Controller (rev 02)
01:00.0 PCI bridge: Texas Instruments XIO3130 PCI Express Switch (Upstream) (rev 02)
02:00.0 PCI bridge: Texas Instruments XIO3130 PCI Express Switch (Downstream) (rev 01)
03:00.0 Ethernet controller: Red Hat, Inc Virtio network device (rev 01)
04:00.0 PCI bridge: Texas Instruments XIO3130 PCI Express Switch (Upstream) (rev 02)
05:00.0 PCI bridge: Texas Instruments XIO3130 PCI Express Switch (Downstream) (rev 01)
05:01.0 PCI bridge: Texas Instruments XIO3130 PCI Express Switch (Downstream) (rev 01)
06:00.0 SCSI storage controller: Red Hat, Inc Virtio block device (rev 01)
08:00.0 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01)
[root@dhcp-66-145-44 ~]# lspci -vvv -t
-[0000:00]-+-00.0  Intel Corporation 82G33/G31/P35/P31 Express DRAM Controller
           +-01.0  Red Hat, Inc. QXL paravirtual graphic card
           +-02.0-[01-03]----00.0-[02-03]----00.0-[03]----00.0  Red Hat, Inc Virtio network device
           +-03.0-[04-07]----00.0-[05-07]--+-00.0-[06]----00.0  Red Hat, Inc Virtio block device
           |                               -01.0-[07]--
           +-04.0-[08]----00.0  Intel Corporation 82576 Gigabit Network Connection
           +-1f.0  Intel Corporation 82801IB (ICH9) LPC Interface Controller
           +-1f.2  Intel Corporation 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode]
           -1f.3  Intel Corporation 82801I (ICH9 Family) SMBus Controller

[root@dhcp-66-145-44 ~]# ifconfig
ens3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        ether 00:1b:21:42:33:84  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        device memory 0x98400000-9841ffff  

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.66.145.44  netmask 255.255.252.0  broadcast 10.66.147.255
        inet6 2620:52:0:4292:986a:6bff:fe6c:6d6e  prefixlen 64  scopeid 0x0<global>
        inet6 fe80::986a:6bff:fe6c:6d6e  prefixlen 64  scopeid 0x20<link>
        ether 9a:6a:6b:6c:6d:6e  txqueuelen 1000  (Ethernet)
        RX packets 788  bytes 57561 (56.2 KiB)
        RX errors 0  dropped 6  overruns 0  frame 0
        TX packets 150  bytes 20636 (20.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0


Thanks
Jing Zhao


Comment 36


errata-xmlrpc



2016-11-07 21:17:36 UTC

Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://rhn.redhat.com/errata/RHBA-2016-2673.html

b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c



@@ -940,22 +940,21 @@  Ip4StartAutoConfig (
              &Instance->Dhcp4Handle
              );

-  if (Status == EFI_UNSUPPORTED) {
-    //
-    // No DHCPv4 Service Binding protocol, register a notify.
-    //
-    if (Instance->Dhcp4SbNotifyEvent == NULL) {
-      Instance->Dhcp4SbNotifyEvent = EfiCreateProtocolNotifyEvent (
-                                       &gEfiDhcp4ServiceBindingProtocolGuid,
-                                       TPL_CALLBACK,
-                                       Ip4Config2OnDhcp4SbInstalled,
-                                       (VOID *) Instance,
-                                       &Instance->Registration
-                                       );
-    }
-  }
-
   if (EFI_ERROR (Status)) {
+    if (Status == EFI_UNSUPPORTED) {^M
+      //^M
+      // No DHCPv4 Service Binding protocol, register a notify.^M
+      //^M
+      if (Instance->Dhcp4SbNotifyEvent == NULL) {^M
+        Instance->Dhcp4SbNotifyEvent = EfiCreateProtocolNotifyEvent (^M
+
&gEfiDhcp4ServiceBindingProtocolGuid,^M
+                                         TPL_CALLBACK,^M
+                                         Ip4Config2OnDhcp4SbInstalled,^M
+                                         (VOID *) Instance,^M
+                                         &Instance->Registration^M
+                                         );^M
+      }^M
+    }^M
     return Status;
   }

Понравилась статья? Поделить с друзьями:
  • Assembly referencing error people playground
  • Assembly csharp dll как изменить
  • Assembler syntax error
  • Assembler error a2206
  • Assassins creed valhalla ошибка при запуске d3d12 dll