(Part zero was a patch I already committed that dealt with some trivial cases.)
As I mentioned on #grub, and following up on https://lists.gnu.org/archive/html/grub-devel/2009-04/msg00406.html and thread, I'm working on a patch set to eliminate nested functions from GRUB. I'd like to add a couple of extra reasons to those given by Pavel nearly four years ago: * The trampolines used when taking the address of a nested function are a net cost in terms of code size. With my full set of patches so far, the i386-pc (compressed) kernel gets 52 bytes smaller and a sample core image profile (biosdisk ext2 part_msdos lvm mdraid1x) gets 39 bytes smaller. That's admittedly not lots, but there are some situations on i386-pc that are very close to the wire and where every byte in the core image counts. * Even several years on, we have failed to solve all the build system problems associated with nested functions. See Savannah bugs #36669 and #37938. * It is revealing that if you search the web for "gcc nested functions" or similar, you find several GCC bug reports from GRUB developers. We appear to be in a small minority of free programs making use of this facility, and I for one would rather concentrate on producing a high-quality boot loader rather than fighting arcane compiler features. The vast majority of the nested functions we use - or at any rate the particularly problematic ones that involve trampolines - are iterator hook functions. In the general case, un-nesting these involves passing a context structure as an additional argument to the hook function. I have adopted a mostly formulaic approach to this, exemplified by the attached patch which converts grub_pci_iterate to the new scheme. My approach, which I'll spell out for the sake of those maintaining patches, is as follows: * Whenever a function (usually *_iterate) takes a hook function pointer "foo" as a parameter, add an additional "void *foo_data" parameter immediately after it. * If there is not already a typedef for the hook function type, add one. * Update all implementations of the hook type in question to take an additional "void *data" parameter. * Move each hook that was previously a nested function to the top level of its file, and mark it static. * If a hook requires no local variables from its parent function, mark the data parameter __attribute__ ((unused)) and pass NULL when calling it (either directly or via the relevant *_iterate function). * If a hook only requires a single local variable from its parent function, pass a reference to that variable as its data parameter, and have the hook declare an pointer variable at the top initialised to data (e.g. "static int *found = data"). * If a hook requires more than one local variable from its parent function, declare "struct <name-of-parent>_ctx" with the necessary variables, and convert both the hook and the parent to access the variables in question via that structure. I made use of GCC's non-constant aggregate automatic initialisers extension when initialising the context structure in the parent, which I found clearest. * If a hook has a reasonably clear name already, leave it alone. However, if it is called something excessively general such as "hook", then rename it either to something describing its purpose or else simply to "<name-of-parent>_iter". * Remove any NESTED_FUNC_ATTR from hook declarations, and from any pre-existing typedef for the hook function type. I have a number of patches mostly ready to go, but I'd prefer to make sure that this general approach is agreed before preparing and sending more than one of them. I'd like to work one *_iterate function at a time (except where multiple iterators are entangled in a stack such that we need to change several at once, as is the case in parts of the disk/filesystem stacks), as that's roughly the minimum sensible unit and it makes it reasonably easy to grep for missing changes. Please review. Thanks, -- Colin Watson [cjwat...@ubuntu.com]
=== modified file 'grub-core/bus/cs5536.c' --- grub-core/bus/cs5536.c 2011-12-13 14:13:51 +0000 +++ grub-core/bus/cs5536.c 2013-01-01 14:25:26 +0000 @@ -29,28 +29,39 @@ GRUB_MOD_LICENSE ("GPLv3+"); +/* Context for grub_cs5536_find. */ +struct grub_cs5536_find_ctx +{ + grub_pci_device_t *devp; + int found; +}; + +/* Helper for grub_cs5536_find. */ +static int +grub_cs5536_find_iter (grub_pci_device_t dev, grub_pci_id_t pciid, void *data) +{ + struct grub_cs5536_find_ctx *ctx = data; + + if (pciid == GRUB_CS5536_PCIID) + { + *ctx->devp = dev; + ctx->found = 1; + return 1; + } + return 0; +} + int grub_cs5536_find (grub_pci_device_t *devp) { - int found = 0; - auto int NESTED_FUNC_ATTR hook (grub_pci_device_t dev, - grub_pci_id_t pciid); - - int NESTED_FUNC_ATTR hook (grub_pci_device_t dev, - grub_pci_id_t pciid) - { - if (pciid == GRUB_CS5536_PCIID) - { - *devp = dev; - found = 1; - return 1; - } - return 0; - } + struct grub_cs5536_find_ctx ctx = { + .devp = devp, + .found = 0 + }; - grub_pci_iterate (hook); + grub_pci_iterate (grub_cs5536_find_iter, &ctx); - return found; + return ctx.found; } grub_uint64_t === modified file 'grub-core/bus/emu/pci.c' --- grub-core/bus/emu/pci.c 2010-05-06 07:25:47 +0000 +++ grub-core/bus/emu/pci.c 2013-01-01 12:50:14 +0000 @@ -32,7 +32,7 @@ grub_pci_make_address (grub_pci_device_t } void -grub_pci_iterate (grub_pci_iteratefunc_t hook) +grub_pci_iterate (grub_pci_iteratefunc_t hook, void *hook_data) { struct pci_device_iterator *iter; struct pci_slot_match slot; @@ -43,7 +43,7 @@ grub_pci_iterate (grub_pci_iteratefunc_t slot.func = PCI_MATCH_ANY; iter = pci_slot_match_iterator_create (&slot); while ((dev = pci_device_next (iter))) - hook (dev, dev->vendor_id | (dev->device_id << 16)); + hook (dev, dev->vendor_id | (dev->device_id << 16), hook_data); pci_iterator_destroy (iter); } === modified file 'grub-core/bus/pci.c' --- grub-core/bus/pci.c 2012-05-03 15:26:55 +0000 +++ grub-core/bus/pci.c 2013-01-01 12:50:14 +0000 @@ -98,7 +98,7 @@ grub_pci_make_address (grub_pci_device_t } void -grub_pci_iterate (grub_pci_iteratefunc_t hook) +grub_pci_iterate (grub_pci_iteratefunc_t hook, void *hook_data) { grub_pci_device_t dev; grub_pci_address_t addr; @@ -125,7 +125,7 @@ grub_pci_iterate (grub_pci_iteratefunc_t continue; } - if (hook (dev, id)) + if (hook (dev, id, hook_data)) return; /* Probe only func = 0 if the device if not multifunction */ === modified file 'grub-core/bus/usb/ehci.c' --- grub-core/bus/usb/ehci.c 2012-12-30 09:57:58 +0000 +++ grub-core/bus/usb/ehci.c 2013-01-01 12:50:14 +0000 @@ -454,8 +454,9 @@ grub_ehci_reset (struct grub_ehci *e) } /* PCI iteration function... */ -static int NESTED_FUNC_ATTR -grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) +static int +grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) { grub_uint8_t release; grub_uint32_t class_code; @@ -1814,7 +1815,7 @@ grub_ehci_detect_dev (grub_usb_controlle static void grub_ehci_inithw (void) { - grub_pci_iterate (grub_ehci_pci_iter); + grub_pci_iterate (grub_ehci_pci_iter, NULL); } static grub_err_t === modified file 'grub-core/bus/usb/ohci.c' --- grub-core/bus/usb/ohci.c 2012-07-22 19:09:30 +0000 +++ grub-core/bus/usb/ohci.c 2013-01-01 12:50:14 +0000 @@ -213,9 +213,9 @@ grub_ohci_writereg32 (struct grub_ohci * /* Iterate over all PCI devices. Determine if a device is an OHCI controller. If this is the case, initialize it. */ -static int NESTED_FUNC_ATTR -grub_ohci_pci_iter (grub_pci_device_t dev, - grub_pci_id_t pciid) +static int +grub_ohci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) { grub_uint32_t interf; grub_uint32_t base; @@ -477,7 +477,7 @@ grub_ohci_pci_iter (grub_pci_device_t de static void grub_ohci_inithw (void) { - grub_pci_iterate (grub_ohci_pci_iter); + grub_pci_iterate (grub_ohci_pci_iter, NULL); } === modified file 'grub-core/bus/usb/uhci.c' --- grub-core/bus/usb/uhci.c 2012-02-09 14:00:05 +0000 +++ grub-core/bus/usb/uhci.c 2013-01-01 12:50:14 +0000 @@ -185,9 +185,10 @@ grub_uhci_portstatus (grub_usb_controlle /* Iterate over all PCI devices. Determine if a device is an UHCI controller. If this is the case, initialize it. */ -static int NESTED_FUNC_ATTR +static int grub_uhci_pci_iter (grub_pci_device_t dev, - grub_pci_id_t pciid __attribute__((unused))) + grub_pci_id_t pciid __attribute__((unused)), + void *data __attribute__ ((unused))) { grub_uint32_t class_code; grub_uint32_t class; @@ -351,7 +352,7 @@ grub_uhci_pci_iter (grub_pci_device_t de static void grub_uhci_inithw (void) { - grub_pci_iterate (grub_uhci_pci_iter); + grub_pci_iterate (grub_uhci_pci_iter, NULL); } static grub_uhci_td_t === modified file 'grub-core/commands/efi/fixvideo.c' --- grub-core/commands/efi/fixvideo.c 2012-02-27 13:13:24 +0000 +++ grub-core/commands/efi/fixvideo.c 2013-01-01 13:03:29 +0000 @@ -23,6 +23,7 @@ #include <grub/pci.h> #include <grub/command.h> #include <grub/i18n.h> +#include <grub/mm.h> GRUB_MOD_LICENSE ("GPLv3+"); @@ -40,8 +41,9 @@ static struct grub_video_patch {0, 0, 0, 0, 0} }; -static int NESTED_FUNC_ATTR -scan_card (grub_pci_device_t dev, grub_pci_id_t pciid) +static int +scan_card (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) { grub_pci_address_t addr; @@ -93,7 +95,7 @@ grub_cmd_fixvideo (grub_command_t cmd __ int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused))) { - grub_pci_iterate (scan_card); + grub_pci_iterate (scan_card, NULL); return 0; } === modified file 'grub-core/commands/lspci.c' --- grub-core/commands/lspci.c 2011-11-30 15:20:13 +0000 +++ grub-core/commands/lspci.c 2013-01-01 12:50:14 +0000 @@ -22,6 +22,7 @@ #include <grub/misc.h> #include <grub/extcmd.h> #include <grub/i18n.h> +#include <grub/mm.h> GRUB_MOD_LICENSE ("GPLv3+"); @@ -126,8 +127,9 @@ static const struct grub_arg_option opti static int iospace; -static int NESTED_FUNC_ATTR -grub_lspci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) +static int +grub_lspci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) { grub_uint32_t class; const char *sclass; @@ -218,7 +220,7 @@ grub_cmd_lspci (grub_extcmd_context_t ct char **args __attribute__ ((unused))) { iospace = ctxt->state[0].set; - grub_pci_iterate (grub_lspci_iter); + grub_pci_iterate (grub_lspci_iter, NULL); return GRUB_ERR_NONE; } === modified file 'grub-core/commands/setpci.c' --- grub-core/commands/setpci.c 2012-02-08 18:26:01 +0000 +++ grub-core/commands/setpci.c 2013-01-01 12:50:14 +0000 @@ -83,8 +83,9 @@ static int regsize; static grub_uint16_t regaddr; static const char *varname; -static int NESTED_FUNC_ATTR -grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) +static int +grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) { grub_uint32_t regval = 0; grub_pci_address_t addr; @@ -320,7 +321,7 @@ grub_cmd_setpci (grub_extcmd_context_t c return grub_error (GRUB_ERR_BAD_ARGUMENT, "option -v isn't valid for writes"); - grub_pci_iterate (grub_setpci_iter); + grub_pci_iterate (grub_setpci_iter, NULL); return GRUB_ERR_NONE; } === modified file 'grub-core/disk/ahci.c' --- grub-core/disk/ahci.c 2012-02-08 18:26:01 +0000 +++ grub-core/disk/ahci.c 2013-01-01 12:50:14 +0000 @@ -254,9 +254,10 @@ init_port (struct grub_ahci_device *dev) return 1; } -static int NESTED_FUNC_ATTR +static int grub_ahci_pciinit (grub_pci_device_t dev, - grub_pci_id_t pciid __attribute__ ((unused))) + grub_pci_id_t pciid __attribute__ ((unused)), + void *data __attribute__ ((unused))) { grub_pci_address_t addr; grub_uint32_t class; @@ -394,7 +395,7 @@ grub_ahci_pciinit (grub_pci_device_t dev static grub_err_t grub_ahci_initialize (void) { - grub_pci_iterate (grub_ahci_pciinit); + grub_pci_iterate (grub_ahci_pciinit, NULL); return grub_errno; } === modified file 'grub-core/disk/pata.c' --- grub-core/disk/pata.c 2012-06-06 10:38:49 +0000 +++ grub-core/disk/pata.c 2013-01-01 12:50:14 +0000 @@ -338,9 +338,10 @@ grub_pata_device_initialize (int port, i } #ifndef GRUB_MACHINE_MIPS_QEMU_MIPS -static int NESTED_FUNC_ATTR +static int grub_pata_pciinit (grub_pci_device_t dev, - grub_pci_id_t pciid) + grub_pci_id_t pciid, + void *data __attribute__ ((unused))) { static int compat_use[2] = { 0 }; grub_pci_address_t addr; @@ -446,7 +447,7 @@ grub_pata_pciinit (grub_pci_device_t dev static grub_err_t grub_pata_initialize (void) { - grub_pci_iterate (grub_pata_pciinit); + grub_pci_iterate (grub_pata_pciinit, NULL); return 0; } #else === modified file 'grub-core/kern/efi/mm.c' --- grub-core/kern/efi/mm.c 2012-05-03 15:26:55 +0000 +++ grub-core/kern/efi/mm.c 2013-01-01 14:26:12 +0000 @@ -109,37 +109,36 @@ grub_efi_free_pages (grub_efi_physical_a #if defined (__i386__) || defined (__x86_64__) +/* Helper for stop_broadcom. */ +static int +find_card (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) +{ + grub_pci_address_t addr; + grub_uint8_t cap; + grub_uint16_t pm_state; + + if ((pciid & 0xffff) != GRUB_PCI_VENDOR_BROADCOM) + return 0; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + if (grub_pci_read (addr) >> 24 != GRUB_PCI_CLASS_NETWORK) + return 0; + cap = grub_pci_find_capability (dev, GRUB_PCI_CAP_POWER_MANAGEMENT); + if (!cap) + return 0; + addr = grub_pci_make_address (dev, cap + 4); + pm_state = grub_pci_read_word (addr); + pm_state = pm_state | 0x03; + grub_pci_write_word (addr, pm_state); + grub_pci_read_word (addr); + return 0; +} + static void stop_broadcom (void) { - auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, - grub_pci_id_t pciid); - - int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, - grub_pci_id_t pciid) - { - grub_pci_address_t addr; - grub_uint8_t cap; - grub_uint16_t pm_state; - - if ((pciid & 0xffff) != GRUB_PCI_VENDOR_BROADCOM) - return 0; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - if (grub_pci_read (addr) >> 24 != GRUB_PCI_CLASS_NETWORK) - return 0; - cap = grub_pci_find_capability (dev, GRUB_PCI_CAP_POWER_MANAGEMENT); - if (!cap) - return 0; - addr = grub_pci_make_address (dev, cap + 4); - pm_state = grub_pci_read_word (addr); - pm_state = pm_state | 0x03; - grub_pci_write_word (addr, pm_state); - grub_pci_read_word (addr); - return 0; - } - - grub_pci_iterate (find_card); + grub_pci_iterate (find_card, NULL); } #endif === modified file 'grub-core/kern/mips/loongson/init.c' --- grub-core/kern/mips/loongson/init.c 2012-06-11 18:44:38 +0000 +++ grub-core/kern/mips/loongson/init.c 2013-01-01 12:50:14 +0000 @@ -49,45 +49,47 @@ grub_machine_mmap_iterate (grub_memory_h return GRUB_ERR_NONE; } +/* Helper for init_pci. */ +static int +set_card (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) +{ + grub_pci_address_t addr; + /* FIXME: autoscan for BARs and devices. */ + switch (pciid) + { + case GRUB_LOONGSON_OHCI_PCIID: + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + grub_pci_write (addr, 0x5025000); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write_word (addr, GRUB_PCI_COMMAND_SERR_ENABLE + | GRUB_PCI_COMMAND_PARITY_ERROR + | GRUB_PCI_COMMAND_BUS_MASTER + | GRUB_PCI_COMMAND_MEM_ENABLED); + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_STATUS); + grub_pci_write_word (addr, 0x0200 | GRUB_PCI_STATUS_CAPABILITIES); + break; + case GRUB_LOONGSON_EHCI_PCIID: + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + grub_pci_write (addr, 0x5026000); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write_word (addr, GRUB_PCI_COMMAND_SERR_ENABLE + | GRUB_PCI_COMMAND_PARITY_ERROR + | GRUB_PCI_COMMAND_BUS_MASTER + | GRUB_PCI_COMMAND_MEM_ENABLED); + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_STATUS); + grub_pci_write_word (addr, (1 << GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT) + | GRUB_PCI_STATUS_CAPABILITIES); + break; + } + return 0; +} + static void init_pci (void) { - auto int NESTED_FUNC_ATTR set_card (grub_pci_device_t dev, grub_pci_id_t pciid); - int NESTED_FUNC_ATTR set_card (grub_pci_device_t dev, grub_pci_id_t pciid) - { - grub_pci_address_t addr; - /* FIXME: autoscan for BARs and devices. */ - switch (pciid) - { - case GRUB_LOONGSON_OHCI_PCIID: - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); - grub_pci_write (addr, 0x5025000); - addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); - grub_pci_write_word (addr, GRUB_PCI_COMMAND_SERR_ENABLE - | GRUB_PCI_COMMAND_PARITY_ERROR - | GRUB_PCI_COMMAND_BUS_MASTER - | GRUB_PCI_COMMAND_MEM_ENABLED); - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_STATUS); - grub_pci_write_word (addr, 0x0200 | GRUB_PCI_STATUS_CAPABILITIES); - break; - case GRUB_LOONGSON_EHCI_PCIID: - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); - grub_pci_write (addr, 0x5026000); - addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); - grub_pci_write_word (addr, GRUB_PCI_COMMAND_SERR_ENABLE - | GRUB_PCI_COMMAND_PARITY_ERROR - | GRUB_PCI_COMMAND_BUS_MASTER - | GRUB_PCI_COMMAND_MEM_ENABLED); - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_STATUS); - grub_pci_write_word (addr, (1 << GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT) - | GRUB_PCI_STATUS_CAPABILITIES); - break; - } - return 0; - } - *((volatile grub_uint32_t *) GRUB_CPU_LOONGSON_PCI_HIT1_SEL_LO) = 0x8000000c; *((volatile grub_uint32_t *) GRUB_CPU_LOONGSON_PCI_HIT1_SEL_HI) = 0xffffffff; @@ -110,7 +112,7 @@ init_pci (void) *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER + GRUB_PCI_REG_ADDRESS_REG1)) = 0; - grub_pci_iterate (set_card); + grub_pci_iterate (set_card, NULL); } void === modified file 'grub-core/kern/vga_init.c' --- grub-core/kern/vga_init.c 2011-07-05 21:46:15 +0000 +++ grub-core/kern/vga_init.c 2013-01-01 14:39:55 +0000 @@ -18,6 +18,7 @@ #ifndef __mips__ #include <grub/pci.h> +#include <grub/mm.h> #endif #include <grub/machine/kernel.h> #include <grub/misc.h> @@ -87,38 +88,42 @@ load_palette (void) grub_vga_palette_write (i, colors[i].r, colors[i].g, colors[i].b); } +#ifndef __mips__ +/* Helper for grub_qemu_init_cirrus. */ +static int +find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused)), + void *data __attribute__ ((unused))) +{ + grub_pci_address_t addr; + grub_uint32_t class; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class = grub_pci_read (addr); + + if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA) + return 0; + + /* FIXME: chooose addresses dynamically. */ + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + grub_pci_write (addr, 0xf0000000 | GRUB_PCI_ADDR_MEM_PREFETCH + | GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1); + grub_pci_write (addr, 0xf2000000 + | GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32); + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write (addr, GRUB_PCI_COMMAND_MEM_ENABLED + | GRUB_PCI_COMMAND_IO_ENABLED); + + return 1; +} +#endif + void grub_qemu_init_cirrus (void) { #ifndef __mips__ - auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid); - int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused))) - { - grub_pci_address_t addr; - grub_uint32_t class; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - class = grub_pci_read (addr); - - if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA) - return 0; - - /* FIXME: chooose addresses dynamically. */ - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); - grub_pci_write (addr, 0xf0000000 | GRUB_PCI_ADDR_MEM_PREFETCH - | GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32); - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1); - grub_pci_write (addr, 0xf2000000 - | GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32); - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); - grub_pci_write (addr, GRUB_PCI_COMMAND_MEM_ENABLED - | GRUB_PCI_COMMAND_IO_ENABLED); - - return 1; - } - - grub_pci_iterate (find_card); + grub_pci_iterate (find_card, NULL); #endif grub_outb (GRUB_VGA_IO_MISC_COLOR, === modified file 'grub-core/video/bochs.c' --- grub-core/video/bochs.c 2012-12-30 09:57:58 +0000 +++ grub-core/video/bochs.c 2013-01-01 12:50:14 +0000 @@ -199,6 +199,29 @@ grub_video_bochs_set_palette (unsigned i return grub_video_fb_set_palette (start, count, palette_data); } +/* Helper for grub_video_bochs_setup. */ +static int +find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data) +{ + int *found = data; + grub_pci_address_t addr; + grub_uint32_t class; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class = grub_pci_read (addr); + + if (((class >> 16) & 0xffff) != 0x0300 || pciid != 0x11111234) + return 0; + + *found = 1; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + framebuffer.base = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK; + framebuffer.dev = dev; + + return 1; +} + static grub_err_t grub_video_bochs_setup (unsigned int width, unsigned int height, grub_video_mode_type_t mode_type, @@ -210,27 +233,6 @@ grub_video_bochs_setup (unsigned int wid int pitch, bytes_per_pixel; grub_size_t page_size; /* The size of a page in bytes. */ - auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid); - int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid) - { - grub_pci_address_t addr; - grub_uint32_t class; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - class = grub_pci_read (addr); - - if (((class >> 16) & 0xffff) != 0x0300 || pciid != 0x11111234) - return 0; - - found = 1; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); - framebuffer.base = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK; - framebuffer.dev = dev; - - return 1; - } - /* Decode depth from mode_type. If it is zero, then autodetect. */ depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS; @@ -280,7 +282,7 @@ grub_video_bochs_setup (unsigned int wid if (page_size > BOCHS_APERTURE_SIZE) return grub_error (GRUB_ERR_IO, "Not enough video memory for this mode"); - grub_pci_iterate (find_card); + grub_pci_iterate (find_card, &found); if (!found) return grub_error (GRUB_ERR_IO, "Couldn't find graphics card"); === modified file 'grub-core/video/cirrus.c' --- grub-core/video/cirrus.c 2012-12-30 09:57:58 +0000 +++ grub-core/video/cirrus.c 2013-01-01 12:50:14 +0000 @@ -235,6 +235,29 @@ grub_video_cirrus_set_palette (unsigned return grub_video_fb_set_palette (start, count, palette_data); } +/* Helper for grub_video_cirrus_setup. */ +static int +find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data) +{ + int *found = data; + grub_pci_address_t addr; + grub_uint32_t class; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class = grub_pci_read (addr); + + if (((class >> 16) & 0xffff) != 0x0300 || pciid != 0x00b81013) + return 0; + + *found = 1; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + framebuffer.base = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK; + framebuffer.dev = dev; + + return 1; +} + static grub_err_t grub_video_cirrus_setup (unsigned int width, unsigned int height, grub_video_mode_type_t mode_type, @@ -245,27 +268,6 @@ grub_video_cirrus_setup (unsigned int wi int found = 0; int pitch, bytes_per_pixel; - auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid); - int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid) - { - grub_pci_address_t addr; - grub_uint32_t class; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - class = grub_pci_read (addr); - - if (((class >> 16) & 0xffff) != 0x0300 || pciid != 0x00b81013) - return 0; - - found = 1; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); - framebuffer.base = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK; - framebuffer.dev = dev; - - return 1; - } - /* Decode depth from mode_type. If it is zero, then autodetect. */ depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS; @@ -314,7 +316,7 @@ grub_video_cirrus_setup (unsigned int wi if (framebuffer.page_size > CIRRUS_APERTURE_SIZE) return grub_error (GRUB_ERR_IO, "Not enough video memory for this mode"); - grub_pci_iterate (find_card); + grub_pci_iterate (find_card, &found); if (!found) return grub_error (GRUB_ERR_IO, "Couldn't find graphics card"); === modified file 'grub-core/video/efi_uga.c' --- grub-core/video/efi_uga.c 2012-02-27 13:13:24 +0000 +++ grub-core/video/efi_uga.c 2013-01-01 13:05:55 +0000 @@ -81,77 +81,88 @@ find_line_len (grub_uint32_t *fb_base, g return 0; } -static int -find_framebuf (grub_uint32_t *fb_base, grub_uint32_t *line_len) +/* Context for find_framebuf. */ +struct find_framebuf_ctx { - int found = 0; + grub_uint32_t *fb_base; + grub_uint32_t *line_len; + int found; +}; - auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, - grub_pci_id_t pciid); +/* Helper for find_framebuf. */ +static int +find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data) +{ + struct find_framebuf_ctx *ctx = data; + grub_pci_address_t addr; - int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, - grub_pci_id_t pciid) + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + if (grub_pci_read (addr) >> 24 == 0x3) { - grub_pci_address_t addr; + int i; - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - if (grub_pci_read (addr) >> 24 == 0x3) + grub_dprintf ("fb", "Display controller: %d:%d.%d\nDevice id: %x\n", + grub_pci_get_bus (dev), grub_pci_get_device (dev), + grub_pci_get_function (dev), pciid); + addr += 8; + for (i = 0; i < 6; i++, addr += 4) { - int i; + grub_uint32_t old_bar1, old_bar2, type; + grub_uint64_t base64; + + old_bar1 = grub_pci_read (addr); + if ((! old_bar1) || (old_bar1 & GRUB_PCI_ADDR_SPACE_IO)) + continue; - grub_dprintf ("fb", "Display controller: %d:%d.%d\nDevice id: %x\n", - grub_pci_get_bus (dev), grub_pci_get_device (dev), - grub_pci_get_function (dev), pciid); - addr += 8; - for (i = 0; i < 6; i++, addr += 4) + type = old_bar1 & GRUB_PCI_ADDR_MEM_TYPE_MASK; + if (type == GRUB_PCI_ADDR_MEM_TYPE_64) { - grub_uint32_t old_bar1, old_bar2, type; - grub_uint64_t base64; + if (i == 5) + break; - old_bar1 = grub_pci_read (addr); - if ((! old_bar1) || (old_bar1 & GRUB_PCI_ADDR_SPACE_IO)) - continue; - - type = old_bar1 & GRUB_PCI_ADDR_MEM_TYPE_MASK; - if (type == GRUB_PCI_ADDR_MEM_TYPE_64) - { - if (i == 5) - break; - - old_bar2 = grub_pci_read (addr + 4); - } - else - old_bar2 = 0; - - base64 = old_bar2; - base64 <<= 32; - base64 |= (old_bar1 & GRUB_PCI_ADDR_MEM_MASK); - - grub_dprintf ("fb", "%s(%d): 0x%llx\n", - ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) ? - "VMEM" : "MMIO"), i, - (unsigned long long) base64); - - if ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) && (! found)) - { - *fb_base = base64; - if (find_line_len (fb_base, line_len)) - found++; - } - - if (type == GRUB_PCI_ADDR_MEM_TYPE_64) - { - i++; - addr += 4; - } + old_bar2 = grub_pci_read (addr + 4); + } + else + old_bar2 = 0; + + base64 = old_bar2; + base64 <<= 32; + base64 |= (old_bar1 & GRUB_PCI_ADDR_MEM_MASK); + + grub_dprintf ("fb", "%s(%d): 0x%llx\n", + ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) ? + "VMEM" : "MMIO"), i, + (unsigned long long) base64); + + if ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) && (! ctx->found)) + { + *ctx->fb_base = base64; + if (find_line_len (ctx->fb_base, ctx->line_len)) + ctx->found++; } - } - return found; + if (type == GRUB_PCI_ADDR_MEM_TYPE_64) + { + i++; + addr += 4; + } + } } - grub_pci_iterate (find_card); - return found; + return ctx->found; +} + +static int +find_framebuf (grub_uint32_t *fb_base, grub_uint32_t *line_len) +{ + struct find_framebuf_ctx ctx = { + .fb_base = fb_base, + .line_len = line_len, + .found = 0 + }; + + grub_pci_iterate (find_card, &ctx); + return ctx.found; } static int === modified file 'grub-core/video/radeon_fuloong2e.c' --- grub-core/video/radeon_fuloong2e.c 2012-12-30 09:57:58 +0000 +++ grub-core/video/radeon_fuloong2e.c 2013-01-01 12:50:14 +0000 @@ -60,6 +60,32 @@ grub_video_radeon_fuloong2e_video_fini ( return grub_video_fb_fini (); } +#ifndef TEST +/* Helper for grub_video_radeon_fuloong2e_setup. */ +static int +find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data) +{ + int *found = data; + grub_pci_address_t addr; + grub_uint32_t class; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class = grub_pci_read (addr); + + if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA + || pciid != 0x515a1002) + return 0; + + *found = 1; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + framebuffer.base = grub_pci_read (addr); + framebuffer.dev = dev; + + return 1; +} +#endif + static grub_err_t grub_video_radeon_fuloong2e_setup (unsigned int width, unsigned int height, unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) @@ -69,28 +95,6 @@ grub_video_radeon_fuloong2e_setup (unsig int found = 0; #ifndef TEST - auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid); - int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid) - { - grub_pci_address_t addr; - grub_uint32_t class; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - class = grub_pci_read (addr); - - if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA - || pciid != 0x515a1002) - return 0; - - found = 1; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); - framebuffer.base = grub_pci_read (addr); - framebuffer.dev = dev; - - return 1; - } - /* Decode depth from mode_type. If it is zero, then autodetect. */ depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS; @@ -100,7 +104,7 @@ grub_video_radeon_fuloong2e_setup (unsig return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "Only 640x480x16 is supported"); - grub_pci_iterate (find_card); + grub_pci_iterate (find_card, &found); if (!found) return grub_error (GRUB_ERR_IO, "Couldn't find graphics card"); #endif === modified file 'grub-core/video/sis315pro.c' --- grub-core/video/sis315pro.c 2012-12-30 09:57:58 +0000 +++ grub-core/video/sis315pro.c 2013-01-01 12:50:14 +0000 @@ -88,6 +88,37 @@ grub_video_sis315pro_video_fini (void) #include "sis315_init.c" +#ifndef TEST +/* Helper for grub_video_sis315pro_setup. */ +static int +find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data) +{ + int *found = data; + grub_pci_address_t addr; + grub_uint32_t class; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class = grub_pci_read (addr); + + if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA + || pciid != GRUB_SIS315PRO_PCIID) + return 0; + + *found = 1; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + framebuffer.base = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK; + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1); + framebuffer.mmiobase = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK; + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG2); + framebuffer.io = (grub_pci_read (addr) & GRUB_PCI_ADDR_IO_MASK) + + GRUB_MACHINE_PCI_IO_BASE; + framebuffer.dev = dev; + + return 1; +} +#endif + static grub_err_t grub_video_sis315pro_setup (unsigned int width, unsigned int height, unsigned int mode_type, @@ -99,33 +130,6 @@ grub_video_sis315pro_setup (unsigned int unsigned i; #ifndef TEST - auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid); - int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid) - { - grub_pci_address_t addr; - grub_uint32_t class; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - class = grub_pci_read (addr); - - if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA - || pciid != GRUB_SIS315PRO_PCIID) - return 0; - - found = 1; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); - framebuffer.base = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK; - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1); - framebuffer.mmiobase = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK; - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG2); - framebuffer.io = (grub_pci_read (addr) & GRUB_PCI_ADDR_IO_MASK) - + GRUB_MACHINE_PCI_IO_BASE; - framebuffer.dev = dev; - - return 1; - } - /* Decode depth from mode_type. If it is zero, then autodetect. */ depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS; @@ -135,7 +139,7 @@ grub_video_sis315pro_setup (unsigned int return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "Only 640x480x8 is supported"); - grub_pci_iterate (find_card); + grub_pci_iterate (find_card, &found); if (!found) return grub_error (GRUB_ERR_IO, "Couldn't find graphics card"); #endif === modified file 'grub-core/video/sm712.c' --- grub-core/video/sm712.c 2012-12-30 09:57:58 +0000 +++ grub-core/video/sm712.c 2013-01-01 12:50:14 +0000 @@ -360,6 +360,32 @@ grub_sm712_write_dda_lookup (int idx, gr GRUB_SM712_CR_DDA_LOOKUP_REG1_START + idx); } +#if !defined (TEST) && !defined(GENINIT) +/* Helper for grub_video_sm712_setup. */ +static int +find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data) +{ + int *found = data; + grub_pci_address_t addr; + grub_uint32_t class; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class = grub_pci_read (addr); + + if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA + || pciid != GRUB_SM712_PCIID) + return 0; + + *found = 1; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + framebuffer.base = grub_pci_read (addr); + framebuffer.dev = dev; + + return 1; +} +#endif + static grub_err_t grub_video_sm712_setup (unsigned int width, unsigned int height, unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) @@ -370,28 +396,6 @@ grub_video_sm712_setup (unsigned int wid grub_err_t err; int found = 0; - auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid); - int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid) - { - grub_pci_address_t addr; - grub_uint32_t class; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - class = grub_pci_read (addr); - - if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA - || pciid != GRUB_SM712_PCIID) - return 0; - - found = 1; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); - framebuffer.base = grub_pci_read (addr); - framebuffer.dev = dev; - - return 1; - } - /* Decode depth from mode_type. If it is zero, then autodetect. */ depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS; @@ -401,7 +405,7 @@ grub_video_sm712_setup (unsigned int wid return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "Only 1024x600x16 is supported"); - grub_pci_iterate (find_card); + grub_pci_iterate (find_card, &found); if (!found) return grub_error (GRUB_ERR_IO, "Couldn't find graphics card"); /* Fill mode info details. */ === modified file 'include/grub/pci.h' --- include/grub/pci.h 2012-05-04 08:54:38 +0000 +++ include/grub/pci.h 2013-01-01 12:50:14 +0000 @@ -132,13 +132,14 @@ grub_pci_get_function (grub_pci_device_t #include <grub/cpu/pci.h> #endif -typedef int NESTED_FUNC_ATTR (*grub_pci_iteratefunc_t) - (grub_pci_device_t dev, grub_pci_id_t pciid); +typedef int (*grub_pci_iteratefunc_t) + (grub_pci_device_t dev, grub_pci_id_t pciid, void *data); grub_pci_address_t EXPORT_FUNC(grub_pci_make_address) (grub_pci_device_t dev, int reg); -void EXPORT_FUNC(grub_pci_iterate) (grub_pci_iteratefunc_t hook); +void EXPORT_FUNC(grub_pci_iterate) (grub_pci_iteratefunc_t hook, + void *hook_data); struct grub_pci_dma_chunk;
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel