1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "osboot.h"
6 
7 #include <stdio.h>
8 #include <string.h>
9 #include <xefi.h>
10 
11 #include <zircon/pixelformat.h>
12 
13 static efi_guid AcpiTableGUID = ACPI_TABLE_GUID;
14 static efi_guid Acpi2TableGUID = ACPI_20_TABLE_GUID;
15 static efi_guid SmbiosTableGUID = SMBIOS_TABLE_GUID;
16 static efi_guid Smbios3TableGUID = SMBIOS3_TABLE_GUID;
17 static uint8_t ACPI_RSD_PTR[8] = "RSD PTR ";
18 static uint8_t SmbiosAnchor[4] = "_SM_";
19 static uint8_t Smbios3Anchor[5] = "_SM3_";
20 
find_acpi_root(efi_handle img,efi_system_table * sys)21 uint64_t find_acpi_root(efi_handle img, efi_system_table* sys) {
22     efi_configuration_table* cfgtab = sys->ConfigurationTable;
23     for (size_t i = 0; i < sys->NumberOfTableEntries; i++) {
24         if (xefi_cmp_guid(&cfgtab[i].VendorGuid, &AcpiTableGUID) &&
25             xefi_cmp_guid(&cfgtab[i].VendorGuid, &Acpi2TableGUID)) {
26             // not an ACPI table
27             continue;
28         }
29         if (memcmp(cfgtab[i].VendorTable, ACPI_RSD_PTR, 8)) {
30             // not the Root Description Pointer
31             continue;
32         }
33         return (uint64_t)cfgtab[i].VendorTable;
34     }
35     return 0;
36 }
37 
find_smbios(efi_handle img,efi_system_table * sys)38 uint64_t find_smbios(efi_handle img, efi_system_table* sys) {
39     efi_configuration_table* cfgtab = sys->ConfigurationTable;
40     for (size_t i = 0; i < sys->NumberOfTableEntries; i++) {
41         if (!xefi_cmp_guid(&cfgtab[i].VendorGuid, &SmbiosTableGUID)) {
42             if (!memcmp(cfgtab[i].VendorTable, SmbiosAnchor, sizeof(SmbiosAnchor))) {
43                 return (uint64_t)cfgtab[i].VendorTable;
44             }
45         } else if (!xefi_cmp_guid(&cfgtab[i].VendorGuid, &Smbios3TableGUID)) {
46             if (!memcmp(cfgtab[i].VendorTable, Smbios3Anchor, sizeof(Smbios3Anchor))) {
47                 return (uint64_t)cfgtab[i].VendorTable;
48             }
49         }
50     }
51     return 0;
52 }
53 
get_bit_range(uint32_t mask,int * high,int * low)54 static void get_bit_range(uint32_t mask, int* high, int* low) {
55     *high = -1;
56     *low = -1;
57     int idx = 0;
58     while (mask) {
59         if (*low < 0 && (mask & 1)) *low = idx;
60         idx++;
61         mask >>= 1;
62     }
63     *high = idx - 1;
64 }
65 
get_zx_pixel_format_from_bitmask(efi_pixel_bitmask bitmask)66 static int get_zx_pixel_format_from_bitmask(efi_pixel_bitmask bitmask) {
67     int r_hi = -1, r_lo = -1, g_hi = -1, g_lo = -1, b_hi = -1, b_lo = -1;
68 
69     get_bit_range(bitmask.RedMask, &r_hi, &r_lo);
70     get_bit_range(bitmask.GreenMask, &g_hi, &g_lo);
71     get_bit_range(bitmask.BlueMask, &b_hi, &b_lo);
72 
73     if (r_lo < 0 || g_lo < 0 || b_lo < 0) {
74         goto unsupported;
75     }
76 
77     if ((r_hi == 23 && r_lo == 16) &&
78         (g_hi == 15 && g_lo == 8) &&
79         (b_hi == 7 && b_lo == 0)) {
80         return ZX_PIXEL_FORMAT_RGB_x888;
81     }
82 
83     if ((r_hi == 7 && r_lo == 5) &&
84         (g_hi == 4 && g_lo == 2) &&
85         (b_hi == 1 && b_lo == 0)) {
86         return ZX_PIXEL_FORMAT_RGB_332;
87     }
88 
89     if ((r_hi == 15 && r_lo == 11) &&
90         (g_hi == 10 && g_lo == 5) &&
91         (b_hi == 4 && b_lo == 0)) {
92         return ZX_PIXEL_FORMAT_RGB_565;
93     }
94 
95     if ((r_hi == 7 && r_lo == 6) &&
96         (g_hi == 5 && g_lo == 4) &&
97         (b_hi == 3 && b_lo == 2)) {
98         return ZX_PIXEL_FORMAT_RGB_2220;
99     }
100 
101 unsupported:
102     printf("unsupported pixel format bitmask: r %08x / g %08x / b %08x\n",
103             bitmask.RedMask, bitmask.GreenMask, bitmask.BlueMask);
104     return ZX_PIXEL_FORMAT_NONE;
105 }
106 
get_zx_pixel_format(efi_graphics_output_protocol * gop)107 uint32_t get_zx_pixel_format(efi_graphics_output_protocol* gop) {
108     efi_graphics_pixel_format efi_fmt = gop->Mode->Info->PixelFormat;
109     switch (efi_fmt) {
110     case PixelBlueGreenRedReserved8BitPerColor:
111         return ZX_PIXEL_FORMAT_RGB_x888;
112     case PixelBitMask:
113         return get_zx_pixel_format_from_bitmask(gop->Mode->Info->PixelInformation);
114     default:
115         printf("unsupported pixel format %d!\n", efi_fmt);
116         return ZX_PIXEL_FORMAT_NONE;
117     }
118 }
119