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