~hamo/ubuntu/precise/grub2/grub2.hi_res

« back to all changes in this revision

Viewing changes to loader/i386/efi/linux.c

Tags: upstream-1.98+20100705
ImportĀ upstreamĀ versionĀ 1.98+20100705

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
#include <grub/cpu/linux.h>
30
30
#include <grub/efi/api.h>
31
31
#include <grub/efi/efi.h>
32
 
#include <grub/efi/uga_draw.h>
33
 
#include <grub/pci.h>
34
32
#include <grub/command.h>
35
33
#include <grub/memory.h>
 
34
#include <grub/env.h>
 
35
#include <grub/video.h>
 
36
#include <grub/time.h>
36
37
#include <grub/i18n.h>
37
38
 
38
39
#define GRUB_LINUX_CL_OFFSET            0x1000
286
287
    }
287
288
}
288
289
 
 
290
static grub_err_t
 
291
grub_linux_setup_video (struct linux_kernel_params *params)
 
292
{
 
293
  struct grub_video_mode_info mode_info;
 
294
  void *framebuffer;
 
295
  grub_err_t err;
 
296
 
 
297
  err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
 
298
 
 
299
  if (err)
 
300
    return err;
 
301
 
 
302
  params->lfb_width = mode_info.width;
 
303
  params->lfb_height = mode_info.height;
 
304
  params->lfb_depth = mode_info.bpp;
 
305
  params->lfb_line_len = mode_info.pitch;
 
306
 
 
307
  params->lfb_base = (grub_size_t) framebuffer;
 
308
  params->lfb_size = ALIGN_UP (params->lfb_line_len * params->lfb_height,
 
309
                               65536);
 
310
 
 
311
  params->red_mask_size = mode_info.red_mask_size;
 
312
  params->red_field_pos = mode_info.red_field_pos;
 
313
  params->green_mask_size = mode_info.green_mask_size;
 
314
  params->green_field_pos = mode_info.green_field_pos;
 
315
  params->blue_mask_size = mode_info.blue_mask_size;
 
316
  params->blue_field_pos = mode_info.blue_field_pos;
 
317
  params->reserved_mask_size = mode_info.reserved_mask_size;
 
318
  params->reserved_field_pos = mode_info.reserved_field_pos;
 
319
 
 
320
  params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE;
 
321
 
 
322
#ifdef GRUB_MACHINE_PCBIOS
 
323
  /* VESA packed modes may come with zeroed mask sizes, which need
 
324
     to be set here according to DAC Palette width.  If we don't,
 
325
     this results in Linux displaying a black screen.  */
 
326
  if (mode_info.bpp <= 8)
 
327
    {
 
328
      struct grub_vbe_info_block controller_info;
 
329
      int status;
 
330
      int width = 8;
 
331
 
 
332
      status = grub_vbe_bios_get_controller_info (&controller_info);
 
333
 
 
334
      if (status == GRUB_VBE_STATUS_OK &&
 
335
          (controller_info.capabilities & GRUB_VBE_CAPABILITY_DACWIDTH))
 
336
        status = grub_vbe_bios_set_dac_palette_width (&width);
 
337
 
 
338
      if (status != GRUB_VBE_STATUS_OK)
 
339
        /* 6 is default after mode reset.  */
 
340
        width = 6;
 
341
 
 
342
      params->red_mask_size = params->green_mask_size
 
343
        = params->blue_mask_size = width;
 
344
      params->reserved_mask_size = 0;
 
345
    }
 
346
#endif
 
347
 
 
348
  return 0;
 
349
}
 
350
 
289
351
#ifdef __x86_64__
290
352
extern grub_uint8_t grub_linux_trampoline_start[];
291
353
extern grub_uint8_t grub_linux_trampoline_end[];
300
362
  grub_efi_uintn_t desc_size;
301
363
  grub_efi_uint32_t desc_version;
302
364
  int e820_num;
 
365
  const char *modevar;
 
366
  char *tmp;
 
367
  grub_err_t err;
303
368
 
304
369
  params = real_mode_mem;
305
370
 
353
418
  grub_mmap_iterate (hook);
354
419
  params->mmap_size = e820_num;
355
420
 
 
421
  grub_dprintf ("linux", "Trampoline at %p. code32=%x, real_mode_mem=%p\n",
 
422
                ((char *) prot_mode_mem + (prot_mode_pages << 12)),
 
423
                (unsigned) params->code32_start, real_mode_mem);
 
424
 
 
425
  modevar = grub_env_get ("gfxpayload");
 
426
 
 
427
  /* Now all graphical modes are acceptable.
 
428
     May change in future if we have modes without framebuffer.  */
 
429
  if (modevar && *modevar != 0)
 
430
    {
 
431
      tmp = grub_xasprintf ("%s;auto", modevar);
 
432
      if (! tmp)
 
433
        return grub_errno;
 
434
      err = grub_video_set_mode (tmp, GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
 
435
      grub_free (tmp);
 
436
    }
 
437
  else
 
438
    err = grub_video_set_mode ("auto", GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
 
439
 
 
440
  if (!err)
 
441
    err = grub_linux_setup_video (params);
 
442
 
 
443
  if (err)
 
444
    {
 
445
      grub_print_error ();
 
446
      grub_printf ("Booting however\n");
 
447
      grub_errno = GRUB_ERR_NONE;
 
448
    }
 
449
 
356
450
  mmap_size = find_mmap_size ();
357
451
  if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
358
452
                               &desc_size, &desc_version) <= 0)
425
519
  return GRUB_ERR_NONE;
426
520
}
427
521
 
428
 
static grub_efi_guid_t uga_draw_guid = GRUB_EFI_UGA_DRAW_GUID;
429
 
 
430
 
 
431
 
#define RGB_MASK        0xffffff
432
 
#define RGB_MAGIC       0x121314
433
 
#define LINE_MIN        800
434
 
#define LINE_MAX        4096
435
 
#define FBTEST_STEP     (0x10000 >> 2)
436
 
#define FBTEST_COUNT    8
437
 
 
438
 
static int
439
 
find_line_len (grub_uint32_t *fb_base, grub_uint32_t *line_len)
440
 
{
441
 
  grub_uint32_t *base = (grub_uint32_t *) (grub_target_addr_t) *fb_base;
442
 
  int i;
443
 
 
444
 
  for (i = 0; i < FBTEST_COUNT; i++, base += FBTEST_STEP)
445
 
    {
446
 
      if ((*base & RGB_MASK) == RGB_MAGIC)
447
 
        {
448
 
          int j;
449
 
 
450
 
          for (j = LINE_MIN; j <= LINE_MAX; j++)
451
 
            {
452
 
              if ((base[j] & RGB_MASK) == RGB_MAGIC)
453
 
                {
454
 
                  *fb_base = (grub_uint32_t) (grub_target_addr_t) base;
455
 
                  *line_len = j << 2;
456
 
 
457
 
                  return 1;
458
 
                }
459
 
            }
460
 
 
461
 
          break;
462
 
        }
463
 
    }
464
 
 
465
 
  return 0;
466
 
}
467
 
 
468
 
static int
469
 
find_framebuf (grub_uint32_t *fb_base, grub_uint32_t *line_len)
470
 
{
471
 
  int found = 0;
472
 
 
473
 
  auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev,
474
 
                                       grub_pci_id_t pciid);
475
 
 
476
 
  int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev,
477
 
                                  grub_pci_id_t pciid)
478
 
    {
479
 
      grub_pci_address_t addr;
480
 
 
481
 
      addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
482
 
      if (grub_pci_read (addr) >> 24 == 0x3)
483
 
        {
484
 
          int i;
485
 
 
486
 
          grub_printf ("Display controller: %d:%d.%d\nDevice id: %x\n",
487
 
                       grub_pci_get_bus (dev), grub_pci_get_device (dev),
488
 
                       grub_pci_get_function (dev), pciid);
489
 
          addr += 8;
490
 
          for (i = 0; i < 6; i++, addr += 4)
491
 
            {
492
 
              grub_uint32_t old_bar1, old_bar2, type;
493
 
              grub_uint64_t base64;
494
 
 
495
 
              old_bar1 = grub_pci_read (addr);
496
 
              if ((! old_bar1) || (old_bar1 & GRUB_PCI_ADDR_SPACE_IO))
497
 
                continue;
498
 
 
499
 
              type = old_bar1 & GRUB_PCI_ADDR_MEM_TYPE_MASK;
500
 
              if (type == GRUB_PCI_ADDR_MEM_TYPE_64)
501
 
                {
502
 
                  if (i == 5)
503
 
                    break;
504
 
 
505
 
                  old_bar2 = grub_pci_read (addr + 4);
506
 
                }
507
 
              else
508
 
                old_bar2 = 0;
509
 
 
510
 
              base64 = old_bar2;
511
 
              base64 <<= 32;
512
 
              base64 |= (old_bar1 & GRUB_PCI_ADDR_MEM_MASK);
513
 
 
514
 
              grub_printf ("%s(%d): 0x%llx\n",
515
 
                           ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) ?
516
 
                            "VMEM" : "MMIO"), i,
517
 
                           (unsigned long long) base64);
518
 
 
519
 
              if ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) && (! found))
520
 
                {
521
 
                  *fb_base = base64;
522
 
                  if (find_line_len (fb_base, line_len))
523
 
                    found++;
524
 
                }
525
 
 
526
 
              if (type == GRUB_PCI_ADDR_MEM_TYPE_64)
527
 
                {
528
 
                  i++;
529
 
                  addr += 4;
530
 
                }
531
 
            }
532
 
        }
533
 
 
534
 
      return found;
535
 
    }
536
 
 
537
 
  grub_pci_iterate (find_card);
538
 
  return found;
539
 
}
540
 
 
541
 
static int
542
 
grub_linux_setup_video (struct linux_kernel_params *params)
543
 
{
544
 
  grub_efi_uga_draw_protocol_t *c;
545
 
  grub_uint32_t width, height, depth, rate, pixel, fb_base, line_len;
546
 
  int ret;
547
 
 
548
 
  c = grub_efi_locate_protocol (&uga_draw_guid, 0);
549
 
  if (! c)
550
 
    return 1;
551
 
 
552
 
  if (efi_call_5 (c->get_mode, c, &width, &height, &depth, &rate))
553
 
    return 1;
554
 
 
555
 
  grub_printf ("Video mode: %ux%u-%u@%u\n", width, height, depth, rate);
556
 
 
557
 
  grub_efi_set_text_mode (0);
558
 
  pixel = RGB_MAGIC;
559
 
  efi_call_10 (c->blt, c, (struct grub_efi_uga_pixel *) &pixel,
560
 
               GRUB_EFI_UGA_VIDEO_FILL, 0, 0, 0, 0, 1, height, 0);
561
 
  ret = find_framebuf (&fb_base, &line_len);
562
 
  grub_efi_set_text_mode (1);
563
 
 
564
 
  if (! ret)
565
 
    {
566
 
      grub_printf ("Can\'t find frame buffer address\n");
567
 
      return 1;
568
 
    }
569
 
 
570
 
  grub_printf ("Frame buffer base: 0x%x\n", fb_base);
571
 
  grub_printf ("Video line length: %d\n", line_len);
572
 
 
573
 
  params->lfb_width = width;
574
 
  params->lfb_height = height;
575
 
  params->lfb_depth = depth;
576
 
  params->lfb_line_len = line_len;
577
 
 
578
 
  params->lfb_base = fb_base;
579
 
  params->lfb_size = ALIGN_UP (line_len * params->lfb_height, 65536);
580
 
 
581
 
  params->red_mask_size = 8;
582
 
  params->red_field_pos = 16;
583
 
  params->green_mask_size = 8;
584
 
  params->green_field_pos = 8;
585
 
  params->blue_mask_size = 8;
586
 
  params->blue_field_pos = 0;
587
 
  params->reserved_mask_size = 8;
588
 
  params->reserved_field_pos = 24;
589
 
 
590
 
  params->have_vga = GRUB_VIDEO_LINUX_TYPE_VESA;
591
 
  params->vid_mode = 0x338;  /* 1024x768x32  */
592
 
 
593
 
  return 0;
594
 
}
595
 
 
596
522
static grub_err_t
597
523
grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
598
524
                int argc, char *argv[])
806
732
  grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE);
807
733
 
808
734
  /* XXX there is no way to know if the kernel really supports EFI.  */
809
 
  grub_printf ("   [Linux-bzImage, setup=0x%x, size=0x%x]\n",
810
 
               (unsigned) real_size, (unsigned) prot_size);
811
 
 
812
 
  grub_linux_setup_video (params);
 
735
  grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n",
 
736
                (unsigned) real_size, (unsigned) prot_size);
813
737
 
814
738
  /* Detect explicitly specified memory size, if any.  */
815
739
  linux_mem_size = 0;
876
800
 
877
801
  if (grub_errno == GRUB_ERR_NONE)
878
802
    {
879
 
      grub_loader_set (grub_linux_boot, grub_linux_unload, 1);
 
803
      grub_loader_set (grub_linux_boot, grub_linux_unload, 0);
880
804
      loaded = 1;
881
805
    }
882
806
 
989
913
      goto fail;
990
914
    }
991
915
 
992
 
  grub_printf ("   [Initrd, addr=0x%x, size=0x%x]\n",
993
 
               (unsigned) addr, (unsigned) size);
 
916
  grub_dprintf ("linux", "Initrd, addr=0x%x, size=0x%x\n",
 
917
                (unsigned) addr, (unsigned) size);
994
918
 
995
919
  lh->ramdisk_image = addr;
996
920
  lh->ramdisk_size = size;