diff --git a/ChangeLog b/ChangeLog index ea293f27a..1a57fff20 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2008-01-22 Robert Millan + + * disk/ieee1275/ofdisk.c (grub_ofdisk_iterate): When + `GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY' flag is set, skip any + device that doesn't look like an SD card. + * include/grub/ieee1275/ieee1275.h (grub_ieee1275_flag): Add + `GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY' flag. + * kern/powerpc/ieee1275/cmain.c (grub_ieee1275_set_flag): Detect + OLPC laptop, and set `GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY' when + found. + 2008-01-22 Robert Millan * kern/powerpc/ieee1275/init.c (grub_claim_heap): Add sanity check to diff --git a/disk/ieee1275/ofdisk.c b/disk/ieee1275/ofdisk.c index e1b31b6d0..d86d95327 100644 --- a/disk/ieee1275/ofdisk.c +++ b/disk/ieee1275/ofdisk.c @@ -30,6 +30,33 @@ grub_ofdisk_iterate (int (*hook) (const char *name)) int dev_iterate (struct grub_ieee1275_devalias *alias) { + grub_dprintf ("disk", "disk name = %s\n", alias->name); + + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY)) + { + grub_ieee1275_phandle_t dev; + char tmp[8]; + + if (grub_ieee1275_finddevice (alias->path, &dev)) + { + grub_dprintf ("disk", "finddevice (%s) failed\n", alias->path); + return 0; + } + + if (grub_ieee1275_get_property (dev, "iconname", tmp, + sizeof tmp, 0)) + { + grub_dprintf ("disk", "get iconname failed\n"); + return 0; + } + + if (grub_strcmp (tmp, "sdmmc")) + { + grub_dprintf ("disk", "device is not an SD card\n"); + return 0; + } + } + if (! grub_strcmp (alias->type, "block")) hook (alias->name); else if ((! grub_strcmp (alias->type, "scsi")) diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index e1cf0c4ba..008a114f6 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -83,6 +83,9 @@ enum grub_ieee1275_flag /* CodeGen firmware does not correctly implement "output-device output" */ GRUB_IEEE1275_FLAG_BROKEN_OUTPUT, + + /* OLPC / XO firmware hangs when accessing USB devices. */ + GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY, }; extern int EXPORT_FUNC(grub_ieee1275_test_flag) (enum grub_ieee1275_flag flag); diff --git a/kern/powerpc/ieee1275/cmain.c b/kern/powerpc/ieee1275/cmain.c index 91e22b374..2b7cce56c 100644 --- a/kern/powerpc/ieee1275/cmain.c +++ b/kern/powerpc/ieee1275/cmain.c @@ -49,27 +49,35 @@ grub_ieee1275_set_flag (enum grub_ieee1275_flag flag) static void grub_ieee1275_find_options (void) { + grub_ieee1275_phandle_t root; grub_ieee1275_phandle_t options; grub_ieee1275_phandle_t openprom; int rc; int 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); - grub_ieee1275_finddevice ("/openprom", &openprom); - rc = grub_ieee1275_get_property (openprom, "CodeGen-copyright", tmp, sizeof (tmp), 0); #define SF "SmartFirmware(tm)" 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 */ @@ -101,6 +109,30 @@ grub_ieee1275_find_options (void) } } } + + 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 brekage, 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); + } } void cmain (void);