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

« back to all changes in this revision

Viewing changes to efiemu/pnvram.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Robert Millan, Updated translations
  • Date: 2010-11-22 12:24:56 UTC
  • mfrom: (1.26.4 upstream) (17.3.36 sid)
  • mto: (17.3.43 sid)
  • mto: This revision was merged to the branch mainline in revision 89.
  • Revision ID: james.westby@ubuntu.com-20101122122456-y82z3sfb7k4zfdcc
Tags: 1.99~20101122-1
[ Colin Watson ]
* New Bazaar snapshot.  Too many changes to list in full, but some of the
  more user-visible ones are as follows:
  - GRUB script:
    + Function parameters, "break", "continue", "shift", "setparams",
      "return", and "!".
    + "export" command supports multiple variable names.
    + Multi-line quoted strings support.
    + Wildcard expansion.
  - sendkey support.
  - USB hotunplugging and USB serial support.
  - Rename CD-ROM to cd on BIOS.
  - Add new --boot-directory option to grub-install, grub-reboot, and
    grub-set-default; the old --root-directory option is still accepted
    but was often confusing.
  - Basic btrfs detection/UUID support (but no file reading yet).
  - bash-completion for utilities.
  - If a device is listed in device.map, always assume that it is
    BIOS-visible rather than using extra layers such as LVM or RAID.
  - Add grub-mknetdir script (closes: #550658).
  - Remove deprecated "root" command.
  - Handle RAID devices containing virtio components.
  - GRUB Legacy configuration file support (via grub-menulst2cfg).
  - Keyboard layout support (via grub-mklayout and grub-kbdcomp).
  - Check generated grub.cfg for syntax errors before saving.
  - Pause execution for at most ten seconds if any errors are displayed,
    so that the user has a chance to see them.
  - Support submenus.
  - Write embedding zone using Reed-Solomon, so that it's robust against
    being partially overwritten (closes: #550702, #591416, #593347).
  - GRUB_DISABLE_LINUX_RECOVERY and GRUB_DISABLE_NETBSD_RECOVERY merged
    into a single GRUB_DISABLE_RECOVERY variable.
  - Fix loader memory allocation failure (closes: #551627).
  - Don't call savedefault on recovery entries (closes: #589325).
  - Support triple-indirect blocks on ext2 (closes: #543924).
  - Recognise DDF1 fake RAID (closes: #603354).

[ Robert Millan ]
* Use dpkg architecture wildcards.

[ Updated translations ]
* Slovenian (Vanja Cvelbar).  Closes: #604003
* Dzongkha (dawa pemo via Tenzin Dendup).  Closes: #604102

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Export pnvram and some variables for runtime */
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/file.h>
21
 
#include <grub/err.h>
22
 
#include <grub/normal.h>
23
 
#include <grub/mm.h>
24
 
#include <grub/misc.h>
25
 
#include <grub/charset.h>
26
 
#include <grub/efiemu/efiemu.h>
27
 
#include <grub/efiemu/runtime.h>
28
 
#include <grub/extcmd.h>
29
 
 
30
 
/* Place for final location of variables */
31
 
static int nvram_handle = 0;
32
 
static int nvramsize_handle = 0;
33
 
static int high_monotonic_count_handle = 0;
34
 
static int timezone_handle = 0;
35
 
static int accuracy_handle = 0;
36
 
static int daylight_handle = 0;
37
 
 
38
 
static grub_size_t nvramsize;
39
 
 
40
 
/* Parse signed value */
41
 
static int
42
 
grub_strtosl (const char *arg, char **end, int base)
43
 
{
44
 
  if (arg[0] == '-')
45
 
    return -grub_strtoul (arg + 1, end, base);
46
 
  return grub_strtoul (arg, end, base);
47
 
}
48
 
 
49
 
static inline int
50
 
hextoval (char c)
51
 
{
52
 
  if (c >= '0' && c <= '9')
53
 
    return c - '0';
54
 
  if (c >= 'a' && c <= 'z')
55
 
    return c - 'a' + 10;
56
 
  if (c >= 'A' && c <= 'Z')
57
 
    return c - 'A' + 10;
58
 
  return 0;
59
 
}
60
 
 
61
 
static inline grub_err_t
62
 
unescape (char *in, char *out, char *outmax, int *len)
63
 
{
64
 
  char *ptr, *dptr;
65
 
  dptr = out;
66
 
  for (ptr = in; *ptr && dptr < outmax; )
67
 
    if (*ptr == '%' && ptr[1] && ptr[2])
68
 
      {
69
 
        *dptr = (hextoval (ptr[1]) << 4) | (hextoval (ptr[2]));
70
 
        ptr += 3;
71
 
        dptr++;
72
 
      }
73
 
    else
74
 
      {
75
 
        *dptr = *ptr;
76
 
        ptr++;
77
 
        dptr++;
78
 
      }
79
 
  if (dptr == outmax)
80
 
    return grub_error (GRUB_ERR_OUT_OF_MEMORY,
81
 
                       "too many NVRAM variables for reserved variable space."
82
 
                       " Try increasing EfiEmu.pnvram.size");
83
 
  *len = dptr - out;
84
 
  return 0;
85
 
}
86
 
 
87
 
/* Export stuff for efiemu */
88
 
static grub_err_t
89
 
nvram_set (void * data __attribute__ ((unused)))
90
 
{
91
 
  const char *env;
92
 
  /* Take definitive pointers */
93
 
  char *nvram = grub_efiemu_mm_obtain_request (nvram_handle);
94
 
  grub_uint32_t *nvramsize_def
95
 
    = grub_efiemu_mm_obtain_request (nvramsize_handle);
96
 
  grub_uint32_t *high_monotonic_count
97
 
    = grub_efiemu_mm_obtain_request (high_monotonic_count_handle);
98
 
  grub_int16_t *timezone
99
 
    = grub_efiemu_mm_obtain_request (timezone_handle);
100
 
  grub_uint8_t *daylight
101
 
    = grub_efiemu_mm_obtain_request (daylight_handle);
102
 
  grub_uint32_t *accuracy
103
 
    = grub_efiemu_mm_obtain_request (accuracy_handle);
104
 
  char *nvramptr;
105
 
 
106
 
  auto int iterate_env (struct grub_env_var *var);
107
 
  int iterate_env (struct grub_env_var *var)
108
 
  {
109
 
    char *guid, *attr, *name, *varname;
110
 
    struct efi_variable *efivar;
111
 
    int len = 0;
112
 
    int i;
113
 
    grub_uint64_t guidcomp;
114
 
 
115
 
    if (grub_memcmp (var->name, "EfiEmu.pnvram.",
116
 
                     sizeof ("EfiEmu.pnvram.") - 1) != 0)
117
 
      return 0;
118
 
 
119
 
    guid = var->name + sizeof ("EfiEmu.pnvram.") - 1;
120
 
 
121
 
    attr = grub_strchr (guid, '.');
122
 
    if (!attr)
123
 
      return 0;
124
 
    attr++;
125
 
 
126
 
    name = grub_strchr (attr, '.');
127
 
    if (!name)
128
 
      return 0;
129
 
    name++;
130
 
 
131
 
    efivar = (struct efi_variable *) nvramptr;
132
 
    if (nvramptr - nvram + sizeof (struct efi_variable) > nvramsize)
133
 
      {
134
 
        grub_error (GRUB_ERR_OUT_OF_MEMORY,
135
 
                    "too many NVRAM variables for reserved variable space."
136
 
                    " Try increasing EfiEmu.pnvram.size");
137
 
        return 1;
138
 
      }
139
 
 
140
 
    nvramptr += sizeof (struct efi_variable);
141
 
 
142
 
    efivar->guid.data1 = grub_cpu_to_le32 (grub_strtoul (guid, &guid, 16));
143
 
    if (*guid != '-')
144
 
      return 0;
145
 
    guid++;
146
 
 
147
 
    efivar->guid.data2 = grub_cpu_to_le16 (grub_strtoul (guid, &guid, 16));
148
 
    if (*guid != '-')
149
 
      return 0;
150
 
    guid++;
151
 
 
152
 
    efivar->guid.data3 = grub_cpu_to_le16 (grub_strtoul (guid, &guid, 16));
153
 
    if (*guid != '-')
154
 
      return 0;
155
 
    guid++;
156
 
 
157
 
    guidcomp = grub_strtoull (guid, 0, 16);
158
 
    for (i = 0; i < 8; i++)
159
 
      efivar->guid.data4[i] = (guidcomp >> (56 - 8 * i)) & 0xff;
160
 
 
161
 
    efivar->attributes = grub_strtoull (attr, 0, 16);
162
 
 
163
 
    varname = grub_malloc (grub_strlen (name) + 1);
164
 
    if (! varname)
165
 
      return 1;
166
 
 
167
 
    if (unescape (name, varname, varname + grub_strlen (name) + 1, &len))
168
 
      return 1;
169
 
 
170
 
    len = grub_utf8_to_utf16 ((grub_uint16_t *) nvramptr,
171
 
                              (nvramsize - (nvramptr - nvram)) / 2,
172
 
                              (grub_uint8_t *) varname, len, NULL);
173
 
 
174
 
    if (len < 0)
175
 
      {
176
 
        grub_error (GRUB_ERR_BAD_ARGUMENT, "broken UTF-8 in variable name");
177
 
        return 1;
178
 
      }
179
 
 
180
 
    nvramptr += 2 * len;
181
 
    *((grub_uint16_t *) nvramptr) = 0;
182
 
    nvramptr += 2;
183
 
    efivar->namelen = 2 * len + 2;
184
 
 
185
 
    if (unescape (var->value, nvramptr, nvram + nvramsize, &len))
186
 
      {
187
 
        efivar->namelen = 0;
188
 
        return 1;
189
 
      }
190
 
 
191
 
    nvramptr += len;
192
 
 
193
 
    efivar->size = len;
194
 
 
195
 
    return 0;
196
 
  }
197
 
 
198
 
  /* Copy to definitive loaction */
199
 
  grub_dprintf ("efiemu", "preparing pnvram\n");
200
 
 
201
 
  env = grub_env_get ("EfiEmu.pnvram.high_monotonic_count");
202
 
  *high_monotonic_count = env ? grub_strtoul (env, 0, 0) : 1;
203
 
  env = grub_env_get ("EfiEmu.pnvram.timezone");
204
 
  *timezone = env ? grub_strtosl (env, 0, 0) : GRUB_EFI_UNSPECIFIED_TIMEZONE;
205
 
  env = grub_env_get ("EfiEmu.pnvram.accuracy");
206
 
  *accuracy = env ? grub_strtoul (env, 0, 0) : 50000000;
207
 
  env = grub_env_get ("EfiEmu.pnvram.daylight");
208
 
  *daylight = env ? grub_strtoul (env, 0, 0) : 0;
209
 
 
210
 
  nvramptr = nvram;
211
 
  grub_memset (nvram, 0, nvramsize);
212
 
  grub_env_iterate (iterate_env);
213
 
  if (grub_errno)
214
 
    return grub_errno;
215
 
  *nvramsize_def = nvramsize;
216
 
 
217
 
  /* Register symbols */
218
 
  grub_efiemu_register_symbol ("efiemu_variables", nvram_handle, 0);
219
 
  grub_efiemu_register_symbol ("efiemu_varsize", nvramsize_handle, 0);
220
 
  grub_efiemu_register_symbol ("efiemu_high_monotonic_count",
221
 
                               high_monotonic_count_handle, 0);
222
 
  grub_efiemu_register_symbol ("efiemu_time_zone", timezone_handle, 0);
223
 
  grub_efiemu_register_symbol ("efiemu_time_daylight", daylight_handle, 0);
224
 
  grub_efiemu_register_symbol ("efiemu_time_accuracy",
225
 
                               accuracy_handle, 0);
226
 
 
227
 
  return GRUB_ERR_NONE;
228
 
}
229
 
 
230
 
static void
231
 
nvram_unload (void * data __attribute__ ((unused)))
232
 
{
233
 
  grub_efiemu_mm_return_request (nvram_handle);
234
 
  grub_efiemu_mm_return_request (nvramsize_handle);
235
 
  grub_efiemu_mm_return_request (high_monotonic_count_handle);
236
 
  grub_efiemu_mm_return_request (timezone_handle);
237
 
  grub_efiemu_mm_return_request (accuracy_handle);
238
 
  grub_efiemu_mm_return_request (daylight_handle);
239
 
}
240
 
 
241
 
grub_err_t
242
 
grub_efiemu_pnvram (void)
243
 
{
244
 
  const char *size;
245
 
  grub_err_t err;
246
 
 
247
 
  nvramsize = 0;
248
 
 
249
 
  size = grub_env_get ("EfiEmu.pnvram.size");
250
 
  if (size)
251
 
    nvramsize = grub_strtoul (size, 0, 0);
252
 
 
253
 
  if (!nvramsize)
254
 
    nvramsize = 2048;
255
 
 
256
 
  err = grub_efiemu_register_prepare_hook (nvram_set, nvram_unload, 0);
257
 
  if (err)
258
 
    return err;
259
 
 
260
 
  nvram_handle
261
 
    = grub_efiemu_request_memalign (1, nvramsize,
262
 
                                    GRUB_EFI_RUNTIME_SERVICES_DATA);
263
 
  nvramsize_handle
264
 
    = grub_efiemu_request_memalign (1, sizeof (grub_uint32_t),
265
 
                                    GRUB_EFI_RUNTIME_SERVICES_DATA);
266
 
  high_monotonic_count_handle
267
 
    = grub_efiemu_request_memalign (1, sizeof (grub_uint32_t),
268
 
                                    GRUB_EFI_RUNTIME_SERVICES_DATA);
269
 
  timezone_handle
270
 
    = grub_efiemu_request_memalign (1, sizeof (grub_uint16_t),
271
 
                                    GRUB_EFI_RUNTIME_SERVICES_DATA);
272
 
  daylight_handle
273
 
    = grub_efiemu_request_memalign (1, sizeof (grub_uint8_t),
274
 
                                    GRUB_EFI_RUNTIME_SERVICES_DATA);
275
 
  accuracy_handle
276
 
    = grub_efiemu_request_memalign (1, sizeof (grub_uint32_t),
277
 
                                    GRUB_EFI_RUNTIME_SERVICES_DATA);
278
 
 
279
 
  return GRUB_ERR_NONE;
280
 
}