Zanim wprowadzimy niezbędne zmiany w klasie Guest, będziemy potrzebować kilku klas pomocniczych:
- RemoteMemory Celem tej klasy jest zapewnienie interfejsu alloc/free do pamięci gościa. Będzie ona instancjonowana z informacji memorymap komunikatów rozruchowych.
• Code Ta klasa abstrahuje wywołanie asemblera w celu wygenerowania kodu binarnego z ciągu zawierającego asembler.
Naszą implementację RemoteMemory oparliśmy na module porcji 9. Metody add_region (1) i del_region (2) będą używane wyłącznie na etapie inicjalizacji. Gdy obiekt zostanie w pełni zainicjowany, pamięć może zostać zażądana za pomocą alloc (3), wykorzystując żenująco nieefektywną strategię alokacji, ale będzie to wystarczające dla naszych potrzeb.
Kod (1) jest tworzony z ciągu kodu asemblera i słownika symboli. Definicje tych symboli są dodawane do kodu asemblera razem z dyrektywą „include macros.asm”, gdzie możemy dodawać nasze niestandardowe makra. Jedyną metodą tej klasy jest build (2), która wywołuje asembler i kompiluje kod pod określonym adresem bazowym, zwracając wynikowy plik binarny. Teraz możemy przejść do modyfikacji klasy Guest:
Pierwsza zmiana dotyczy metody messages, więc teraz wywołujemy _init_boot_info (1), gdy nadejdzie komunikat rozruchowy, aby zainicjować dwie właściwości: symbole i pamięć (instancję RemoteMemory). Zakresy adresów opisujące obszary dostępnej pamięci są dodawane do obiektu memory, a zakres adresu od zera do końca jądra jest usuwany z dostępnej pamięci. Zaimplementowano nowe metody w celu zbudowania operacji, które składają się na komunikat żądania:
- op_write (2) Pobiera instancję Code (i opcjonalnie adres bazowy), buduje kod i koduje wynikowy plik binarny w operacji zapisu, która jest następnie dodawana do listy operacji żądania.
- op_exec (3) Pobiera adres i koduje go w operacji wykonania, dodając go do listy operacji.
- op_commit (4) Pobiera zawartość z listy operacji w celu zbudowania i wysłania komunikatu żądania.
Te metody zapewniają API niskiego poziomu, ale zaimplementowaliśmy metodę execute (5) dla najczęstszego przypadku użycia, wymagając jedynie instancji Code. Przetestujmy tę nową funkcjonalność, wykonując kod w gościu:
Gdy nadejdzie komunikat rozruchowy, skrypt wstrzykuje fragment kodu do komputera gościa, aby wysłać komunikat „hello world!” (1)
UWAGA: Makra OOB_PRINT i REPLY_EMPTY są zdefiniowane w pliku „macros.asm”, który został pominięty w kodzie ze względu na zwięzłość.
Możemy zobaczyć komunikat „hello world!” i pustą odpowiedź wygenerowaną przez wstrzyknięty kod!