Mercurial > hg > Members > taiki > EFIKernel
view boot/bootx64.c @ 15:ac5d699b9787
add config and open.
author | taiki |
---|---|
date | Tue, 29 Jan 2013 14:45:00 +0900 |
parents | 479240de2d64 09ced7d8f64a |
children | 2013da6b3211 |
line wrap: on
line source
/* * This program is EFI boot loader. * load Mach-O kernel, and locate on memory, and jump kernel. * * Author: Taiki TAIRA. */ #include "bootx64.h" INTN efi_error(CHAR16* error_massage, EFI_STATUS status) { Print(L"%s", error_massage); if (status < 0) return ERROR; return SUCCESS; } EFI_STATUS load_mach_o() { Print(L"kernel load ... \n"); return EFI_SUCCESS; } EFI_STATUS open(CHAR16 *name, UINTN *fd, fs_t *fs) { EFI_STATUS status; EFI_FILE_HANDLE fh; if (name == NULL || fd == NULL) return EFI_INVALID_PARAMETER; status = uefi_call_wrapper(fs->volume->Open, 5, fs->volume, &fh, name, EFI_FILE_MODE_READ, (UINT64)0); if (status == EFI_SUCCESS) { *fd = (UINTN)fh; } return status; } EFI_STATUS config_fs_one(EFI_HANDLE dev, VOID *fs) { EFI_STATUS status; EFI_FILE_IO_INTERFACE *volume; EFI_FILE_HANDLE volume_fh; EFI_GUID LocalFsProtocol = LOCALFS_PROTOCOL; status = uefi_call_wrapper(BS->HandleProtocol, 3, dev, &FileSystemProtocol, (VOID **)&volume); if (EFI_ERROR(status)) return EFI_INVALID_PARAMETER; /* alloc */ status = uefi_call_wrapper(volume->OpenVolume, 2, volume, &volume_fh); if (EFI_ERROR(status)) { Print(L"Can not open volume.\n"); return status; } Print(L"Open volume.\n"); fs_t *fs_tmp = (fs_t *)fs; SetMem(fs, sizeof(fs_t), 0); fs_tmp->dev = dev; fs_tmp->volume = volume_fh; status = LibInstallProtocolInterfaces(&dev, &LocalFsProtocol, fs, NULL); if (EFI_ERROR(status)) return status; /* free */ return EFI_SUCCESS; } EFI_STATUS config_fs(EFI_HANDLE boot_handle, fs_t *fs, dev_tab_t *boot_dev) { UINTN size = 0; UINTN i; EFI_GUID *proto = NULL; Print(L"configure filesystems for all volume. \n"); uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, &FileSystemProtocol, NULL, &size, NULL); if (size == 0) return EFI_UNSUPPORTED; /* alloc */ dev_tab_t *dev_tab = NULL; // all devices EFI_STATUS status = uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, &FileSystemProtocol, NULL, &size, (VOID **)dev_tab); if (status != EFI_SUCCESS) { efi_error(L"can't get handler.\n", status); /* free */ return status; } UINTN ndev = size / sizeof(EFI_HANDLE); for (i = 0; i < ndev; i++) { VOID *fs = NULL; config_fs_one(dev_tab[i].dev, &fs); dev_tab[i].fs = fs; } status = uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, proto, NULL, &size, NULL); if (EFI_ERROR(status)) { Print(L"No useable filesystem found.\n"); return status; } SetMem(proto, sizeof(EFI_HANDLE), 0); uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, &proto, NULL, &size, NULL); EFI_HANDLE *tab = NULL; SetMem(tab, size, 0); status = uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, proto, NULL, &size, tab); if (status != EFI_SUCCESS) { Print(L"faild to get handles\n"); } size /= sizeof(EFI_HANDLE); UINTN idx = 0; for (i=0; i<size; i++) { dev_tab[idx].dev = tab[i]; if (tab[i] == boot_handle) boot_dev = dev_tab + idx; idx++; } return EFI_SUCCESS; } /* start cbc kernel boot loader. */ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *system_table) { InitializeLib(image, system_table); EFI_LOADED_IMAGE *info; CHAR16 *kname = L"kernel"; Print(L"Boot start. %s\n", kname); uefi_call_wrapper(BS->SetWatchdogTimer, 4, 0, 0x0, 0, NULL); Print(L"Set watchdog timer.\n"); EFI_STATUS status = uefi_call_wrapper(BS->HandleProtocol, 3, image, &LoadedImageProtocol, (VOID **) &info); if (efi_error(L"Load error.\n", status)) { return EFI_LOAD_ERROR; } fs_t fs; dev_tab_t boot_dev; status = config_fs(info->DeviceHandle, &fs, &boot_dev); UINTN fd; open(kname, &fd, &fs); status = EFI_SUCCESS; return status; }