OSDev
http://osdev.ru/

EFI Boot Services - загрузка файла
http://osdev.ru/viewtopic.php?f=6&t=1118
Страница 1 из 1

Автор:  KIV [ 10 окт 2015, 02:39 ]
Заголовок сообщения:  EFI Boot Services - загрузка файла

Решил, что пора бы разобраться с UEFI, всё же подавляющее большинство новых материнских плат уже его поддерживает. Для начала поигрался с консольным вводом-выводом, но этого явно мало для создания полноценного загрузчика. А именно - нужно уметь грузить файлы в ОЗУ с загрузочного диска. Если под BIOS был простой int 0x13, а драйвер ФС каждый лепил сам, то на UEFI эти функции уже реализованы в прошивке. Более того, до вызова Exit Boot Services прямой доступ к железу строго-настрого запрещён спецификацией.

В отличии от BIOS UEFI куда более универсальная и всеохватывающая спецификация (местами, быть может даже слишком), поэтому так сходу разобраться у меня не получается. Никто не может подкинуть примера чтения в ОЗУ файла, находящегося на той же ФС, что и наш загрузчик?

Автор:  dixie [ 11 окт 2015, 12:49 ]
Заголовок сообщения:  Re: EFI Boot Services - загрузка файла

EFI местами крив и уныл до безобразия... Работа с экраном, с клавиатурой - даже новые протоколы.
Дикие баги - в общем, бяка :) Но есть уже везде, да.

Я использую древний EFI тулкит, аж под 1.x, добавляя прямо в свой код описание новых протоколов - поскольку он ближе и понятней (проще ;)).
Вот в этом архиве есть архив с 64-битной частью EFIшного варианта загрузчика (QSINIT_EFI.ZIP), там можно покурить на тему работы с клавиатурой, экраном, чтение файла, определение загрузочного диска/раздела. Это, собстно, типа hal функций, которые зовутся из 32-битной части.

Чтение файла там mfs_open/read/close (имя в статическом буфере).

Автор:  KIV [ 16 окт 2015, 13:48 ]
Заголовок сообщения:  Re: EFI Boot Services - загрузка файла

В итоге реализовал следующую функцию загрузки файла:
Код:
if (efiSysTable->BootServices->OpenProtocol(efiImageHandle, &loadedImageProtocol, (void**)&efiLoadedImage,
      efiImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL) != EFI_SUCCESS) {
   fatalError("failed to get LoadedImageProtocol");
}
if (efiSysTable->BootServices->OpenProtocol(efiLoadedImage->DeviceHandle, &simpleFileSystemProtocol, (void**)&efiFileIoInterface,
      efiImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL) != EFI_SUCCESS) {
   fatalError("failed to get SimpleFileSystemProtocol");
}
if (efiFileIoInterface->OpenVolume(efiFileIoInterface, &efiFileSystem) != EFI_SUCCESS) {
   fatalError("failed to get FileProtocol");
}   
...
int platform_loadFile(const char *fileName, void *buffer, int bufferSize) {
   CHAR16 *fileNameUTF16 = makeUTF16(fileName);
   if (fileNameUTF16 == NULL) return -1;
   for (CHAR16 *chr = fileNameUTF16; *chr; chr++) {
      if (*chr == '/') {
         *chr = '\\';
      }
   }
   EFI_FILE_HANDLE file;
   int count = -1;
   if (efiFileSystem->Open(efiFileSystem, &file, fileNameUTF16, EFI_FILE_MODE_READ, 0) == EFI_SUCCESS) {
      UINTN infoSize = 0;
      if (file->GetInfo(file, &fileInfoId, &infoSize, NULL) == EFI_BUFFER_TOO_SMALL) {
         EFI_FILE_INFO *info = malloc(infoSize);
         if (file->GetInfo(file, &fileInfoId, &infoSize, info) == EFI_SUCCESS) {
            if (buffer && bufferSize) {
               UINTN cnt = bufferSize;
               if (file->Read(file, &cnt, buffer) == EFI_SUCCESS) {
                  count = cnt;
               }
            } else {
               count = info->FileSize;
            }
         } else
         free(info);
      } else
      file->Close(file);
   }
   free(fileNameUTF16);
   return count;
}

Если не указывать буфер для загрузки, то можно узнать размер файла, затем выделить под него место и прочитать данные. Мне этого в принципе достаточно - гружу файл целиком, а потом в ОЗУ разбираюсь уже что загрузил.

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/