source: grub-pc/trunk/fuentes/grub-core/loader/i386/xen.c @ 22

Last change on this file since 22 was 22, checked in by mabarracus, 4 years ago

updated version and apply net.ifnames=0 into debian/rules

File size: 18.9 KB
Line 
1/*
2 *  GRUB  --  GRand Unified Bootloader
3 *  Copyright (C) 2013  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/loader.h>
20#include <grub/memory.h>
21#include <grub/normal.h>
22#include <grub/file.h>
23#include <grub/disk.h>
24#include <grub/err.h>
25#include <grub/misc.h>
26#include <grub/types.h>
27#include <grub/dl.h>
28#include <grub/mm.h>
29#include <grub/term.h>
30#include <grub/cpu/linux.h>
31#include <grub/video.h>
32#include <grub/video_fb.h>
33#include <grub/command.h>
34#include <grub/xen/relocator.h>
35#include <grub/i18n.h>
36#include <grub/elf.h>
37#include <grub/elfload.h>
38#include <grub/lib/cmdline.h>
39#include <grub/xen.h>
40#include <grub/xen_file.h>
41#include <grub/linux.h>
42
43GRUB_MOD_LICENSE ("GPLv3+");
44
45static struct grub_relocator *relocator = NULL;
46static grub_uint64_t max_addr;
47static grub_dl_t my_mod;
48static int loaded = 0;
49static struct start_info next_start;
50static void *kern_chunk_src;
51static struct grub_xen_file_info xen_inf;
52static struct xen_multiboot_mod_list *xen_module_info_page;
53static grub_uint64_t modules_target_start;
54static grub_size_t n_modules;
55
56#define PAGE_SIZE 4096
57#define MAX_MODULES (PAGE_SIZE / sizeof (struct xen_multiboot_mod_list))
58#define PAGE_SHIFT 12
59#define STACK_SIZE 1048576
60#define ADDITIONAL_SIZE (1 << 19)
61#define ALIGN_SIZE (1 << 22)
62#define LOG_POINTERS_PER_PAGE 9
63#define POINTERS_PER_PAGE (1 << LOG_POINTERS_PER_PAGE)
64
65static grub_uint64_t
66page2offset (grub_uint64_t page)
67{
68  return page << PAGE_SHIFT;
69}
70
71#ifdef __x86_64__
72#define NUMBER_OF_LEVELS 4
73#define INTERMEDIATE_OR 7
74#else
75#define NUMBER_OF_LEVELS 3
76#define INTERMEDIATE_OR 3
77#endif
78
79static grub_uint64_t
80get_pgtable_size (grub_uint64_t total_pages, grub_uint64_t virt_base)
81{
82  if (!virt_base)
83    total_pages++;
84  grub_uint64_t ret = 0;
85  grub_uint64_t ll = total_pages;
86  int i;
87  for (i = 0; i < NUMBER_OF_LEVELS; i++)
88    {
89      ll = (ll + POINTERS_PER_PAGE - 1) >> LOG_POINTERS_PER_PAGE;
90      /* PAE wants all 4 root directories present.  */
91#ifdef __i386__
92      if (i == 1)
93        ll = 4;
94#endif
95      ret += ll;
96    }
97  for (i = 1; i < NUMBER_OF_LEVELS; i++)
98    if (virt_base >> (PAGE_SHIFT + i * LOG_POINTERS_PER_PAGE))
99      ret++;
100  return ret;
101}
102
103static void
104generate_page_table (grub_uint64_t *where, grub_uint64_t paging_start,
105                     grub_uint64_t total_pages, grub_uint64_t virt_base,
106                     grub_xen_mfn_t *mfn_list)
107{
108  if (!virt_base)
109    total_pages++;
110
111  grub_uint64_t lx[NUMBER_OF_LEVELS], lxs[NUMBER_OF_LEVELS];
112  grub_uint64_t nlx, nls, sz = 0;
113  int l;
114
115  nlx = total_pages;
116  nls = virt_base >> PAGE_SHIFT;
117  for (l = 0; l < NUMBER_OF_LEVELS; l++)
118    {
119      nlx = (nlx + POINTERS_PER_PAGE - 1) >> LOG_POINTERS_PER_PAGE;
120      /* PAE wants all 4 root directories present.  */
121#ifdef __i386__
122      if (l == 1)
123        nlx = 4;
124#endif
125      lx[l] = nlx;
126      sz += lx[l];
127      lxs[l] = nls & (POINTERS_PER_PAGE - 1);
128      if (nls && l != 0)
129        sz++;
130      nls >>= LOG_POINTERS_PER_PAGE;
131    }
132
133  grub_uint64_t lp;
134  grub_uint64_t j;
135  grub_uint64_t *pg = (grub_uint64_t *) where;
136  int pr = 0;
137
138  grub_memset (pg, 0, sz * PAGE_SIZE);
139
140  lp = paging_start + lx[NUMBER_OF_LEVELS - 1];
141  for (l = NUMBER_OF_LEVELS - 1; l >= 1; l--)
142    {
143      if (lxs[l] || pr)
144        pg[0] = page2offset (mfn_list[lp++]) | INTERMEDIATE_OR;
145      if (pr)
146        pg += POINTERS_PER_PAGE;
147      for (j = 0; j < lx[l - 1]; j++)
148        pg[j + lxs[l]] = page2offset (mfn_list[lp++]) | INTERMEDIATE_OR;
149      pg += lx[l] * POINTERS_PER_PAGE;
150      if (lxs[l])
151        pr = 1;
152    }
153
154  if (lxs[0] || pr)
155    pg[0] = page2offset (mfn_list[total_pages]) | 5;
156  if (pr)
157    pg += POINTERS_PER_PAGE;
158
159  for (j = 0; j < total_pages; j++)
160    {
161      if (j >= paging_start && j < lp)
162        pg[j + lxs[0]] = page2offset (mfn_list[j]) | 5;
163      else
164        pg[j + lxs[0]] = page2offset (mfn_list[j]) | 7;
165    }
166}
167
168static grub_err_t
169set_mfns (grub_xen_mfn_t * new_mfn_list, grub_xen_mfn_t pfn)
170{
171  grub_xen_mfn_t i, t;
172  grub_xen_mfn_t cn_pfn = -1, st_pfn = -1;
173  struct mmu_update m2p_updates[4];
174
175
176  for (i = 0; i < grub_xen_start_page_addr->nr_pages; i++)
177    {
178      if (new_mfn_list[i] == grub_xen_start_page_addr->console.domU.mfn)
179        cn_pfn = i;
180      if (new_mfn_list[i] == grub_xen_start_page_addr->store_mfn)
181        st_pfn = i;
182    }
183  if (cn_pfn == (grub_xen_mfn_t)-1)
184    return grub_error (GRUB_ERR_BUG, "no console");
185  if (st_pfn == (grub_xen_mfn_t)-1)
186    return grub_error (GRUB_ERR_BUG, "no store");
187  t = new_mfn_list[pfn];
188  new_mfn_list[pfn] = new_mfn_list[cn_pfn];
189  new_mfn_list[cn_pfn] = t;
190  t = new_mfn_list[pfn + 1];
191  new_mfn_list[pfn + 1] = new_mfn_list[st_pfn];
192  new_mfn_list[st_pfn] = t;
193
194  m2p_updates[0].ptr = page2offset (new_mfn_list[pfn]) | MMU_MACHPHYS_UPDATE;
195  m2p_updates[0].val = pfn;
196  m2p_updates[1].ptr =
197    page2offset (new_mfn_list[pfn + 1]) | MMU_MACHPHYS_UPDATE;
198  m2p_updates[1].val = pfn + 1;
199  m2p_updates[2].ptr =
200    page2offset (new_mfn_list[cn_pfn]) | MMU_MACHPHYS_UPDATE;
201  m2p_updates[2].val = cn_pfn;
202  m2p_updates[3].ptr =
203    page2offset (new_mfn_list[st_pfn]) | MMU_MACHPHYS_UPDATE;
204  m2p_updates[3].val = st_pfn;
205
206  grub_xen_mmu_update (m2p_updates, 4, NULL, DOMID_SELF);
207
208  return GRUB_ERR_NONE;
209}
210
211static grub_err_t
212grub_xen_boot (void)
213{
214  struct grub_relocator_xen_state state;
215  grub_relocator_chunk_t ch;
216  grub_err_t err;
217  grub_size_t pgtsize;
218  struct start_info *nst;
219  grub_uint64_t nr_info_pages;
220  grub_uint64_t nr_pages, nr_pt_pages, nr_need_pages;
221  struct gnttab_set_version gnttab_setver;
222  grub_xen_mfn_t *new_mfn_list;
223  grub_size_t i;
224
225  if (grub_xen_n_allocated_shared_pages)
226    return grub_error (GRUB_ERR_BUG, "active grants");
227
228  state.mfn_list = max_addr;
229  next_start.mfn_list = max_addr + xen_inf.virt_base;
230  next_start.first_p2m_pfn = max_addr >> PAGE_SHIFT;    /* Is this right? */
231  pgtsize = sizeof (grub_xen_mfn_t) * grub_xen_start_page_addr->nr_pages;
232  err = grub_relocator_alloc_chunk_addr (relocator, &ch, max_addr, pgtsize);
233  next_start.nr_p2m_frames = (pgtsize + PAGE_SIZE - 1) >> PAGE_SHIFT;
234  if (err)
235    return err;
236  new_mfn_list = get_virtual_current_address (ch);
237  grub_memcpy (new_mfn_list,
238               (void *) grub_xen_start_page_addr->mfn_list, pgtsize);
239  max_addr = ALIGN_UP (max_addr + pgtsize, PAGE_SIZE);
240
241  err = grub_relocator_alloc_chunk_addr (relocator, &ch,
242                                         max_addr, sizeof (next_start));
243  if (err)
244    return err;
245  state.start_info = max_addr + xen_inf.virt_base;
246  nst = get_virtual_current_address (ch);
247  max_addr = ALIGN_UP (max_addr + sizeof (next_start), PAGE_SIZE);
248
249  next_start.nr_pages = grub_xen_start_page_addr->nr_pages;
250  grub_memcpy (next_start.magic, grub_xen_start_page_addr->magic,
251               sizeof (next_start.magic));
252  next_start.store_mfn = grub_xen_start_page_addr->store_mfn;
253  next_start.store_evtchn = grub_xen_start_page_addr->store_evtchn;
254  next_start.console.domU = grub_xen_start_page_addr->console.domU;
255  next_start.shared_info = grub_xen_start_page_addr->shared_info;
256
257  err = set_mfns (new_mfn_list, max_addr >> PAGE_SHIFT);
258  if (err)
259    return err;
260  max_addr += 2 * PAGE_SIZE;
261
262  next_start.pt_base = max_addr + xen_inf.virt_base;
263  state.paging_start = max_addr >> PAGE_SHIFT;
264
265  nr_info_pages = max_addr >> PAGE_SHIFT;
266  nr_pages = nr_info_pages;
267
268  while (1)
269    {
270      nr_pages = ALIGN_UP (nr_pages, (ALIGN_SIZE >> PAGE_SHIFT));
271      nr_pt_pages = get_pgtable_size (nr_pages, xen_inf.virt_base);
272      nr_need_pages =
273        nr_info_pages + nr_pt_pages +
274        ((ADDITIONAL_SIZE + STACK_SIZE) >> PAGE_SHIFT);
275      if (nr_pages >= nr_need_pages)
276        break;
277      nr_pages = nr_need_pages;
278    }
279
280  grub_dprintf ("xen", "bootstrap domain %llx+%llx\n",
281                (unsigned long long) xen_inf.virt_base,
282                (unsigned long long) page2offset (nr_pages));
283
284  err = grub_relocator_alloc_chunk_addr (relocator, &ch,
285                                         max_addr, page2offset (nr_pt_pages));
286  if (err)
287    return err;
288
289  generate_page_table (get_virtual_current_address (ch),
290                       max_addr >> PAGE_SHIFT, nr_pages,
291                       xen_inf.virt_base, new_mfn_list);
292
293  max_addr += page2offset (nr_pt_pages);
294  state.stack = max_addr + STACK_SIZE + xen_inf.virt_base;
295  state.entry_point = xen_inf.entry_point;
296
297  next_start.nr_p2m_frames += nr_pt_pages;
298  next_start.nr_pt_frames = nr_pt_pages;
299  state.paging_size = nr_pt_pages;
300
301  *nst = next_start;
302
303  grub_memset (&gnttab_setver, 0, sizeof (gnttab_setver));
304
305  gnttab_setver.version = 1;
306  grub_xen_grant_table_op (GNTTABOP_set_version, &gnttab_setver, 1);
307
308  for (i = 0; i < ARRAY_SIZE (grub_xen_shared_info->evtchn_pending); i++)
309    grub_xen_shared_info->evtchn_pending[i] = 0;
310
311  return grub_relocator_xen_boot (relocator, state, nr_pages,
312                                  xen_inf.virt_base <
313                                  PAGE_SIZE ? page2offset (nr_pages) : 0,
314                                  nr_pages - 1,
315                                  page2offset (nr_pages - 1) +
316                                  xen_inf.virt_base);
317}
318
319static grub_err_t
320grub_xen_unload (void)
321{
322  grub_dl_unref (my_mod);
323  loaded = 0;
324  return GRUB_ERR_NONE;
325}
326
327#define HYPERCALL_INTERFACE_SIZE 32
328
329#ifdef __x86_64__
330static grub_uint8_t template[] =
331  {
332    0x51, /* push %rcx */
333    0x41, 0x53, /* push %r11 */
334    0x48, 0xc7, 0xc0, 0xbb, 0xaa, 0x00, 0x00,   /* mov    $0xaabb,%rax */
335    0x0f, 0x05,  /* syscall  */
336    0x41, 0x5b, /* pop %r11 */
337    0x59, /* pop %rcx  */
338    0xc3 /* ret */
339  };
340
341static grub_uint8_t template_iret[] =
342  {
343    0x51, /* push   %rcx */
344    0x41, 0x53, /* push   %r11 */
345    0x50, /* push   %rax */
346    0x48, 0xc7, 0xc0, 0x17, 0x00, 0x00, 0x00, /* mov    $0x17,%rax */
347    0x0f, 0x05 /* syscall */
348  };
349#define CALLNO_OFFSET 6
350#else
351
352static grub_uint8_t template[] =
353  {
354    0xb8, 0xbb, 0xaa, 0x00, 0x00, /* mov imm32, %eax */
355    0xcd, 0x82,  /* int $0x82  */
356    0xc3 /* ret */
357  };
358
359static grub_uint8_t template_iret[] =
360  {
361    0x50, /* push   %eax */
362    0xb8, 0x17, 0x00, 0x00, 0x00, /* mov    $0x17,%eax */
363    0xcd, 0x82,  /* int $0x82  */
364  };
365#define CALLNO_OFFSET 1
366
367#endif
368
369
370static void
371set_hypercall_interface (grub_uint8_t *tgt, unsigned callno)
372{
373  if (callno == 0x17)
374    {
375      grub_memcpy (tgt, template_iret, ARRAY_SIZE (template_iret));
376      grub_memset (tgt + ARRAY_SIZE (template_iret), 0xcc,
377                   HYPERCALL_INTERFACE_SIZE - ARRAY_SIZE (template_iret));
378      return;
379    }
380  grub_memcpy (tgt, template, ARRAY_SIZE (template));
381  grub_memset (tgt + ARRAY_SIZE (template), 0xcc,
382               HYPERCALL_INTERFACE_SIZE - ARRAY_SIZE (template));
383  tgt[CALLNO_OFFSET] = callno & 0xff;
384  tgt[CALLNO_OFFSET + 1] = callno >> 8;
385}
386
387#ifdef __x86_64__
388#define grub_elfXX_load grub_elf64_load
389#else
390#define grub_elfXX_load grub_elf32_load
391#endif
392
393static grub_err_t
394grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)),
395              int argc, char *argv[])
396{
397  grub_file_t file;
398  grub_elf_t elf;
399  grub_err_t err;
400
401  if (argc == 0)
402    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
403
404  grub_loader_unset ();
405
406  grub_memset (&next_start, 0, sizeof (next_start));
407
408  xen_module_info_page = NULL;
409  n_modules = 0;
410
411  grub_create_loader_cmdline (argc - 1, argv + 1,
412                              (char *) next_start.cmd_line,
413                              sizeof (next_start.cmd_line) - 1);
414
415  file = grub_file_open (argv[0]);
416  if (!file)
417    return grub_errno;
418
419  elf = grub_xen_file (file);
420  if (!elf)
421    goto fail;
422
423  err = grub_xen_get_info (elf, &xen_inf);
424  if (err)
425    goto fail;
426#ifdef __x86_64__
427  if (xen_inf.arch != GRUB_XEN_FILE_X86_64)
428#else
429  if (xen_inf.arch != GRUB_XEN_FILE_I386_PAE
430      && xen_inf.arch != GRUB_XEN_FILE_I386_PAE_BIMODE)
431#endif
432    {
433      grub_error (GRUB_ERR_BAD_OS, "incompatible architecture: %d",
434                  xen_inf.arch);
435      goto fail;
436    }
437
438  if (xen_inf.virt_base & (PAGE_SIZE - 1))
439    {
440      grub_error (GRUB_ERR_BAD_OS, "unaligned virt_base");
441      goto fail;
442    }
443  grub_dprintf ("xen", "virt_base = %llx, entry = %llx\n",
444                (unsigned long long) xen_inf.virt_base,
445                (unsigned long long) xen_inf.entry_point);
446
447  relocator = grub_relocator_new ();
448  if (!relocator)
449    goto fail;
450
451  grub_relocator_chunk_t ch;
452  grub_addr_t kern_start = xen_inf.kern_start - xen_inf.paddr_offset;
453  grub_addr_t kern_end = xen_inf.kern_end - xen_inf.paddr_offset;
454
455  if (xen_inf.has_hypercall_page)
456    {
457      grub_dprintf ("xen", "hypercall page at 0x%llx\n",
458                    (unsigned long long) xen_inf.hypercall_page);
459      if (xen_inf.hypercall_page - xen_inf.virt_base < kern_start)
460        kern_start = xen_inf.hypercall_page - xen_inf.virt_base;
461
462      if (xen_inf.hypercall_page - xen_inf.virt_base + PAGE_SIZE > kern_end)
463        kern_end = xen_inf.hypercall_page - xen_inf.virt_base + PAGE_SIZE;
464    }
465
466  max_addr = ALIGN_UP (kern_end, PAGE_SIZE);
467
468  err = grub_relocator_alloc_chunk_addr (relocator, &ch, kern_start,
469                                         kern_end - kern_start);
470  if (err)
471    goto fail;
472  kern_chunk_src = get_virtual_current_address (ch);
473
474  grub_dprintf ("xen", "paddr_offset = 0x%llx\n",
475                (unsigned long long) xen_inf.paddr_offset);
476  grub_dprintf ("xen", "kern_start = 0x%llx, kern_end = 0x%llx\n",
477                (unsigned long long) xen_inf.kern_start,
478                (unsigned long long) xen_inf.kern_end);
479
480  err = grub_elfXX_load (elf, argv[0],
481                         (grub_uint8_t *) kern_chunk_src - kern_start
482                         - xen_inf.paddr_offset, 0, 0, 0);
483
484  if (xen_inf.has_hypercall_page)
485    {
486      unsigned i;
487      for (i = 0; i < PAGE_SIZE / HYPERCALL_INTERFACE_SIZE; i++)
488        set_hypercall_interface ((grub_uint8_t *) kern_chunk_src +
489                                 i * HYPERCALL_INTERFACE_SIZE +
490                                 xen_inf.hypercall_page - xen_inf.virt_base -
491                                 kern_start, i);
492    }
493
494  if (err)
495    goto fail;
496
497  grub_dl_ref (my_mod);
498  loaded = 1;
499
500  grub_loader_set (grub_xen_boot, grub_xen_unload, 0);
501  loaded = 1;
502
503  goto fail;
504
505fail:
506
507  if (elf)
508    grub_elf_close (elf);
509  else if (file)
510    grub_file_close (file);
511
512  if (grub_errno != GRUB_ERR_NONE)
513    loaded = 0;
514
515  return grub_errno;
516}
517
518static grub_err_t
519grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
520                 int argc, char *argv[])
521{
522  grub_size_t size = 0;
523  grub_err_t err;
524  struct grub_linux_initrd_context initrd_ctx;
525  grub_relocator_chunk_t ch;
526
527  if (argc == 0)
528    {
529      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
530      goto fail;
531    }
532
533  if (!loaded)
534    {
535      grub_error (GRUB_ERR_BAD_ARGUMENT,
536                  N_("you need to load the kernel first"));
537      goto fail;
538    }
539
540  if (next_start.mod_start || next_start.mod_len)
541    {
542      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("initrd already loaded"));
543      goto fail;
544    }
545
546  if (grub_initrd_init (argc, argv, &initrd_ctx))
547    goto fail;
548
549  size = grub_get_initrd_size (&initrd_ctx);
550
551  if (size)
552    {
553      err = grub_relocator_alloc_chunk_addr (relocator, &ch, max_addr, size);
554      if (err)
555        return err;
556
557      if (grub_initrd_load (&initrd_ctx, argv,
558                            get_virtual_current_address (ch)))
559        goto fail;
560    }
561
562  next_start.mod_start = max_addr + xen_inf.virt_base;
563  next_start.mod_len = size;
564
565  max_addr = ALIGN_UP (max_addr + size, PAGE_SIZE);
566
567  grub_dprintf ("xen", "Initrd, addr=0x%x, size=0x%x\n",
568                (unsigned) next_start.mod_start, (unsigned) size);
569
570fail:
571  grub_initrd_close (&initrd_ctx);
572
573  return grub_errno;
574}
575
576static grub_err_t
577grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
578                 int argc, char *argv[])
579{
580  grub_size_t size = 0;
581  grub_err_t err;
582  grub_relocator_chunk_t ch;
583  grub_size_t cmdline_len;
584  int nounzip = 0;
585  grub_file_t file;
586
587  if (argc == 0)
588    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
589
590  if (grub_strcmp (argv[0], "--nounzip") == 0)
591    {
592      argv++;
593      argc--;
594      nounzip = 1;
595    }
596
597  if (argc == 0)
598    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
599
600  if (!loaded)
601    {
602      return grub_error (GRUB_ERR_BAD_ARGUMENT,
603                         N_("you need to load the kernel first"));
604    }
605
606  if ((next_start.mod_start || next_start.mod_len) && !xen_module_info_page)
607    {
608      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("initrd already loaded"));
609    }
610
611  /* Leave one space for terminator.  */
612  if (n_modules >= MAX_MODULES - 1)
613    {
614      return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many modules");
615    }
616
617  if (!xen_module_info_page)
618    {
619      n_modules = 0;
620      max_addr = ALIGN_UP (max_addr, PAGE_SIZE);
621      modules_target_start = max_addr;
622      next_start.mod_start = max_addr + xen_inf.virt_base;
623      next_start.flags |= SIF_MULTIBOOT_MOD;
624
625      err = grub_relocator_alloc_chunk_addr (relocator, &ch,
626                                             max_addr, MAX_MODULES
627                                             *
628                                             sizeof (xen_module_info_page
629                                                     [0]));
630      if (err)
631        return err;
632      xen_module_info_page = get_virtual_current_address (ch);
633      grub_memset (xen_module_info_page, 0, MAX_MODULES
634                   * sizeof (xen_module_info_page[0]));
635      max_addr += MAX_MODULES * sizeof (xen_module_info_page[0]);
636    }
637
638  max_addr = ALIGN_UP (max_addr, PAGE_SIZE);
639
640  if (nounzip)
641    grub_file_filter_disable_compression ();
642  file = grub_file_open (argv[0]);
643  if (!file)
644    return grub_errno;
645  size = grub_file_size (file);
646
647  cmdline_len = grub_loader_cmdline_size (argc - 1, argv + 1);
648
649  err = grub_relocator_alloc_chunk_addr (relocator, &ch,
650                                         max_addr, cmdline_len);
651  if (err)
652    goto fail;
653
654  grub_create_loader_cmdline (argc - 1, argv + 1,
655                              get_virtual_current_address (ch), cmdline_len);
656
657  xen_module_info_page[n_modules].cmdline = max_addr - modules_target_start;
658  max_addr = ALIGN_UP (max_addr + cmdline_len, PAGE_SIZE);
659
660  if (size)
661    {
662      err = grub_relocator_alloc_chunk_addr (relocator, &ch, max_addr, size);
663      if (err)
664        goto fail;
665      if (grub_file_read (file, get_virtual_current_address (ch), size)
666          != (grub_ssize_t) size)
667        {
668          if (!grub_errno)
669            grub_error (GRUB_ERR_FILE_READ_ERROR,
670                        N_("premature end of file %s"), argv[0]);
671          goto fail;
672        }
673    }
674  next_start.mod_len = max_addr + size - modules_target_start;
675  xen_module_info_page[n_modules].mod_start = max_addr - modules_target_start;
676  xen_module_info_page[n_modules].mod_end =
677    max_addr + size - modules_target_start;
678
679  n_modules++;
680  grub_dprintf ("xen", "module, addr=0x%x, size=0x%x\n",
681                (unsigned) max_addr, (unsigned) size);
682  max_addr = ALIGN_UP (max_addr + size, PAGE_SIZE);
683
684
685fail:
686  grub_file_close (file);
687
688  return grub_errno;
689}
690
691static grub_command_t cmd_xen, cmd_initrd, cmd_module, cmd_multiboot;
692
693GRUB_MOD_INIT (xen)
694{
695  cmd_xen = grub_register_command ("linux", grub_cmd_xen,
696                                   0, N_("Load Linux."));
697  cmd_multiboot = grub_register_command ("multiboot", grub_cmd_xen,
698                                         0, N_("Load Linux."));
699  cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd,
700                                      0, N_("Load initrd."));
701  cmd_module = grub_register_command ("module", grub_cmd_module,
702                                      0, N_("Load module."));
703  my_mod = mod;
704}
705
706GRUB_MOD_FINI (xen)
707{
708  grub_unregister_command (cmd_xen);
709  grub_unregister_command (cmd_initrd);
710  grub_unregister_command (cmd_multiboot);
711  grub_unregister_command (cmd_module);
712}
Note: See TracBrowser for help on using the repository browser.