~ubuntu-branches/debian/sid/grub2/sid-200907171838

« back to all changes in this revision

Viewing changes to kern/ieee1275/init.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Millan
  • Date: 2009-07-02 13:23:51 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090702132351-tanpn0ryyijp93gu
Tags: 1.96+20090702-1
* New SVN snapshot.
* rules: Remove duplicated files in sparc64-ieee1275 port.
* rules: Comment out -DGRUB_ASSUME_LINUX_HAS_FB_SUPPORT=1 setting.  We'll
  re-evaluate using it when it's more mature.  (Closes: #535026).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  init.c -- Initialize GRUB on the newworld mac (PPC).  */
 
2
/*
 
3
 *  GRUB  --  GRand Unified Bootloader
 
4
 *  Copyright (C) 2003,2004,2005,2007,2008 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/kernel.h>
 
21
#include <grub/dl.h>
 
22
#include <grub/disk.h>
 
23
#include <grub/mm.h>
 
24
#include <grub/partition.h>
 
25
#include <grub/normal.h>
 
26
#include <grub/fs.h>
 
27
#include <grub/setjmp.h>
 
28
#include <grub/env.h>
 
29
#include <grub/misc.h>
 
30
#include <grub/time.h>
 
31
#include <grub/machine/console.h>
 
32
#include <grub/machine/kernel.h>
 
33
#include <grub/cpu/kernel.h>
 
34
#include <grub/ieee1275/ofdisk.h>
 
35
#include <grub/ieee1275/ieee1275.h>
 
36
 
 
37
/* The minimal heap size we can live with. */
 
38
#define HEAP_MIN_SIZE           (unsigned long) (2 * 1024 * 1024)
 
39
 
 
40
/* The maximum heap size we're going to claim */
 
41
#define HEAP_MAX_SIZE           (unsigned long) (4 * 1024 * 1024)
 
42
 
 
43
/* If possible, we will avoid claiming heap above this address, because it
 
44
   seems to cause relocation problems with OSes that link at 4 MiB */
 
45
#define HEAP_MAX_ADDR           (unsigned long) (4 * 1024 * 1024)
 
46
 
 
47
extern char _start[];
 
48
extern char _end[];
 
49
 
 
50
void
 
51
grub_exit (void)
 
52
{
 
53
  grub_ieee1275_exit ();
 
54
}
 
55
 
 
56
/* Translate an OF filesystem path (separated by backslashes), into a GRUB
 
57
   path (separated by forward slashes).  */
 
58
static void
 
59
grub_translate_ieee1275_path (char *filepath)
 
60
{
 
61
  char *backslash;
 
62
 
 
63
  backslash = grub_strchr (filepath, '\\');
 
64
  while (backslash != 0)
 
65
    {
 
66
      *backslash = '/';
 
67
      backslash = grub_strchr (filepath, '\\');
 
68
    }
 
69
}
 
70
 
 
71
void
 
72
grub_machine_set_prefix (void)
 
73
{
 
74
  char bootpath[64]; /* XXX check length */
 
75
  char *filename;
 
76
  char *prefix;
 
77
 
 
78
  if (grub_env_get ("prefix"))
 
79
    /* We already set prefix in grub_machine_init().  */
 
80
    return;
 
81
 
 
82
  if (grub_prefix[0])
 
83
    {
 
84
      grub_env_set ("prefix", grub_prefix);
 
85
      /* Prefix is hardcoded in the core image.  */
 
86
      return;
 
87
    }
 
88
 
 
89
  if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath,
 
90
                                  sizeof (bootpath), 0))
 
91
    {
 
92
      /* Should never happen.  */
 
93
      grub_printf ("/chosen/bootpath property missing!\n");
 
94
      grub_env_set ("prefix", "");
 
95
      return;
 
96
    }
 
97
 
 
98
  /* Transform an OF device path to a GRUB path.  */
 
99
 
 
100
  prefix = grub_ieee1275_encode_devname (bootpath);
 
101
 
 
102
  filename = grub_ieee1275_get_filename (bootpath);
 
103
  if (filename)
 
104
    {
 
105
      char *newprefix;
 
106
      char *lastslash = grub_strrchr (filename, '\\');
 
107
 
 
108
      /* Truncate at last directory.  */
 
109
      if (lastslash)
 
110
        {
 
111
          *lastslash = '\0';
 
112
          grub_translate_ieee1275_path (filename);
 
113
 
 
114
          newprefix = grub_malloc (grub_strlen (prefix)
 
115
                                   + grub_strlen (filename));
 
116
          grub_sprintf (newprefix, "%s%s", prefix, filename);
 
117
          grub_free (prefix);
 
118
          prefix = newprefix;
 
119
        }
 
120
    }
 
121
 
 
122
  grub_env_set ("prefix", prefix);
 
123
 
 
124
  grub_free (filename);
 
125
  grub_free (prefix);
 
126
}
 
127
 
 
128
/* Claim some available memory in the first /memory node. */
 
129
static void grub_claim_heap (void)
 
130
{
 
131
  unsigned long total = 0;
 
132
 
 
133
  auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type);
 
134
  int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type)
 
135
  {
 
136
    if (type != 1)
 
137
      return 0;
 
138
 
 
139
    len -= 1; /* Required for some firmware.  */
 
140
 
 
141
    /* Never exceed HEAP_MAX_SIZE  */
 
142
    if (total + len > HEAP_MAX_SIZE)
 
143
      len = HEAP_MAX_SIZE - total;
 
144
 
 
145
    /* Avoid claiming anything above HEAP_MAX_ADDR, if possible. */
 
146
    if ((addr < HEAP_MAX_ADDR) &&                               /* if it's too late, don't bother */
 
147
        (addr + len > HEAP_MAX_ADDR) &&                         /* if it wasn't available anyway, don't bother */
 
148
        (total + (HEAP_MAX_ADDR - addr) > HEAP_MIN_SIZE))       /* only limit ourselves when we can afford to */
 
149
       len = HEAP_MAX_ADDR - addr;
 
150
 
 
151
    /* In theory, firmware should already prevent this from happening by not
 
152
       listing our own image in /memory/available.  The check below is intended
 
153
       as a safeguard in case that doesn't happen.  However, it doesn't protect
 
154
       us from corrupting our module area, which extends up to a
 
155
       yet-undetermined region above _end.  */
 
156
    if ((addr < (grub_addr_t) _end) && ((addr + len) > (grub_addr_t) _start))
 
157
      {
 
158
        grub_printf ("Warning: attempt to claim over our own code!\n");
 
159
        len = 0;
 
160
      }
 
161
 
 
162
    if (len)
 
163
      {
 
164
        /* Claim and use it.  */
 
165
        if (grub_claimmap (addr, len) < 0)
 
166
          return grub_error (GRUB_ERR_OUT_OF_MEMORY,
 
167
                             "Failed to claim heap at 0x%llx, len 0x%llx\n",
 
168
                             addr, len);
 
169
        grub_mm_init_region ((void *) (grub_addr_t) addr, len);
 
170
      }
 
171
 
 
172
    total += len;
 
173
    if (total >= HEAP_MAX_SIZE)
 
174
      return 1;
 
175
 
 
176
    return 0;
 
177
  }
 
178
 
 
179
  if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET))
 
180
    heap_init (HEAP_MAX_ADDR - HEAP_MIN_SIZE, HEAP_MIN_SIZE, 1);
 
181
  else
 
182
    grub_machine_mmap_iterate (heap_init);
 
183
}
 
184
 
 
185
#ifdef __i386__
 
186
 
 
187
grub_uint32_t grub_upper_mem;
 
188
 
 
189
/* We need to call this before grub_claim_memory.  */
 
190
static void
 
191
grub_get_extended_memory (void)
 
192
{
 
193
  auto int NESTED_FUNC_ATTR find_ext_mem (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type);
 
194
  int NESTED_FUNC_ATTR find_ext_mem (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type)
 
195
    {
 
196
      if (type == 1 && addr == 0x100000)
 
197
        {
 
198
          grub_upper_mem = len;
 
199
          return 1;
 
200
        }
 
201
 
 
202
      return 0;
 
203
    }
 
204
 
 
205
  grub_machine_mmap_iterate (find_ext_mem);
 
206
}
 
207
 
 
208
#endif
 
209
 
 
210
static grub_uint64_t ieee1275_get_time_ms (void);
 
211
 
 
212
void
 
213
grub_machine_init (void)
 
214
{
 
215
  char args[256];
 
216
  grub_ssize_t actual;
 
217
 
 
218
  grub_ieee1275_init ();
 
219
 
 
220
  grub_console_init ();
 
221
#ifdef __i386__
 
222
  grub_get_extended_memory ();
 
223
#endif
 
224
  grub_claim_heap ();
 
225
  grub_ofdisk_init ();
 
226
 
 
227
  /* Process commandline.  */
 
228
  if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args,
 
229
                                  sizeof args, &actual) == 0
 
230
      && actual > 1)
 
231
    {
 
232
      int i = 0;
 
233
 
 
234
      while (i < actual)
 
235
        {
 
236
          char *command = &args[i];
 
237
          char *end;
 
238
          char *val;
 
239
 
 
240
          end = grub_strchr (command, ';');
 
241
          if (end == 0)
 
242
            i = actual; /* No more commands after this one.  */
 
243
          else
 
244
            {
 
245
              *end = '\0';
 
246
              i += end - command + 1;
 
247
              while (grub_isspace(args[i]))
 
248
                i++;
 
249
            }
 
250
 
 
251
          /* Process command.  */
 
252
          val = grub_strchr (command, '=');
 
253
          if (val)
 
254
            {
 
255
              *val = '\0';
 
256
              grub_env_set (command, val + 1);
 
257
            }
 
258
        }
 
259
    }
 
260
 
 
261
  grub_install_get_time_ms (ieee1275_get_time_ms);
 
262
}
 
263
 
 
264
void
 
265
grub_machine_fini (void)
 
266
{
 
267
  grub_ofdisk_fini ();
 
268
  grub_console_fini ();
 
269
}
 
270
 
 
271
static grub_uint64_t
 
272
ieee1275_get_time_ms (void)
 
273
{
 
274
  grub_uint32_t msecs = 0;
 
275
 
 
276
  grub_ieee1275_milliseconds (&msecs);
 
277
 
 
278
  return msecs;
 
279
}
 
280
 
 
281
grub_uint32_t
 
282
grub_get_rtc (void)
 
283
{
 
284
  return ieee1275_get_time_ms ();
 
285
}
 
286
 
 
287
grub_addr_t
 
288
grub_arch_modules_addr (void)
 
289
{
 
290
  return ALIGN_UP((grub_addr_t) _end + GRUB_MOD_GAP, GRUB_MOD_ALIGN);
 
291
}