~ubuntu-branches/ubuntu/trusty/grub2/trusty

« back to all changes in this revision

Viewing changes to grub-core/loader/sparc64/ieee1275/linux.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2014-01-16 15:18:04 UTC
  • mfrom: (17.6.38 experimental)
  • Revision ID: package-import@ubuntu.com-20140116151804-3foouk7fpqcq3sxx
Tags: 2.02~beta2-2
* Convert patch handling to git-dpm.
* Add bi-endian support to ELF parser (Tomohiro B Berry).
* Adjust restore_mkdevicemap.patch to mark get_kfreebsd_version as static,
  to appease "gcc -Werror=missing-prototypes".
* Cherry-pick from upstream:
  - Change grub-macbless' manual page section to 8.
* Install grub-glue-efi, grub-macbless, grub-render-label, and
  grub-syslinux2cfg.
* grub-shell: Pass -no-pad to xorriso when building floppy images.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
#include <grub/i18n.h>
29
29
#include <grub/memory.h>
30
30
#include <grub/lib/cmdline.h>
 
31
#include <grub/linux.h>
31
32
 
32
33
GRUB_MOD_LICENSE ("GPLv3+");
33
34
 
180
181
 
181
182
#define FOUR_MB (4 * 1024 * 1024)
182
183
 
 
184
/* Context for alloc_phys.  */
 
185
struct alloc_phys_ctx
 
186
{
 
187
  grub_addr_t size;
 
188
  grub_addr_t ret;
 
189
};
 
190
 
 
191
/* Helper for alloc_phys.  */
 
192
static int
 
193
alloc_phys_choose (grub_uint64_t addr, grub_uint64_t len,
 
194
                   grub_memory_type_t type, void *data)
 
195
{
 
196
  struct alloc_phys_ctx *ctx = data;
 
197
  grub_addr_t end = addr + len;
 
198
 
 
199
  if (type != 1)
 
200
    return 0;
 
201
 
 
202
  addr = ALIGN_UP (addr, FOUR_MB);
 
203
  if (addr + ctx->size >= end)
 
204
    return 0;
 
205
 
 
206
  if (addr >= grub_phys_start && addr < grub_phys_end)
 
207
    {
 
208
      addr = ALIGN_UP (grub_phys_end, FOUR_MB);
 
209
      if (addr + ctx->size >= end)
 
210
        return 0;
 
211
    }
 
212
  if ((addr + ctx->size) >= grub_phys_start
 
213
      && (addr + ctx->size) < grub_phys_end)
 
214
    {
 
215
      addr = ALIGN_UP (grub_phys_end, FOUR_MB);
 
216
      if (addr + ctx->size >= end)
 
217
        return 0;
 
218
    }
 
219
 
 
220
  if (loaded)
 
221
    {
 
222
      grub_addr_t linux_end = ALIGN_UP (linux_paddr + linux_size, FOUR_MB);
 
223
 
 
224
      if (addr >= linux_paddr && addr < linux_end)
 
225
        {
 
226
          addr = linux_end;
 
227
          if (addr + ctx->size >= end)
 
228
            return 0;
 
229
        }
 
230
      if ((addr + ctx->size) >= linux_paddr
 
231
          && (addr + ctx->size) < linux_end)
 
232
        {
 
233
          addr = linux_end;
 
234
          if (addr + ctx->size >= end)
 
235
            return 0;
 
236
        }
 
237
    }
 
238
 
 
239
  ctx->ret = addr;
 
240
  return 1;
 
241
}
 
242
 
183
243
static grub_addr_t
184
244
alloc_phys (grub_addr_t size)
185
245
{
186
 
  grub_addr_t ret = (grub_addr_t) -1;
187
 
 
188
 
  auto int NESTED_FUNC_ATTR choose (grub_uint64_t addr, grub_uint64_t len,
189
 
                                    grub_memory_type_t type);
190
 
  int NESTED_FUNC_ATTR choose (grub_uint64_t addr, grub_uint64_t len,
191
 
                               grub_memory_type_t type)
192
 
  {
193
 
    grub_addr_t end = addr + len;
194
 
 
195
 
    if (type != 1)
196
 
      return 0;
197
 
 
198
 
    addr = ALIGN_UP (addr, FOUR_MB);
199
 
    if (addr + size >= end)
200
 
      return 0;
201
 
 
202
 
    if (addr >= grub_phys_start && addr < grub_phys_end)
203
 
      {
204
 
        addr = ALIGN_UP (grub_phys_end, FOUR_MB);
205
 
        if (addr + size >= end)
206
 
          return 0;
207
 
      }
208
 
    if ((addr + size) >= grub_phys_start
209
 
        && (addr + size) < grub_phys_end)
210
 
      {
211
 
        addr = ALIGN_UP (grub_phys_end, FOUR_MB);
212
 
        if (addr + size >= end)
213
 
          return 0;
214
 
      }
215
 
 
216
 
    if (loaded)
217
 
      {
218
 
        grub_addr_t linux_end = ALIGN_UP (linux_paddr + linux_size, FOUR_MB);
219
 
 
220
 
        if (addr >= linux_paddr && addr < linux_end)
221
 
          {
222
 
            addr = linux_end;
223
 
            if (addr + size >= end)
224
 
              return 0;
225
 
          }
226
 
        if ((addr + size) >= linux_paddr
227
 
            && (addr + size) < linux_end)
228
 
          {
229
 
            addr = linux_end;
230
 
            if (addr + size >= end)
231
 
              return 0;
232
 
          }
233
 
      }
234
 
 
235
 
    ret = addr;
236
 
    return 1;
237
 
  }
238
 
 
239
 
  grub_machine_mmap_iterate (choose);
240
 
 
241
 
  return ret;
 
246
  struct alloc_phys_ctx ctx = {
 
247
    .size = size,
 
248
    .ret = (grub_addr_t) -1
 
249
  };
 
250
 
 
251
  grub_machine_mmap_iterate (alloc_phys_choose, &ctx);
 
252
 
 
253
  return ctx.ret;
242
254
}
243
255
 
244
256
static grub_err_t
250
262
  linux_entry = elf->ehdr.ehdr64.e_entry;
251
263
  linux_addr = 0x40004000;
252
264
  off = 0x4000;
253
 
  linux_size = grub_elf64_size (elf, filename, 0, 0);
 
265
  linux_size = grub_elf64_size (elf, 0, 0);
254
266
  if (linux_size == 0)
255
267
    return grub_errno;
256
268
 
275
287
  base = linux_entry - off;
276
288
 
277
289
  /* Now load the segments into the area we claimed.  */
278
 
  auto grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr, int *do_load);
279
 
  grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr, int *do_load)
280
 
    {
281
 
      if (phdr->p_type != PT_LOAD)
282
 
        {
283
 
          *do_load = 0;
284
 
          return 0;
285
 
        }
286
 
      *do_load = 1;
287
 
 
288
 
      /* Adjust the program load address to linux_addr.  */
289
 
      *addr = (phdr->p_paddr - base) + (linux_addr - off);
290
 
      return 0;
291
 
    }
292
 
  return grub_elf64_load (elf, filename, offset_phdr, 0, 0);
 
290
  return grub_elf64_load (elf, filename, (void *) (linux_addr - off - base), GRUB_ELF_LOAD_FLAGS_NONE, 0, 0);
293
291
}
294
292
 
295
293
static grub_err_t
371
369
grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
372
370
                 int argc, char *argv[])
373
371
{
374
 
  grub_file_t *files = 0;
375
372
  grub_size_t size = 0;
376
373
  grub_addr_t paddr;
377
374
  grub_addr_t addr;
378
375
  int ret;
379
 
  int i;
380
 
  int nfiles = 0;
381
 
  grub_uint8_t *ptr;
 
376
  struct grub_linux_initrd_context initrd_ctx;
382
377
 
383
378
  if (argc == 0)
384
379
    {
392
387
      goto fail;
393
388
    }
394
389
 
395
 
  files = grub_zalloc (argc * sizeof (files[0]));
396
 
  if (!files)
 
390
  if (grub_initrd_init (argc, argv, &initrd_ctx))
397
391
    goto fail;
398
392
 
399
 
  for (i = 0; i < argc; i++)
400
 
    {
401
 
      grub_file_filter_disable_compression ();
402
 
      files[i] = grub_file_open (argv[i]);
403
 
      if (! files[i])
404
 
        goto fail;
405
 
      nfiles++;
406
 
      size += ALIGN_UP(grub_file_size (files[i]), 4);
407
 
    }
 
393
  size = grub_get_initrd_size (&initrd_ctx);
408
394
 
409
395
  addr = 0x60000000;
410
396
 
426
412
  grub_dprintf ("loader", "Loading initrd at vaddr 0x%lx, paddr 0x%lx, size 0x%lx\n",
427
413
                addr, paddr, size);
428
414
 
429
 
  ptr = (void *) addr;
430
 
  for (i = 0; i < nfiles; i++)
431
 
    {
432
 
      grub_ssize_t cursize = grub_file_size (files[i]);
433
 
      if (grub_file_read (files[i], ptr, cursize) != cursize)
434
 
        {
435
 
          if (!grub_errno)
436
 
            grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
437
 
                        argv[i]);
438
 
          goto fail;
439
 
        }
440
 
      ptr += cursize;
441
 
      grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4));
442
 
      ptr += ALIGN_UP_OVERHEAD (cursize, 4);
443
 
    }
 
415
  if (grub_initrd_load (&initrd_ctx, argv, (void *) addr))
 
416
    goto fail;
444
417
 
445
418
  initrd_addr = addr;
446
419
  initrd_paddr = paddr;
447
420
  initrd_size = size;
448
421
 
449
422
 fail:
450
 
  for (i = 0; i < nfiles; i++)
451
 
    grub_file_close (files[i]);
452
 
  grub_free (files);
 
423
  grub_initrd_close (&initrd_ctx);
453
424
 
454
425
  return grub_errno;
455
426
}
456
427
 
 
428
/* Helper for determine_phys_base.  */
 
429
static int
 
430
get_physbase (grub_uint64_t addr, grub_uint64_t len __attribute__ ((unused)),
 
431
              grub_memory_type_t type, void *data __attribute__ ((unused)))
 
432
{
 
433
  if (type != 1)
 
434
    return 0;
 
435
  if (addr < phys_base)
 
436
    phys_base = addr;
 
437
  return 0;
 
438
}
 
439
 
457
440
static void
458
441
determine_phys_base (void)
459
442
{
460
 
  auto int NESTED_FUNC_ATTR get_physbase (grub_uint64_t addr, grub_uint64_t len __attribute__((unused)), grub_uint32_t type);
461
 
  int NESTED_FUNC_ATTR get_physbase (grub_uint64_t addr, grub_uint64_t len __attribute__((unused)), grub_uint32_t type)
462
 
  {
463
 
    if (type != 1)
464
 
      return 0;
465
 
    if (addr < phys_base)
466
 
      phys_base = addr;
467
 
    return 0;
468
 
  }
469
 
 
470
443
  phys_base = ~(grub_uint64_t) 0;
471
 
  grub_machine_mmap_iterate (get_physbase);
 
444
  grub_machine_mmap_iterate (get_physbase, NULL);
472
445
}
473
446
 
474
447
static void