~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to xen/arch/x86/boot/reloc.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************************************
 
2
 * reloc.c
 
3
 * 
 
4
 * 32-bit flat memory-map routines for relocating Multiboot structures
 
5
 * and modules. This is most easily done early with paging disabled.
 
6
 * 
 
7
 * Copyright (c) 2009, Citrix Systems, Inc.
 
8
 * 
 
9
 * Authors:
 
10
 *    Keir Fraser <keir.fraser@citrix.com>
 
11
 */
 
12
 
 
13
asm (
 
14
    "    .text                         \n"
 
15
    "    .globl _start                 \n"
 
16
    "_start:                           \n"
 
17
    "    mov  $_start,%edi             \n"
 
18
    "    call 1f                       \n"
 
19
    "1:  pop  %esi                     \n"
 
20
    "    sub  $1b-_start,%esi          \n"
 
21
    "    mov  $__bss_start-_start,%ecx \n"
 
22
    "    rep  movsb                    \n"
 
23
    "    xor  %eax,%eax                \n"
 
24
    "    mov  $_end,%ecx               \n"
 
25
    "    sub  %edi,%ecx                \n"
 
26
    "    rep  stosb                    \n"
 
27
    "    mov  $reloc,%eax              \n"
 
28
    "    jmp  *%eax                    \n"
 
29
    );
 
30
 
 
31
typedef unsigned int u32;
 
32
#include "../../../include/xen/multiboot.h"
 
33
 
 
34
extern char _start[];
 
35
 
 
36
static void *memcpy(void *dest, const void *src, unsigned int n)
 
37
{
 
38
    char *s = (char *)src, *d = dest;
 
39
    while ( n-- )
 
40
        *d++ = *s++;
 
41
    return dest;
 
42
}
 
43
 
 
44
static void *reloc_mbi_struct(void *old, unsigned int bytes)
 
45
{
 
46
    static void *alloc = &_start;
 
47
    alloc = (void *)(((unsigned long)alloc - bytes) & ~15ul);
 
48
    return memcpy(alloc, old, bytes);
 
49
}
 
50
 
 
51
static char *reloc_mbi_string(char *old)
 
52
{
 
53
    char *p;
 
54
    for ( p = old; *p != '\0'; p++ )
 
55
        continue;
 
56
    return reloc_mbi_struct(old, p - old + 1);
 
57
}
 
58
 
 
59
multiboot_info_t *reloc(multiboot_info_t *mbi_old)
 
60
{
 
61
    multiboot_info_t *mbi = reloc_mbi_struct(mbi_old, sizeof(*mbi));
 
62
    int i;
 
63
 
 
64
    if ( mbi->flags & MBI_CMDLINE )
 
65
        mbi->cmdline = (u32)reloc_mbi_string((char *)mbi->cmdline);
 
66
 
 
67
    if ( mbi->flags & MBI_MODULES )
 
68
    {
 
69
        module_t *mods = reloc_mbi_struct(
 
70
            (module_t *)mbi->mods_addr, mbi->mods_count * sizeof(module_t));
 
71
        u32 max_addr = 0;
 
72
 
 
73
        mbi->mods_addr = (u32)mods;
 
74
 
 
75
        for ( i = 0; i < mbi->mods_count; i++ )
 
76
        {
 
77
            if ( mods[i].string )
 
78
                mods[i].string = (u32)reloc_mbi_string((char *)mods[i].string);
 
79
            if ( mods[i].mod_end > max_addr )
 
80
                max_addr = mods[i].mod_end;
 
81
        }
 
82
 
 
83
        /*
 
84
         * 32-bit Xen only maps bottom 1GB of memory at boot time. Relocate 
 
85
         * modules which extend beyond this (GRUB2 in particular likes to 
 
86
         * place modules as high as possible below 4GB).
 
87
         */
 
88
#define BOOTMAP_END (1ul<<30) /* 1GB */
 
89
        if ( (XEN_BITSPERLONG == 32) && (max_addr > BOOTMAP_END) )
 
90
        {
 
91
            char *mod_alloc = (char *)BOOTMAP_END;
 
92
            for ( i = 0; i < mbi->mods_count; i++ )
 
93
                mod_alloc -= mods[i].mod_end - mods[i].mod_start;
 
94
            for ( i = 0; i < mbi->mods_count; i++ )
 
95
            {
 
96
                u32 mod_len = mods[i].mod_end - mods[i].mod_start;
 
97
                mods[i].mod_start = (u32)memcpy(
 
98
                    mod_alloc, (char *)mods[i].mod_start, mod_len);
 
99
                mods[i].mod_end = mods[i].mod_start + mod_len;
 
100
                mod_alloc += mod_len;
 
101
            }
 
102
        }
 
103
    }
 
104
 
 
105
    if ( mbi->flags & MBI_MEMMAP )
 
106
        mbi->mmap_addr = (u32)reloc_mbi_struct(
 
107
            (memory_map_t *)mbi->mmap_addr, mbi->mmap_length);
 
108
 
 
109
    /* Mask features we don't understand or don't relocate. */
 
110
    mbi->flags &= (MBI_MEMLIMITS |
 
111
                   MBI_DRIVES |
 
112
                   MBI_CMDLINE |
 
113
                   MBI_MODULES |
 
114
                   MBI_MEMMAP);
 
115
 
 
116
    return mbi;
 
117
}