efi: use LocateHandle() and HandleProtocol() to check for multiple gop protocols to find a usable one

the gop returned by LocateProtocol() is not usable on thinkpad x230,
so iterate over all handles to find a usable one.
This commit is contained in:
cinap_lenrek 2014-10-19 19:55:45 +02:00
parent d6ea496960
commit d7785060fb
3 changed files with 64 additions and 39 deletions

View file

@ -9,8 +9,6 @@ enum {
UINTN MK; UINTN MK;
EFI_HANDLE IH; EFI_HANDLE IH;
EFI_SYSTEM_TABLE *ST; EFI_SYSTEM_TABLE *ST;
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
EFI_FILE_PROTOCOL *root; EFI_FILE_PROTOCOL *root;
void void
@ -45,12 +43,6 @@ unload(void)
eficall(2, ST->BootServices->ExitBootServices, IH, MK); eficall(2, ST->BootServices->ExitBootServices, IH, MK);
} }
EFI_STATUS
LocateProtocol(EFI_GUID *guid, void *reg, void **pif)
{
return eficall(3, ST->BootServices->LocateProtocol, guid, reg, pif);
}
void void
fsinit(void) fsinit(void)
{ {
@ -58,7 +50,8 @@ fsinit(void)
fs = nil; fs = nil;
root = nil; root = nil;
if(LocateProtocol(&EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, nil, &fs)) if(eficall(3, ST->BootServices->LocateProtocol,
&EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, nil, &fs))
return; return;
if(eficall(2, fs->OpenVolume, fs, &root)){ if(eficall(2, fs->OpenVolume, fs, &root)){
root = nil; root = nil;
@ -227,47 +220,72 @@ lowbit(ulong mask)
static void static void
screenconf(char **cfg) screenconf(char **cfg)
{ {
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
EFI_HANDLE *Handles;
UINTN Count;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info; EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
ulong mr, mg, mb, mx, mc; ulong mr, mg, mb, mx, mc;
int bits, depth; int i, bits, depth;
char *s; char *s;
gop = nil; Count = 0;
if(LocateProtocol(&EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, nil, &gop) || gop == nil) Handles = nil;
if(eficall(5, ST->BootServices->LocateHandleBuffer,
ByProtocol, &EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, nil, &Count, &Handles))
return; return;
if((info = gop->Mode->Info) == nil) for(i=0; i<Count; i++){
return; gop = nil;
if(eficall(3, ST->BootServices->HandleProtocol,
Handles[i], &EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, &gop))
continue;
switch(info->PixelFormat){ if(gop == nil)
default: continue;
return; /* unsupported */ if((info = gop->Mode->Info) == nil)
continue;
case PixelRedGreenBlueReserved8BitPerColor: switch(info->PixelFormat){
mr = 0x000000ff; default:
mg = 0x0000ff00; continue; /* unsupported */
mb = 0x00ff0000;
mx = 0xff000000;
break;
case PixelBlueGreenRedReserved8BitPerColor: case PixelRedGreenBlueReserved8BitPerColor:
mb = 0x000000ff; mr = 0x000000ff;
mg = 0x0000ff00; mg = 0x0000ff00;
mr = 0x00ff0000; mb = 0x00ff0000;
mx = 0xff000000; mx = 0xff000000;
break; break;
case PixelBitMask: case PixelBlueGreenRedReserved8BitPerColor:
mr = info->PixelInformation.RedMask; mb = 0x000000ff;
mg = info->PixelInformation.GreenMask; mg = 0x0000ff00;
mb = info->PixelInformation.BlueMask; mr = 0x00ff0000;
mx = info->PixelInformation.ReservedMask; mx = 0xff000000;
break; break;
case PixelBitMask:
mr = info->PixelInformation.RedMask;
mg = info->PixelInformation.GreenMask;
mb = info->PixelInformation.BlueMask;
mx = info->PixelInformation.ReservedMask;
break;
}
if((depth = topbit(mr | mg | mb | mx)) == 0)
continue;
/* make sure we have linear framebuffer */
if(gop->Mode->FrameBufferBase == 0)
continue;
if(gop->Mode->FrameBufferSize == 0)
continue;
goto Found;
} }
return;
if((depth = topbit(mr | mg | mb | mx)) == 0) Found:
return;
s = *cfg; s = *cfg;
memmove(s, "*bootscreen=", 12), s += 12; memmove(s, "*bootscreen=", 12), s += 12;
s = decfmt(s, 0, info->PixelsPerScanLine), *s++ = 'x'; s = decfmt(s, 0, info->PixelsPerScanLine), *s++ = 'x';
@ -297,7 +315,7 @@ screenconf(char **cfg)
*s++ = ' '; *s++ = ' ';
*s++ = '0', *s++ = 'x'; *s++ = '0', *s++ = 'x';
s = hexfmt(s, 0, gop->Mode->FrameBufferBase), *s++ = '\n'; s = hexfmt(s, 16, gop->Mode->FrameBufferBase), *s++ = '\n';
*s = '\0'; *s = '\0';
print(*cfg); print(*cfg);

View file

@ -10,6 +10,12 @@ typedef uintptr UINTN;
typedef void* EFI_HANDLE; typedef void* EFI_HANDLE;
typedef UINT32 EFI_STATUS; typedef UINT32 EFI_STATUS;
enum {
AllHandles,
ByRegisterNotify,
ByProtocol,
};
typedef struct { typedef struct {
UINT32 Data1; UINT32 Data1;
UINT16 Data2; UINT16 Data2;

View file

@ -367,6 +367,7 @@ bootkern(void *f)
memset(d, 0, t - d); memset(d, 0, t - d);
close(f); close(f);
print("boot\n");
unload(); unload();
jump(e); jump(e);