~darkmuggle-deactivatedaccount/ubuntu/quantal/grub2/fix-872244

« back to all changes in this revision

Viewing changes to grub-core/video/readers/tga.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  GRUB  --  GRand Unified Bootloader
 
3
 *  Copyright (C) 2006,2007  Free Software Foundation, Inc.
 
4
 *
 
5
 *  GRUB is free software: you can redistribute it and/or modify
 
6
 *  it under the terms of the GNU General Public License as published by
 
7
 *  the Free Software Foundation, either version 3 of the License, or
 
8
 *  (at your option) any later version.
 
9
 *
 
10
 *  GRUB is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 
17
 */
 
18
 
 
19
#include <grub/bitmap.h>
 
20
#include <grub/types.h>
 
21
#include <grub/normal.h>
 
22
#include <grub/dl.h>
 
23
#include <grub/mm.h>
 
24
#include <grub/misc.h>
 
25
#include <grub/bufio.h>
 
26
 
 
27
/* Uncomment following define to enable TGA debug.  */
 
28
//#define TGA_DEBUG
 
29
 
 
30
#if defined(TGA_DEBUG)
 
31
#define dump_int_field(x) grub_printf( #x " = %d (0x%04x)\n", x, x);
 
32
static grub_command_t cmd;
 
33
#endif
 
34
 
 
35
enum
 
36
{
 
37
  GRUB_TGA_IMAGE_TYPE_NONE = 0,
 
38
  GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_INDEXCOLOR = 1,
 
39
  GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR = 2,
 
40
  GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_BLACK_AND_WHITE = 3,
 
41
  GRUB_TGA_IMAGE_TYPE_RLE_INDEXCOLOR = 9,
 
42
  GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR = 10,
 
43
  GRUB_TGA_IMAGE_TYPE_RLE_BLACK_AND_WHITE = 11,
 
44
};
 
45
 
 
46
enum
 
47
{
 
48
  GRUB_TGA_COLOR_MAP_TYPE_NONE = 0,
 
49
  GRUB_TGA_COLOR_MAP_TYPE_INCLUDED = 1
 
50
};
 
51
 
 
52
enum
 
53
{
 
54
  GRUB_TGA_IMAGE_ORIGIN_RIGHT = 0x10,
 
55
  GRUB_TGA_IMAGE_ORIGIN_TOP   = 0x20
 
56
};
 
57
 
 
58
struct grub_tga_header
 
59
{
 
60
  grub_uint8_t id_length;
 
61
  grub_uint8_t color_map_type;
 
62
  grub_uint8_t image_type;
 
63
 
 
64
  /* Color Map Specification.  */
 
65
  grub_uint16_t color_map_first_index;
 
66
  grub_uint16_t color_map_length;
 
67
  grub_uint8_t color_map_bpp;
 
68
 
 
69
  /* Image Specification.  */
 
70
  grub_uint16_t image_x_origin;
 
71
  grub_uint16_t image_y_origin;
 
72
  grub_uint16_t image_width;
 
73
  grub_uint16_t image_height;
 
74
  grub_uint8_t image_bpp;
 
75
  grub_uint8_t image_descriptor;
 
76
} __attribute__ ((packed));
 
77
 
 
78
static grub_err_t
 
79
tga_load_truecolor_rle_R8G8B8 (struct grub_video_bitmap *bitmap,
 
80
                               struct grub_tga_header *header,
 
81
                               grub_file_t file)
 
82
{
 
83
  unsigned int x;
 
84
  unsigned int y;
 
85
  grub_uint8_t type;
 
86
  grub_uint8_t *ptr;
 
87
  grub_uint8_t tmp[4]; /* Size should be max_bpp / 8.  */
 
88
  grub_uint8_t bytes_per_pixel;
 
89
 
 
90
  bytes_per_pixel = header->image_bpp / 8;
 
91
 
 
92
  for (y = 0; y < header->image_height; y++)
 
93
    {
 
94
      ptr = bitmap->data;
 
95
      if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0)
 
96
        ptr += y * bitmap->mode_info.pitch;
 
97
      else
 
98
        ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch;
 
99
 
 
100
      for (x = 0; x < header->image_width;)
 
101
        {
 
102
          if (grub_file_read (file, &type, sizeof (type)) != sizeof(type))
 
103
            return grub_errno;
 
104
 
 
105
          if (type & 0x80)
 
106
            {
 
107
              /* RLE-encoded packet.  */
 
108
              type &= 0x7f;
 
109
              type++;
 
110
 
 
111
              if (grub_file_read (file, &tmp[0], bytes_per_pixel)
 
112
                  != bytes_per_pixel)
 
113
                return grub_errno;
 
114
 
 
115
              while (type)
 
116
                {
 
117
                  if (x < header->image_width)
 
118
                    {
 
119
                      ptr[0] = tmp[2];
 
120
                      ptr[1] = tmp[1];
 
121
                      ptr[2] = tmp[0];
 
122
                      ptr += 3;
 
123
                    }
 
124
 
 
125
                  type--;
 
126
                  x++;
 
127
                }
 
128
            }
 
129
          else
 
130
            {
 
131
              /* RAW-encoded packet.  */
 
132
              type++;
 
133
 
 
134
              while (type)
 
135
                {
 
136
                  if (grub_file_read (file, &tmp[0], bytes_per_pixel)
 
137
                      != bytes_per_pixel)
 
138
                    return grub_errno;
 
139
 
 
140
                  if (x < header->image_width)
 
141
                    {
 
142
                      ptr[0] = tmp[2];
 
143
                      ptr[1] = tmp[1];
 
144
                      ptr[2] = tmp[0];
 
145
                      ptr += 3;
 
146
                    }
 
147
 
 
148
                  type--;
 
149
                  x++;
 
150
                }
 
151
            }
 
152
        }
 
153
    }
 
154
  return GRUB_ERR_NONE;
 
155
}
 
156
 
 
157
static grub_err_t
 
158
tga_load_truecolor_rle_R8G8B8A8 (struct grub_video_bitmap *bitmap,
 
159
                                 struct grub_tga_header *header,
 
160
                                 grub_file_t file)
 
161
{
 
162
  unsigned int x;
 
163
  unsigned int y;
 
164
  grub_uint8_t type;
 
165
  grub_uint8_t *ptr;
 
166
  grub_uint8_t tmp[4]; /* Size should be max_bpp / 8.  */
 
167
  grub_uint8_t bytes_per_pixel;
 
168
 
 
169
  bytes_per_pixel = header->image_bpp / 8;
 
170
 
 
171
  for (y = 0; y < header->image_height; y++)
 
172
    {
 
173
      ptr = bitmap->data;
 
174
      if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0)
 
175
        ptr += y * bitmap->mode_info.pitch;
 
176
      else
 
177
        ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch;
 
178
 
 
179
      for (x = 0; x < header->image_width;)
 
180
        {
 
181
          if (grub_file_read (file, &type, sizeof (type)) != sizeof(type))
 
182
            return grub_errno;
 
183
 
 
184
          if (type & 0x80)
 
185
            {
 
186
              /* RLE-encoded packet.  */
 
187
              type &= 0x7f;
 
188
              type++;
 
189
 
 
190
              if (grub_file_read (file, &tmp[0], bytes_per_pixel)
 
191
                  != bytes_per_pixel)
 
192
                return grub_errno;
 
193
 
 
194
              while (type)
 
195
                {
 
196
                  if (x < header->image_width)
 
197
                    {
 
198
                      ptr[0] = tmp[2];
 
199
                      ptr[1] = tmp[1];
 
200
                      ptr[2] = tmp[0];
 
201
                      ptr[3] = tmp[3];
 
202
                      ptr += 4;
 
203
                    }
 
204
 
 
205
                  type--;
 
206
                  x++;
 
207
                }
 
208
            }
 
209
          else
 
210
            {
 
211
              /* RAW-encoded packet.  */
 
212
              type++;
 
213
 
 
214
              while (type)
 
215
                {
 
216
                  if (grub_file_read (file, &tmp[0], bytes_per_pixel)
 
217
                      != bytes_per_pixel)
 
218
                    return grub_errno;
 
219
 
 
220
                  if (x < header->image_width)
 
221
                    {
 
222
                      ptr[0] = tmp[2];
 
223
                      ptr[1] = tmp[1];
 
224
                      ptr[2] = tmp[0];
 
225
                      ptr[3] = tmp[3];
 
226
                      ptr += 4;
 
227
                    }
 
228
 
 
229
                  type--;
 
230
                  x++;
 
231
                }
 
232
            }
 
233
        }
 
234
    }
 
235
  return GRUB_ERR_NONE;
 
236
}
 
237
 
 
238
static grub_err_t
 
239
tga_load_truecolor_R8G8B8 (struct grub_video_bitmap *bitmap,
 
240
                           struct grub_tga_header *header,
 
241
                           grub_file_t file)
 
242
{
 
243
  unsigned int x;
 
244
  unsigned int y;
 
245
  grub_uint8_t *ptr;
 
246
  grub_uint8_t tmp[4]; /* Size should be max_bpp / 8.  */
 
247
  grub_uint8_t bytes_per_pixel;
 
248
 
 
249
  bytes_per_pixel = header->image_bpp / 8;
 
250
 
 
251
  for (y = 0; y < header->image_height; y++)
 
252
    {
 
253
      ptr = bitmap->data;
 
254
      if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0)
 
255
        ptr += y * bitmap->mode_info.pitch;
 
256
      else
 
257
        ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch;
 
258
 
 
259
      for (x = 0; x < header->image_width; x++)
 
260
        {
 
261
          if (grub_file_read (file, &tmp[0], bytes_per_pixel)
 
262
              != bytes_per_pixel)
 
263
            return grub_errno;
 
264
 
 
265
          ptr[0] = tmp[2];
 
266
          ptr[1] = tmp[1];
 
267
          ptr[2] = tmp[0];
 
268
 
 
269
          ptr += 3;
 
270
        }
 
271
    }
 
272
  return GRUB_ERR_NONE;
 
273
}
 
274
 
 
275
static grub_err_t
 
276
tga_load_truecolor_R8G8B8A8 (struct grub_video_bitmap *bitmap,
 
277
                             struct grub_tga_header *header,
 
278
                             grub_file_t file)
 
279
{
 
280
  unsigned int x;
 
281
  unsigned int y;
 
282
  grub_uint8_t *ptr;
 
283
  grub_uint8_t tmp[4]; /* Size should be max_bpp / 8.  */
 
284
  grub_uint8_t bytes_per_pixel;
 
285
 
 
286
  bytes_per_pixel = header->image_bpp / 8;
 
287
 
 
288
  for (y = 0; y < header->image_height; y++)
 
289
    {
 
290
      ptr = bitmap->data;
 
291
      if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0)
 
292
        ptr += y * bitmap->mode_info.pitch;
 
293
      else
 
294
        ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch;
 
295
 
 
296
      for (x = 0; x < header->image_width; x++)
 
297
        {
 
298
          if (grub_file_read (file, &tmp[0], bytes_per_pixel)
 
299
              != bytes_per_pixel)
 
300
            return grub_errno;
 
301
 
 
302
          ptr[0] = tmp[2];
 
303
          ptr[1] = tmp[1];
 
304
          ptr[2] = tmp[0];
 
305
          ptr[3] = tmp[3];
 
306
 
 
307
          ptr += 4;
 
308
        }
 
309
    }
 
310
  return GRUB_ERR_NONE;
 
311
}
 
312
 
 
313
static grub_err_t
 
314
grub_video_reader_tga (struct grub_video_bitmap **bitmap,
 
315
                       const char *filename)
 
316
{
 
317
  grub_file_t file;
 
318
  grub_ssize_t pos;
 
319
  struct grub_tga_header header;
 
320
  int has_alpha;
 
321
 
 
322
  file = grub_buffile_open (filename, 0);
 
323
  if (! file)
 
324
    return grub_errno;
 
325
 
 
326
  /* TGA Specification states that we SHOULD start by reading
 
327
     ID from end of file, but we really don't care about that as we are
 
328
     not going to support developer area & extensions at this point.  */
 
329
 
 
330
  /* Read TGA header from beginning of file.  */
 
331
  if (grub_file_read (file, &header, sizeof (header))
 
332
      != sizeof (header))
 
333
    {
 
334
      grub_file_close (file);
 
335
      return grub_errno;
 
336
    }
 
337
 
 
338
  /* Skip ID field.  */
 
339
  pos = grub_file_tell (file);
 
340
  pos += header.id_length;
 
341
  grub_file_seek (file, pos);
 
342
  if (grub_errno != GRUB_ERR_NONE)
 
343
    {
 
344
      grub_file_close (file);
 
345
      return grub_errno;
 
346
    }
 
347
 
 
348
#if defined(TGA_DEBUG)
 
349
  grub_printf("tga: header\n");
 
350
  dump_int_field(header.id_length);
 
351
  dump_int_field(header.color_map_type);
 
352
  dump_int_field(header.image_type);
 
353
  dump_int_field(header.color_map_first_index);
 
354
  dump_int_field(header.color_map_length);
 
355
  dump_int_field(header.color_map_bpp);
 
356
  dump_int_field(header.image_x_origin);
 
357
  dump_int_field(header.image_y_origin);
 
358
  dump_int_field(header.image_width);
 
359
  dump_int_field(header.image_height);
 
360
  dump_int_field(header.image_bpp);
 
361
  dump_int_field(header.image_descriptor);
 
362
#endif
 
363
 
 
364
  /* Check that bitmap encoding is supported.  */
 
365
  switch (header.image_type)
 
366
    {
 
367
      case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR:
 
368
      case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR:
 
369
        break;
 
370
 
 
371
      default:
 
372
        grub_file_close (file);
 
373
        return grub_error (GRUB_ERR_BAD_FILE_TYPE,
 
374
                           "unsupported bitmap format (unknown encoding)");
 
375
    }
 
376
 
 
377
  /* Check that bitmap depth is supported.  */
 
378
  switch (header.image_bpp)
 
379
    {
 
380
      case 24:
 
381
        has_alpha = 0;
 
382
        break;
 
383
 
 
384
      case 32:
 
385
        has_alpha = 1;
 
386
        break;
 
387
 
 
388
      default:
 
389
        grub_file_close (file);
 
390
        return grub_error (GRUB_ERR_BAD_FILE_TYPE,
 
391
                           "unsupported bitmap format (bpp=%d)",
 
392
                           header.image_bpp);
 
393
    }
 
394
 
 
395
  /* Allocate bitmap.  If there is alpha information store it too.  */
 
396
  if (has_alpha)
 
397
    {
 
398
      grub_video_bitmap_create (bitmap, header.image_width,
 
399
                                header.image_height,
 
400
                                GRUB_VIDEO_BLIT_FORMAT_RGBA_8888);
 
401
      if (grub_errno != GRUB_ERR_NONE)
 
402
        {
 
403
          grub_file_close (file);
 
404
          return grub_errno;
 
405
        }
 
406
 
 
407
      /* Load bitmap data.  */
 
408
      switch (header.image_type)
 
409
        {
 
410
          case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR:
 
411
            tga_load_truecolor_R8G8B8A8 (*bitmap, &header, file);
 
412
            break;
 
413
 
 
414
          case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR:
 
415
            tga_load_truecolor_rle_R8G8B8A8 (*bitmap, &header, file);
 
416
            break;
 
417
        }
 
418
    }
 
419
  else
 
420
    {
 
421
      grub_video_bitmap_create (bitmap, header.image_width,
 
422
                                header.image_height,
 
423
                                GRUB_VIDEO_BLIT_FORMAT_RGB_888);
 
424
      if (grub_errno != GRUB_ERR_NONE)
 
425
        {
 
426
          grub_file_close (file);
 
427
          return grub_errno;
 
428
        }
 
429
 
 
430
      /* Load bitmap data.  */
 
431
      switch (header.image_type)
 
432
        {
 
433
          case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR:
 
434
            tga_load_truecolor_R8G8B8 (*bitmap, &header, file);
 
435
            break;
 
436
 
 
437
          case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR:
 
438
            tga_load_truecolor_rle_R8G8B8 (*bitmap, &header, file);
 
439
            break;
 
440
        }
 
441
    }
 
442
 
 
443
  /* If there was a loading problem, destroy bitmap.  */
 
444
  if (grub_errno != GRUB_ERR_NONE)
 
445
    {
 
446
      grub_video_bitmap_destroy (*bitmap);
 
447
      *bitmap = 0;
 
448
    }
 
449
 
 
450
  grub_file_close (file);
 
451
  return grub_errno;
 
452
}
 
453
 
 
454
#if defined(TGA_DEBUG)
 
455
static grub_err_t
 
456
grub_cmd_tgatest (grub_command_t cmd __attribute__ ((unused)),
 
457
                  int argc, char **args)
 
458
{
 
459
  struct grub_video_bitmap *bitmap = 0;
 
460
 
 
461
  if (argc != 1)
 
462
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
 
463
 
 
464
  grub_video_reader_tga (&bitmap, args[0]);
 
465
  if (grub_errno != GRUB_ERR_NONE)
 
466
    return grub_errno;
 
467
 
 
468
  grub_video_bitmap_destroy (bitmap);
 
469
 
 
470
  return GRUB_ERR_NONE;
 
471
}
 
472
#endif
 
473
 
 
474
static struct grub_video_bitmap_reader tga_reader = {
 
475
  .extension = ".tga",
 
476
  .reader = grub_video_reader_tga,
 
477
  .next = 0
 
478
};
 
479
 
 
480
GRUB_MOD_INIT(tga)
 
481
{
 
482
  grub_video_bitmap_reader_register (&tga_reader);
 
483
#if defined(TGA_DEBUG)
 
484
  cmd = grub_register_command ("tgatest", grub_cmd_tgatest,
 
485
                               "FILE", "Tests loading of TGA bitmap.");
 
486
#endif
 
487
}
 
488
 
 
489
GRUB_MOD_FINI(tga)
 
490
{
 
491
#if defined(TGA_DEBUG)
 
492
  grub_unregister_command (cmd);
 
493
#endif
 
494
  grub_video_bitmap_reader_unregister (&tga_reader);
 
495
}