automake commit without merge history

This commit is contained in:
BVK Chaitanya 2010-05-06 11:34:04 +05:30
parent 265d68cd10
commit 8c41176882
810 changed files with 4980 additions and 2508 deletions

View file

@ -0,0 +1,165 @@
/* cmain.c - Startup code for the PowerPC. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/kernel.h>
#include <grub/misc.h>
#include <grub/types.h>
#include <grub/machine/kernel.h>
#include <grub/ieee1275/ieee1275.h>
int (*grub_ieee1275_entry_fn) (void *);
grub_ieee1275_phandle_t grub_ieee1275_chosen;
grub_ieee1275_ihandle_t grub_ieee1275_mmu;
static grub_uint32_t grub_ieee1275_flags;
int
grub_ieee1275_test_flag (enum grub_ieee1275_flag flag)
{
return (grub_ieee1275_flags & (1 << flag));
}
void
grub_ieee1275_set_flag (enum grub_ieee1275_flag flag)
{
grub_ieee1275_flags |= (1 << flag);
}
#define SF "SmartFirmware(tm)"
#define OHW "PPC Open Hack'Ware"
static void
grub_ieee1275_find_options (void)
{
grub_ieee1275_phandle_t root;
grub_ieee1275_phandle_t options;
grub_ieee1275_phandle_t openprom;
grub_ieee1275_phandle_t bootrom;
int rc;
grub_uint32_t realmode = 0;
char tmp[32];
int is_smartfirmware = 0;
int is_olpc = 0;
grub_ieee1275_finddevice ("/", &root);
grub_ieee1275_finddevice ("/options", &options);
grub_ieee1275_finddevice ("/openprom", &openprom);
rc = grub_ieee1275_get_integer_property (options, "real-mode?", &realmode,
sizeof realmode, 0);
if (((rc >= 0) && realmode) || (grub_ieee1275_mmu == 0))
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_REAL_MODE);
rc = grub_ieee1275_get_property (openprom, "CodeGen-copyright",
tmp, sizeof (tmp), 0);
if (rc >= 0 && !grub_strncmp (tmp, SF, sizeof (SF) - 1))
is_smartfirmware = 1;
rc = grub_ieee1275_get_property (root, "architecture",
tmp, sizeof (tmp), 0);
if (rc >= 0 && !grub_strcmp (tmp, "OLPC"))
is_olpc = 1;
if (is_smartfirmware)
{
/* Broken in all versions */
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_BROKEN_OUTPUT);
/* There are two incompatible ways of checking the version number. Try
both. */
rc = grub_ieee1275_get_property (openprom, "SmartFirmware-version",
tmp, sizeof (tmp), 0);
if (rc < 0)
rc = grub_ieee1275_get_property (openprom, "firmware-version",
tmp, sizeof (tmp), 0);
if (rc >= 0)
{
/* It is tempting to implement a version parser to set the flags for
e.g. 1.3 and below. However, there's a special situation here.
3rd party updates which fix the partition bugs are common, and for
some reason their fixes aren't being merged into trunk. So for
example we know that 1.2 and 1.3 are broken, but there's 1.2.99
and 1.3.99 which are known good (and applying this workaround
would cause breakage). */
if (!grub_strcmp (tmp, "1.0")
|| !grub_strcmp (tmp, "1.1")
|| !grub_strcmp (tmp, "1.2")
|| !grub_strcmp (tmp, "1.3"))
{
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0);
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_0_BASED_PARTITIONS);
}
}
}
if (is_olpc)
{
/* OLPC / XO laptops have three kinds of storage devices:
- NAND flash. These are accessible via OFW callbacks, but:
- Follow strange semantics, imposed by hardware constraints.
- Its ABI is undocumented, and not stable.
They lack "device_type" property, which conveniently makes GRUB
skip them.
- USB drives. Not accessible, because OFW shuts down the controller
in order to prevent collisions with applications accessing it
directly. Even worse, attempts to access it will NOT return
control to the caller, so we have to avoid probing them.
- SD cards. These work fine.
To avoid breakage, we only need to skip USB probing. However,
since detecting SD cards is more reliable, we do that instead.
*/
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY);
}
if (! grub_ieee1275_finddevice ("/rom/boot-rom", &bootrom))
{
rc = grub_ieee1275_get_property (bootrom, "model", tmp, sizeof (tmp), 0);
if (rc >= 0 && !grub_strncmp (tmp, OHW, sizeof (OHW) - 1))
{
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_BROKEN_OUTPUT);
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CANNOT_SET_COLORS);
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET);
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM);
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_ANSI);
}
}
}
#undef SF
#undef OHW
void
grub_ieee1275_init (void)
{
grub_ieee1275_finddevice ("/chosen", &grub_ieee1275_chosen);
if (grub_ieee1275_get_integer_property (grub_ieee1275_chosen, "mmu", &grub_ieee1275_mmu,
sizeof grub_ieee1275_mmu, 0) < 0)
grub_ieee1275_mmu = 0;
grub_ieee1275_find_options ();
}

View file

@ -0,0 +1,609 @@
/* of.c - Access the Open Firmware client interface. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/ieee1275/ieee1275.h>
#include <grub/types.h>
#define IEEE1275_PHANDLE_INVALID ((grub_ieee1275_cell_t) -1)
#define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_cell_t) 0)
#define IEEE1275_CELL_INVALID ((grub_ieee1275_cell_t) -1)
int
grub_ieee1275_finddevice (char *name, grub_ieee1275_phandle_t *phandlep)
{
struct find_device_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t device;
grub_ieee1275_cell_t phandle;
}
args;
INIT_IEEE1275_COMMON (&args.common, "finddevice", 1, 1);
args.device = (grub_ieee1275_cell_t) name;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
*phandlep = args.phandle;
if (args.phandle == IEEE1275_PHANDLE_INVALID)
return -1;
return 0;
}
int
grub_ieee1275_get_property (grub_ieee1275_phandle_t phandle,
const char *property, void *buf,
grub_size_t size, grub_ssize_t *actual)
{
struct get_property_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t phandle;
grub_ieee1275_cell_t prop;
grub_ieee1275_cell_t buf;
grub_ieee1275_cell_t buflen;
grub_ieee1275_cell_t size;
}
args;
INIT_IEEE1275_COMMON (&args.common, "getprop", 4, 1);
args.phandle = phandle;
args.prop = (grub_ieee1275_cell_t) property;
args.buf = (grub_ieee1275_cell_t) buf;
args.buflen = (grub_ieee1275_cell_t) size;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
if (actual)
*actual = (grub_ssize_t) args.size;
if (args.size == IEEE1275_CELL_INVALID)
return -1;
return 0;
}
int
grub_ieee1275_get_integer_property (grub_ieee1275_phandle_t phandle,
const char *property, grub_uint32_t *buf,
grub_size_t size, grub_ssize_t *actual)
{
int ret;
ret = grub_ieee1275_get_property (phandle, property, (void *) buf, size, actual);
#ifndef GRUB_CPU_WORDS_BIGENDIAN
/* Integer properties are always in big endian. */
if (ret == 0)
{
unsigned int i;
size /= sizeof (grub_uint32_t);
for (i = 0; i < size; i++)
buf[i] = grub_be_to_cpu32 (buf[i]);
}
#endif
return ret;
}
int
grub_ieee1275_next_property (grub_ieee1275_phandle_t phandle, char *prev_prop,
char *prop)
{
struct get_property_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t phandle;
grub_ieee1275_cell_t prev_prop;
grub_ieee1275_cell_t next_prop;
grub_ieee1275_cell_t flags;
}
args;
INIT_IEEE1275_COMMON (&args.common, "nextprop", 3, 1);
args.phandle = phandle;
args.prev_prop = (grub_ieee1275_cell_t) prev_prop;
args.next_prop = (grub_ieee1275_cell_t) prop;
args.flags = (grub_ieee1275_cell_t) -1;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
return (int) args.flags;
}
int
grub_ieee1275_get_property_length (grub_ieee1275_phandle_t phandle,
const char *prop, grub_ssize_t *length)
{
struct get_property_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t phandle;
grub_ieee1275_cell_t prop;
grub_ieee1275_cell_t length;
}
args;
INIT_IEEE1275_COMMON (&args.common, "getproplen", 2, 1);
args.phandle = phandle;
args.prop = (grub_ieee1275_cell_t) prop;
args.length = (grub_ieee1275_cell_t) -1;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
*length = args.length;
if (args.length == IEEE1275_CELL_INVALID)
return -1;
return 0;
}
int
grub_ieee1275_instance_to_package (grub_ieee1275_ihandle_t ihandle,
grub_ieee1275_phandle_t *phandlep)
{
struct instance_to_package_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t ihandle;
grub_ieee1275_cell_t phandle;
}
args;
INIT_IEEE1275_COMMON (&args.common, "instance-to-package", 1, 1);
args.ihandle = ihandle;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
*phandlep = args.phandle;
if (args.phandle == IEEE1275_PHANDLE_INVALID)
return -1;
return 0;
}
int
grub_ieee1275_package_to_path (grub_ieee1275_phandle_t phandle,
char *path, grub_size_t len,
grub_ssize_t *actual)
{
struct instance_to_package_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t phandle;
grub_ieee1275_cell_t buf;
grub_ieee1275_cell_t buflen;
grub_ieee1275_cell_t actual;
}
args;
INIT_IEEE1275_COMMON (&args.common, "package-to-path", 3, 1);
args.phandle = phandle;
args.buf = (grub_ieee1275_cell_t) path;
args.buflen = (grub_ieee1275_cell_t) len;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
if (actual)
*actual = args.actual;
if (args.actual == IEEE1275_CELL_INVALID)
return -1;
return 0;
}
int
grub_ieee1275_instance_to_path (grub_ieee1275_ihandle_t ihandle,
char *path, grub_size_t len,
grub_ssize_t *actual)
{
struct instance_to_path_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t ihandle;
grub_ieee1275_cell_t buf;
grub_ieee1275_cell_t buflen;
grub_ieee1275_cell_t actual;
}
args;
INIT_IEEE1275_COMMON (&args.common, "instance-to-path", 3, 1);
args.ihandle = ihandle;
args.buf = (grub_ieee1275_cell_t) path;
args.buflen = (grub_ieee1275_cell_t) len;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
if (actual)
*actual = args.actual;
if (args.actual == IEEE1275_CELL_INVALID)
return -1;
return 0;
}
int
grub_ieee1275_write (grub_ieee1275_ihandle_t ihandle, void *buffer,
grub_size_t len, grub_ssize_t *actualp)
{
struct write_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t ihandle;
grub_ieee1275_cell_t buf;
grub_ieee1275_cell_t len;
grub_ieee1275_cell_t actual;
}
args;
INIT_IEEE1275_COMMON (&args.common, "write", 3, 1);
args.ihandle = ihandle;
args.buf = (grub_ieee1275_cell_t) buffer;
args.len = (grub_ieee1275_cell_t) len;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
if (actualp)
*actualp = args.actual;
return 0;
}
int
grub_ieee1275_read (grub_ieee1275_ihandle_t ihandle, void *buffer,
grub_size_t len, grub_ssize_t *actualp)
{
struct write_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t ihandle;
grub_ieee1275_cell_t buf;
grub_ieee1275_cell_t len;
grub_ieee1275_cell_t actual;
}
args;
INIT_IEEE1275_COMMON (&args.common, "read", 3, 1);
args.ihandle = ihandle;
args.buf = (grub_ieee1275_cell_t) buffer;
args.len = (grub_ieee1275_cell_t) len;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
if (actualp)
*actualp = args.actual;
return 0;
}
int
grub_ieee1275_seek (grub_ieee1275_ihandle_t ihandle, grub_disk_addr_t pos,
grub_ssize_t *result)
{
struct write_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t ihandle;
grub_ieee1275_cell_t pos_hi;
grub_ieee1275_cell_t pos_lo;
grub_ieee1275_cell_t result;
}
args;
INIT_IEEE1275_COMMON (&args.common, "seek", 3, 1);
args.ihandle = ihandle;
/* To prevent stupid gcc warning. */
#if GRUB_IEEE1275_CELL_SIZEOF >= 8
args.pos_hi = 0;
args.pos_lo = pos;
#else
args.pos_hi = (grub_ieee1275_cell_t) (pos >> (8 * GRUB_IEEE1275_CELL_SIZEOF));
args.pos_lo = (grub_ieee1275_cell_t)
(pos & ((1ULL << (8 * GRUB_IEEE1275_CELL_SIZEOF)) - 1));
#endif
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
if (result)
*result = args.result;
return 0;
}
int
grub_ieee1275_peer (grub_ieee1275_phandle_t node,
grub_ieee1275_phandle_t *result)
{
struct peer_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t node;
grub_ieee1275_cell_t result;
}
args;
INIT_IEEE1275_COMMON (&args.common, "peer", 1, 1);
args.node = node;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
*result = args.result;
if (args.result == 0)
return -1;
return 0;
}
int
grub_ieee1275_child (grub_ieee1275_phandle_t node,
grub_ieee1275_phandle_t *result)
{
struct child_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t node;
grub_ieee1275_cell_t result;
}
args;
INIT_IEEE1275_COMMON (&args.common, "child", 1, 1);
args.node = node;
args.result = IEEE1275_PHANDLE_INVALID;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
*result = args.result;
if (args.result == 0)
return -1;
return 0;
}
int
grub_ieee1275_parent (grub_ieee1275_phandle_t node,
grub_ieee1275_phandle_t *result)
{
struct parent_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t node;
grub_ieee1275_cell_t result;
}
args;
INIT_IEEE1275_COMMON (&args.common, "parent", 1, 1);
args.node = node;
args.result = IEEE1275_PHANDLE_INVALID;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
*result = args.result;
return 0;
}
int
grub_ieee1275_interpret (const char *command, grub_ieee1275_cell_t *catch)
{
struct enter_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t command;
grub_ieee1275_cell_t catch;
}
args;
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET))
return -1;
INIT_IEEE1275_COMMON (&args.common, "interpret", 1, 1);
args.command = (grub_ieee1275_cell_t) command;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
if (catch)
*catch = args.catch;
return 0;
}
int
grub_ieee1275_enter (void)
{
struct enter_args
{
struct grub_ieee1275_common_hdr common;
}
args;
INIT_IEEE1275_COMMON (&args.common, "enter", 0, 0);
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
return 0;
}
void
grub_ieee1275_exit (void)
{
struct exit_args
{
struct grub_ieee1275_common_hdr common;
}
args;
INIT_IEEE1275_COMMON (&args.common, "exit", 0, 0);
IEEE1275_CALL_ENTRY_FN (&args);
for (;;) ;
}
int
grub_ieee1275_open (const char *path, grub_ieee1275_ihandle_t *result)
{
struct open_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t path;
grub_ieee1275_cell_t result;
}
args;
INIT_IEEE1275_COMMON (&args.common, "open", 1, 1);
args.path = (grub_ieee1275_cell_t) path;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
*result = args.result;
if (args.result == IEEE1275_IHANDLE_INVALID)
return -1;
return 0;
}
int
grub_ieee1275_close (grub_ieee1275_ihandle_t ihandle)
{
struct close_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t ihandle;
}
args;
INIT_IEEE1275_COMMON (&args.common, "close", 1, 0);
args.ihandle = ihandle;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
return 0;
}
int
grub_ieee1275_claim (grub_addr_t addr, grub_size_t size, unsigned int align,
grub_addr_t *result)
{
struct claim_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t addr;
grub_ieee1275_cell_t size;
grub_ieee1275_cell_t align;
grub_ieee1275_cell_t base;
}
args;
INIT_IEEE1275_COMMON (&args.common, "claim", 3, 1);
args.addr = (grub_ieee1275_cell_t) addr;
args.size = (grub_ieee1275_cell_t) size;
args.align = (grub_ieee1275_cell_t) align;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
if (result)
*result = args.base;
if (args.base == IEEE1275_CELL_INVALID)
return -1;
return 0;
}
int
grub_ieee1275_release (grub_addr_t addr, grub_size_t size)
{
struct release_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t addr;
grub_ieee1275_cell_t size;
}
args;
INIT_IEEE1275_COMMON (&args.common, "release", 2, 0);
args.addr = addr;
args.size = size;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
return 0;
}
int
grub_ieee1275_set_property (grub_ieee1275_phandle_t phandle,
const char *propname, void *buf,
grub_size_t size, grub_ssize_t *actual)
{
struct set_property_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t phandle;
grub_ieee1275_cell_t propname;
grub_ieee1275_cell_t buf;
grub_ieee1275_cell_t size;
grub_ieee1275_cell_t actual;
}
args;
INIT_IEEE1275_COMMON (&args.common, "setprop", 4, 1);
args.size = (grub_ieee1275_cell_t) size;
args.buf = (grub_ieee1275_cell_t) buf;
args.propname = (grub_ieee1275_cell_t) propname;
args.phandle = (grub_ieee1275_cell_t) phandle;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
*actual = args.actual;
if ((args.actual == IEEE1275_CELL_INVALID) || (args.actual != args.size))
return -1;
return 0;
}
int
grub_ieee1275_set_color (grub_ieee1275_ihandle_t ihandle,
int index, int r, int g, int b)
{
struct set_color_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t method;
grub_ieee1275_cell_t ihandle;
grub_ieee1275_cell_t index;
grub_ieee1275_cell_t b;
grub_ieee1275_cell_t g;
grub_ieee1275_cell_t r;
grub_ieee1275_cell_t catch_result;
}
args;
INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 1);
args.method = (grub_ieee1275_cell_t) "color!";
args.ihandle = ihandle;
args.index = index;
args.r = r;
args.g = g;
args.b = b;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
return args.catch_result;
}
int
grub_ieee1275_milliseconds (grub_uint32_t *msecs)
{
struct milliseconds_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t msecs;
}
args;
INIT_IEEE1275_COMMON (&args.common, "milliseconds", 0, 1);
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
*msecs = args.msecs;
return 0;
}

View file

@ -0,0 +1,288 @@
/* init.c -- Initialize GRUB on the newworld mac (PPC). */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/kernel.h>
#include <grub/dl.h>
#include <grub/disk.h>
#include <grub/mm.h>
#include <grub/partition.h>
#include <grub/normal.h>
#include <grub/fs.h>
#include <grub/setjmp.h>
#include <grub/env.h>
#include <grub/misc.h>
#include <grub/time.h>
#include <grub/machine/console.h>
#include <grub/machine/kernel.h>
#include <grub/cpu/kernel.h>
#include <grub/ieee1275/ofdisk.h>
#include <grub/ieee1275/ieee1275.h>
/* The minimal heap size we can live with. */
#define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024)
/* The maximum heap size we're going to claim */
#define HEAP_MAX_SIZE (unsigned long) (32 * 1024 * 1024)
/* If possible, we will avoid claiming heap above this address, because it
seems to cause relocation problems with OSes that link at 4 MiB */
#define HEAP_MAX_ADDR (unsigned long) (32 * 1024 * 1024)
extern char _start[];
extern char _end[];
void
grub_exit (void)
{
grub_ieee1275_exit ();
}
/* Translate an OF filesystem path (separated by backslashes), into a GRUB
path (separated by forward slashes). */
static void
grub_translate_ieee1275_path (char *filepath)
{
char *backslash;
backslash = grub_strchr (filepath, '\\');
while (backslash != 0)
{
*backslash = '/';
backslash = grub_strchr (filepath, '\\');
}
}
void
grub_machine_set_prefix (void)
{
char bootpath[64]; /* XXX check length */
char *filename;
char *prefix;
if (grub_prefix[0])
{
grub_env_set ("prefix", grub_prefix);
/* Prefix is hardcoded in the core image. */
return;
}
if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath,
sizeof (bootpath), 0))
{
/* Should never happen. */
grub_printf ("/chosen/bootpath property missing!\n");
grub_env_set ("prefix", "");
return;
}
/* Transform an OF device path to a GRUB path. */
prefix = grub_ieee1275_encode_devname (bootpath);
filename = grub_ieee1275_get_filename (bootpath);
if (filename)
{
char *newprefix;
char *lastslash = grub_strrchr (filename, '\\');
/* Truncate at last directory. */
if (lastslash)
{
*lastslash = '\0';
grub_translate_ieee1275_path (filename);
newprefix = grub_xasprintf ("%s%s", prefix, filename);
if (newprefix)
{
grub_free (prefix);
prefix = newprefix;
}
}
}
grub_env_set ("prefix", prefix);
grub_free (filename);
grub_free (prefix);
}
/* Claim some available memory in the first /memory node. */
static void grub_claim_heap (void)
{
unsigned long total = 0;
auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type);
int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type)
{
if (type != 1)
return 0;
len -= 1; /* Required for some firmware. */
/* Never exceed HEAP_MAX_SIZE */
if (total + len > HEAP_MAX_SIZE)
len = HEAP_MAX_SIZE - total;
/* Avoid claiming anything above HEAP_MAX_ADDR, if possible. */
if ((addr < HEAP_MAX_ADDR) && /* if it's too late, don't bother */
(addr + len > HEAP_MAX_ADDR) && /* if it wasn't available anyway, don't bother */
(total + (HEAP_MAX_ADDR - addr) > HEAP_MIN_SIZE)) /* only limit ourselves when we can afford to */
len = HEAP_MAX_ADDR - addr;
/* In theory, firmware should already prevent this from happening by not
listing our own image in /memory/available. The check below is intended
as a safeguard in case that doesn't happen. However, it doesn't protect
us from corrupting our module area, which extends up to a
yet-undetermined region above _end. */
if ((addr < (grub_addr_t) _end) && ((addr + len) > (grub_addr_t) _start))
{
grub_printf ("Warning: attempt to claim over our own code!\n");
len = 0;
}
if (len)
{
/* Claim and use it. */
if (grub_claimmap (addr, len) < 0)
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"failed to claim heap at 0x%llx, len 0x%llx",
addr, len);
grub_mm_init_region ((void *) (grub_addr_t) addr, len);
}
total += len;
if (total >= HEAP_MAX_SIZE)
return 1;
return 0;
}
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET))
heap_init (HEAP_MAX_ADDR - HEAP_MIN_SIZE, HEAP_MIN_SIZE, 1);
else
grub_machine_mmap_iterate (heap_init);
}
#ifdef __i386__
grub_uint32_t grub_upper_mem;
/* We need to call this before grub_claim_memory. */
static void
grub_get_extended_memory (void)
{
auto int NESTED_FUNC_ATTR find_ext_mem (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type);
int NESTED_FUNC_ATTR find_ext_mem (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type)
{
if (type == 1 && addr == 0x100000)
{
grub_upper_mem = len;
return 1;
}
return 0;
}
grub_machine_mmap_iterate (find_ext_mem);
}
#endif
static grub_uint64_t ieee1275_get_time_ms (void);
void
grub_machine_init (void)
{
char args[256];
grub_ssize_t actual;
grub_ieee1275_init ();
grub_console_init ();
#ifdef __i386__
grub_get_extended_memory ();
#endif
grub_claim_heap ();
grub_ofdisk_init ();
/* Process commandline. */
if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args,
sizeof args, &actual) == 0
&& actual > 1)
{
int i = 0;
while (i < actual)
{
char *command = &args[i];
char *end;
char *val;
end = grub_strchr (command, ';');
if (end == 0)
i = actual; /* No more commands after this one. */
else
{
*end = '\0';
i += end - command + 1;
while (grub_isspace(args[i]))
i++;
}
/* Process command. */
val = grub_strchr (command, '=');
if (val)
{
*val = '\0';
grub_env_set (command, val + 1);
}
}
}
grub_install_get_time_ms (ieee1275_get_time_ms);
}
void
grub_machine_fini (void)
{
grub_ofdisk_fini ();
grub_console_fini ();
}
static grub_uint64_t
ieee1275_get_time_ms (void)
{
grub_uint32_t msecs = 0;
grub_ieee1275_milliseconds (&msecs);
return msecs;
}
grub_uint32_t
grub_get_rtc (void)
{
return ieee1275_get_time_ms ();
}
grub_addr_t
grub_arch_modules_addr (void)
{
return ALIGN_UP((grub_addr_t) _end + GRUB_MOD_GAP, GRUB_MOD_ALIGN);
}

View file

@ -0,0 +1,74 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2004,2005,2007,2008 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/machine/memory.h>
#include <grub/ieee1275/ieee1275.h>
#include <grub/types.h>
grub_err_t
grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
{
grub_ieee1275_phandle_t root;
grub_ieee1275_phandle_t memory;
grub_uint32_t available[32];
grub_ssize_t available_size;
grub_uint32_t address_cells = 1;
grub_uint32_t size_cells = 1;
int i;
/* Determine the format of each entry in `available'. */
grub_ieee1275_finddevice ("/", &root);
grub_ieee1275_get_integer_property (root, "#address-cells", &address_cells,
sizeof address_cells, 0);
grub_ieee1275_get_integer_property (root, "#size-cells", &size_cells,
sizeof size_cells, 0);
if (size_cells > address_cells)
address_cells = size_cells;
/* Load `/memory/available'. */
if (grub_ieee1275_finddevice ("/memory", &memory))
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"couldn't find /memory node");
if (grub_ieee1275_get_integer_property (memory, "available", available,
sizeof available, &available_size))
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"couldn't examine /memory/available property");
/* Decode each entry and call `hook'. */
i = 0;
available_size /= sizeof (grub_uint32_t);
while (i < available_size)
{
grub_uint64_t address;
grub_uint64_t size;
address = available[i++];
if (address_cells == 2)
address = (address << 32) | available[i++];
size = available[i++];
if (size_cells == 2)
size = (size << 32) | available[i++];
if (hook (address, size, GRUB_MACHINE_MEMORY_AVAILABLE))
break;
}
return grub_errno;
}

View file

@ -0,0 +1,435 @@
/* openfw.c -- Open firmware support functions. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/types.h>
#include <grub/err.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/machine/kernel.h>
#include <grub/ieee1275/ieee1275.h>
enum grub_ieee1275_parse_type
{
GRUB_PARSE_FILENAME,
GRUB_PARSE_PARTITION,
};
/* Walk children of 'devpath', calling hook for each. */
int
grub_children_iterate (char *devpath,
int (*hook) (struct grub_ieee1275_devalias *alias))
{
grub_ieee1275_phandle_t dev;
grub_ieee1275_phandle_t child;
char *childtype, *childpath;
char *childname;
int ret = 0;
if (grub_ieee1275_finddevice (devpath, &dev))
return 0;
if (grub_ieee1275_child (dev, &child))
return 0;
childtype = grub_malloc (IEEE1275_MAX_PROP_LEN);
if (!childtype)
return 0;
childpath = grub_malloc (IEEE1275_MAX_PATH_LEN);
if (!childpath)
{
grub_free (childtype);
return 0;
}
childname = grub_malloc (IEEE1275_MAX_PROP_LEN);
if (!childname)
{
grub_free (childpath);
grub_free (childtype);
return 0;
}
do
{
struct grub_ieee1275_devalias alias;
grub_ssize_t actual;
if (grub_ieee1275_get_property (child, "device_type", childtype,
IEEE1275_MAX_PROP_LEN, &actual))
childtype[0] = 0;
if (dev == child)
continue;
if (grub_ieee1275_package_to_path (child, childpath,
IEEE1275_MAX_PATH_LEN, &actual))
continue;
if (grub_strcmp (devpath, childpath) == 0)
continue;
if (grub_ieee1275_get_property (child, "name", childname,
IEEE1275_MAX_PROP_LEN, &actual))
continue;
alias.type = childtype;
alias.path = childpath;
alias.name = childname;
ret = hook (&alias);
if (ret)
break;
}
while (grub_ieee1275_peer (child, &child) != -1);
grub_free (childname);
grub_free (childpath);
grub_free (childtype);
return ret;
}
int
grub_ieee1275_devices_iterate (int (*hook) (struct grub_ieee1275_devalias *alias))
{
auto int it_through (struct grub_ieee1275_devalias *alias);
int it_through (struct grub_ieee1275_devalias *alias)
{
if (hook (alias))
return 1;
return grub_children_iterate (alias->path, it_through);
}
return grub_children_iterate ("/", it_through);
}
/* Iterate through all device aliases. This function can be used to
find a device of a specific type. */
int
grub_devalias_iterate (int (*hook) (struct grub_ieee1275_devalias *alias))
{
grub_ieee1275_phandle_t aliases;
char *aliasname, *devtype;
grub_ssize_t actual;
struct grub_ieee1275_devalias alias;
int ret = 0;
if (grub_ieee1275_finddevice ("/aliases", &aliases))
return 0;
aliasname = grub_malloc (IEEE1275_MAX_PROP_LEN);
if (!aliasname)
return 0;
devtype = grub_malloc (IEEE1275_MAX_PROP_LEN);
if (!devtype)
{
grub_free (aliasname);
return 0;
}
/* Find the first property. */
aliasname[0] = '\0';
while (grub_ieee1275_next_property (aliases, aliasname, aliasname) > 0)
{
grub_ieee1275_phandle_t dev;
grub_ssize_t pathlen;
char *devpath;
grub_dprintf ("devalias", "devalias name = %s\n", aliasname);
grub_ieee1275_get_property_length (aliases, aliasname, &pathlen);
/* The property `name' is a special case we should skip. */
if (!grub_strcmp (aliasname, "name"))
continue;
/* Sun's OpenBoot often doesn't zero terminate the device alias
strings, so we will add a NULL byte at the end explicitly. */
pathlen += 1;
devpath = grub_malloc (pathlen);
if (! devpath)
{
grub_free (devtype);
grub_free (aliasname);
return 0;
}
if (grub_ieee1275_get_property (aliases, aliasname, devpath, pathlen,
&actual))
{
grub_dprintf ("devalias", "get_property (%s) failed\n", aliasname);
goto nextprop;
}
devpath [actual] = '\0';
if (grub_ieee1275_finddevice (devpath, &dev))
{
grub_dprintf ("devalias", "finddevice (%s) failed\n", devpath);
goto nextprop;
}
if (grub_ieee1275_get_property (dev, "device_type", devtype,
IEEE1275_MAX_PROP_LEN, &actual))
{
/* NAND device don't have device_type property. */
devtype[0] = 0;
}
alias.name = aliasname;
alias.path = devpath;
alias.type = devtype;
ret = hook (&alias);
nextprop:
grub_free (devpath);
if (ret)
break;
}
grub_free (devtype);
grub_free (aliasname);
return ret;
}
/* Call the "map" method of /chosen/mmu. */
int
grub_ieee1275_map (grub_addr_t phys, grub_addr_t virt, grub_size_t size,
grub_uint32_t mode)
{
struct map_args {
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t method;
grub_ieee1275_cell_t ihandle;
grub_ieee1275_cell_t mode;
grub_ieee1275_cell_t size;
grub_ieee1275_cell_t virt;
#ifdef GRUB_MACHINE_SPARC64
grub_ieee1275_cell_t phys_high;
#endif
grub_ieee1275_cell_t phys_low;
grub_ieee1275_cell_t catch_result;
} args;
INIT_IEEE1275_COMMON (&args.common, "call-method",
#ifdef GRUB_MACHINE_SPARC64
7,
#else
6,
#endif
1);
args.method = (grub_ieee1275_cell_t) "map";
args.ihandle = grub_ieee1275_mmu;
#ifdef GRUB_MACHINE_SPARC64
args.phys_high = 0;
#endif
args.phys_low = phys;
args.virt = virt;
args.size = size;
args.mode = mode; /* Format is WIMG0PP. */
args.catch_result = (grub_ieee1275_cell_t) -1;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
return -1;
return args.catch_result;
}
int
grub_claimmap (grub_addr_t addr, grub_size_t size)
{
if (grub_ieee1275_claim (addr, size, 0, 0))
return -1;
if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_REAL_MODE)
&& grub_ieee1275_map (addr, addr, size, 0x00))
{
grub_printf ("map failed: address 0x%llx, size 0x%llx\n",
(long long) addr, (long long) size);
grub_ieee1275_release (addr, size);
return -1;
}
return 0;
}
/* Get the device arguments of the Open Firmware node name `path'. */
static char *
grub_ieee1275_get_devargs (const char *path)
{
char *colon = grub_strchr (path, ':');
if (! colon)
return 0;
return grub_strdup (colon + 1);
}
/* Get the device path of the Open Firmware node name `path'. */
static char *
grub_ieee1275_get_devname (const char *path)
{
char *colon = grub_strchr (path, ':');
char *newpath = 0;
int pathlen = grub_strlen (path);
auto int match_alias (struct grub_ieee1275_devalias *alias);
int match_alias (struct grub_ieee1275_devalias *curalias)
{
/* briQ firmware can change capitalization in /chosen/bootpath. */
if (! grub_strncasecmp (curalias->path, path, pathlen))
{
newpath = grub_strdup (curalias->name);
return 1;
}
return 0;
}
if (colon)
pathlen = (int)(colon - path);
/* Try to find an alias for this device. */
grub_devalias_iterate (match_alias);
if (! newpath)
newpath = grub_strndup (path, pathlen);
return newpath;
}
static char *
grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype)
{
char type[64]; /* XXX check size. */
char *device = grub_ieee1275_get_devname (path);
char *args = grub_ieee1275_get_devargs (path);
char *ret = 0;
grub_ieee1275_phandle_t dev;
if (!args)
/* Shouldn't happen. */
return 0;
/* We need to know what type of device it is in order to parse the full
file path properly. */
if (grub_ieee1275_finddevice (device, &dev))
{
grub_error (GRUB_ERR_UNKNOWN_DEVICE, "device %s not found", device);
goto fail;
}
if (grub_ieee1275_get_property (dev, "device_type", &type, sizeof type, 0))
{
grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"device %s lacks a device_type property", device);
goto fail;
}
if (!grub_strcmp ("block", type))
{
/* The syntax of the device arguments is defined in the CHRP and PReP
IEEE1275 bindings: "[partition][,[filename]]". */
char *comma = grub_strchr (args, ',');
if (ptype == GRUB_PARSE_FILENAME)
{
if (comma)
{
char *filepath = comma + 1;
/* Make sure filepath has leading backslash. */
if (filepath[0] != '\\')
ret = grub_xasprintf ("\\%s", filepath);
else
ret = grub_strdup (filepath);
}
}
else if (ptype == GRUB_PARSE_PARTITION)
{
if (!comma)
ret = grub_strdup (args);
else
ret = grub_strndup (args, (grub_size_t)(comma - args));
}
}
else
{
/* XXX Handle net devices by configuring & registering a grub_net_dev
here, then return its name?
Example path: "net:<server ip>,<file name>,<client ip>,<gateway
ip>,<bootp retries>,<tftp retries>". */
grub_printf ("Unsupported type %s for device %s\n", type, device);
}
fail:
grub_free (device);
grub_free (args);
return ret;
}
char *
grub_ieee1275_get_filename (const char *path)
{
return grub_ieee1275_parse_args (path, GRUB_PARSE_FILENAME);
}
/* Convert a device name from IEEE1275 syntax to GRUB syntax. */
char *
grub_ieee1275_encode_devname (const char *path)
{
char *device = grub_ieee1275_get_devname (path);
char *partition = grub_ieee1275_parse_args (path, GRUB_PARSE_PARTITION);
char *encoding;
if (partition && partition[0])
{
unsigned int partno = grub_strtoul (partition, 0, 0);
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_0_BASED_PARTITIONS))
/* GRUB partition 1 is OF partition 0. */
partno++;
encoding = grub_xasprintf ("(%s,%d)", device, partno);
}
else
encoding = grub_xasprintf ("(%s)", device);
grub_free (partition);
grub_free (device);
return encoding;
}
/* On i386, a firmware-independant grub_reboot() is provided by realmode.S. */
#ifndef __i386__
void
grub_reboot (void)
{
grub_ieee1275_interpret ("reset-all", 0);
}
#endif
void
grub_halt (void)
{
/* Not standardized. We try three known commands. */
grub_ieee1275_interpret ("shut-down", 0);
grub_ieee1275_interpret ("power-off", 0);
grub_ieee1275_interpret ("poweroff", 0);
}