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

« back to all changes in this revision

Viewing changes to grub-core/mmap/efi/mmap.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
/* Mmap management. */
 
2
/*
 
3
 *  GRUB  --  GRand Unified Bootloader
 
4
 *  Copyright (C) 2009  Free Software Foundation, Inc.
 
5
 *
 
6
 *  GRUB is free software: you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation, either version 3 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  GRUB is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
20
#include <grub/machine/memory.h>
 
21
#include <grub/memory.h>
 
22
#include <grub/err.h>
 
23
#include <grub/efi/api.h>
 
24
#include <grub/efi/efi.h>
 
25
#include <grub/mm.h>
 
26
#include <grub/misc.h>
 
27
 
 
28
#define NEXT_MEMORY_DESCRIPTOR(desc, size)      \
 
29
  ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
 
30
 
 
31
grub_err_t
 
32
grub_machine_mmap_iterate (grub_memory_hook_t hook)
 
33
{
 
34
  grub_efi_uintn_t mmap_size = 0;
 
35
  grub_efi_memory_descriptor_t *map_buf = 0;
 
36
  grub_efi_uintn_t map_key = 0;
 
37
  grub_efi_uintn_t desc_size = 0;
 
38
  grub_efi_uint32_t desc_version = 0;
 
39
  grub_efi_memory_descriptor_t *desc;
 
40
 
 
41
  if (grub_efi_get_memory_map (&mmap_size, map_buf,
 
42
                               &map_key, &desc_size,
 
43
                               &desc_version) < 0)
 
44
    return grub_errno;
 
45
 
 
46
  map_buf = grub_malloc (mmap_size);
 
47
  if (! map_buf)
 
48
    return grub_errno;
 
49
 
 
50
  if (grub_efi_get_memory_map (&mmap_size, map_buf,
 
51
                               &map_key, &desc_size,
 
52
                               &desc_version) <= 0)
 
53
    {
 
54
      grub_free (map_buf);
 
55
      return grub_errno;
 
56
    }
 
57
 
 
58
  for (desc = map_buf;
 
59
       desc < NEXT_MEMORY_DESCRIPTOR (map_buf, mmap_size);
 
60
       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
 
61
    {
 
62
      grub_dprintf ("mmap", "EFI memory region 0x%llx-0x%llx: %d\n",
 
63
                    (unsigned long long) desc->physical_start,
 
64
                    (unsigned long long) desc->physical_start
 
65
                    + desc->num_pages * 4096, desc->type);
 
66
      switch (desc->type)
 
67
        {
 
68
        case GRUB_EFI_RUNTIME_SERVICES_CODE:
 
69
          hook (desc->physical_start, desc->num_pages * 4096,
 
70
                GRUB_MEMORY_CODE);
 
71
          break;
 
72
 
 
73
        case GRUB_EFI_UNUSABLE_MEMORY:
 
74
          hook (desc->physical_start, desc->num_pages * 4096,
 
75
                GRUB_MEMORY_BADRAM);
 
76
          break;
 
77
 
 
78
        default:
 
79
          grub_printf ("Unknown memory type %d, considering reserved\n",
 
80
                       desc->type);
 
81
 
 
82
        case GRUB_EFI_RESERVED_MEMORY_TYPE:
 
83
        case GRUB_EFI_RUNTIME_SERVICES_DATA:
 
84
        case GRUB_EFI_MEMORY_MAPPED_IO:
 
85
        case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE:
 
86
        case GRUB_EFI_PAL_CODE:
 
87
          hook (desc->physical_start, desc->num_pages * 4096,
 
88
                GRUB_MEMORY_RESERVED);
 
89
          break;
 
90
 
 
91
        case GRUB_EFI_LOADER_CODE:
 
92
        case GRUB_EFI_LOADER_DATA:
 
93
        case GRUB_EFI_BOOT_SERVICES_CODE:
 
94
        case GRUB_EFI_BOOT_SERVICES_DATA:
 
95
        case GRUB_EFI_CONVENTIONAL_MEMORY:
 
96
          hook (desc->physical_start, desc->num_pages * 4096,
 
97
                GRUB_MEMORY_AVAILABLE);
 
98
          break;
 
99
 
 
100
        case GRUB_EFI_ACPI_RECLAIM_MEMORY:
 
101
          hook (desc->physical_start, desc->num_pages * 4096,
 
102
                GRUB_MEMORY_ACPI);
 
103
          break;
 
104
 
 
105
        case GRUB_EFI_ACPI_MEMORY_NVS:
 
106
          hook (desc->physical_start, desc->num_pages * 4096,
 
107
                GRUB_MEMORY_NVS);
 
108
          break;
 
109
        }
 
110
    }
 
111
 
 
112
  return GRUB_ERR_NONE;
 
113
}
 
114
 
 
115
static inline grub_efi_memory_type_t
 
116
make_efi_memtype (int type)
 
117
{
 
118
  switch (type)
 
119
    {
 
120
    case GRUB_MEMORY_CODE:
 
121
      return GRUB_EFI_RUNTIME_SERVICES_CODE;
 
122
 
 
123
      /* No way to remove a chunk of memory from EFI mmap.
 
124
         So mark it as unusable. */
 
125
    case GRUB_MEMORY_HOLE:
 
126
    case GRUB_MEMORY_RESERVED:
 
127
      return GRUB_EFI_UNUSABLE_MEMORY;
 
128
 
 
129
    case GRUB_MEMORY_AVAILABLE:
 
130
      return GRUB_EFI_CONVENTIONAL_MEMORY;
 
131
 
 
132
    case GRUB_MEMORY_ACPI:
 
133
      return GRUB_EFI_ACPI_RECLAIM_MEMORY;
 
134
 
 
135
    case GRUB_MEMORY_NVS:
 
136
      return GRUB_EFI_ACPI_MEMORY_NVS;
 
137
    }
 
138
 
 
139
  return GRUB_EFI_UNUSABLE_MEMORY;
 
140
}
 
141
 
 
142
struct overlay
 
143
{
 
144
  struct overlay *next;
 
145
  grub_efi_physical_address_t address;
 
146
  grub_efi_uintn_t pages;
 
147
  int handle;
 
148
};
 
149
 
 
150
static struct overlay *overlays = 0;
 
151
static int curhandle = 1;
 
152
 
 
153
int
 
154
grub_mmap_register (grub_uint64_t start, grub_uint64_t size, int type)
 
155
{
 
156
  grub_uint64_t end = start + size;
 
157
  grub_efi_physical_address_t address;
 
158
  grub_efi_boot_services_t *b;
 
159
  grub_efi_uintn_t pages;
 
160
  grub_efi_status_t status;
 
161
  struct overlay *curover;
 
162
 
 
163
  curover = (struct overlay *) grub_malloc (sizeof (struct overlay));
 
164
  if (! curover)
 
165
    return 0;
 
166
 
 
167
  b = grub_efi_system_table->boot_services;
 
168
  address = start & (~0x3ffULL);
 
169
  pages = (end - address  + 0x3ff) >> 12;
 
170
  status = efi_call_2 (b->free_pages, address, pages);
 
171
  if (status != GRUB_EFI_SUCCESS && status != GRUB_EFI_NOT_FOUND)
 
172
    {
 
173
      grub_free (curover);
 
174
      return 0;
 
175
    }
 
176
  status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ADDRESS,
 
177
                       make_efi_memtype (type), pages, &address);
 
178
  if (status != GRUB_EFI_SUCCESS)
 
179
    {
 
180
      grub_free (curover);
 
181
      return 0;
 
182
    }
 
183
  curover->next = overlays;
 
184
  curover->handle = curhandle++;
 
185
  curover->address = address;
 
186
  curover->pages = pages;
 
187
  overlays = curover;
 
188
 
 
189
  return curover->handle;
 
190
}
 
191
 
 
192
grub_err_t
 
193
grub_mmap_unregister (int handle)
 
194
{
 
195
  struct overlay *curover, *prevover;
 
196
  grub_efi_boot_services_t *b;
 
197
  grub_efi_status_t status;
 
198
 
 
199
  b = grub_efi_system_table->boot_services;
 
200
 
 
201
 
 
202
  for (curover = overlays, prevover = 0; curover;
 
203
       prevover = curover, curover = curover->next)
 
204
    {
 
205
      if (curover->handle == handle)
 
206
        {
 
207
          status = efi_call_2 (b->free_pages, curover->address, curover->pages);
 
208
          if (prevover != 0)
 
209
            prevover->next = curover->next;
 
210
          else
 
211
            overlays = curover->next;
 
212
          grub_free (curover);
 
213
          return GRUB_ERR_NONE;
 
214
        }
 
215
    }
 
216
  return grub_error (GRUB_ERR_BAD_ARGUMENT, "handle %d not found", handle);
 
217
}
 
218
 
 
219
/* Result is always page-aligned. */
 
220
void *
 
221
grub_mmap_malign_and_register (grub_uint64_t align __attribute__ ((unused)),
 
222
                               grub_uint64_t size,
 
223
                               int *handle, int type,
 
224
                               int flags __attribute__ ((unused)))
 
225
{
 
226
  grub_efi_physical_address_t address;
 
227
  grub_efi_boot_services_t *b;
 
228
  grub_efi_uintn_t pages;
 
229
  grub_efi_status_t status;
 
230
  struct overlay *curover;
 
231
  grub_efi_allocate_type_t atype;
 
232
 
 
233
  curover = (struct overlay *) grub_malloc (sizeof (struct overlay));
 
234
  if (! curover)
 
235
    return 0;
 
236
 
 
237
  b = grub_efi_system_table->boot_services;
 
238
 
 
239
  address = 0xffffffff;
 
240
 
 
241
#if GRUB_TARGET_SIZEOF_VOID_P < 8
 
242
  /* Limit the memory access to less than 4GB for 32-bit platforms.  */
 
243
  atype = GRUB_EFI_ALLOCATE_MAX_ADDRESS;
 
244
#else
 
245
  atype = GRUB_EFI_ALLOCATE_ANY_PAGES;
 
246
#endif
 
247
 
 
248
  pages = (size + 0x3ff) >> 12;
 
249
  status = efi_call_4 (b->allocate_pages, atype,
 
250
                       make_efi_memtype (type), pages, &address);
 
251
  if (status != GRUB_EFI_SUCCESS)
 
252
    {
 
253
      grub_free (curover);
 
254
      return 0;
 
255
    }
 
256
 
 
257
  if (address == 0)
 
258
    {
 
259
      /* Uggh, the address 0 was allocated... This is too annoying,
 
260
         so reallocate another one.  */
 
261
      address = 0xffffffff;
 
262
      status = efi_call_4 (b->allocate_pages, atype,
 
263
                           make_efi_memtype (type), pages, &address);
 
264
      grub_efi_free_pages (0, pages);
 
265
      if (status != GRUB_EFI_SUCCESS)
 
266
        return 0;
 
267
    }
 
268
 
 
269
  curover->next = overlays;
 
270
  curover->handle = curhandle++;
 
271
  curover->address = address;
 
272
  curover->pages = pages;
 
273
  overlays = curover;
 
274
  *handle = curover->handle;
 
275
 
 
276
  return UINT_TO_PTR (curover->address);
 
277
}
 
278
 
 
279
void
 
280
grub_mmap_free_and_unregister (int handle)
 
281
{
 
282
  grub_mmap_unregister (handle);
 
283
}