2#ifndef PEDIGREE_UEFI_FRAMEBUFFER_H
3#define PEDIGREE_UEFI_FRAMEBUFFER_H
11 uint32_t pixel_format;
15 uint32_t reserved_mask;
16 uint32_t pixels_per_scanline;
25 uint64_t framebuffer_size;
38 uint32_t width, height, pitch, bpp, format;
41typedef uint64_t (*efi_free_pool_t)(
void*);
49 if (!info || !info->width || !info->height || info->pixels_per_scanline < info->width ||
50 info->pixels_per_scanline > UINT32_MAX / 4)
53 uint32_t format = info->pixel_format;
56 if (info->green_mask != 0x0000ff00 ||
57 (info->reserved_mask && info->reserved_mask != 0xff000000))
59 if (info->red_mask == 0x000000ff && info->blue_mask == 0x00ff0000)
61 else if (info->red_mask == 0x00ff0000 && info->blue_mask == 0x000000ff)
73 if (!graphics || !graphics->mode)
78 if (!info || mode->info_size <
sizeof(*info) || !mode->max_mode || mode->mode >= mode->max_mode ||
79 !mode->framebuffer || !framebuffer_format(info, &format))
82 const uint32_t pitch = info->pixels_per_scanline * 4;
83 const uint64_t span = (uint64_t)pitch * info->height;
84 if (span > mode->framebuffer_size || mode->framebuffer_size > UINT64_MAX - mode->framebuffer)
86 *output = (
boot_framebuffer_t){mode->framebuffer, info->width, info->height, pitch, 32, format};
90static int preferred_framebuffer_size(
const efi_edid_active_t* edid, uint32_t* width,
92 static const uint8_t header[] = {0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0};
93 if (!edid || !edid->bytes || edid->size < 128)
95 const uint8_t* bytes = edid->bytes;
97 for (
unsigned i = 0; i <
sizeof(header); ++i)
98 if (bytes[i] != header[i])
100 for (
unsigned i = 0; i < 128; ++i)
101 checksum += bytes[i];
102 if (checksum || bytes[18] != 1 || !(bytes[24] & 2))
104 const uint8_t* timing = bytes + 54;
105 if (!(timing[0] | timing[1]) || (timing[17] & 0x80))
107 const uint32_t x = timing[2] | ((uint32_t)(timing[4] & 0xf0) << 4);
108 const uint32_t y = timing[5] | ((uint32_t)(timing[7] & 0xf0) << 4);
120 if (decode_framebuffer(graphics, output))
122 if (!graphics || !graphics->mode || !graphics->query_mode || !graphics->set_mode || !free_pool)
124 uint32_t preferred_width = 0, preferred_height = 0;
125 preferred_framebuffer_size(edid, &preferred_width, &preferred_height);
126 const uint32_t count = graphics->mode->max_mode;
127 int ceiling_preferred = 2;
128 uint64_t ceiling_area = UINT64_MAX;
129 uint32_t ceiling_mode = UINT32_MAX;
130 for (uint32_t attempt = 0; attempt < count; ++attempt) {
131 int best_preferred = -1;
132 uint64_t best_area = 0;
133 uint32_t best_mode = 0, best_width = 0, best_height = 0;
134 for (uint32_t candidate = 0; candidate < count; ++candidate) {
138 const uint64_t status = graphics->query_mode(graphics, candidate, &size, &info);
139 if (!status && info && size >=
sizeof(*info) && framebuffer_format(info, &format)) {
140 const int preferred = info->width == preferred_width && info->height == preferred_height;
141 const uint64_t area = (uint64_t)info->width * info->height;
142 const int below_ceiling =
143 preferred < ceiling_preferred ||
144 (preferred == ceiling_preferred &&
145 (area < ceiling_area || (area == ceiling_area && candidate < ceiling_mode)));
147 (preferred > best_preferred ||
148 (preferred == best_preferred &&
149 (area > best_area || (area == best_area && candidate > best_mode))))) {
150 best_preferred = preferred;
152 best_mode = candidate;
153 best_width = info->width;
154 best_height = info->height;
160 if (best_preferred < 0)
162 if (!graphics->set_mode(graphics, best_mode) && graphics->mode &&
163 graphics->mode->mode == best_mode && decode_framebuffer(graphics, output) &&
164 output->width == best_width && output->height == best_height)
167 ceiling_preferred = best_preferred;
168 ceiling_area = best_area;
169 ceiling_mode = best_mode;