#include "graphics.h"
#include "proto/graphics-output.h"
#include "splash.h"
+#include "unaligned-fundamental.h"
#include "util.h"
struct bmp_file {
int32_t y_pixel_meter;
uint32_t colors_used;
uint32_t colors_important;
+ uint32_t channel_mask_r;
+ uint32_t channel_mask_g;
+ uint32_t channel_mask_b;
+ uint32_t channel_mask_a;
} _packed_;
+#define SIZEOF_BMP_DIB offsetof(struct bmp_dib, channel_mask_r)
+#define SIZEOF_BMP_DIB_RGB offsetof(struct bmp_dib, channel_mask_a)
+#define SIZEOF_BMP_DIB_RGBA sizeof(struct bmp_dib)
+
struct bmp_map {
uint8_t blue;
uint8_t green;
assert(ret_map);
assert(pixmap);
- if (size < sizeof(struct bmp_file) + sizeof(struct bmp_dib))
+ if (size < sizeof(struct bmp_file) + SIZEOF_BMP_DIB)
return EFI_INVALID_PARAMETER;
/* check file header */
/* check device-independent bitmap */
struct bmp_dib *dib = (struct bmp_dib *) (bmp + sizeof(struct bmp_file));
- if (dib->size < sizeof(struct bmp_dib))
+ if (dib->size < SIZEOF_BMP_DIB)
return EFI_UNSUPPORTED;
switch (dib->depth) {
assert(dib);
- if (IN_SET(dib->depth, 16, 32) && dib->size >= sizeof(*dib) + 3 * sizeof(uint32_t)) {
- uint32_t *mask = (uint32_t *) ((uint8_t *) dib + sizeof(*dib));
- channel_mask[R] = mask[R];
- channel_mask[G] = mask[G];
- channel_mask[B] = mask[B];
- channel_shift[R] = __builtin_ctz(mask[R]);
- channel_shift[G] = __builtin_ctz(mask[G]);
- channel_shift[B] = __builtin_ctz(mask[B]);
- channel_scale[R] = 0xff / ((1 << __builtin_popcount(mask[R])) - 1);
- channel_scale[G] = 0xff / ((1 << __builtin_popcount(mask[G])) - 1);
- channel_scale[B] = 0xff / ((1 << __builtin_popcount(mask[B])) - 1);
-
- if (dib->size >= sizeof(*dib) + 4 * sizeof(uint32_t) && mask[A] != 0) {
- channel_mask[A] = mask[A];
- channel_shift[A] = __builtin_ctz(mask[A]);
- channel_scale[A] = 0xff / ((1 << __builtin_popcount(mask[A])) - 1);
+ if (IN_SET(dib->depth, 16, 32) && dib->size >= SIZEOF_BMP_DIB_RGB) {
+ channel_mask[R] = dib->channel_mask_r;
+ channel_mask[G] = dib->channel_mask_g;
+ channel_mask[B] = dib->channel_mask_b;
+ channel_shift[R] = __builtin_ctz(dib->channel_mask_r);
+ channel_shift[G] = __builtin_ctz(dib->channel_mask_g);
+ channel_shift[B] = __builtin_ctz(dib->channel_mask_b);
+ channel_scale[R] = 0xff / ((1 << __builtin_popcount(dib->channel_mask_r)) - 1);
+ channel_scale[G] = 0xff / ((1 << __builtin_popcount(dib->channel_mask_g)) - 1);
+ channel_scale[B] = 0xff / ((1 << __builtin_popcount(dib->channel_mask_b)) - 1);
+
+ if (dib->size >= SIZEOF_BMP_DIB_RGBA && dib->channel_mask_a != 0) {
+ channel_mask[A] = dib->channel_mask_a;
+ channel_shift[A] = __builtin_ctz(dib->channel_mask_a);
+ channel_scale[A] = 0xff / ((1 << __builtin_popcount(dib->channel_mask_a)) - 1);
} else {
channel_mask[A] = 0;
channel_shift[A] = 0;
case 16:
case 32: {
- uint32_t i = dib->depth == 16 ? *(uint16_t *) in : *(uint32_t *) in;
+ uint32_t i = dib->depth == 16 ? unaligned_read_ne16(in) :
+ unaligned_read_ne32(in);
uint8_t r = ((i & channel_mask[R]) >> channel_shift[R]) * channel_scale[R],
g = ((i & channel_mask[G]) >> channel_shift[G]) * channel_scale[G],