logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

UefiVarPoC.sys nie widzi tabeli ACPI SAVT w rejestrze, jak znaleźć ją w pamięci?

Gelip 08 Kwi 2026 20:56 234 8
REKLAMA
  • #1 21880068
    Gelip
    Poziom 36  
    Posty: 5206
    Pomógł: 321
    Ocena: 607
    @ElektrodaBot

    Opis


    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)

    Sposób działania


    * aplikacja SaveRt.efi zapisuje tabele UEFI RT w tabeli ACPI SAVT
    ACPI table SAVT installed, key=0x716C2018
    
    *** RT saved in ACPI table SAVT at 0x0000000077966000 *** 

    * sterownik UefiVarPoC.sys powinien odczytać tę tabelę z rejestru Windows ale jej chyba tam niema bo DbgView pokazuje:
    [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:



    SaveRt.c
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • #2 21880075
    ElektrodaBot
    AI od OpenAI ChatGPT4
    Posty: 8774
    Pomógł: 353
    Ocena: 930
    Gelip napisał:
    @ElektrodaBot

    Opis


    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
    XSDT
    . (learn.microsoft.com)

    ---

    Co najprawdopodobniej jest teraz nie tak

    1. Problemem nie jest sama tabela
    SAVT
    , tylko sposób jej szukania


    Twój sterownik zakłada istnienie klucza:

    Kod: text
    Zaloguj się, aby zobaczyć kod


    i dodatkowo oczekuje w nim wartości
    Address
    oraz
    Length
    .

    To założenie jest bardzo wątłe. Sam komunikat:

    Kod: text
    Zaloguj się, aby zobaczyć kod


    oznacza tylko tyle, że pod tą ścieżką nie ma klucza. To nie dowodzi, że tabela
    SAVT
    nie istnieje w ACPI.

    Dodatkowo rejestr nie jest źródłem pierwotnym dla tabel ACPI. Źródłem pierwotnym są tabele wskazane przez
    RSDP
    i zebrane w
    RSDT/XSDT
    . (learn.microsoft.com)

    2. Adres z
    RW Everything
    nie musi zgadzać się z adresem wypisanym przez
    SaveRt.efi


    To jest bardzo ważne.

    EFI_ACPI_TABLE_PROTOCOL.InstallAcpiTable()
    instaluje tabelę do
    RSDT/XSDT
    , a zwracany
    TableKey
    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ć
    RSDP
    przez EFI System Table. Windows tak właśnie robi. (learn.microsoft.com)

    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.
  • REKLAMA
  • #3 21880090
    Gelip
    Poziom 36  
    Posty: 5206
    Pomógł: 321
    Ocena: 607
    @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)
  • #4 21880097
    ElektrodaBot
    AI od OpenAI ChatGPT4
    Posty: 8774
    Pomógł: 353
    Ocena: 930
    Gelip napisał:
    @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.
  • REKLAMA
  • #5 21880114
    Gelip
    Poziom 36  
    Posty: 5206
    Pomógł: 321
    Ocena: 607
    @ElektrodaBot
    Sterownik UefiVarPoC.sys skompilował się.
    Sterownik SaveRt.efi - trochę błędów kompilacji:
    /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
  • REKLAMA
  • #6 21880122
    ElektrodaBot
    AI od OpenAI ChatGPT4
    Posty: 8774
    Pomógł: 353
    Ocena: 930
    Gelip napisał:
    @ElektrodaBot
    Sterownik UefiVarPoC.sys skompilował się.
    Sterownik SaveRt.efi - trochę błędów kompilacji:
    /root/MyWorkspace/SaveRtPkg/SaveRt/SaveRt.c:307:70: error: ‘b’ undeclared ...
    Poniżej masz pełny poprawiony
    SaveRt.c
    .

    Najpierw dwie krótkie uwagi:

    Co powodowało błędy kompilacji

    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.
  • #7 21880179
    Gelip
    Poziom 36  
    Posty: 5206
    Pomógł: 321
    Ocena: 607
    @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.
  • #8 21880190
    ElektrodaBot
    AI od OpenAI ChatGPT4
    Posty: 8774
    Pomógł: 353
    Ocena: 930
    Gelip napisał:
    @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.
  • #9 21880204
    Gelip
    Poziom 36  
    Posty: 5206
    Pomógł: 321
    Ocena: 607
    @ElektrodaBot
    Taaaak - wersja z blokiem handoff działa na każdym komputerze - także w VMware:
    Spoiler:
    [UefiNvram] DriverEntry
    [UefiNvram] Scanning low memory for handoff block: 0x80000 - 0x4000000
    [UefiNvram] Handoff block found at PA=0x3FFF000
    [UefiNvram]   Version:          1
    [UefiNvram]   Size:             1908
    [UefiNvram]   SAVT source addr: 0x3FFA2000
    [UefiNvram] RT info:
    [UefiNvram]   GetVariable phys: 0x3FF176C0
    [UefiNvram]   SetVariable phys: 0x3FF175B0
    [UefiNvram]   RtRegionCount:    7
    [UefiNvram]   Region[0]: RT_code  PA=0x3E7CB000  pages=5  attr=0x800000000000000F
    [UefiNvram] Mapped RT_code  PA=0x3E7CB000  VA=FFFFFADFE21E8000  size=20480
    [UefiNvram]   Region[1]: RT_code  PA=0x3EBE3000  pages=6  attr=0x800000000000000F
    [UefiNvram] Mapped RT_code  PA=0x3EBE3000  VA=FFFFFADFE21E1000  size=24576
    [UefiNvram]   Region[2]: RT_code  PA=0x3EC34000  pages=2  attr=0x800000000000000F
    [UefiNvram] Mapped RT_code  PA=0x3EC34000  VA=FFFFFADFE51E9000  size=8192
    [UefiNvram]   Region[3]: RT_code  PA=0x3FF17000  pages=32  attr=0x800000000000000F
    [UefiNvram] Mapped RT_code  PA=0x3FF17000  VA=FFFFFADFE1C1D000  size=131072
    [UefiNvram]   Region[4]: RT_data  PA=0x3FF37000  pages=75  attr=0x800000000000000F
    [UefiNvram] Mapped RT_data  PA=0x3FF37000  VA=FFFFFADFE1BD2000  size=307200
    [UefiNvram]   Region[5]: RT_data  PA=0x3FF82000  pages=5  attr=0x800000000000000F
    [UefiNvram] Mapped RT_data  PA=0x3FF82000  VA=FFFFFADFE21DA000  size=20480
    [UefiNvram]   Region[6]: MMIO  PA=0xFFC00000  pages=24  attr=0x8000000000000000
    [UefiNvram] Mapped MMIO  PA=0xFFC00000  VA=FFFFFADFE1BBA000  size=98304
    [UefiNvram] GetVariable=FFFFFADFE1C1D6C0  SetVariable=FFFFFADFE1C1D5B0
    [UefiNvram] EFI NVRAM ready
    [UefiNvram] === SELF TEST ===
    [UefiNvram] Calling GetVariable('BootOrder')...
    [UefiNvram]   Result: efiStatus=0x0 len=10 attrs=0x00000007
    [UefiNvram]   BootOrder (5 entries):
     0001
     0000
     0002
     0003
     0004
     
    [UefiNvram]   BootCurrent: status=0x0 val=0001
    [UefiNvram] === END SELF TEST ===
    

Podsumowanie tematu

✨ 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.
REKLAMA