/* * Copyright (C) 2013 David Decotigny * * Sample EFI shell session, together with drv0_use.efi: * * # Loading first instance: * * fs0:\> load drv0.efi * Driver instance loaded successfully. * load: Image fs0:\drv0.efi loaded at 2FD7C000 - Success * * # Testing 1st instance: * * fs0:\> drv0_use.efi * Playing with driver instance 0... * Hello Sample UEFI Driver! * Hello was called 1 time(s). * * fs0:\> drv0_use.efi * Playing with driver instance 0... * Hello Sample UEFI Driver! * Hello was called 2 time(s). * * # Loading another instance: * * fs0:\> load drv0.efi * Driver instance loaded successfully. * load: Image fs0:\drv0.efi loaded at 2FD6D000 - Success * * # Using both instances: * * fs0:\> drv0_use.efi * Playing with driver instance 0... * Hello Sample UEFI Driver! * Hello was called 3 time(s). * Playing with driver instance 1... * Hello Sample UEFI Driver! * Hello was called 1 time(s). * * fs0:\> drv0_use.efi * Playing with driver instance 0... * Hello Sample UEFI Driver! * Hello was called 4 time(s). * Playing with driver instance 1... * Hello Sample UEFI Driver! * Hello was called 2 time(s). * * # Removing 1st instance: * * fs0:\> dh * Handle dump * 1: Image(DxeCore) * [...] * 79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi) * 7A: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi) * * fs0:\> unload 79 * 79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi) * Unload driver image (y/n)? y * Driver instance unloaded. * unload: Success * * # Only 2nd instance remaining: * * fs0:\> drv0_use.efi * Playing with driver instance 0... * Hello Sample UEFI Driver! * Hello was called 3 time(s). * * # Removing 2nd/last instance: * * fs0:\> dh * Handle dump * 1: Image(DxeCore) * [...] * 79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi) * * fs0:\> unload 79 * 79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi) * Unload driver image (y/n)? y * Driver instance unloaded. * unload: Success * * # Expect error: no other drv0 instance left * * fs0:\> drv0_use.efi * Error looking up handles for proto: 14 */ #include #include #include "drv0.h" static const EFI_GUID GnuEfiAppsDrv0ProtocolGuid = GNU_EFI_APPS_DRV0_PROTOCOL_GUID; static struct { GNU_EFI_APPS_DRV0_PROTOCOL Proto; UINTN Counter; } InternalGnuEfiAppsDrv0ProtocolData; static EFI_STATUS EFI_FUNCTION Drv0SayHello( IN struct _GNU_EFI_APPS_DRV0_PROTOCOL *This, IN const CHAR16 *HelloWho ) { if (! HelloWho) return EFI_INVALID_PARAMETER; Print(L"Hello %s!\n", HelloWho); InternalGnuEfiAppsDrv0ProtocolData.Counter ++; return EFI_SUCCESS; } static EFI_STATUS EFI_FUNCTION Drv0GetNumberOfHello( IN struct _GNU_EFI_APPS_DRV0_PROTOCOL *This, OUT UINTN *NumberOfHello ) { if (! NumberOfHello) return EFI_INVALID_PARAMETER; *NumberOfHello = InternalGnuEfiAppsDrv0ProtocolData.Counter; return EFI_SUCCESS; } static EFI_STATUS EFI_FUNCTION Drv0Unload(IN EFI_HANDLE ImageHandle) { LibUninstallProtocolInterfaces(ImageHandle, &GnuEfiAppsDrv0ProtocolGuid, &InternalGnuEfiAppsDrv0ProtocolData.Proto, NULL); Print(L"Driver instance unloaded.\n", ImageHandle); return EFI_SUCCESS; } EFI_STATUS efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SysTab) { EFI_STATUS Status; EFI_LOADED_IMAGE *LoadedImage = NULL; InitializeLib(ImageHandle, SysTab); /* Initialize global protocol definition + data */ InternalGnuEfiAppsDrv0ProtocolData.Proto.SayHello = (GNU_EFI_APPS_DRV0_SAY_HELLO) Drv0SayHello; InternalGnuEfiAppsDrv0ProtocolData.Proto.GetNumberOfHello = (GNU_EFI_APPS_DRV0_GET_NUMBER_OF_HELLO) Drv0GetNumberOfHello; InternalGnuEfiAppsDrv0ProtocolData.Counter = 0; /* Grab handle to this image: we'll attach our proto instance to it */ Status = uefi_call_wrapper(BS->OpenProtocol, 6, ImageHandle, &LoadedImageProtocol, &LoadedImage, ImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (EFI_ERROR(Status)) { Print(L"Could not open loaded image protocol: %d\n", Status); return Status; } /* Attach our proto to the current driver image */ Status = LibInstallProtocolInterfaces( &ImageHandle, &GnuEfiAppsDrv0ProtocolGuid, &InternalGnuEfiAppsDrv0ProtocolData.Proto, NULL); if (EFI_ERROR(Status)) { Print(L"Error registering driver instance: %d\n", Status); return Status; } /* Register Unload callback, used to unregister current protocol * instance from system */ LoadedImage->Unload = (EFI_IMAGE_UNLOAD)Drv0Unload; Print(L"Driver instance loaded successfully.\n"); return EFI_SUCCESS; /* at this point, this instance stays resident * until image is unloaded, eg. with shell's unload, * ExitBootServices() */ }