ゼロからのOS自作入門 読みメモ 2章 その5

その4の続き

EFI_MEMORY_DESCRIPTOR構造体

///
/// Definition of an EFI memory descriptor.
///
typedef struct {
  ///
  /// Type of the memory region.
  /// Type EFI_MEMORY_TYPE is defined in the
  /// AllocatePages() function description.
  ///
  UINT32                Type;
  ///
  /// Physical address of the first byte in the memory region. PhysicalStart must be
  /// aligned on a 4 KiB boundary, and must not be above 0xfffffffffffff000. Type
  /// EFI_PHYSICAL_ADDRESS is defined in the AllocatePages() function description
  ///
  EFI_PHYSICAL_ADDRESS  PhysicalStart;
  ///
  /// Virtual address of the first byte in the memory region.
  /// VirtualStart must be aligned on a 4 KiB boundary,
  /// and must not be above 0xfffffffffffff000.
  ///
  EFI_VIRTUAL_ADDRESS   VirtualStart;
  ///
  /// NumberOfPagesNumber of 4 KiB pages in the memory region.
  /// NumberOfPages must not be 0, and must not be any value
  /// that would represent a memory page with a start address,
  /// either physical or virtual, above 0xfffffffffffff000.
  ///
  UINT64                NumberOfPages;
  ///
  /// Attributes of the memory region that describe the bit mask of capabilities
  /// for that memory region, and not necessarily the current settings for that
  /// memory region.
  ///
  UINT64                Attribute;
} EFI_MEMORY_DESCRIPTOR;
  • Type
    • メモリ領域の種別
  • PhysicalStart
    • メモリ領域先頭の物理メモリアドレス
  • VirtualStart
  • NumberOfPages
    • メモリ領域の大きさ
  • Attribute
    • メモリ領域が使える用途を示すビット集合

メモリマップ構造体

struct MemoryMap {
  UINTN buffer_size;
  VOID* buffer;
  UINTN map_size;
  UINTN map_key;
  UINTN descriptor_size;
  UINT32 descriptor_version;
}

メモリマップのファイルへの保存

  • Main.cのメモリマップのファイルへの保存部
  CHAR8 memmap_buf[4096 * 4]; // メモリマップを確保
  struct MemoryMap memmap = {sizeof(memmap_buf), memmap_buf, 0, 0, 0, 0};
  GetMemoryMap(&memmap); // メモリマップを取得、gBS->GetMemoryMapに値が入る

  EFI_FILE_PROTOCOL* root_dir;
  OpenRootDir(image_handle, &root_dir); // 書き込み先のファイルを開く。存在しなければ新規作成。これはルートディレクトリを開いている。

  EFI_FILE_PROTOCOL* memmap_file;
  root_dir->Open(
      root_dir, &memmap_file, L"\\memmap",  // root_dir を開いている。ファイル名はmemmap
      EFI_FILE_MODE_READ | EFI_FILE_MORE_WRITE | EFI_FILE_MORE_CREATE, 0); // 読み|書き|作成モードでオープン

  SaveMemoryMap(&memmap, memmap_file); // ここで取得したメモリマップを保存する
  memmap_file->Close(memmap_file); // ファイルを閉じる

以下追ったコード

  • EFI_FILE_PROTOCOL
/// The EFI_FILE_PROTOCOL provides file IO access to supported file systems.
/// An EFI_FILE_PROTOCOL provides access to a file's or directory's contents,
/// and is also a reference to a location in the directory tree of the file system
/// in which the file resides. With any given file handle, other files may be opened
/// relative to this file's location, yielding new file handles.
///
struct _EFI_FILE_PROTOCOL {
  ///
  /// The version of the EFI_FILE_PROTOCOL interface. The version specified
  /// by this specification is EFI_FILE_PROTOCOL_LATEST_REVISION.
  /// Future versions are required to be backward compatible to version 1.0.
  ///
  UINT64                Revision;
  EFI_FILE_OPEN         Open;
  EFI_FILE_CLOSE        Close;
  EFI_FILE_DELETE       Delete;
  EFI_FILE_READ         Read;
  EFI_FILE_WRITE        Write;
  EFI_FILE_GET_POSITION GetPosition;
  EFI_FILE_SET_POSITION SetPosition;
  EFI_FILE_GET_INFO     GetInfo;
  EFI_FILE_SET_INFO     SetInfo;
  EFI_FILE_FLUSH        Flush;
  EFI_FILE_OPEN_EX      OpenEx;
  EFI_FILE_READ_EX      ReadEx;
  EFI_FILE_WRITE_EX     WriteEx;
  EFI_FILE_FLUSH_EX     FlushEx;
};

サポートされているファイルシステムへのファイルIOアクセスを提供している

  • OpenRootDir
    • Main.cで定義したOpenRootDir
EFI_STATUS OpenRootDir(EFI_HANDLE image_handle, EFI_FILE_PROTOCOL** root) {
  EFI_LOADED_IMAGE_PROTOCOL* loaded_image;
  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* fs;

  // handle のチェック
  gBS->OpenProtocol(
      image_handle,
      &gEfiLoadedImageProtocolGuid,
      (VOID**)&loaded_image,
      image_handle,
      NULL,
      EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);

  gBS->OpenProtocol(
      loaded_image->DeviceHandle,
      &gEfiSimpleFileSystemProtocolGuid,
      (VOID**)&fs,
      image_handle,
      NULL,
      EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);

  // root を開く
  fs->OpenVolume(fs, root);

  return EFI_SUCCESS;
}
  • EFI_OPEN_PROTOCOL
/**
  Queries a handle to determine if it supports a specified protocol. If the protocol is supported by the
  handle, it opens the protocol on behalf of the calling agent.

...
**/
typedef
EFI_STATUS
(EFIAPI *EFI_OPEN_PROTOCOL)(
  IN  EFI_HANDLE                Handle,
  IN  EFI_GUID                  *Protocol,
  OUT VOID                      **Interface, OPTIONAL
  IN  EFI_HANDLE                AgentHandle,
  IN  EFI_HANDLE                ControllerHandle,
  IN  UINT32                    Attributes
  );

handleが指定されたプロトコルをサポートしているかどうかを判別する

  • OpenVolume
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume;
/**
  Open the root directory on a volume.
...
**/
typedef
EFI_STATUS
(EFIAPI *EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME)(
  IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL    *This,
  OUT EFI_FILE_PROTOCOL                 **Root
  );

rootディレクトリを開く

  • EFI_FILE_OPEN
/**
  Opens a new file relative to the source file's location.
...
**/
typedef
EFI_STATUS
(EFIAPI *EFI_FILE_OPEN)(
  IN EFI_FILE_PROTOCOL        *This, // ファイルを開く場所
  OUT EFI_FILE_PROTOCOL       **NewHandle, // 開いたファイル?
  IN CHAR16                   *FileName, // 開くファイルの名前
  IN UINT64                   OpenMode, // 作成読み書きのモード指定
  IN UINT64                   Attributes
  );

指定したファイルを開く

  • EFI_FILE_CLOSE
/**
  Closes a specified file handle.
...
**/
typedef
EFI_STATUS
(EFIAPI *EFI_FILE_CLOSE)(
  IN EFI_FILE_PROTOCOL  *This
  );

指定したファイルを閉じる

ペース遅いけどSaveMemoryMap次追います