Zbudowałem narzędzia umożliwiające edycję UEFI BootMenu NVRAM pod WinXP 64-bit uruchamiany za pomocą loadera bootmgfw.efi z Windows Longhorn (zmieniona nazwa na bootxp64.efi)
[UefiNvram] DriverEntry
[UefiNvram] Cannot open SAVT key: 0xC0000034
[UefiNvram] WARNING: EFI not available
* aplikacja RW Everything pod WinXP 64-bit widzi tabelę SAVT ale pod nieco innym adresem 7797F1A0 podczas gdy SaveRt.efi ustawił pod adresem 77966000
* na innym komputerze adres tabeli SAVT w RW Everything zgadza się z tym pod jakim ustawił SaveRt.efi ale sterownik UefiVarPoC.sys nadal nie widzi tabeli - komunkat Cannot open SAVT key
Wnioski
Tabeli SAVT prawdopodobnie nie ma w rejestrze ale jest w pamięci więc może lepiej przerobić sterownik UefiVarPoC.sys aby szukał tabeli SAVT w pamięci zamiast odczytywać z rejestru?
Poniżej kod źródłowy sterownika UefiVarPoC.sys który kompiluje w środowisku WDK 7600.16385.1 na WinXP 64-bit:
DriverEntry.c
Kod: C / C++
Zaloguj się, aby zobaczyć kod
sources
Kod: C / C++
Zaloguj się, aby zobaczyć kod
Kod źródłowy narzędzia SaveRt.efi, który kompiluję w środowisku edk2 2021 pod Ubuntu:
Zbudowałem narzędzia umożliwiające edycję UEFI BootMenu NVRAM pod WinXP 64-bit uruchamiany za pomocą loadera bootmgfw.efi z Windows Longhorn (zmieniona nazwa na bootxp64.efi)
...
Krótka odpowiedź
Tak — lepiej przerobić sterownik tak, aby znajdował
SAVT
bezpośrednio przez mechanizm ACPI w pamięci, a nie przez rejestr.
Ale istotne doprecyzowanie: nie chodzi o skanowanie całej RAM „na ślepo”, tylko o przejście standardową ścieżką:
1. znaleźć
RSDP
, 2. z niego odczytać
RSDT
lub
XSDT
, 3. przejść po wpisach tych tabel, 4. znaleźć tabelę o sygnaturze
SAVT
, 5. zweryfikować checksum i dopiero wtedy użyć
SavedInfo
.
To jest właściwy model, bo w ACPI to właśnie
RSDP -> RSDT/XSDT -> pozostałe tabele
stanowi kanoniczny mechanizm odkrywania tabel. Windows na platformach UEFI również opiera się na tym łańcuchu, a jeśli obecne są oba wskaźniki, preferuje
jest tylko identyfikatorem tabeli, nie adresem fizycznym. Specyfikacja opisuje
TableKey
jako klucz do późniejszego odwołania/usunięcia tabeli, nie jako wskaźnik na jej finalne położenie. (bsdio.com)
Z tego wynika praktyczny wniosek:
- adres, który wypisujesz w
SaveRt.efi
, to nie musi być finalny adres zainstalowanej tabeli, - firmware może tabelę skopiować / przenieść / opublikować z innego bufora.
To bardzo dobrze tłumaczy sytuację, w której
SaveRt.efi
pokazuje np.
0x77966000
, a
RW Everything
widzi
0x7797F1A0
. To nie musi oznaczać błędu — to jest spójne z hipotezą relokacji lub publikacji z innego bufora. To jest wniosek inżynierski oparty na tym, że protokół zwraca
TableKey
, a tabele są publikowane przez
RSDT/XSDT
, a nie „przez pozostawienie ich pod tym samym adresem”. (bsdio.com)
---
Wniosek praktyczny
Tak, przerób
GelipFindSavedRtInfo()
Obecne podejście:
- rejestr, - konkretna ścieżka, - konkretne wartości
Address
i
Length
jest zbyt kruche.
Znacznie lepiej:
- usunąć zależność od rejestru, - znajdować
SAVT
przez ACPI.
---
Jak to zrobić poprawnie
1. Nie skanuj całej pamięci RAM
Skanowanie całej pamięci po sygnaturze
SAVT
to słaby pomysł, bo:
- łatwo o false positive, - nie masz pewności, czy trafiony blok to rzeczywiście aktywna tabela ACPI, - nie weryfikujesz topologii ACPI.
Zamiast tego:
Etap A — znajdź
RSDP
Na platformie UEFI formalnie system powinien dostać
Natomiast w Twoim przypadku, skoro jesteś już w XP x64 i nie masz standardowej infrastruktury UEFI w jądrze, masz dwie praktyczne drogi:
- wariant lepszy: przekazać
RSDP
lub
XSDT
z
SaveRt.efi
/ loadera do sterownika, - wariant awaryjny: szukać
RSDP
klasycznie w obszarach legacy (
EBDA
,
0xE0000-0xFFFFF
) krokami co 16 bajtów.
Czyli: jeśli możesz zmodyfikować loader albo
SaveRt.efi
, to najczyściej byłoby przekazać sterownikowi bezpośrednio fizyczny adres
RSDP
,
XSDT
albo nawet gotowy fizyczny adres
SAVT
. To będzie bardziej deterministyczne niż późniejsze zgadywanie w kernelu.
Etap B — sparsuj
RSDT/XSDT
To jest już proste:
- mapujesz nagłówek, - sprawdzasz
Signature
,
Length
, checksum, - iterujesz po wpisach, - dla każdego wpisu mapujesz nagłówek tabeli, - szukasz
SAVT
.
Etap C — walidacja
SAVT
Sprawdzasz:
-
Header.Signature == 'SAVT'
, - checksum ACPI, -
SavedInfo.Signature == SAVRT_SIGNATURE
, -
SavedInfo.Version == SAVRT_VERSION
, -
Header.Length >= sizeof(SAVT_ACPI_TABLE)
.
Dopiero wtedy przyjmujesz tabelę jako poprawną.
---
Szkic nowej logiki sterownika
Poniżej koncepcyjny kierunek dla
GelipFindSavedRtInfo()
:
Kod: text
Zaloguj się, aby zobaczyć kod
Kod: text
Zaloguj się, aby zobaczyć kod
Jeżeli chcesz, mogę Ci rozpisać kompletną wersję tej funkcji pod WDK 7600 / XP x64.
---
Bardzo ważna uwaga: u Ciebie jest jeszcze drugi problem
Nawet gdy już znajdziesz
SAVT
, Twój sterownik ma kolejne ryzyko:
mapujesz tylko
EfiRuntimeServicesCode
, a nie mapujesz
EfiRuntimeServicesData
W
SaveRt.efi
wypisujesz zarówno:
-
RT_code
-
RT_data
ale w strukturze przekazujesz i później mapujesz tylko regiony kodu runtime.
To może być niewystarczające, bo firmware’owe
GetVariable()
i
SetVariable()
bardzo często korzystają z własnych danych runtime, nie tylko z kodu. Jeśli zmapujesz tylko kod, to:
- funkcja może wejść, - ale przy pierwszym dostępie do danych runtime poleci wyjątek albo firmware zwróci śmieci.
Co poprawić Zamiast zapisywać tylko
EfiRuntimeServicesCode
, zapisz **wszystkie deskryptory z flagą
EFI_MEMORY_RUNTIME
**, albo przynajmniej:
-
EfiRuntimeServicesCode
-
EfiRuntimeServicesData
To jest jedna z najważniejszych poprawek po samym wykrywaniu
SAVT
.
---
Trzeci problem: status EFI obcinasz z 64 bitów do 32 bitów
Masz:
Kod: text
Zaloguj się, aby zobaczyć kod
To jest niebezpieczne.
EFI_STATUS
na x64 jest 64-bitowy, a błędy mają ustawiony wysoki bit. Po obcięciu do 32 bitów tracisz najważniejszą informację: czy to był sukces czy błąd.
Przykład:
-
EFI_NOT_FOUND = 0x800000000000000E
po obcięciu dostajesz:
-
0x0000000E
czyli wartość, która **już nie niesie bitu błędu**.
Co zrobić W IOCTL-ach zwracaj:
Kod: text
Zaloguj się, aby zobaczyć kod
zamiast
ULONG Status
.
To samo dotyczy logowania.
---
Czwarty problem: metoda odkrywania tabeli a nie sam adres
Jeżeli chcesz zostać przy
SaveRt.efi
, to proponuję jedną z dwóch architektur:
Wariant A — najlepszy praktycznie
SaveRt.efi
zapisuje własny blok handoff w pamięci typu
ACPI NVS
i umieszcza jego adres w
SAVT
.
Sterownik: - znajduje
SAVT
przez
RSDT/XSDT
, - bierze z niej adres bloku, - dalej działa już na prostym, własnym formacie.
Wariant B — jeszcze prostszy
SaveRt.efi
zapisuje od razu komplet
SAVED_RT_INFO
jako część
SAVT
, a sterownik korzysta bezpośrednio z tej struktury.
To już zresztą prawie masz.
---
Co jeszcze bym poprawił w Twoim kodzie
1.
DriverObject->MajorFunction
W pokazanym fragmencie masz:
Kod: text
Zaloguj się, aby zobaczyć kod
Jeżeli to nie jest tylko błąd przy wklejaniu, to powinno być:
Kod: text
Zaloguj się, aby zobaczyć kod
2.
IOCTL_UEFIVAR_GET
Teraz zawsze zwracasz:
Kod: text
Zaloguj się, aby zobaczyć kod
Lepiej zwracać:
Kod: text
Zaloguj się, aby zobaczyć kod
bo wtedy user-mode dostaje rzeczywisty rozmiar odpowiedzi.
3. Cache type przy
MmMapIoSpace
Dajesz wszędzie
MmCached
.
To może zadziałać, ale docelowo lepiej: - zapisać atrybuty UEFI pamięci runtime, - mapować zgodnie z atrybutami.
Na wielu maszynach
MmCached
przejdzie, ale nie traktowałbym tego jako gwarancji.
4. Serializacja wywołań EFI
FAST_MUTEX
jest dobry jako minimum, ale firmware runtime bywa kapryśny:
- niereentrantny, - zależny od konkretnego CPU, - wrażliwy na przerwania / migrację wątku.
Jeżeli po naprawieniu
SAVT
pojawią się losowe zawieszenia, to kolejny krok to: - przypięcie wątku do jednego CPU, - wywołania tylko z
PASSIVE_LEVEL
, - ewentualnie ostrzejsza serializacja.
---
Co bym zrobił na Twoim miejscu
Minimalny plan naprawczy
1. **Wywaliłbym odczyt
SAVT
z rejestru.** 2. Napisałbym nową wersję
GelipFindSavedRtInfo()
: -
RSDP
-
XSDT/RSDT
-
SAVT
- checksum 3. W
SaveRt.efi
zapisywałbym: - wszystkie regiony z
EFI_MEMORY_RUNTIME
, - nie tylko
RT_code
. 4. Zmieniłbym
EFI_STATUS
w IOCTL-ach na
ULONGLONG
. 5. Dopiero potem test: -
BootOrder
-
BootCurrent
- zapis testowej zmiennej OEM.
---
Odpowiedź na Twoje pytanie wprost
Czy przerobić sterownik, aby szukał
SAVT
w pamięci zamiast w rejestrze?
**Tak. Zdecydowanie tak.
Ale precyzyjnie:
- nie „w pamięci ogólnie”, - tylko przez parsowanie ACPI (
RSDP -> XSDT/RSDT -> SAVT
)**.
To będzie: - bardziej poprawne architektonicznie, - mniej zależne od konkretnej wersji Windows, - odporniejsze na brak klucza rejestru, - zgodne z tym, jak tabele ACPI są naprawdę publikowane i odnajdywane. (learn.microsoft.com)
---
Jeśli chcesz, mogę zrobić następny krok
Mogę Ci w kolejnym poście przygotować jedną z dwóch rzeczy:
1. **gotową implementację
GelipFindSavedRtInfo()
dla XP x64 / WDK 7600, która: - znajdzie
RSDP
, - sparsuje
RSDT/XSDT
, - odnajdzie
SAVT
;
albo
2. listę konkretnych poprawek do
SaveRt.c
, aby zapisywał komplet regionów runtime (
code + data + attributes
) w formacie wygodnym dla sterownika.
Jeżeli chcesz, to najlepiej od razu przygotuję wersję „drop-in replacement”** dla Twojej funkcji
GelipFindSavedRtInfo()
.
Możesz mnie wywołać w każdym temacie pisząc @ElektrodaBot. Zastrzeżenie: Niektóre odpowiedzi udzielone przez ElektrodaBota mogą być niedokładne. Elektroda nie ponosi odpowiedzialności za dokładność, rzetelność ani kompletność prezentowanych informacji. Wszystkie odpowiedzi ElektrodaBota powinny być zweryfikowane przez użytkownika. OpenAI może monitorować i zapisywać informacje wprowadzane po wywołaniu ElektrodaBota.
@ElektrodaBot Aby nie poprawiać za dużo na raz popraw na razie tylko to co napisałeś w pod "Minimalny plan naprawczy". Zamieść pełny poprawiony kod SaveRt.c i DriverEntry.c tak abym mógł skompilować to w swoim środowisku programistycznym czyli:
SaveRt.c w edk2 2021 pod Ubuntu (mam pozostałe pliki SaveRtPkg/SaveRtPkg.dsc, SaveRtPkg/SaveRt/SaveRt.c i SaveRt.inf)
DriverEntry.c w WDK 7600.16385.1 pod WinXP 64-bit (mam też plik sources)
@ElektrodaBot Aby nie poprawiać za dużo na raz popraw na razie tylko to co napisałeś w pod "Minimalny plan naprawczy". Zamieść pełny poprawiony kod SaveRt.c i DriverEntry.c tak abym mógł skompilować...
Poniżej masz dwie pełne, spójne wersje plików po poprawkach ograniczonych do „minimalnego planu naprawczego”, czyli:
1. sterownik nie czyta już
SAVT
z rejestru, tylko szuka jej przez ACPI:
RSDP -> XSDT/RSDT -> SAVT
, 2.
SaveRt.c
zapisuje wszystkie regiony z
EFI_MEMORY_RUNTIME
, a nie tylko
EfiRuntimeServicesCode
, 3. statusy EFI w IOCTL-ach są 64-bitowe (
ULONGLONG
), 4. poprawione jest przypisanie
DriverObject->MajorFunction[...]
, 5. zachowana jest możliwie mała liczba zmian poza tym zakresem, ale poprawiłem też kilka oczywistych literówek/błędów technicznych, żeby kod był sensowny do kompilacji i użycia.
Ważne uwagi przed kompilacją
1. Zmieniona wersja struktury Podniosłem:
Kod: text
Zaloguj się, aby zobaczyć kod
bo zmienił się format
SAVED_RT_INFO
— teraz zawiera wszystkie regiony runtime wraz z typem i atrybutami.
To oznacza: - nowy sterownik nie powinien pracować ze starą tabelą
SAVT
, - trzeba użyć nowego
SaveRt.efi
razem z nowym sterownikiem.
2. Zmienione ABI IOCTL Pola
Status
w odpowiedziach IOCTL są teraz 64-bitowe:
-
UEFIVAR_GET_RESPONSE.Status
-
UEFIVAR_SET_RESPONSE.Status
Jeżeli masz aplikację user-mode korzystającą z tego sterownika, to musisz tam zmienić te same struktury.
---
SaveRt.c
Kod: text
Zaloguj się, aby zobaczyć kod
---
DriverEntry.c
Kod: text
Zaloguj się, aby zobaczyć kod
---
Plik
sources
Ten może zostać bez zmian:
Kod: Text
Zaloguj się, aby zobaczyć kod
---
Co teraz przetestować
Po wgraniu nowych wersji sprawdzałbym kolejno:
1. uruchom
SaveRt.efi
, 2. sprawdź, czy wypisuje listę
RT region[...]
, 3. uruchom XP x64, 4. załaduj sterownik, 5. w
DbgView
powinieneś zobaczyć mniej więcej taki ciąg: -
Scanning EBDA...
lub
Scanning 0xE0000-0xFFFFF...
-
RSDP found...
-
Using XSDT...
albo
Using RSDT...
-
Found ACPI table ... SAVT
-
SAVT validated
- mapowanie regionów runtime -
EFI NVRAM ready
- wynik self-testu
BootOrder
/
BootCurrent
---
Możliwy następny problem
Jeżeli mimo tego dalej nie znajdzie
RSDP
, to nie znaczy jeszcze, że cała koncepcja jest zła. To będzie raczej oznaczało, że na tej konkretnej platformie/loaderze RSDP nie jest już łatwo dostępny klasycznym skanem legacy. Wtedy następnym krokiem będzie przekazanie adresu
RSDP
albo bezpośrednio
SAVT
z
SaveRt.efi
do systemu innym kanałem.
Jeżeli chcesz, w następnym kroku mogę Ci przygotować: 1. wersję z dodatkowym debugiem ACPI, która wypisze wszystkie sygnatury tabel z
XSDT/RSDT
, 2. albo od razu wersję z fallbackiem: skanowanie pamięci po sygnaturze
SAVT
, gdy
RSDP
nie zostanie znaleziony.
Możesz mnie wywołać w każdym temacie pisząc @ElektrodaBot. Zastrzeżenie: Niektóre odpowiedzi udzielone przez ElektrodaBota mogą być niedokładne. Elektroda nie ponosi odpowiedzialności za dokładność, rzetelność ani kompletność prezentowanych informacji. Wszystkie odpowiedzi ElektrodaBota powinny być zweryfikowane przez użytkownika. OpenAI może monitorować i zapisywać informacje wprowadzane po wywołaniu ElektrodaBota.
/root/MyWorkspace/SaveRtPkg/SaveRt/SaveRt.c:307:70: error: ‘b’ undeclared (first use in this function)
Status = gBS->AllocatePool(EfiLoaderData, MemMapSize, (VOID [b])&MemMap);
^
/root/MyWorkspace/SaveRtPkg/SaveRt/SaveRt.c:307:70: note: each undeclared identifier is reported only once for each function it appears in
/root/MyWorkspace/SaveRtPkg/SaveRt/SaveRt.c:307:9: error: declaration of type name as array of voids
Status = gBS->AllocatePool(EfiLoaderData, MemMapSize, (VOID [b])&MemMap);
^
/root/MyWorkspace/SaveRtPkg/SaveRt/SaveRt.c:337:28: error: expected expression before ‘/’ token
(VOID [/b])&AcpiTableProtocol
^
/root/MyWorkspace/SaveRtPkg/SaveRt/SaveRt.c: In function ‘ChainloadBootloader’:
/root/MyWorkspace/SaveRtPkg/SaveRt/SaveRt.c:388:28: error: ‘b’ undeclared (first use in this function)
(VOID [b])&LoadedImage
^
/root/MyWorkspace/SaveRtPkg/SaveRt/SaveRt.c:388:21: error: declaration of type name as array of voids
(VOID [b])&LoadedImage
^
/root/MyWorkspace/SaveRtPkg/SaveRt/SaveRt.c: At top level:
cc1: error: unrecognized command line option ‘-Wno-unused-const-variable’ [-Werror]
cc1: all warnings being treated as errors
GNUmakefile:324: recipe for target '/root/MyWorkspace/Build/SaveRtPkg/RELEASE_GCC5/X64/SaveRtPkg/SaveRt/SaveRt/OUTPUT/SaveRt.obj' failed
make: *** [/root/MyWorkspace/Build/SaveRtPkg/RELEASE_GCC5/X64/SaveRtPkg/SaveRt/SaveRt/OUTPUT/SaveRt.obj] Error 1
build.py...
: error 7000: Failed to execute command
make tbuild [/root/MyWorkspace/Build/SaveRtPkg/RELEASE_GCC5/X64/SaveRtPkg/SaveRt/SaveRt]
build.py...
: error F002: Failed to build module
/root/MyWorkspace/SaveRtPkg/SaveRt/SaveRt.inf [X64, GCC5, RELEASE]
- Failed -
Build end time: 15:57:36, Apr.08 2026
Build total time: 00:00:15
Popraw zamieszczając pełny poprawiony kod SaveRt.c
1. W poprzednio wklejonym kodzie forum/formatowanie uszkodziło rzutowania: - zamiast
(VOID [b])&MemMap
- zrobiło się coś w rodzaju
(VOID [b])&MemMap
To są zwykłe artefakty formatowania i właśnie to generowało błędy: -
‘b’ undeclared
-
declaration of type name as array of voids
2. Błąd:
Kod: text
Zaloguj się, aby zobaczyć kod
nie wynika z
SaveRt.c
**, tylko z konfiguracji toolchaina
edk2/GCC5
w Twoim środowisku. Czyli: - kod poniżej naprawia błędy składniowe, - ale jeśli ten komunikat nadal zostanie, to trzeba osobno poprawić
tools_def.txt
albo użyć nowszego GCC.
---
Ważne Ten plik jest zgodny z wcześniej zmienionym sterownikiem, czyli:
-
SAVRT_VERSION = 2
- zapisuje **wszystkie regiony z
EFI_MEMORY_RUNTIME
- struktura
SAVED_RT_INFO
jest rozszerzona
Czyli
SaveRt.efi
i
UefiVarPoC.sys
muszą być używane w tej samej wersji**.
---
Pełny
SaveRt.c
Kod: text
Zaloguj się, aby zobaczyć kod
---
Jeśli po tej podmianie nadal zostanie tylko ten błąd:
Kod: text
Zaloguj się, aby zobaczyć kod
to znaczy, że źródło jest już poprawne, a problem jest wyłącznie w konfiguracji GCC/edk2.
Wtedy trzeba zrobić jedną z rzeczy:
Opcja 1 — poprawić
Conf/tools_def.txt
usunąć flagę:
Kod: text
Zaloguj się, aby zobaczyć kod
z wpisów dla
GCC5
.
Opcja 2 — użyć nowszego GCC bo Twoje aktualne
cc1
tej opcji nie zna.
---
Co proponuję dalej
Jeżeli chcesz, w następnym poście mogę od razu podać:
1. krótką poprawkę do
SaveRt.inf
, żeby uniknąć potencjalnych problemów z bibliotekami, 2. albo pełny, finalny
DriverEntry.c
jeszcze raz, ale już w wersji dokładnie sparowanej z tym
SaveRt.c
, 3. albo minimalną poprawkę
tools_def.txt
pod stary GCC, żeby zniknął ostatni błąd toolchaina.
Możesz mnie wywołać w każdym temacie pisząc @ElektrodaBot. Zastrzeżenie: Niektóre odpowiedzi udzielone przez ElektrodaBota mogą być niedokładne. Elektroda nie ponosi odpowiedzialności za dokładność, rzetelność ani kompletność prezentowanych informacji. Wszystkie odpowiedzi ElektrodaBota powinny być zweryfikowane przez użytkownika. OpenAI może monitorować i zapisywać informacje wprowadzane po wywołaniu ElektrodaBota.
@ElektrodaBot Nie trzeba nic zmieniać w żadnej konfiguracji toolchaina - te wszystkie błędy kompilacji produkuje forum ponieważ w tym przypadku zamienia wszelkie znaki dwie gwiazdki na znaczniki formatowania pogrubienia - litera b w nawiasie kwadratowym ze znakiem / lub bez - ech Żeby to zauważyć musiałem porównać mój stary kod przed poprawkami z kodem jaki wstawiłem na forum i wszystko stało się jasne.
Po poprawieniu kodu SaveRt.c z postu #4 kompilacja przebiega w 18 sekund
- Done -
Build end time: 16:56:09, Apr.08 2026
Build total time: 00:00:18
Pytanie - czy możesz wstawiać kod na zewnętrzne serwery np. pastebin.com a na forum dawać tylko link ?
Wracając to tematu:
Przetestowałem SaveRt.efi w VMware i na laptopie. W VMware nie może opublikować danych RT bo błąd ACPI Table Protocol not found a na laptopie publikuje dane RT, ale sterownik w WinXP nie widzi tabel ACPI:
[UefiNvram] DriverEntry
[UefiNvram] Scanning EBDA for RSDP at 0x9D800
[UefiNvram] Scanning 0xE0000-0xFFFFF for RSDP
[UefiNvram] RSDP not found
[UefiNvram] SAVT not found via ACPI
[UefiNvram] WARNING: EFI not available
Trzeba rozszerzyć skanowanie albo zmienić sposób dotarcia do tabeli ACPI SAVT.
Popraw kod wstawiając pełny poprawiony kod - jeśli możesz jako link do pastebin.com lub w inny sposób aby forum nie popsuło kodu.
@ElektrodaBot Nie trzeba nic zmieniać w żadnej konfiguracji toolchaina - te wszystkie błędy kompilacji produkuje forum ponieważ w tym przypadku zamienia wszelkie znaki dwie gwiazdki na znaczniki f...
Nie, z tego interfejsu nie mogę wrzucać plików na pastebin ani inne zewnętrzne serwery i publikować tam gotowych plików.
Mogę natomiast zrobić dwie rzeczy: 1. wkleić pełny kod tutaj, 2. napisać go tak, żeby nie zawierał sekwencji dwóch gwiazdek, skoro forum ją psuje.
W Twoim przypadku samo „szukanie RSDP szerzej” nie jest najlepszą drogą. Skoro XP uruchomiony w ten sposób nie widzi klasycznej ścieżki do ACPI, to lepiej zmienić mechanizm przekazania danych.
Co zmieniłem
Zamiast polegać na: -
RSDP -> XSDT/RSDT -> SAVT
dodałem blok handoff w
EfiACPIMemoryNVS
, który:
-
SaveRt.efi
zapisuje poniżej 64 MB fizycznie, - sterownik
UefiVarPoC.sys
skanuje po stronach i znajduje po własnej sygnaturze, - zawiera komplet
SAVED_RT_INFO
.
Dzięki temu: - działa także wtedy, gdy XP nie widzi ACPI, - działa także wtedy, gdy w VMware nie ma
ACPI Table Protocol
, - tabela
SAVT
może dalej być publikowana pomocniczo, ale sterownik już nie zależy od niej.
Poniżej daję pełny
SaveRt.c
i pełny
DriverEntry.c
w wersji sparowanej ze sobą.
Uwaga praktyczna: - oba pliki używają: -
SAVRT_VERSION = 2
-
MAX_RT_REGIONS = 64
- bloku handoff o sygnaturze
"SAVTHOF1"
Jeżeli podmienisz tylko jeden z nich, to nie zadziała.
---
SaveRt.c
Kod: text
Zaloguj się, aby zobaczyć kod
---
DriverEntry.c
Kod: text
Zaloguj się, aby zobaczyć kod
---
Dlaczego ten wariant powinien zadziałać lepiej
1. Nie zależy od RSDP U Ciebie log pokazał:
Kod: text
Zaloguj się, aby zobaczyć kod
To oznacza, że dla tego sposobu bootowania XP legacy-skany RSDP są niewystarczające. Nowy wariant tego nie potrzebuje.
2. Nie zależy od
ACPI Table Protocol
W VMware miałeś:
Kod: text
Zaloguj się, aby zobaczyć kod
Teraz to już nie jest blokujące, bo: -
SAVT
jest tylko dodatkiem, - kluczowy jest handoff block.
3. Sterownik dostaje komplet mapowań runtime Nie tylko
RT_code
, ale wszystkie deskryptory z
EFI_MEMORY_RUNTIME
, więc szansa powodzenia
GetVariable
i
SetVariable
jest wyraźnie większa.
---
Co przetestować po kolei
Test 1 — log z
SaveRt.efi
Oczekiwane wpisy: -
Saved RT pointers
-
Runtime regions (EFI_MEMORY_RUNTIME)
-
Handoff block saved at ...
- opcjonalnie: -
ACPI table SAVT installed...
- albo
ACPI Table Protocol not found...
Najważniejsze jest:
Kod: text
Zaloguj się, aby zobaczyć kod
Test 2 — log sterownika Oczekiwane:
Kod: text
Zaloguj się, aby zobaczyć kod
Test 3 — self-test Najlepiej, żeby pokazał: -
BootOrder
-
BootCurrent
---
Jeśli nadal nie zadziała
Wtedy następny krok będzie już bardzo konkretny:
1. dodać do sterownika log: - pierwszych 16 bajtów znalezionego bloku, - liczby regionów, - adresów
GetVariable
i
SetVariable
;
2. ewentualnie ograniczyć lub zmienić typ cache przy
MmMapIoSpace
;
3. jeżeli będą wyjątki przy wywołaniu firmware, wtedy trzeba będzie: - wymusić jeden CPU, - dopilnować
PASSIVE_LEVEL
, - ewentualnie dodać prosty wrapper ASM.
---
Jeżeli chcesz, w następnym poście mogę przygotować jeszcze jedną wersję: - z dodatkowym bardzo szczegółowym debugowaniem, taką typowo „diagnostyczną”, żeby po jednym logu z DbgView było wiadomo dokładnie, na którym etapie to staje.
Możesz mnie wywołać w każdym temacie pisząc @ElektrodaBot. Zastrzeżenie: Niektóre odpowiedzi udzielone przez ElektrodaBota mogą być niedokładne. Elektroda nie ponosi odpowiedzialności za dokładność, rzetelność ani kompletność prezentowanych informacji. Wszystkie odpowiedzi ElektrodaBota powinny być zweryfikowane przez użytkownika. OpenAI może monitorować i zapisywać informacje wprowadzane po wywołaniu ElektrodaBota.
✨ Opis dotyczy narzędzi do edycji UEFI BootMenu NVRAM pod WinXP 64-bit uruchamianym przez bootmgfw.efi z Windows Longhorn. SaveRt.efi zapisuje tabele UEFI RT w tabeli ACPI SAVT, jednak sterownik UefiVarPoC.sys nie potrafi odczytać klucza SAVT z rejestru Windows i zgłasza błąd Cannot open SAVT key oraz WARNING: EFI not available. RW Everything pod WinXP 64-bit widzi tabelę SAVT, ale czasem pod innym adresem niż ustawiony przez SaveRt.efi; na innym komputerze adres w RW Everything zgadza się z adresem zapisanym przez SaveRt.efi, lecz sterownik nadal nie znajduje tabeli w rejestrze. Wygenerowane przez model językowy.